/* =========================================================
   Press Start 2P (v16, Latin subset) — self-hosted.
   Source: @fontsource/press-start-2p npm package, Google Fonts v16
   License: SIL OFL 1.1 (see /fonts/LICENSE.txt).
   ========================================================= */
@font-face {
  font-family: 'Press Start 2P';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/press-start-2p-v16-latin.woff2') format('woff2'),
       url('../fonts/press-start-2p-v16-latin.woff') format('woff');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* =========================================================
   PUCKSONNET — Draft Lottery
   Mobile-first responsive styles.
   Breakpoints: base (<=480), tablet (>=768), desktop (>=1024)
   ========================================================= */

:root {
  /* Pucksonnet palette */
  --ice-cyan: #96EDF6;
  --ice-light-cyan: #B8F6FA;
  --black: #000000;
  --red: #E2231A;
  --white: #FFFFFF;
  /* Crease blue — the painted goalie crease on hockey ice. Used for the
     odds-tag background so it reads as "hockey" rather than "alert". */
  --crease-blue: #2E6FBE;
  /* Movement tag colors (post-sim odds-tag variants).
     up  = team moved up in the draft (positive) → green
     down = team moved down (negative) → red
     flat = no movement → darker cyan (stays on-palette, less attention) */
  --move-up: #1AAB5B;
  --move-down: #E2231A;
  --move-flat: #5AC8D6;
  /* v73: grey drop-shadow replaces the old white offset. Softer for
     large surfaces (cards, panels, draw strip), punchier for buttons.
     Keep text-shadows white — only BOX shadows move to grey. */
  --shadow-drop: rgba(0, 0, 0, 0.35);
  --shadow-drop-deep: rgba(0, 0, 0, 0.55);
}

* { box-sizing: border-box; }

/* Periods render with a full glyph cell in Press Start 2P, so the space
   before/after reads as a double gap. Wrap periods in <span class="period">
   and negative-margin both sides to tighten them everywhere we use this. */
.period {
  display: inline-block;
  margin-left: -0.25em;
  margin-right: -0.2em;
}

html, body { height: 100%; }

body {
  margin: 0;
  /* No bottom padding — ticker was removed (v54) so the disclaimer is
     now the last element. Previous 80/90/100px reserves were for the
     fixed-position ticker bar. */
  padding: 0;
  min-height: 100vh;
  font-family: 'Press Start 2P', monospace;
  /* v=249: unify whole surface to lighter #C8F3F8 (was #B0F0F6 in v=248). */
  background-color: #C8F3F8;
  background-image:
    linear-gradient(115deg, rgba(255, 255, 255, 0.4) 0%, rgba(255, 255, 255, 0) 25%),
    linear-gradient(-65deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 30%);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-transform: uppercase;
  overflow-x: hidden;
  position: relative;
}

.main-wrapper {
  width: 100%;
  max-width: 1000px;
  padding: 0 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 10;
}

/* v57: kill the trailing bottom margin on whatever the last content
   block inside .main-wrapper is. .lottery-card carries 20-40px bottom
   margins that stacked with the disclaimer's top margin, producing
   the "HUGE" gap the user called out. Now the disclaimer's own
   margin-top (10/12/14) controls the gap alone. */
.main-wrapper > :last-child { margin-bottom: 0; }

/* ===== STICKY CONTROL SHELL (v88) =====
   Wraps the site header + (optionally) the action-zone + the FULL-page
   draw-strip. As the user scrolls the card/odds grid below, the whole
   shell pins to the viewport top so the hamburger menu, mode toggle,
   PUSH-TO-START button, and (on FULL) the live draw strip stay
   interactable at every scroll position. ATTEMPTS counter has been
   pulled OUT of this shell into main-wrapper so it scrolls away —
   per user directive, attempts is not control, it's a stat.
   z-index sits above main-wrapper (10) but keeps .menu-panel (50)
   winning inside its own stacking context when the hamburger opens.
   .sticky-shell-inner provides the 12/20 horizontal padding that
   the contained action-zone + drawing-header + draw-strip previously
   inherited from main-wrapper, so their widths and alignments are
   unchanged from the pre-restructure layout. */
.sticky-shell {
  position: sticky;
  top: 0;
  z-index: 40;
  /* v102 (fix #3): the darker #84E9F4 band was bleeding down behind
     the action-zone / draw-strip because it was painted on the outer
     shell. Now only the header row gets the dark band (via the
     .header-container pseudo-element below). The shell itself paints
     the LIGHTER #C8F3F8 (same as page bg) so the portion below the
     header blends seamlessly into the page. Without a shell bg, the
     card grid would scroll visibly underneath the sticky chrome. */
  width: 100%;
  /* v=249: unify to lighter #C8F3F8. */
  background-color: #C8F3F8;
}

.sticky-shell-inner {
  /* v101 (fix #2): 1000px cap + auto margins so the action-zone,
     attempts counter, drawing-header, and draw-strip all align with
     the .main-wrapper content below. Before this, those elements
     stretched to the full viewport width on wide desktops because
     this container had no max-width. */
  width: 100%;
  max-width: 1000px;
  margin: 0 auto;
  padding: 0 12px;
}
@media (min-width: 768px) {
  .sticky-shell-inner { padding: 0 20px; }
}
@media (min-width: 1024px) {
  .sticky-shell-inner { padding: 0 20px; }
}

/* ===== HEADER ===== */

.header-container {
  /* v102 (fix #3): content capped at 1000px and centered (PUCKSON.NET
     aligns with cards' left edge, hamburger aligns with right edge),
     but the darker #84E9F4 band extends edge-to-edge via a pseudo-
     element. Using ::before with left/right: 50% - 50vw is safer than
     box-shadow + clip-path because it won't clip the menu-panel
     dropdown when the hamburger opens. z-index: 0 on the container
     gives the ::before's z-index: -1 a local stacking context so the
     dark band paints behind header siblings but ABOVE the sticky-
     shell's own background (otherwise z-index: -1 would escape and
     the band would be hidden). */
  position: relative;
  z-index: 0;
  width: 100%;
  max-width: 1000px;
  /* v=107: bottom margin 10 -> 6 to tighten the gap between the header
     band and the mode-selector / start-button action zone below. */
  margin: 0 auto 6px;
  padding: 10px 12px;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}

.header-container::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(50% - 50vw);
  right: calc(50% - 50vw);
  background: #69E4F1;
  z-index: -1;
}

.title-logo {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.nhl-text {
  display: block;
  color: var(--black);
  font-size: 1.1rem;
  letter-spacing: -2px;
  line-height: 1;
  /* Pucksonnet recipe: single white drop shadow, bottom-right. */
  text-shadow: 3px 3px 0 var(--white);
}

.main-title {
  color: var(--ice-light-cyan);
  font-size: 1rem;
  -webkit-text-stroke: 1px var(--black);
  text-shadow: 2px 2px 0 var(--black);
  line-height: 1;
  text-align: center;
}

/* ===== GRID ===== */

/* White box that wraps the column headers + team cards as one unit. */
.lottery-card {
  width: 100%;
  background: transparent;
  padding: 12px 10px;
  /* v105: cut from 32 -> 14 to tighten the gap between the card grid
     and the "% ODDS BY PICK" header on FULL. On QUICK the lottery-card
     is .main-wrapper's last child, so its bottom margin is zeroed by
     `.main-wrapper > :last-child`, so this change is FULL-only. */
  margin-bottom: 14px;
}

/* Column headers live inside the white box, above the grid.
   Mobile shows the first header-row only (1-col grid).
   Tablet/desktop shows both (2-col grid). */
.grid-headers {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  width: 100%;
  margin-bottom: 8px;
  padding: 0 10px;
}

.grid-headers .header-row {
  display: flex;
  align-items: center;
  color: var(--black);
  font-size: 0.5rem;
  word-spacing: -0.2em;
  text-shadow: 1px 1px 0 var(--white);
}

/* Hide the second header row on mobile (only one column of cards there). */
.grid-headers .header-row:nth-child(2) { display: none; }

.grid-headers .header-rank {
  width: 28px;
  margin-right: 10px;
  text-align: right;
  flex-shrink: 0;
}
.grid-headers .header-team { flex: 1 1 auto; text-align: left; }
.grid-headers .header-odds {
  min-width: 78px;
  text-align: right;
  flex-shrink: 0;
}

.lottery-grid {
  display: grid;
  grid-template-columns: 1fr;         /* mobile: single column */
  grid-auto-flow: row;
  gap: 10px;
  width: 100%;
}

.plate-container {
  display: flex;
  align-items: center;
  background: transparent;
  padding: 3px 10px;
  opacity: 0;
  transform: translateX(-10px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}

.plate-container.is-revealed {
  opacity: 1;
  transform: translateX(0);
}

.rank-num {
  width: 28px;
  font-size: 0.85rem;
  color: var(--black);
  text-align: right;
  margin-right: 10px;
  text-shadow: 2px 2px 0px var(--white);
  flex-shrink: 0;
}

.team-box {
  display: flex;
  flex-grow: 1;
  align-items: center;
  gap: 10px;
  border: none;
  min-width: 0;
}

/* Logo slot — sized below at each breakpoint. Slightly larger than the
   pre-retro layout to let the pixelated canvas breathe. `overflow: visible`
   so drop-shadow isn't clipped. */
.team-logo {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible;
}

/* <img> renders briefly before JS swaps in the canvas; both share styling.
   Retro feel comes from two stacked filters:
   1. url(#retro-posterize)  -> color quantization (defined in index.html).
      Crushes each RGB channel into 4 steps (64 discrete colors).
   2. CRT boost               -> saturation + contrast + drop-shadow.
   `image-rendering: pixelated` kicks in if the canvas ever scales UP
   (unused at current sizes but future-proof). */
.team-logo img,
.team-logo canvas {
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  filter: url(#retro-posterize)
          saturate(1.6) contrast(1.2) brightness(1.03)
          drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.7));
}

.team-name-stack {
  display: flex;
  flex-direction: column;
  justify-content: center;
  color: var(--black);
  line-height: 1.3;
  font-size: 0.5rem;
  word-spacing: -0.25em;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-align: left;
}

.team-name-stack > span {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.team-metric {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  color: var(--black);
  flex-shrink: 0;
  min-width: 78px;
  text-align: right;
}

.metric-value {
  font-size: 0.78rem;
  margin-bottom: 2px;
  letter-spacing: 1px;
  text-shadow: 2px 2px 0 var(--white);
}

.metric-label {
  font-size: 0.35rem;
  word-spacing: -0.2em;
  white-space: nowrap;
}

/* ===== WINNER FLASH ===== */

@keyframes flash-winner {
  0%, 100% { background: var(--white); color: var(--black); }
  50%      { background: var(--black); color: var(--white); }
}

.plate-container.winner {
  animation: flash-winner 0.8s step-end infinite;
}
.plate-container.winner .rank-num,
.plate-container.winner .team-name-stack,
.plate-container.winner .team-metric {
  animation: flash-winner 0.8s step-end infinite;
}

/* ===== CONTROLS ===== */

/* ===== PRIMARY NAV ===== */

/* Hamburger menu: 3-bar icon + current page label + dropdown panel.
   Lives inside .header-inner and is pushed to the right with margin-left:auto. */
.menu-wrap {
  position: relative;
  margin-left: auto;
}

.menu-toggle {
  display: flex;
  align-items: center;
  gap: 12px;
  background: transparent;
  border: none;
  /* Zero horizontal padding so the menu-current tag's right edge sits
     flush with .menu-wrap — matches the right edge of .btn-start below
     (both are bound only by .header-container / .main-wrapper padding,
     which are the same at every breakpoint). */
  padding: 4px 0;
  cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  line-height: 1;
  text-transform: uppercase;
}

/* Legacy .menu-icon rules removed in v=145 — new .menu-wrap .menu-icon rules below own the class now. */

/* v74: press-in effect on the hamburger toggle. Matches the arcade
   "push" treatment on .btn-start and .mode-arrow — the whole button
   drops 3px down/right and its children's box-shadows collapse so the
   shadow appears "absorbed". Fires on :active (mouse down) AND while
   the panel is open (aria-expanded="true") so the sunk state is stable
   as long as the menu is actually open. */
.menu-toggle:active,
.menu-toggle[aria-expanded="true"] {
  transform: translate(3px, 3px);
}
.menu-toggle:active .menu-icon > span,
.menu-toggle[aria-expanded="true"] .menu-icon > span,
.menu-toggle:active .menu-current,
.menu-toggle[aria-expanded="true"] .menu-current {
  box-shadow: 0 0 0 transparent;
}

/* Desktop hover: half-push (matches .btn-start and .mode-arrow hover).
   translate(2px, 2px) with shadow reduced to 1px so it reads as "about
   to commit" — not the full sunk state. Wrapped in (hover: hover) so
   touch devices don't get a sticky hovered appearance after a tap. */
@media (hover: hover) {
  .menu-toggle:hover:not([aria-expanded="true"]) {
    transform: translate(2px, 2px);
  }
  .menu-toggle:hover:not([aria-expanded="true"]) .menu-icon > span {
    box-shadow: 1px 1px 0 var(--shadow-drop-deep);
  }
  .menu-toggle:hover:not([aria-expanded="true"]) .menu-current {
    box-shadow: 2px 2px 0 var(--shadow-drop-deep);
  }
}

/* Current-page pill: solid black box with white text. Fixed min-width
   sized to fit the longest label (ANALYTICS / PROSPECTS, 9 chars) so the
   pill never resizes when the active page changes. inline-flex centers
   the label both horizontally and vertically inside the taller box.
   box-shadow matches the START button so both right edges line up
   pixel-for-pixel (both extend 4px right of their box). */
.menu-current {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
  font-size: 0.65rem;
  line-height: 1;
  background: var(--black);
  color: var(--white);
  padding: 10px 12px;
  /* Fixed width (not min-width) so the tag is the same size on every
     page regardless of whether it reads LOTTERY / PROSPECTS / ANALYTICS.
     12ch comfortably fits the 9-char names + 24px padding at every
     breakpoint — ch scales with font-size, so this holds from mobile
     through desktop without separate overrides. */
  width: 12ch;
  text-align: center;
  box-shadow: 4px 4px 0 var(--shadow-drop);
}

/* Dropdown panel: absolute below the toggle. Hidden by default.
   Width locked to match the .menu-current pill's outer width exactly.
   With the global `* { box-sizing: border-box }` rule at the top of this
   file, .menu-current's `width: 12ch` already includes its 12px side
   padding — so the panel just needs the same 12ch width and matching
   font-size at every breakpoint (so 1ch resolves identically). Both are
   anchored `right: 0`, so their right edges line up pixel-for-pixel. */
.menu-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  display: none;
  flex-direction: column;
  gap: 6px;
  background: var(--ice-cyan);
  border: 3px solid var(--black);
  box-shadow: 4px 4px 0 var(--black);
  padding: 8px 6px;
  font-size: 0.65rem;
  width: 12ch;
  z-index: 50;
}

.menu-panel.is-open { display: flex; }

/* Dropdown items match the current-page pill treatment: on hover (and focus),
   swap to the solid-black box with white text. All three items render in the
   same black text at rest. Size matches .menu-current. */
.menu-item {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.65rem;
  background: transparent;
  color: var(--black);
  text-decoration: none;
  text-transform: uppercase;
  /* Narrow horizontal padding — panel is only 12ch + 24px wide and the
     longest label (ANALYTICS / PROSPECTS) is 9 chars, so we keep side
     padding minimal to leave breathing room without blowing past the
     pill width above. */
  padding: 8px 4px;
  text-align: center;
  white-space: nowrap;
  transition: background 0.1s, color 0.1s;
}

.menu-item:hover,
.menu-item:focus-visible {
  background: var(--black);
  color: var(--white);
  outline: none;
}

.action-zone {
  display: grid;
  /* v=162: action-zone grid mirrors .card-grid exactly — same col
     count (2/3/4 at mobile/768+/1024+), same gap (12/16/20), same
     horizontal padding as lottery-card (10/14/16). mode-wrap sits in
     col 1, btn-start in the LAST col, middle cols empty. That way
     both controls inherit card-column geometry for free. */
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  width: 100%;
  /* v88: sticky moved UP to .sticky-shell (wraps header + action-zone
     + optional draw-strip). action-zone itself is a plain grid again,
     no sticky/z-index of its own. Background kept so when the shell
     is pinned the action-zone bar stays opaque over scrolling cards.
     Attempts-counter has been moved OUT of this grid to main-wrapper
     so it scrolls away instead of sticking.
     v=107: top padding trimmed 4 -> 2 to tighten the header→controls
     gap per user directive. */
  margin-bottom: 0;
  padding: 2px 10px;
  /* v=249: unify to lighter #C8F3F8. */
  background-color: #C8F3F8;
}

.action-prompt {
  grid-column: 1 / span 2;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  text-align: left;
  color: var(--black);
  font-size: 0.55rem;
  line-height: 1.2;
  animation: arcade-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes arcade-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.5; }
}

/* ===== Sim mode selector (arcade cursor) =====
   Replaces the static "press start to begin..." prompt with a
   < QUICK > / < FULL > toggle. Occupies the same two-column slot
   the prompt used to, so the red START button stays pinned right. */
.mode-selector {
  grid-column: 1 / span 2;
  display: flex;
  align-items: center;
  /* v103: gap bumped from 2 -> 10 so the arrows aren't pinched against
     "FULL / LOTTERY SIM". Flex `gap` applies between all children
     equally, so the arrow<->stack breathing room is symmetric on both
     sides. Tablet/desktop get proportionally wider gaps below. */
  gap: 10px;
  color: var(--black);
}

.mode-arrow {
  font-family: 'Press Start 2P', monospace;
  /* v=249: match unified surface. */
  background: #C8F3F8;
  border: 3px solid var(--black);
  color: var(--black);
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  line-height: 1;
  box-shadow: 3px 3px 0 var(--shadow-drop-deep);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: transform 0.1s, box-shadow 0.1s;
}

/* Push-in press, matches .btn-start pattern */
.mode-arrow:active {
  transform: translate(3px, 3px);
  box-shadow: 0 0 0 transparent;
  background: var(--black);
  color: var(--white);
}

@media (hover: hover) {
  .mode-arrow:hover {
    transform: translate(2px, 2px);
    box-shadow: 1px 1px 0 var(--shadow-drop-deep);
    background: var(--black);
    color: var(--white);
  }
}

.mode-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1;
  gap: 4px;
  /* v100: second line is now the static "LOTTERY SIMULATOR" string,
     which is wider than QUICK/FULL at any breakpoint — it naturally
     anchors the stack width so the QUICK<->FULL swap can't shift the
     arrows. Explicit min-width no longer needed. */
}

.mode-tag {
  /* v103: bumped from 0.4 -> 0.5 base (and proportionally at larger
     breakpoints below) so "LOTTERY SIM" reads clearly on mobile. */
  font-size: 0.5rem;
  color: var(--black);
  opacity: 0.7;
  letter-spacing: 1px;
  white-space: nowrap; /* keep "LOTTERY SIM" on one line */
}

.mode-current {
  font-size: 0.8rem;
  color: var(--black);
  text-shadow: 2px 2px 0 var(--white);
}

/* Standalone prompt row: used on fulldraw.html to show the dynamic
   "PRESS START TO DRAW BALL N..." text under the action-zone, since the
   action-zone itself now holds the mode selector instead of the prompt. */
.action-prompt-standalone {
  width: 100%;
  text-align: center;
  margin: 0 0 10px;
  padding: 0 4px;
  font-size: 0.55rem;
  color: var(--black);
  opacity: 0.8;
}
@media (min-width: 768px) {
  .action-prompt-standalone { font-size: 0.7rem; margin-bottom: 14px; }
}
@media (min-width: 1024px) {
  .action-prompt-standalone { font-size: 0.85rem; margin-bottom: 18px; }
}

.btn-start {
  /* v=162: btn-start lives in the LAST column of action-zone's grid
     (which now mirrors card-grid: 2/3/4 cols per breakpoint).
     grid-column: -2 / -1 targets the last col regardless of count. */
  grid-column: -2 / -1;
  /* v=132: same keycap chrome as .cap-btn / .cap-select (3px black
     border, inset top highlight + inset bottom shadow for 3D depth,
     3px drop shadow). Red fill stays so the start button still reads
     as the primary action. */
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 9px 8px 12px;
  line-height: 1;
  background-color: var(--red);
  color: var(--white);
  border: 3px solid var(--black);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.65rem;
  cursor: pointer;
  text-transform: uppercase;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.35),
    inset 0 -5px 0 rgba(0, 0, 0, 0.35),
    3px 3px 0 var(--shadow-drop-deep);
  transition: transform 0.1s, box-shadow 0.1s;
}

/* Two-line button: small "PUSH TO" over a bigger action word. */
.btn-start .btn-top  {
  font-size: 0.4rem;
  opacity: 0.9;
  line-height: 1;
  white-space: nowrap;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.35);
}
.btn-start .btn-main {
  font-size: 0.7rem;
  line-height: 1;
  white-space: nowrap;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.35);
}

/* Press-in: sink 2px into the keycap slot, collapse drop shadow. */
.btn-start:active:not(:disabled) {
  transform: translate(2px, 2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.35),
    inset 0 -5px 0 rgba(0, 0, 0, 0.35),
    1px 1px 0 var(--shadow-drop-deep);
  background-color: #A80D26;
}

@media (hover: hover) {
  .btn-start:hover:not(:disabled) {
    background-color: #A80D26;
  }
}

.btn-start:disabled {
  background-color: #7a7a7a;
  color: #cfcfcf;
  cursor: not-allowed;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.25),
    inset 0 -5px 0 rgba(0, 0, 0, 0.25),
    3px 3px 0 var(--shadow-drop);
}

/* ===== SITE DISCLAIMER =====
   Small grey centered trademark notice shown on every page directly
   above the fixed ticker. Kept in the Press Start 2P family for visual
   consistency but text-transform is disabled so the legal-style
   sentence reads in its natural case. */

.site-disclaimer {
  position: relative;
  z-index: 1;
  width: 100%;
  /* v57: width matches .main-wrapper (max-width 1000, padding 0 12).
     Previously capped at 720px / auto-centered, which left the
     disclaimer visibly narrower than the content above it. */
  max-width: 1000px;
  /* v57: top gap shrunk from 24/32/36 to 10/12/14 — was "HUGE" per
     user feedback. Bottom gap trimmed too so the footer sits snug. */
  margin: 10px auto 14px;
  padding: 0 12px;
  font-family: 'Press Start 2P', monospace;
  /* v56: shrunk from 0.5/0.55/0.6 to 0.4/0.45/0.5 per user directive.
     font-weight: normal explicit so PS2P is never accidentally bolded
     by an inherited rule — pixel font has a single weight anyway. */
  font-size: 0.4rem;
  font-weight: normal;
  line-height: 1.8;
  color: #4a5560;
  text-align: center;
  text-transform: none;
  letter-spacing: 0.3px;
  word-spacing: normal;
  /* v=275: reserve ~4 lines so PS2P font-swap doesn't shift layout.
     Em-based -> scales with font-size at each breakpoint. */
  min-height: 7.2em;
}

@media (min-width: 768px) {
  .site-disclaimer {
    font-size: 0.45rem;
    margin: 12px auto 16px;
    padding: 0 20px;
  }
}

@media (min-width: 1024px) {
  .site-disclaimer {
    font-size: 0.5rem;
    margin: 14px auto 18px;
  }
}

/* ===== TICKER (removed v54) =====
   The fixed-position scrolling ticker at the bottom of every page was
   removed. HTML nodes and JS builders have been stripped from the four
   pages. Kept a null rule so any stale cached script that still tries
   to reference these selectors fails gracefully (display: none). */
.ticker-container,
.ticker-content,
.ticker-item { display: none; }

/* =========================================================
   TABLET: >= 768px
   Grid becomes 2 columns like the original.
   Fonts bump up. Padding opens up.
   ========================================================= */
@media (min-width: 768px) {
  body {
    /* ticker removed — no bottom reserve needed. */
    padding: 0;
  }
  .main-wrapper { padding: 0 20px; }

  .header-container {
    /* v=107: margin 14 -> 8, padding-y 14 -> 10 to tighten header→
       controls gap on tablet. */
    margin-bottom: 8px;
    padding: 10px 20px;
    gap: 18px;
  }

  .nhl-text { font-size: 1.55rem; }
  .main-title { font-size: 1.4rem; text-shadow: 3px 3px 0 var(--black); }

  /* v=107: padding-y 6 -> 3 (tablet) to tighten header→controls gap. */
  .action-zone { margin-bottom: 0; gap: 18px; padding: 3px 0; }
  .menu-toggle { gap: 14px; }
  .menu-current { font-size: 0.75rem; }
  /* Panel font-size kept in lockstep with .menu-current so `calc(12ch + 24px)`
     resolves to the same pixel width as the button above. */
  .menu-panel { font-size: 0.75rem; }
  .menu-item { font-size: 0.75rem; padding: 9px 4px; }
  .btn-start { font-size: 0.75rem; }
  .btn-start .btn-top  { font-size: 0.45rem; }
  .btn-start .btn-main { font-size: 0.8rem; }
  .action-prompt { font-size: 0.7rem; }
  .mode-selector { gap: 14px; }
  .mode-arrow { width: 38px; height: 38px; font-size: 0.85rem; background: #C8F3F8; }
  .mode-stack { gap: 5px; }
  .mode-tag { font-size: 0.6rem; }
  .mode-current { font-size: 0.95rem; }

  .lottery-card {
    padding: 16px 14px;
    /* v105: cut from 36 -> 18 (see base rule). */
    margin-bottom: 18px;
  }

  .grid-headers {
    grid-template-columns: 1fr 1fr;
    gap: 12px 28px;
    margin-bottom: 10px;
    padding: 0 13px;
  }
  .grid-headers .header-row { font-size: 0.6rem; }
  .grid-headers .header-row:nth-child(2) { display: flex; }
  .grid-headers .header-rank { width: 30px; margin-right: 12px; }
  .grid-headers .header-odds { min-width: 100px; }

  .lottery-grid {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: repeat(8, 1fr);
    grid-auto-flow: column;
    gap: 12px 28px;
  }

  .plate-container { padding: 4px 13px; }
  .rank-num { width: 30px; font-size: 1.1rem; margin-right: 12px; }
  .team-box { gap: 14px; }
  .team-logo { width: 34px; height: 34px; }
  .team-name-stack { font-size: 0.65rem; line-height: 1.4; }
  .team-metric { min-width: 100px; }
  .metric-value { font-size: 0.95rem; }
  .metric-label { font-size: 0.43rem; }

}

/* =========================================================
   DESKTOP: >= 1024px
   Full original sizing.
   ========================================================= */
@media (min-width: 1024px) {
  body {
    /* ticker removed — no bottom reserve needed. */
    padding: 0;
  }
  .main-wrapper { padding: 0 20px; }

  .header-container {
    /* v=107: margin 18 -> 8, padding-y 14 -> 10 to tighten header→
       controls gap on desktop. */
    margin-bottom: 8px;
    padding: 10px 20px;
    gap: 28px;
    flex-wrap: nowrap;
  }

  .nhl-text { font-size: 1.9rem; }
  .main-title { font-size: 1.8rem; -webkit-text-stroke: 1.5px var(--black); }

  /* v=107: padding-y 6 -> 3 (desktop) to tighten header→controls gap. */
  .action-zone { margin-bottom: 0; gap: 24px; padding: 3px 0; }
  .menu-toggle { gap: 18px; }
  .menu-current { font-size: 0.85rem; }
  .menu-panel { font-size: 0.85rem; }
  .menu-item { font-size: 0.85rem; padding: 10px 4px; }
  .btn-start { font-size: 0.85rem; }
  .btn-start .btn-top  { font-size: 0.5rem; }
  .btn-start .btn-main { font-size: 0.9rem; }
  .action-prompt { font-size: 0.85rem; }
  .mode-selector { gap: 18px; }
  .mode-arrow { width: 44px; height: 44px; font-size: 1rem; background: #C8F3F8; }
  .mode-stack { gap: 6px; }
  .mode-tag { font-size: 0.65rem; }
  .mode-current { font-size: 1.1rem; }

  /* v105: margin-bottom cut from 40 -> 22 (see base rule). */
  .lottery-card { padding: 20px 16px; margin-bottom: 22px; }

  .grid-headers {
    gap: 15px 40px;
    margin-bottom: 12px;
    padding: 0 15px;
  }
  .grid-headers .header-row { font-size: 0.7rem; }
  .grid-headers .header-rank { width: 34px; margin-right: 15px; }
  .grid-headers .header-odds { min-width: 120px; }

  .lottery-grid { gap: 15px 40px; }

  .plate-container { padding: 6px 15px; }
  .rank-num { width: 34px; font-size: 1.3rem; margin-right: 15px; }
  .team-box { gap: 16px; }
  .team-logo { width: 44px; height: 44px; }
  .team-name-stack { font-size: 0.7rem; }
  .team-metric { min-width: 120px; }
  .metric-value { font-size: 1.25rem; margin-bottom: 4px; }
  .metric-label { font-size: 0.48rem; }

}

/* =========================================================
   CARD GRID (Layout E deploy, 2026-04-20)
   Trading-card tiles replace the old table-style rows.
   Each .card-wrap is a perspective viewport; .flipper does the
   3D rotateY; .face.front / .face.back absolutely fill the wrap.
   Reveal animation is opacity-only so it can't fight the flip.
   ========================================================= */

/* Section header above the card grid. Red pixel-font title that labels
   what's displayed below: pre-sim = odds, post-sim = simulated draft
   order. Text is swapped by main.js / fulldraw.js when the sim completes.
   Word-spacing tightened to counteract PS2P's fat default space.

   No bottom margin + adjacent-sibling rule that collapses the
   .lottery-card's top padding below so the header hugs the TAP hint /
   grid directly underneath it (`.board-header + .lottery-card`). */
.board-header {
  width: 100%;
  margin: 0;
  padding: 0 4px;
  /* Left-aligned at every breakpoint per v56 directive. Previously
     center on mobile, left on 768+. Unified now so the section titles
     always sit flush-left with the card grid below them. */
  text-align: left;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.7rem;
  line-height: 1.1;
  color: var(--red);
  text-transform: uppercase;
  letter-spacing: 0;
  word-spacing: -0.35em;
  /* v65: Pucksonnet white pixel drop-shadow on the red section titles
     (LOTTERY DRAWING / 2026 DRAFT LOTTERY ODDS / % ODDS BY PICK, etc.).
     Matches the .nhl-text + .draw-strip-label treatment so every red
     header on the site reads as a chunky arcade caption. Shadow scales
     with font-size at 768 / 1024 breakpoints below. */
  text-shadow: 2px 2px 0 var(--white);
}

.board-header + .lottery-card { padding-top: 4px; }

/* #drawing-header uses the default .board-header treatment (red pixel
   text, no fill, no border). Per v55 directive the cyan banner-bar
   look moved to the .draw-strip BOX below it — the header itself stays
   consistent with the other red section titles on the page. */

.card-hint {
  width: 100%;
  margin: 0 0 10px;
  padding: 0 4px;
  /* Left-aligned at every breakpoint per v56 directive. The negative
     left margin pulls the hint over .lottery-card's 10px horizontal
     padding so the text-start lines up with the board-header above it.
     Tablet/desktop bump the negative margin to 14px / 16px to match the
     wider padding — see media queries below.
     v=165: mobile font bumped down to 0.38rem + word-spacing much
     tighter so the hint sits compactly under the header. */
  text-align: left;
  margin-left: -10px;
  font-size: 0.38rem;
  letter-spacing: 2px;
  color: var(--black);
  opacity: 0.55;
  word-spacing: -0.5em;
}

/* On mobile the hint stays centered (inherits .card-hint's default).
   On tablet/desktop it goes flush-left, aligned to the board-header's
   text (see media queries below). The alignment uses a negative left
   margin equal to .lottery-card's padding-left, since the hint lives
   inside .lottery-card while the header is a sibling of it — so the
   hint needs to pull back out over the card's horizontal padding to
   match the header's left edge. Applies to BOTH the QUICK (index) and
   FULL (fulldraw) pages — same rule, same offset. */

.card-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr); /* mobile default */
  gap: 12px;
  width: 100%;
}

.card-wrap {
  position: relative;
  perspective: 900px;
  /* Shrunk from 10/7 after the back-face abbrev was moved into a top
     tag — the freed vertical slack in the back body lets the card sit
     shorter without crowding the stats. Same aspect is mirrored on
     .mini-card below so QUICK + FULL cards are the exact same size at
     every breakpoint. */
  aspect-ratio: 10 / 6.5;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.card-wrap.is-revealed { opacity: 1; }

.flipper {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  -webkit-transform-style: preserve-3d;
  transition: transform 0.55s cubic-bezier(0.3, 1.4, 0.4, 1);
  cursor: pointer;
  /* Force GPU compositing layer up front so iOS Safari doesn't build
     it mid-flip on first tap (which causes a momentary mirrored
     flash before the transform stabilizes). translateZ(0) triggers
     layer creation; will-change reinforces the hint. */
  transform: translateZ(0);
  will-change: transform;
}

.card-wrap.flipped .flipper { transform: translateZ(0) rotateY(180deg); }

.face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* Each face also gets its own layer + preserve-3d so its
     children (tags, stats) stay parented to the face's rotation
     throughout the animation instead of getting flattened into a
     root-level compositing layer mid-flip. */
  transform: translateZ(0);
  will-change: transform;
  /* v=250: card faces (front + back) #B8F6FA, slightly lighter than page bg. */
  background: #B8F6FA;
  border: 3px solid var(--black);
  box-shadow: 4px 4px 0 var(--shadow-drop);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Shared corner tags.
   iOS Safari quirk: giving a child of a 3D-transformed ancestor a
   z-index promotes it to a standalone compositing layer that drops
   the parent face's rotateY(180deg), so the tag ends up only wearing
   the flipper's 180° and reads mirrored. Fix is to drop z-index and
   rely on DOM order (tags are rendered last in each face so they
   paint on top). backface-visibility kept as a belt on top of that. */
/* Unified tag spec — seed (top-left), odds (top-right), and abbrev
   (top-center, back face only) all share identical dimensions so corners
   line up across QUICK + FULL, front + back. Matching .mc-seed / .mc-odds
   / .abbrev-tag rules in the FULL DRAW block below keep the two card
   systems visually locked. */
.seed-badge {
  position: absolute;
  top: 6px;
  left: 6px;
  /* v63: crease-blue experiment reverted. Tags back to black ("I accept
     defeat"). Text stays on the card-face cyan per the v62 rule so the
     pill reads as a recessed chip on each palette. Winner/runner-up
     cards swap text color via overrides further down. */
  background: var(--black);
  color: #B0F0F6;
  font-size: 0.5rem;
  line-height: 1;
  padding: 4px 5px;
  min-width: 44px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  word-spacing: normal;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.odds-tag {
  position: absolute;
  top: 6px;
  right: 6px;
  /* v63: matches .seed-badge — black pill, card-face-cyan text. */
  background: var(--black);
  color: #B0F0F6;
  font-size: 0.5rem;
  line-height: 1;
  padding: 4px 5px;
  min-width: 44px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  word-spacing: normal;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* Centered abbrev tag on back faces. v59: dropped the black pill fill
   per user directive ("no color background. Just black text"). Kept
   the absolute-positioned placement + dimensions so layout below is
   unaffected. Used on both QUICK .face.back and FULL .mc-face.back. */
.abbrev-tag {
  position: absolute;
  top: 6px;
  left: 50%;
  transform: translateX(-50%);
  background: transparent;
  color: var(--black);
  font-size: 0.5rem;
  line-height: 1;
  padding: 4px 5px;
  min-width: 44px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  letter-spacing: 1px;
  word-spacing: normal;
  /* v86: white pixel drop-shadow mirrors .face.front .team-name-stack .name
     so every back-face abbrev gets the same arcade depth as the front.
     Medal variants override to champagne / silver under .winner /
     .runner-up below. */
  text-shadow: 1.5px 1.5px 0 #fff;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* Directional variants (up/down/flat) intentionally NO-OP — every tag
   shares the same neutral black/cyan palette. The +N / -N / - symbol
   in the text carries direction; we don't double-up with bg color. */

/* --- FRONT --- */
.face.front {
  align-items: center;
  /* Group logo + name-stack as one centered cluster so they sit snug
     together instead of being pushed to opposite ends of the card. */
  justify-content: center;
  gap: 0;
  padding: 28px 8px 14px;
}

.face.front .team-logo {
  flex: 1;
  width: 100%;
  /* v57: slight site-wide shrink per user feedback. 135→125 base,
     170→155 tablet, 200→180 desktop (see media queries below).
     v65: another shave per user directive "reduce the size of the
     logos on cards slightly, on every device" — 125→115 base,
     155→145 tablet, 180→170 desktop. */
  max-width: 115px;
  max-height: 115px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Override the default .team-logo sizing inside cards so the logo fills
   the available space instead of locking to the old 30/38/48 px slot. */
.face.front .team-logo,
.face.front .team-logo img,
.face.front .team-logo canvas {
  width: 100%;
  height: 100%;
}

.face.front .team-name-stack {
  width: 100%;
  padding: 0 4px;
  text-align: center;
  font-size: 0.45rem;
  line-height: 1.5;
  color: var(--black);
  /* v=266: 0 -> -6, mobile was too loose after v=263. */
  margin-top: -6px;
  /* override column styling from the legacy .team-name-stack rule */
  flex: 0 0 auto;
  overflow: visible;
}

.face.front .team-name-stack > span {
  display: block;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

/* City line: smaller + grey (secondary). */
.face.front .team-name-stack .city {
  font-size: 0.45rem;
  color: #5A6F7A;
}

/* Nickname line: bigger + black + arcade white drop-shadow (matches the
   Pucksonnet abbrev treatment used on FULL back faces — now applied to
   the primary name label on every card front, QUICK and FULL). */
.face.front .team-name-stack .name {
  font-size: 0.7rem;
  color: var(--black);
  margin-top: 1px;
  letter-spacing: 0;
  word-spacing: -0.5em;
  white-space: nowrap;
  text-shadow: 1.5px 1.5px 0 #fff;
}

.flip-hint,
.back-hint {
  font-size: 0.3rem;
  letter-spacing: 2px;
  color: #5A6F7A;
  text-align: center;
  margin-top: 2px;
  word-spacing: -0.2em;
}

/* --- BACK --- */
.face.back {
  /* translateZ(0) is a no-op spatially but keeps the compositing
     layer primed (see .face base rule). The rotateY is what
     actually flips this face's content. */
  transform: translateZ(0) rotateY(180deg);
  /* v=251: match front-face #B8F6FA (was #F1FAFC near-white). */
  background: #B8F6FA;
  /* Top padding clears the seed / abbrev / odds tag row (tag lives at
     top:6px + 22px height = ~28px). Bottom a hair more so stats don't
     kiss the border. */
  padding: 32px 10px 8px;
}

/* Legacy .back-header + .back-header .big retained as empty shells —
   renderCard no longer emits them. Kept only so any cached markup on
   disk still parses; safe to remove in a future pass. */

.stats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* 4 equal-height rows that fill the back-card body. */
  grid-auto-rows: 1fr;
  gap: 0;
  font-size: 0.4rem;
  flex: 1;
  word-spacing: -0.2em;
}

.stats li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 2px;
  border-bottom: 1px dashed rgba(0, 0, 0, 0.2);
  color: var(--black);
}

/* Final row — no trailing rule. */
.stats li:last-child { border-bottom: none; }

.stats li .label { color: #5A6F7A; }
.stats li .value { color: var(--black); font-size: 0.45rem; }

/* --- GOLD (PICK 1) & SILVER (PICK 2) --- */
/* Champagne / Ice palette. v60: the blinking pulse is back (border +
   pixel-shadow alternate on a 0.7s step-end beat), suppressed via
   :not(.is-dead) so the D1 winner card does NOT blink during FULL's
   mid-D2 state (D1 winner is hard-excluded there and carries .is-dead).
   Everywhere else — QUICK COMPLETE, FULL DRAW_1 end, FULL COMPLETE —
   the winner / runner-up card blinks. */
.card-wrap.winner .face {
  background: #FFF2B8;
  border-color: #F0C850;
  box-shadow: 4px 4px 0 var(--shadow-drop);
}

.card-wrap.runner-up .face {
  background: #E6EAF0;
  border-color: #BFC4CE;
  box-shadow: 4px 4px 0 var(--shadow-drop);
}

@keyframes card-blink-winner {
  0%, 49.99%  { border-color: #F0C850; box-shadow: 4px 4px 0 var(--shadow-drop); }
  50%, 100%   { border-color: #B88A20; box-shadow: 4px 4px 0 #F0C850; }
}
@keyframes card-blink-runner-up {
  0%, 49.99%  { border-color: #BFC4CE; box-shadow: 4px 4px 0 var(--shadow-drop); }
  50%, 100%   { border-color: #8A8E96; box-shadow: 4px 4px 0 #BFC4CE; }
}
.card-wrap.winner:not(.is-dead) .face {
  animation: card-blink-winner 0.7s step-end infinite;
}
.card-wrap.runner-up:not(.is-dead) .face {
  animation: card-blink-runner-up 0.7s step-end infinite;
}

/* v62: tag text color matches the card face the tag sits on (per user
   directive "same color as the card the tag is above"). Base rule
   above paints both .seed-badge + .odds-tag text as the regular face
   cyan (#B0F0F6). Winner + runner-up cards swap the face background,
   so their tag text needs to swap in lockstep: champagne (#FFF2B8) on
   the gold winner face, silver (#E6EAF0) on the runner-up face. */
.card-wrap.winner .seed-badge,
.card-wrap.winner .odds-tag {
  color: #FFF2B8;
}
.card-wrap.runner-up .seed-badge,
.card-wrap.runner-up .odds-tag {
  color: #E6EAF0;
}

/* =========================================================
   CARD GRID - TABLET: >= 768px -> 3 columns
   ========================================================= */
@media (min-width: 768px) {
  .card-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
  }
  .board-header { font-size: 0.9rem; margin-bottom: 0; text-align: left; text-shadow: 3px 3px 0 var(--white); }
  .board-header + .lottery-card { padding-top: 6px; }
  /* Hint shifts left by .lottery-card's padding-left (14px) so its text
     lines up exactly with .board-header's text. Applies to both QUICK
     and FULL pages. */
  .card-hint { font-size: 0.55rem; margin-bottom: 12px; text-align: left; margin-left: -14px; }
  .seed-badge,
  .odds-tag,
  .abbrev-tag {
    font-size: 0.6rem;
    padding: 5px 7px;
    min-width: 56px;
    height: 26px;
    top: 8px;
  }
  .seed-badge { left: 10px; }
  .odds-tag { right: 10px; }
  .face.front { padding: 32px 10px 18px; }
  .face.front .team-logo { max-width: 145px; max-height: 145px; }
  /* v=266: -2 -> -8 to tighten tablet back closer to original. */
  .face.front .team-name-stack { font-size: 0.55rem; padding: 0 6px; margin-top: -8px; }
  .face.front .team-name-stack .city { font-size: 0.5rem; }
  .face.front .team-name-stack .name { font-size: 0.8rem; }
  .flip-hint, .back-hint { font-size: 0.35rem; }
  /* Back padding on tablet clears the larger 26px tag at top:8px. */
  .face.back { padding: 38px 12px 10px; }
  .stats { font-size: 0.5rem; }
  .stats li .value { font-size: 0.55rem; }
}

/* =========================================================
   CARD GRID - DESKTOP: >= 1024px -> 4 columns
   ========================================================= */
@media (min-width: 1024px) {
  .card-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 20px;
  }
  .board-header { font-size: 1.1rem; margin-bottom: 0; text-align: left; text-shadow: 3px 3px 0 var(--white); }
  .board-header + .lottery-card { padding-top: 8px; }
  /* At 1024 .lottery-card's padding-left is 16px, so bump the negative
     margin to keep the hint's text-start aligned with the header. */
  .card-hint { font-size: 0.6rem; margin-bottom: 14px; text-align: left; margin-left: -16px; }
  /* v=257: bumped padding-top 34 -> 46 so the logo/name cluster
     sits more vertically centered in the white area below the strip. */
  .face.front { padding: 46px 10px 22px; }
  .face.front .team-logo { max-width: 170px; max-height: 170px; }
  /* v=263: -12 -> -4 for breathing room. */
  .face.front .team-name-stack { font-size: 0.6rem; padding: 0 6px; margin-top: -4px; }
  .face.front .team-name-stack .city { font-size: 0.55rem; }
  .face.front .team-name-stack .name { font-size: 0.9rem; }
  .face.back { padding: 40px 14px 10px; }
  .stats { font-size: 0.55rem; }
  .stats li .value { font-size: 0.6rem; }
}

/* =========================================================
   "COMING SOON" PLACEHOLDER PAGES (Prospects, Analytics)
   Reuses the .lottery-card shell so the page chrome stays
   consistent across all three tabs.
   ========================================================= */
.soon-card {
  min-height: 50vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* v=283: drop uniform gap; per-child margins control the
     title->badge->sub stack so the badge sits TIGHT under the
     title (REDRAW pattern). */
  gap: 0;
  padding: 40px 20px;
  text-align: center;
}
.soon-title {
  font-family: 'Press Start 2P', monospace;
  font-size: 1.2rem;
  color: var(--black);
  margin: 0 0 6px;
  word-spacing: -0.5em;
  text-shadow: 3px 3px 0 var(--white);
}
.soon-sub {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem;
  color: #5A6F7A;
  margin: 0;
  word-spacing: -0.6em;
  /* v=283: wider so 2-line copy wraps cleanly on each breakpoint. */
  max-width: 42ch;
  line-height: 1.6;
}
.soon-badge {
  /* v=284: matches .draw-strip-redraw EXACTLY (flat black rect,
     no drop shadow). Bigger font/padding per user pref but the
     visual treatment mirrors REDRAW. */
  display: inline-block;
  background: var(--black);
  color: var(--white);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.75rem;
  padding: 12px 22px;
  border: 1.5px solid #000;
  letter-spacing: 3px;
  line-height: 1;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.45);
  margin: 0 0 26px;
}
@media (min-width: 768px) {
  .soon-title { font-size: 1.8rem; margin-bottom: 8px; }
  .soon-sub { font-size: 0.7rem; max-width: 50ch; }
  .soon-badge { font-size: 0.95rem; padding: 14px 28px; margin-bottom: 32px; }
}
@media (min-width: 1024px) {
  .soon-title { font-size: 2.4rem; margin-bottom: 10px; }
  .soon-sub { font-size: 0.8rem; max-width: 56ch; }
  .soon-badge { font-size: 1.15rem; padding: 16px 34px; margin-bottom: 36px; }
}

/* =========================================================
   FULL DRAW (fulldraw.html)
   Per-click ball draw with mini-card grid. Cards flip to
   reveal alive-combos + 14-ball status on the back.
   ========================================================= */

/* Ball pill palette — shared by draw-strip + card backs. */
:root {
  --ball-gold: #F6C94A;
  --ball-gold-deep: #D99B1F;
  --ball-alive-a: #FFFFFF;
  --ball-alive-b: #F6F1E3;
  --ball-alive-c: #D8CFB8;
  --ball-grey: #8F9AA1;
  --ball-grey-deep: #5A6570;
  --ball-red: #E53935;
  --ball-red-deep: #9B2320;
}

/* ---------- Drawn-balls strip ---------- */
/* Draw strip wears the darker cyan fill (same tone as the site header)
   per v55 — makes the drawing BOX itself the cyan banner element, while
   the LOTTERY DRAWING header above it stays as a plain red .board-header.
   Chunky 3px black border + 4px white pixel shadow keeps the pixel-art
   card shell language. */
.draw-strip {
  /* Width clamped to the same inner edge the card grid uses (matches
     .lottery-card's horizontal padding at each breakpoint). Previously
     width: 100% made the strip visually wider than the cards because
     nothing inset it by the card-grid's own padding. Top margin added
     (v56) to open up the gap between the LOTTERY DRAWING header and
     the box — previously 0 which cramped the two together. */
  width: calc(100% - 20px);
  /* v58: top margin trimmed from 16px → 6px (base) per user feedback —
     v57's 16/22/28 felt too loose under the LOTTERY DRAWING header. */
  margin: 6px 10px 14px;
  display: grid;
  /* Red DRAW-N label pinned left (auto-sized) + 4 equal ball cells. */
  grid-template-columns: auto repeat(4, 1fr);
  align-items: center;
  gap: 10px;
  justify-items: center;
  /* v88: padding tightened from 8px -> 6px so the strip hugs the
     shrunken balls more closely. */
  padding: 6px 12px;
  background: #84E9F4;
  border: 3px solid var(--black);
  box-shadow: 4px 4px 0 var(--shadow-drop);
}

/* Left-side label inside the draw strip (e.g. "DRAW 1"). Mirrors the
   PUCKSON.NET wordmark treatment — black pixel text with a bottom-right
   white pixel-shadow — so the label reads as a chunky header rather
   than a red accent. Sized larger than before for presence. */
.draw-strip-label {
  justify-self: start;
  font-family: 'Press Start 2P', monospace;
  color: var(--black);
  font-size: 0.75rem;
  letter-spacing: 1px;
  white-space: nowrap;
  text-shadow: 2px 2px 0 var(--white);
  padding: 0 4px;
}
.draw-ball {
  /* v88: balls shrunk ~18% (44 -> 36) and the draw-strip's vertical
     padding tightens with it so the box height scales proportionally. */
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 3px solid var(--black);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.7rem;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #000;
  word-spacing: normal;
  box-shadow:
    inset -2px -3px 0 rgba(0,0,0,0.15),
    inset 2px 2px 0 rgba(255,255,255,0.35);
}
/* Empty slot on the light-cyan card: pearl-white pearl ball that
   mirrors the gold pearl's lighting (same radial origin at 32% 28%,
   same inset highlight/lowlight), just swapped to the off-white
   gradient. Matches .mc-ball.alive on the back face so the draw-strip
   and the combo-inventory view share one visual language — the
   "yet to drop" ball looks like a pearl resting in the socket, not
   a flat white disc. Numeral is a deep pixel grey so it reads as
   "inactive" against the bright pearl. */
.draw-ball-slot {
  background: radial-gradient(
    circle at 32% 28%,
    var(--ball-alive-a),
    var(--ball-alive-b) 55%,
    var(--ball-alive-c) 100%
  );
  color: var(--ball-grey-deep);
  border-color: var(--black);
  /* Inherit .draw-ball's inset pearl shadow — do NOT override to none. */
}
.draw-ball-slot .draw-ball-label { opacity: 0.9; }
/* NHL shield rendered inside empty draw-strip slots instead of a
   placeholder slot number. Shrunk so it reads as a faint "waiting"
   marker rather than dominating the ball face. Same exact retro-filter
   chain .team-logo uses so the shield matches the rest of the site. */
.draw-ball-logo {
  display: block;
  /* v88: shrunk from 20 -> 16 to keep the shield proportional to the
     smaller ball. */
  width: 16px;
  height: 16px;
  object-fit: contain;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  filter: url(#retro-posterize)
          saturate(1.6) contrast(1.2) brightness(1.03)
          drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.7));
  opacity: 0.55;
  pointer-events: none;
  user-select: none;
}
.draw-ball-slot .draw-ball-label {
  /* Let the logo paint full-opacity against the label's 0.9 opacity
     wrapper — the logo's own opacity handles fade. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 0;
}
.draw-ball.drawn {
  background: radial-gradient(circle at 32% 28%, #FFF5C8, var(--ball-gold) 60%, var(--ball-gold-deep) 100%);
  color: #1a1a1a;
  text-shadow: 1px 1px 0 rgba(255,255,255,0.5);
  border-color: var(--black);
  /* v72: drumline cycle carries the arrival motion, so the commit is
     just a small scale pop on the lock-in beat. */
  animation: ball-pop 0.28s ease-out;
}
@keyframes ball-pop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.18); }
  100% { transform: scale(1); }
}
@media (min-width: 768px) {
  /* Draw strip follows lottery-card's 14px horizontal padding at tablet.
     v56: top margin bumped to 22px for more breathing room under the
     LOTTERY DRAWING header. */
  .draw-strip {
    width: calc(100% - 28px);
    /* v58: top margin 22 → 10. */
    /* v88: vertical padding trimmed 12 -> 8 to match smaller balls. */
    margin: 10px 14px 18px;
    padding: 8px 18px;
    gap: 16px;
  }
  /* v88: ~20% smaller (60 -> 48). */
  .draw-ball { width: 48px; height: 48px; font-size: 0.9rem; }
  .draw-ball-logo { width: 22px; height: 22px; }
  .draw-strip-label {
    font-size: 1rem;
    padding: 0 8px;
    text-shadow: 3px 3px 0 var(--white);
  }
}
@media (min-width: 1024px) {
  /* Draw strip follows lottery-card's 16px horizontal padding at desktop.
     v56: top margin bumped to 28px for more breathing room under the
     LOTTERY DRAWING header. */
  .draw-strip {
    width: calc(100% - 32px);
    /* v58: top margin 28 → 12. */
    /* v88: vertical padding trimmed for shrunken desktop balls.
       v=107: vertical padding trimmed 10 -> 7 and margin 12/22 -> 8/16
       to shrink draw-box height proportionally with the smaller balls. */
    margin: 8px 16px 16px;
    padding: 7px 18px;
  }
  /* v88: ~21% smaller (68 -> 54).
     v=107: desktop balls shrunk further (54 -> 42) per user directive —
     the draw-strip padding above gets the matching proportional cut. */
  .draw-ball { width: 42px; height: 42px; font-size: 0.8rem; }
  .draw-ball-logo { width: 20px; height: 20px; }
  .draw-strip-label {
    font-size: 1.2rem;
  }
}

/* ---------- Card shell (reused from QUICK) ----------
   FULL's grid, card shell, flipper, faces, logo, name-stack, seed badge,
   and odds tag are EXACTLY the QUICK rules defined higher up in this
   file. fulldraw.html renders <div class="card-grid" id="mini-grid"> so
   the same .card-grid / .card-wrap / .flipper / .face / .team-logo /
   .team-name-stack / .seed-badge / .odds-tag path fires on both pages.

   Only FULL-specific pieces live below:
     - .card-wrap.is-dead opacity (eliminated teams)
     - .odds-tag up/down directional flash (live odds movement)
     - .mc-body / .mc-alive / .mc-balls / .mc-ball-row / .mc-ball
       back-face body (COMBOS ALIVE + 14 balls grid)

   Note: .full-card used to override .lottery-card padding at base + 768px.
   That made FULL's grid slightly wider than QUICK's at desktop (no 1024
   rule existed for .full-card, so the 768 rule held at 1024 and won over
   .lottery-card's 20px 16px). The override is removed so .lottery-card's
   responsive padding applies uniformly on both pages.
*/

/* Dead teams (0 alive combos) — fade the whole card but keep color so
   the red kill ball and any other ball states stay readable. Higher
   specificity than .card-wrap.is-revealed so it overrides the reveal
   opacity: 1. */
.card-wrap.is-revealed.is-dead {
  opacity: 0.55;
}

/* Live directional flash on the odds-tag — fulldraw.js adds .up or
   .down each time the per-team odds tick up or down vs. the snapshot
   from the previous draw. Transition applied here so QUICK's static
   odds-tag doesn't get unnecessary easing. */
.odds-tag {
  transition: background-color 0.3s ease, color 0.3s ease;
}

/* ---------- Back face (combos alive + 14 balls) ----------
   `inset` top value reserves vertical room for the seed/odds tags
   (top: 5px + ~14px tag height + a hair of breathing room) so that
   the abbrev never overlaps them, even on short cards. */
.mc-body {
  position: absolute;
  /* Top inset clears the abbrev-tag row (tag at top:6px + 22px height).
     Was 21px back when the abbrev lived inside this body — now it can
     sit centered below the tag row. */
  inset: 32px 3px 6px 3px;
  padding: 0 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
}
/* Legacy .mc-abbrev — kept so stale markup doesn't break if cached.
   renderMiniCard no longer emits it; the abbrev is now an .abbrev-tag
   in the top-center slot next to seed/odds. */
.mc-abbrev {
  display: none;
}
.mc-alive {
  font-family: 'Press Start 2P', monospace;
  /* Base size — number + label share this value so the whole line reads
     as a single compact unit. Bumps at 768 / 1024 below. */
  font-size: 0.5rem;
  color: #1a1a1a;
  letter-spacing: 0;
  margin-bottom: 0;
  /* Tight word-spacing so "XXX COMBOS ALIVE" reads as one word at every
     width. Press Start 2P has a fat default space; -0.55em pulls the
     three tokens right up against each other without colliding. */
  word-spacing: -0.55em;
  white-space: nowrap;
  line-height: 1;
}
.mc-alive b {
  color: var(--ball-gold-deep);
  font-weight: normal;
  /* Match the label size exactly (user requirement) and inherit word-
     spacing so the number sits as tight against "COMBOS" as the rest of
     the line. */
  font-size: inherit;
  word-spacing: inherit;
}
/* v70: dual-count numeric spans painted red. Cyan (v69) was too low-
   contrast against the black back-card body for some users. Red pops
   against black and rhymes with the .board-header palette elsewhere. */
.mc-alive b.alive-num {
  color: var(--red);
}
/* v71: pipe separator between COMBOS and BALLS. Solid black (no
   opacity dimming) per user directive — the red numbers already carry
   the visual hierarchy, so the separator is just a crisp divider. */
.mc-alive .alive-sep {
  color: #000;
}
.mc-alive.knocked-out {
  color: var(--red);
  font-size: 0.5rem;
  letter-spacing: 1px;
  text-shadow: 1px 1px 0 #000;
  word-spacing: -0.1em;
}
.mc-balls {
  display: flex;
  flex-direction: column;
  /* Tight vertical gap — mobile cards are narrow so we need every px. */
  gap: 1px;
  align-items: center;
}
.mc-ball-row {
  display: flex;
  gap: 3px;
  justify-content: center;
}
.mc-ball {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1.5px solid #000;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.34rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #000;
  word-spacing: normal;
  flex-shrink: 0;
  box-shadow:
    inset -1px -2px 0 rgba(0,0,0,0.15),
    inset 1px 1px 0 rgba(255,255,255,0.35);
}
/* NHL shield placeholder rendered inside undrawn balls instead of a
   number. Sized down to ~half the ball so it reads as a faint marker,
   not a filled icon. Same exact retro-filter chain .team-logo uses
   (posterize + saturate/contrast/brightness + drop-shadow) so the
   shield sits in the same visual family as every team logo on the
   site. */
.mc-ball-logo {
  width: 50%;
  height: 50%;
  object-fit: contain;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  filter: url(#retro-posterize)
          saturate(1.6) contrast(1.2) brightness(1.03)
          drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.7));
  pointer-events: none;
  user-select: none;
}
.mc-ball.gold {
  background: radial-gradient(circle at 32% 28%, #FFF5C8, var(--ball-gold) 60%, var(--ball-gold-deep) 100%);
  color: #1a1a1a;
  text-shadow: 1px 1px 0 rgba(255,255,255,0.5);
}
.mc-ball.alive {
  background: radial-gradient(circle at 32% 28%, var(--ball-alive-a), var(--ball-alive-b) 55%, var(--ball-alive-c) 100%);
  color: #000;
}
.mc-ball.grey {
  background: radial-gradient(circle at 32% 28%, #C8CED3, var(--ball-grey) 55%, var(--ball-grey-deep) 100%);
  color: #2d2d2d;
  opacity: 0.85;
}
.mc-ball.red {
  background: radial-gradient(circle at 32% 28%, #FFC8C4, var(--ball-red) 55%, var(--ball-red-deep) 100%);
  color: #fff;
  text-shadow: 1px 1px 0 rgba(0,0,0,0.5);
}

/* "WON DRAW N!" celebration line on the back face body. Same size /
   placement as .mc-alive so the layout doesn't jump when the status
   flips. v86: now mirrors the front-face .name treatment exactly —
   black text + white pixel drop-shadow by default — and the
   .card-wrap.winner / .runner-up rules below swap the shadow to
   champagne / silver to match CANUCKS / KRAKEN on the front. */
.mc-alive.mc-won {
  color: var(--black);
  text-shadow: 1.5px 1.5px 0 #fff;
  letter-spacing: 1px;
  word-spacing: -0.1em;
}

/* Gold "OWNS #X OVR!" banner for the D1 winner during PHASE_DRAW_2.
   Sits on the LEFT of the front face. v65: slot widened past the
   back-face abbrev-tag edge so the banner extends toward the odds tag
   — ends ~4px shy of the odds-tag left edge (odds-tag: right:6 +
   min-width 44 = 50px from right; banner right:54 leaves a clean 4px
   gutter). Font bumped + horizontal padding reduced so "OWNS #X OVR!"
   (12 chars) always fits on one line at every viewport. Flat structure
   matches .seed-badge / .odds-tag — solid fill, no shadows. */
.owns-pick-banner {
  position: absolute;
  top: 6px;
  left: 6px;
  right: 54px;
  height: 22px;
  /* v83: simplest possible centering. Zero margin/padding. Block
     layout, text-align: center for horizontal, line-height == height
     for vertical. No flex, no asymmetric padding, no font-sidebearing
     compensation. If the text doesn't fit the banner at a given
     breakpoint, that's a banner-width issue, not a centering issue. */
  margin: 0;
  padding: 0;
  /* v=221: default to cyan (locked-first carries this banner without
     winning DRAW 1). The .card-wrap.winner override below restores
     the gold treatment for the actual D1 winner. */
  background: var(--ice-light-cyan);
  color: var(--black);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.45rem;
  line-height: 22px;
  letter-spacing: 0;
  word-spacing: normal;
  white-space: nowrap;
  text-align: center;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  z-index: 2;
}

/* Single-row layout for the simplified 4-ball post-draw back view.
   The default .mc-ball-row already flex-centers; this variant just
   adds breathing room so the four larger gold balls don't look
   cramped against the card edges. */
.mc-ball-row-4 {
  gap: 6px;
  padding: 0 4px;
}

/* v77: upscale the post-draw 4-ball state. This is the headline view
   of the card (team won / was knocked out / locked a pick) so balls
   AND the status line ("WON DRAW N!" / "KNOCKED OUT") both jump a
   notch bigger than their live-draw counterparts. :has() scopes the
   text bump to cards whose .mc-body contains .mc-ball-row-4 — so the
   mid-draw 14-ball grid keeps its compact sizing. */
.mc-ball-row-4 .mc-ball {
  width: 22px;
  height: 22px;
  font-size: 0.5rem;
}
.mc-body:has(.mc-ball-row-4) .mc-alive,
.mc-body:has(.mc-ball-row-4) .mc-alive.knocked-out,
.mc-body:has(.mc-ball-row-4) .mc-alive.mc-won {
  font-size: 0.7rem;
}
/* v86: extra breathing room between the status line ("WON DRAW N!" /
   "KNOCKED OUT") and the 4-ball row. mid-draw 14-ball grid keeps its
   tight 3px spacing because :has() only matches the post-draw state. */
.mc-body:has(.mc-ball-row-4) {
  gap: 10px;
}

/* FULL back-face bumps at the QUICK breakpoints. Only the back-content
   pieces that FULL owns (body inset, combos-alive line, ball sizes)
   appear here — card shell / logo / name / tags ride on the QUICK
   breakpoint rules defined earlier. */
@media (min-width: 768px) {
  .mc-body { inset: 40px 4px 10px 4px; gap: 4px; }
  .mc-alive { font-size: 0.6rem; }
  .mc-alive.knocked-out { font-size: 0.6rem; }
  .mc-ball { width: 22px; height: 22px; font-size: 0.5rem; border-width: 2px; }
  .mc-ball-row { gap: 5px; }
  .mc-ball-row-4 { gap: 10px; padding: 0 6px; }
  /* v77: post-draw 4-ball row bumps bigger than the live-draw grid. */
  .mc-ball-row-4 .mc-ball { width: 30px; height: 30px; font-size: 0.65rem; }
  .mc-body:has(.mc-ball-row-4) .mc-alive,
  .mc-body:has(.mc-ball-row-4) .mc-alive.knocked-out,
  .mc-body:has(.mc-ball-row-4) .mc-alive.mc-won { font-size: 0.8rem; }
  .mc-body:has(.mc-ball-row-4) { gap: 14px; }
  .mc-balls { gap: 0px; }
  /* Banner shares the top/height spec of .seed-badge / .odds-tag at
     this breakpoint so corners line up with adjacent tags on other
     cards. v65: right edge sits 4px shy of the odds-tag left edge
     (odds-tag at 768+: right:10 + min-width 56 = 66px from right;
     banner right:70 leaves a 4px gutter). Padding trimmed to 5px 3px
     so the bumped font fits comfortably on one line. */
  .owns-pick-banner {
    top: 8px;
    left: 10px;
    right: 70px;
    height: 26px;
    /* v84: zero padding + line-height == height for vertical centering.
       Overrides base 22px line-height at this breakpoint. */
    padding: 0;
    line-height: 26px;
    font-size: 0.55rem;
  }
}
@media (min-width: 1024px) {
  /* Keep the back-face body the same size as tablet — bumping balls to
     28px here previously pushed the 3-row ball grid past the bottom of
     the card. 22px balls + 0.65rem alive line leaves clean breathing
     room inside the 91px .mc-body inset. */
  .mc-alive { font-size: 0.65rem; }
  .mc-ball { width: 22px; height: 22px; font-size: 0.5rem; border-width: 2px; }
  .mc-ball-row { gap: 6px; }
  .mc-ball-row-4 { gap: 12px; padding: 0 8px; }
  /* v77: post-draw 4-ball row bumps bigger than the live-draw grid. */
  .mc-ball-row-4 .mc-ball { width: 34px; height: 34px; font-size: 0.7rem; }
  .mc-body:has(.mc-ball-row-4) .mc-alive,
  .mc-body:has(.mc-ball-row-4) .mc-alive.knocked-out,
  .mc-body:has(.mc-ball-row-4) .mc-alive.mc-won { font-size: 0.9rem; }
  .mc-body:has(.mc-ball-row-4) { gap: 18px; }
  .mc-balls { gap: 1px; }
  /* Height/padding inherited from the 768 rule so they stay locked
     to the seed-badge spec at desktop as well. v65: font bumps once
     more on big desktop cards. */
  .owns-pick-banner { font-size: 0.65rem; }
}

/* =========================================================
   ATTEMPTS COUNTER (both pages)
   v88: Pulled out of the .action-zone grid into its own row.
   v90: Moved BACK inside .sticky-shell-inner so it pins with the
   controls instead of scrolling away — simplest fix to keep the
   sticky band visually complete. Parent is now a block div (not a
   flex container), so right-alignment uses margin-left:auto on a
   fixed-width block instead of align-self:flex-end. Widths match
   .btn-start at each breakpoint so the counter sits directly under
   the button.
   ========================================================= */
.attempts-counter {
  display: block;
  margin-left: auto;
  width: 7.8rem;   /* 12 * 0.65rem — matches .btn-start base */
  text-align: center;
  font-size: 0.4rem;
  line-height: 1;
  color: var(--black);
  opacity: 0.75;
  padding: 0;
  margin-top: 6px;
  margin-bottom: 4px;
  letter-spacing: 1px;
  word-spacing: normal;
  white-space: nowrap;
}
@media (min-width: 768px) {
  /* Match .btn-start width at 768: 12 * 0.75rem = 9rem. */
  .attempts-counter {
    font-size: 0.45rem;
    width: 9rem;
    margin-top: 8px;
    margin-bottom: 4px;
  }
}
@media (min-width: 1024px) {
  /* Match .btn-start width at 1024: 12 * 0.85rem = 10.2rem.
     v88: margin-bottom tightened further (4 -> 0) per user directive
     — desktop gap between counter and next header was still too big. */
  .attempts-counter {
    font-size: 0.5rem;
    width: 10.2rem;
    margin-top: 8px;
    margin-bottom: 0;
  }
}

/* =========================================================
   CARD FRONT - live seed/odds deltas (FULL DRAW only).
   A thin signed number sitting right below each corner badge.
   Classes: .card-delta-wrap positions the slot; inline
   .card-delta carries the color (up/down/flat).
   ========================================================= */
.card-delta-wrap {
  position: absolute;
  /* v=265: +3 from v=264 for a touch more breathing room. */
  top: 31px;
  /* Anchor from the center of the tag above (tag midpoint: left 6 +
     width 44 / 2 = 28). translateX(-50%) then centers the delta text
     under that same midpoint regardless of its natural width, so a
     short "+2" and a long "+88.5%" both center on the tag above. */
  width: auto;
  height: auto;
  white-space: nowrap;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  word-spacing: normal;
  pointer-events: none;
  z-index: 2;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.card-delta-wrap.seed-delta-wrap {
  left: 28px;
  transform: translateX(-50%);
}
.card-delta-wrap.odds-delta-wrap {
  right: 28px;
  transform: translateX(50%);
}
.card-delta {
  padding: 0;
  background: transparent;
}
.card-delta.up   { color: #1F8A3A; } /* green  */
.card-delta.down { color: #E2231A; } /* red    */
.card-delta.flat { color: var(--black); }
@media (min-width: 768px) {
  .card-delta-wrap {
    font-size: 0.6rem;
    /* v=265: +3 from v=264. */
    top: 35px;
  }
  /* Tag midpoint at 768: left 10 + width 56 / 2 = 38. */
  .card-delta-wrap.seed-delta-wrap { left: 38px; }
  .card-delta-wrap.odds-delta-wrap { right: 38px; }
}
@media (min-width: 1024px) {
  /* v=265: +3 from v=264 for a touch more breathing room. */
  .card-delta-wrap { font-size: 0.6rem; top: 37px; }
}

/* OUT badge: same box as the numeric seed, different word. The is-out
   modifier tightens letter spacing so "OUT" doesn't overflow the 44px
   min-width at small breakpoints. */
.seed-badge.is-out {
  background: #6B7278;
  color: var(--white);
  letter-spacing: 0;
}

/* v87: grey OUT tag for the D1 winner during DRAW_2 once all their
   redraw combos are exhausted. Mirrors .seed-badge.is-out but applied
   to the right-side .odds-tag slot (banner stays on the left). */
.odds-tag.is-out {
  background: #6B7278;
  color: var(--white);
  letter-spacing: 0;
}

/* =========================================================
   WINNER / RUNNER-UP TEAM NAME SHADOW (v55)
   Was a blinking pulse — per user directive the blink is
   gone. Name keeps a static pixel-shadow in the medal tone
   (champagne on winner, silver on runner-up) so the card
   still reads as "podium" without animating.
   ========================================================= */
.card-wrap.winner   .face.front .team-name-stack .name {
  text-shadow: 1.5px 1.5px 0 #F0C850;
}
.card-wrap.runner-up .face.front .team-name-stack .name {
  text-shadow: 1.5px 1.5px 0 #BFC4CE;
}
/* v86: back-face abbrev + "WON DRAW N!" line inherit the same medal
   palette used on the front .name so CANUCKS/VAN (winner, gold) and
   KRAKEN/SEA (runner-up, silver) read as a single design system across
   both faces. Base shadow (white) is set on .abbrev-tag / .mc-alive.mc-won
   above; these selectors only swap the shadow color. */
.card-wrap.winner   .face.back .abbrev-tag,
.card-wrap.winner   .mc-alive.mc-won {
  text-shadow: 1.5px 1.5px 0 #F0C850;
}
.card-wrap.runner-up .face.back .abbrev-tag,
.card-wrap.runner-up .mc-alive.mc-won {
  text-shadow: 1.5px 1.5px 0 #BFC4CE;
}
/* Runner-up gets the same full-face silver treatment as the winner
   gets gold — parallels the QUICK sim where D2 winner has been
   painted silver for a while. Kept next to card-silver-pulse so it's
   easy to audit both palettes in one place. */

/* =========================================================
   TRADE OVERLAY (v=92)
   Shared card-face treatment for picks that are part of a
   first-round trade. Two teams render with this treatment
   on the 16-team lottery grid:

     - DET (seed 15) -> STL (resolved). Card identity swaps
       to STL (logo/city/name/abbrev) via renderCard; the
       original DET logo rides a faded .trade-secondary up
       in the top-tag row as a quiet "we got this from DET"
       signal. The back face washes DET season stats to
       light grey and tacks a "DET SEASON RESULTS SHOWN"
       footnote on.

     - TOR (seed 5) conditional. Card keeps TOR identity
       (the pick is top-5 protected). .trade-secondary on
       the front carries a faded BOS logo — the potential
       acquirer. Back face still shows TOR stats normally;
       no footnote.

   Both cards get a .trade-pair (old -> arrow -> new) on the
   BACK face, sitting just below the .abbrev-tag row, washed
   out to 45% opacity so it reads as context, not chrome.
   ========================================================= */

/* Front face: the secondary logo tucks between the seed-badge
   and odds-tag at the same vertical row. Width/height are tuned
   to each breakpoint's tag height so everything middle-aligns.
   pointer-events: auto so the hover tooltip fires; the native
   browser tooltip is driven by a title attribute on the wrapper. */
.face.front .trade-secondary {
  position: absolute;
  top: 6px;
  left: 50%;
  transform: translateX(-50%);
  width: 28px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.5;
  pointer-events: auto;
  cursor: help;
  z-index: 1;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.face.front .trade-secondary:hover {
  opacity: 0.95;
  transform: translateX(-50%) scale(1.08);
}
.face.front .trade-secondary img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  filter: url(#retro-posterize)
          saturate(1.6) contrast(1.2) brightness(1.03)
          drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.7))
          grayscale(0.35);
}

/* Back face: old -> new logo pair washed up under the abbrev-tag text.
   v=95: tightened further to 18px base / 24px @768 so the pair tucks
   directly beneath the three-letter abbrev text with minimal gap.
   Stats / mc-body :has() rules below shrunk to match — previous v=94
   values overshot once the logos moved up. */
.face.back .trade-pair {
  position: absolute;
  /* v=255: sit on the strip in the same slot a non-trade card's
     .abbrev-logo would. Was top: 18px (below the strip). */
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 5px;
  height: 22px;
  opacity: 0.85;
  color: var(--black);
  word-spacing: normal;
  line-height: 1;
  pointer-events: auto;
  cursor: help;
  z-index: 1;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.face.back .trade-pair:hover {
  opacity: 1;
  transform: translateX(-50%) scale(1.06);
}
.face.back .trade-pair .mini-logo {
  width: 18px;
  height: 18px;
  object-fit: contain;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  filter: url(#retro-posterize)
          saturate(1.6) contrast(1.2) brightness(1.03)
          drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.7))
          grayscale(0.35);
}
.face.back .trade-pair .arrow {
  color: var(--black);
  font-size: 0.55rem;
}

/* v=256: footnote + orig-washout restored on resolved trade cards.
   :has(.trade-pair) .mc-body shift NOT restored -- trade-pair lives
   in the strip now (v=255), so FULL .mc-body needs no special inset. */

/* Greyed values + labels for the team-specific stats (W-L-OT,
   POINTS) on identity-swapped cards. Pick-specific odds rows stay
   at normal color. */
.face.back .stats.orig-washout li.team-stat,
.face.back .stats.orig-washout li.team-stat .label,
.face.back .stats.orig-washout li.team-stat .value {
  color: #B5BFC5;
}
.face.back .stats.orig-washout li.team-stat {
  border-bottom-color: rgba(0, 0, 0, 0.08);
}

/* Footnote on the bottom of a resolved-trade back face. */
.face.back .trade-footnote {
  position: absolute;
  left: 6px;
  right: 6px;
  bottom: 6px;
  text-align: center;
  font-size: 0.36rem;
  letter-spacing: 1px;
  color: #6B7B85;
  word-spacing: normal;
  pointer-events: none;
  line-height: 1;
  margin: 0;
}

/* Bump bottom padding when the footnote is present so the last
   stat row doesn't crash into it. */
.face.back:has(.trade-footnote) { padding-bottom: 18px; }

/* Breakpoint bumps: top-tag dimensions grow at 768 (22px -> 26px
   tall, 6px -> 8px top), so the trade overlays scale to match. */
@media (min-width: 768px) {
  .face.front .trade-secondary {
    top: 8px;
    width: 34px;
    height: 26px;
  }
  /* v=256: trade-pair scales with the strip; only footnote breakpoint stays. */
  .face.back .trade-pair {
    gap: 6px;
    height: 26px;
  }
  .face.back .trade-pair .mini-logo {
    width: 22px;
    height: 22px;
  }
  .face.back .trade-pair .arrow {
    font-size: 0.6rem;
  }
  .face.back .trade-footnote {
    font-size: 0.42rem;
    bottom: 8px;
  }
  .face.back:has(.trade-footnote) { padding-bottom: 22px; }
}

/* ============================================================
   TEAM VIEW (v=117)
   One-team ball-by-ball deep dive. Lives in #team-view as a
   sibling of #league-view under the same .board-header row.
   Toggled via .view-toggle-pill. Shares the .lottery-card shell
   aesthetic so it sits flush with the existing grid.
   ============================================================ */

.is-hidden { display: none !important; }

/* Toggle row: board-header title + pill. Stacks centered on mobile. */
/* View toggle row: flex row with header left + LEAGUE/TEAM <select>
   right. v=123 drops the pill; the select is the sole control. */
.view-toggle-row {
  width: 100%;
  display: flex;
  /* v=170: natural flex flow (row = dropdown height), centered so
     REAL-TIME ODDS text and VIEW dropdown are vertically balanced.
     Negative margin-top on the lottery-card below (see rule near
     .view-toggle-row + #league-view > .lottery-card) pulls the TAP
     hint up into the row's bottom empty space. */
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 0;
}
.view-toggle-row .board-header {
  margin: 0;
  flex: 1;
  min-width: 0;
}
/* v=141: view-wrap spans exactly one card's width at each breakpoint.
   Card width formula (card-grid inside lottery-card):
     mobile   : 2 cols, 12px gap, 10px lottery padding  -> (100% - 32)/2
     tablet   : 3 cols, 16px gap, 14px lottery padding  -> (100% - 60)/3
     desktop  : 4 cols, 20px gap, 16px lottery padding  -> (100% - 92)/4
   100% here is the view-toggle-row's content width, which equals the
   main-wrapper content width (same as the lottery-card's outer width).
   margin-right is set to the lottery-card padding so the wrap's right
   edge lines up with the last card's right edge. */
.view-toggle-row .view-wrap {
  margin-right: 10px;
  width: calc((100% - 32px) / 2);
}

@media (min-width: 768px) {
  .view-toggle-row { gap: 16px; }

  .view-toggle-row .view-wrap {
    margin-right: 14px;
    width: calc((100% - 60px) / 3);
  }
}
@media (min-width: 1024px) {
  .view-toggle-row .view-wrap {
    margin-right: 16px;
    width: calc((100% - 92px) / 4);
  }
}



/* v=170: lottery-card gets pulled UP by negative margin-top into
   the view-toggle-row's empty lower half. Row stays dropdown-height
   (so text + dropdown are visually centered) but the TAP hint ends
   up tight below REAL-TIME ODDS via the margin pull.
   Values ≈ (dropdown_height - text_height) / 2 at each breakpoint. */
/* v=171: eased from -10/-12/-14 to -4/-6/-8 so the first card row
   has more breathing room below the VIEW dropdown. */
.view-toggle-row + #league-view > .lottery-card,
.view-toggle-row + #team-view > .lottery-card {
  padding-top: 0;
  margin-top: -4px;
}
@media (min-width: 768px) {
  .view-toggle-row + #league-view > .lottery-card,
  .view-toggle-row + #team-view > .lottery-card {
    margin-top: -6px;
  }
}
@media (min-width: 1024px) {
  .view-toggle-row + #league-view > .lottery-card,
  .view-toggle-row + #team-view > .lottery-card {
    margin-top: -8px;
  }
}

/* League/Team view wrappers. .main-wrapper uses flex column with
   align-items:center so without an explicit width these wrappers
   collapse to content width and the card grid narrows. */
#league-view,
#team-view {
  width: 100%;
}





/* Team view card shell. */
.tv-card { padding: 14px 10px; }
@media (min-width: 768px) { .tv-card { padding: 18px 16px; } }
@media (min-width: 1024px) { .tv-card { padding: 22px 20px; } }

/* Header row: team dropdown + phase context. */
.tv-header {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  margin-bottom: 14px;
}
@media (min-width: 768px) {
  .tv-header {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
  }
}


/* Custom dropdown. */
.tv-dd {
  position: relative;
  display: inline-block;
  min-width: 220px;
}
.tv-dd-trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem;
  background: var(--ice-light-cyan);
  color: var(--black);
  border: 2px solid var(--black);
  box-shadow: 2px 2px 0 var(--shadow-drop);
  cursor: pointer;
  text-align: left;
  letter-spacing: 0.02em;
}
.tv-dd-logo {
  width: 26px;
  height: 26px;
  object-fit: contain;
  filter: url(#retro-posterize) saturate(1.6) contrast(1.2) brightness(1.03)
          drop-shadow(1px 1px 0 rgba(0,0,0,0.7));
  image-rendering: pixelated;
  flex-shrink: 0;
}
.tv-dd-label {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tv-dd-caret {
  display: inline-block;
  width: 14px;
  height: 9px;
  font-size: 0;
  color: transparent;
  flex-shrink: 0;
  margin-left: 6px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M1 1l5 6 5-6z'/><path fill='%23000' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-size: 14px 9px;
  background-position: center;
}

.tv-dd-panel {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 320px;
  overflow-y: auto;
  background: var(--white);
  border: 2px solid var(--black);
  box-shadow: 3px 3px 0 var(--shadow-drop);
  z-index: 30;
}
.tv-dd-panel.is-open { display: block; }

.tv-dd-option {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  background: transparent;
  color: var(--black);
  border: none;
  border-bottom: 1px solid rgba(0,0,0,0.1);
  cursor: pointer;
  text-align: left;
}
.tv-dd-option:last-child { border-bottom: none; }
.tv-dd-option:hover,
.tv-dd-option:focus,
.tv-dd-option.is-focused {
  background: var(--ice-light-cyan);
  outline: none;
}
.tv-dd-option.is-selected {
  background: var(--ice-cyan);
}
.tv-dd-option .tv-dd-logo {
  width: 22px;
  height: 22px;
}

@media (min-width: 768px) {
  .tv-dd { min-width: 260px; }
  .tv-dd-trigger { font-size: 0.6rem; padding: 10px 12px; }
  .tv-dd-option { font-size: 0.55rem; padding: 10px 12px; }
}

/* Stats row: three compact tiles. */
.tv-stats-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-bottom: 14px;
}
.tv-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 6px;
  background: var(--ice-light-cyan);
  border: 2px solid var(--black);
  box-shadow: 2px 2px 0 var(--shadow-drop);
}
.tv-stat-num {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.85rem;
  color: var(--black);
  text-shadow: 1.5px 1.5px 0 var(--white);
}
.tv-stat-num.up { color: var(--move-up); }
.tv-stat-num.down { color: var(--red); }
.tv-stat-label {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.4rem;
  color: var(--black);
  opacity: 0.7;
  letter-spacing: 0.03em;
  text-align: center;
}
@media (min-width: 768px) {
  .tv-stats-row { gap: 10px; margin-bottom: 18px; }
  .tv-stat { padding: 14px 10px; gap: 6px; }
  .tv-stat-num { font-size: 1rem; }
  .tv-stat-label { font-size: 0.45rem; }
}
@media (min-width: 1024px) {
  .tv-stat-num { font-size: 1.15rem; }
  .tv-stat-label { font-size: 0.5rem; }
}

/* -----------------------------------------------------------------
   MATCH strip (v=118): mirrors the LOTTERY DRAWING draw strip above
   the grid, but from one team's perspective. 4 pearl slots paint
   gold (match), red (killer), or washed-gold (post-KO) as balls drop.
   ----------------------------------------------------------------- */
.tv-match-strip {
  display: grid;
  grid-template-columns: auto repeat(4, 1fr);
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--black);
  border: 3px solid var(--black);
  box-shadow: 3px 3px 0 var(--shadow-drop-deep);
  margin-bottom: 14px;
}
.tv-match-label {
  color: var(--ice-cyan);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.05em;
}
.tv-match-slot {
  width: 32px; height: 32px; border-radius: 50%;
  border: 2px solid var(--white);
  display: flex; align-items: center; justify-content: center;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem; color: #1a1a1a; line-height: 1;
  box-shadow: inset -1px -2px 0 rgba(0,0,0,0.15), inset 1px 1px 0 rgba(255,255,255,0.35);
  justify-self: center;
  background: radial-gradient(circle at 32% 28%, #fff, #f0ece0 50%, #d8d1bf 100%);
}
.tv-match-slot.is-pearl { color: transparent; }
.tv-match-slot.is-gold {
  background: radial-gradient(circle at 32% 28%, #FFF5C8, var(--ball-gold) 60%, var(--ball-gold-deep) 100%);
  text-shadow: 1px 1px 0 rgba(255,255,255,0.5);
}
.tv-match-slot.is-gold-wash {
  background: radial-gradient(circle at 32% 28%, #FFF5C8, var(--ball-gold) 60%, var(--ball-gold-deep) 100%);
  text-shadow: 1px 1px 0 rgba(255,255,255,0.5);
  opacity: 0.4;
}
.tv-match-slot.is-red {
  background: radial-gradient(circle at 32% 28%, #FFC8C4, var(--ball-red) 55%, var(--ball-red-deep) 100%);
  color: var(--white);
  text-shadow: 1px 1px 0 rgba(0,0,0,0.5);
}
@media (min-width: 768px) {
  .tv-match-strip { gap: 14px; padding: 12px 18px; }
  .tv-match-label { font-size: 0.65rem; }
  .tv-match-slot { width: 38px; height: 38px; font-size: 0.65rem; }
}

/* -----------------------------------------------------------------
   Shared ball pip used in IN-PLAY and OUT sections. Round marker
   with the same gradient language as the card back-face balls.
   ----------------------------------------------------------------- */
.tv-ball-pip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%;
  border: 2px solid var(--black);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.42rem; color: var(--black); line-height: 1;
  background: var(--white);
  box-shadow: inset -1px -2px 0 rgba(0,0,0,0.15), inset 1px 1px 0 rgba(255,255,255,0.35);
}
.tv-ball-pip.is-alive {
  background: radial-gradient(circle at 32% 28%, var(--ball-alive-a), var(--ball-alive-b) 55%, var(--ball-alive-c) 100%);
}
.tv-ball-pip.is-out {
  background: radial-gradient(circle at 32% 28%, #C8CED3, var(--ball-grey) 55%, var(--ball-grey-deep) 100%);
  color: #2d2d2d; opacity: 0.85;
}
@media (min-width: 768px) {
  .tv-ball-pip { width: 28px; height: 28px; font-size: 0.5rem; }
}

/* -----------------------------------------------------------------
   IN-PLAY band + horizontal grid. Cyan band header shows the meta
   ("N BALLS | M COMBOS"). Body: grid of balls on row 1 and combo
   counts on row 2, up to 7 columns per 2-row block.
   ----------------------------------------------------------------- */
.tv-inplay-band {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%;
  background: var(--ice-cyan);
  color: var(--black);
  border: 3px solid var(--black);
  /* Matches .tv-out-band padding so both bands render the same height. */
  padding: 10px 14px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem;
  box-shadow: 3px 3px 0 var(--shadow-drop-deep);
  margin-bottom: 10px;
  letter-spacing: 0.05em;
  cursor: pointer;
  transition: transform 0.1s, box-shadow 0.1s;
}
.tv-inplay-band:active {
  transform: translate(2px, 2px);
  box-shadow: 1px 1px 0 var(--shadow-drop-deep);
}
.tv-inplay-band-right {
  display: inline-flex; align-items: center; gap: 10px;
}
.tv-inplay-caret {
  display: inline-block;
  width: 14px;
  height: 9px;
  font-size: 0;
  color: transparent;
  flex-shrink: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M1 1l5 6 5-6z'/><path fill='%23000' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-size: 14px 9px;
  background-position: center;
}
.tv-inplay-band[aria-expanded="false"] .tv-inplay-caret {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M3 1l6 3-6 3z'/><path fill='%23000' d='M2 0l6 3-6 3z'/></svg>");
}
.tv-inplay-meta { font-size: 0.45rem; opacity: 0.85; letter-spacing: 0.04em; }
.tv-inplay-body {
  width: 100%;
  display: block;
  background: var(--white);
  border: 3px solid var(--black);
  box-shadow: 3px 3px 0 var(--shadow-drop-deep);
  padding: 10px 12px;
  margin-bottom: 14px;
}
/* Grids wrapper: desktop stacks vertically, mobile lays side-by-side
   so each 7-ball chunk becomes a BALL col + COMBOS col pair. */
.tv-inplay-grids {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* Desktop (default): 7 ball pips on row 1, 7 combo labels on row 2.
   Cells emitted in order [ball1..ball7, combo1..combo7]; default
   grid-auto-flow fills row 1 then row 2. */
.tv-inplay-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-template-rows: auto auto;
  row-gap: 2px;
  column-gap: 4px;
}
.tv-inplay-cell {
  display: flex; align-items: center; justify-content: center;
  padding: 2px 2px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.42rem;
  line-height: 1.2;
}
.tv-inplay-cell.tv-cell-ball { padding: 2px 2px; }
.tv-inplay-cell.tv-cell-combo { font-size: 0.38rem; letter-spacing: 0; }
.tv-inplay-cell.tv-cell-combo-gold { /* v=173: gold moved to ball pip only */ }
.tv-inplay-cell.tv-cell-empty { visibility: hidden; }
.tv-inplay-empty {
  text-align: center;
  padding: 16px 8px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  color: var(--black);
  opacity: 0.5;
}
/* Mobile override: transpose each chunk into a vertical pair of
   columns (ball column + combos column), and put multiple chunks
   side-by-side so 14 balls end up as [BALL COMBOS BALL COMBOS]. */
@media (max-width: 767px) {
  .tv-inplay-grids {
    flex-direction: row;
    justify-content: space-around;
    gap: 18px;
  }
  .tv-inplay-grid {
    grid-template-columns: auto auto;
    grid-template-rows: repeat(7, auto);
    grid-auto-flow: column;
    row-gap: 4px;
    column-gap: 10px;
  }
  .tv-inplay-cell { padding: 3px 1px; font-size: 0.42rem; }
  .tv-inplay-cell.tv-cell-combo { font-size: 0.38rem; }
}
@media (min-width: 768px) {
  .tv-inplay-band { font-size: 0.65rem; padding: 12px 18px; }
  .tv-inplay-meta { font-size: 0.5rem; }

  .tv-inplay-cell { padding: 3px 2px; font-size: 0.5rem; }
  .tv-inplay-cell.tv-cell-combo { font-size: 0.45rem; }
  .tv-inplay-grid { row-gap: 2px; column-gap: 6px; }
}

/* -----------------------------------------------------------------
   OUT band: collapsible. Grey band header with caret; body is a
   wrap of tv-ball-pip.is-out pips (one per OUT ball).
   ----------------------------------------------------------------- */
.tv-out-band {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%;
  background: var(--ball-grey);
  color: var(--white);
  border: 3px solid var(--black);
  padding: 10px 14px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem;
  text-shadow: 1px 1px 0 rgba(0,0,0,0.4);
  box-shadow: 3px 3px 0 var(--shadow-drop-deep);
  cursor: pointer;
  letter-spacing: 0.05em;
  margin-bottom: 14px;
  transition: transform 0.1s, box-shadow 0.1s;
}
.tv-out-band:active {
  transform: translate(2px, 2px);
  box-shadow: 1px 1px 0 var(--shadow-drop-deep);
}
.tv-out-caret {
  display: inline-block;
  width: 14px;
  height: 9px;
  font-size: 0;
  color: transparent;
  flex-shrink: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M1 1l5 6 5-6z'/><path fill='%23000' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-size: 14px 9px;
  background-position: center;
}
.tv-out-band[aria-expanded="false"] .tv-out-caret {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M3 1l6 3-6 3z'/><path fill='%23000' d='M2 0l6 3-6 3z'/></svg>");
}
.tv-out-body {
  background: var(--white);
  border: 3px solid var(--black);
  box-shadow: 3px 3px 0 var(--shadow-drop-deep);
  padding: 12px;
  margin-top: -10px;
  margin-bottom: 14px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
}
@media (min-width: 768px) {
  .tv-out-band { font-size: 0.65rem; padding: 12px 18px; }

}

/* Chart. Structure produced by teamView.js.renderChart:
   <div class="tv-chart">
     <div class="tv-chart-bars">N columns</div>
     <div class="tv-xaxis"></div>
     <div class="tv-xlabels">N labels</div>
   </div>
*/
.tv-chart-wrap {
  background: var(--white);
  border: 2px solid var(--black);
  padding: 12px 10px 10px;
  box-shadow: 2px 2px 0 var(--shadow-drop);
}
.tv-chart-title {
  margin: 0 0 10px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem;
  color: var(--black);
  letter-spacing: 0.02em;
  text-align: center;
}
.tv-chart {
  display: flex;
  flex-direction: column;
}
.tv-chart-bars {
  display: grid;
  gap: 8px;
  align-items: end;
  min-height: 140px;
}
.tv-bar-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 100%;
  gap: 4px;
}
.tv-bar-val {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.4rem;
  color: var(--black);
  white-space: nowrap;
}
.tv-bar-track {
  width: 70%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
.tv-bar {
  width: 100%;
  /* v=244: bumped 4 -> 12 so the smallest bars still show fill
     behind the 2px borders top + bottom. */
  min-height: 12px;
  /* v=244: keycap-cyan bars (option 1 of the bars-v2 mockup) — */
  background: #4ED1DD;
  border: 2px solid var(--black);
  box-shadow:
    inset 0 3px 0 rgba(255, 255, 255, 0.55),
    inset 0 -5px 0 rgba(0, 70, 90, 0.35),
    2px 2px 0 var(--shadow-drop);
}
/* v=245: traded picks (TOR @ pick > 5 -> BOS today) repaint to
   the lottery-ball gold gradient. v=246: drop the question-mark
   help cursor; partner logo overflows top/bottom on tiny bars so
   we set overflow: visible. */
.tv-bar.is-traded {
  background: radial-gradient(
    circle at 32% 28%,
    #FFF5C8,
    var(--ball-gold) 60%,
    var(--ball-gold-deep) 100%
  );
  box-shadow:
    inset 0 3px 0 rgba(255, 255, 255, 0.45),
    inset 0 -4px 0 rgba(0, 0, 0, 0.25),
    2px 2px 0 var(--shadow-drop);
  position: relative;
  overflow: visible;
}

/* v=246: partner logo centered inside a transferred bar. Picks up
   the standard team-logo retro filter. cursor: pointer signals it
   carries the trade tooltip on hover/tap. */
.tv-bar-logo {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 22px;
  height: 22px;
  object-fit: contain;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  filter: url(#retro-posterize)
          saturate(1.6) contrast(1.2) brightness(1.03)
          drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.7));
  cursor: pointer;
  user-select: none;
}
@media (min-width: 768px) {
  .tv-bar-logo { width: 26px; height: 26px; }
}
@media (min-width: 1024px) {
  .tv-bar-logo { width: 30px; height: 30px; }
}
.tv-xaxis {
  height: 2px;
  background: var(--black);
  margin: 0;
}
.tv-xlabels {
  display: grid;
  gap: 8px;
  margin-top: 4px;
}
.tv-xlabel {
  text-align: center;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.45rem;
  color: var(--black);
  letter-spacing: 0.02em;
}
.tv-chart-empty {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  color: var(--black);
  opacity: 0.55;
  text-align: center;
  padding: 30px 10px;
}
@media (min-width: 768px) {
  .tv-chart-bars { min-height: 180px; gap: 10px; }
  .tv-xlabels { gap: 10px; }
  .tv-xlabel { font-size: 0.5rem; }
  .tv-bar-val { font-size: 0.45rem; }
  .tv-chart-title { font-size: 0.65rem; }
}
@media (min-width: 1024px) {
  .tv-chart-bars { min-height: 220px; gap: 12px; }
  .tv-xlabels { gap: 12px; }
  .tv-xlabel { font-size: 0.55rem; }
  .tv-bar-val { font-size: 0.5rem; }
  .tv-chart-title { font-size: 0.75rem; }
}

/* KO state: red banner + dimmed body when selected team is out. */
#team-view.is-ko .tv-stats-row,
#team-view.is-ko .tv-match-strip,
#team-view.is-ko .tv-inplay-band,
#team-view.is-ko .tv-inplay-body,
#team-view.is-ko .tv-out-band,
#team-view.is-ko .tv-out-body,
#team-view.is-ko .tv-chart-wrap {
  opacity: 0.55;
}
.tv-ko-footer {
  margin-top: 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  background: var(--red);
  color: var(--white);
  border: 2px solid var(--black);
  box-shadow: 2px 2px 0 var(--shadow-drop);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.02em;
  text-shadow: 1px 1px 0 rgba(0,0,0,0.35);
}
.tv-ko-footer.is-hidden { display: none; }
@media (min-width: 768px) {
  .tv-ko-footer { font-size: 0.65rem; padding: 12px 16px; }
}

/* ============================================================
   P09-C4 keycap (v=123): unified ice-cyan keycap chrome used by
   the page-menu, mode, view, team-picker trigger, and the IN-PLAY
   + OUT bands on fulldraw.html. Every triggerable surface paints
   the same: light-cyan fill, 3px black border, inset top highlight
   + inset bottom shadow for 3D depth, 3px drop shadow offset.
   ============================================================ */
.cap-btn, .cap-select {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  letter-spacing: 0;
  word-spacing: -0.6em;
  color: var(--black);
  background-color: var(--ice-light-cyan);
  border: 3px solid var(--black);
  padding: 10px 14px 13px;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.9),
    inset 0 -5px 0 rgba(0, 70, 90, 0.25),
    3px 3px 0 var(--shadow-drop-deep);
  cursor: pointer;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: transform 0.1s, box-shadow 0.1s;
  text-align: left;
}
.cap-select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-right: 24px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M1 1l5 6 5-6z'/><path fill='%23000' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-position: right 8px center;
  background-size: 14px 9px;
  text-transform: uppercase;
}
.cap-btn:active, .cap-select:active {
  transform: translate(2px, 2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.9),
    inset 0 -5px 0 rgba(0, 70, 90, 0.25),
    1px 1px 0 var(--shadow-drop-deep);
}
.cap-select:focus {
  outline: 2px solid var(--black);
  outline-offset: -2px;
}
.cap-select:focus:not(:focus-visible) { outline: none; }
.cap-select option {
  background-color: var(--ice-light-cyan);
  color: var(--black);
  font-family: 'Press Start 2P', monospace;
  font-size: inherit;
  text-transform: uppercase;
  letter-spacing: 0;
  word-spacing: -0.6em;
  padding: 8px 10px;
}
@media (min-width: 768px) {
  .cap-btn, .cap-select { font-size: 0.6rem; padding: 12px 18px 15px; }
  .cap-select { padding-right: 26px; }
}
@media (min-width: 1024px) {
  .cap-btn, .cap-select { font-size: 0.65rem; padding: 13px 20px 16px; }
}

/* v=144: menu adopts the same wrap+label+select pattern as
   .mode-wrap / .view-wrap. The wrap carries the keycap chrome; a
   .cap-label box on the left paints the darker cyan with the
   hamburger SVG centered inside; the inner <select> stays
   transparent and carries the chevron on its right. */
.menu-wrap {
  margin-left: auto;
  display: inline-flex;
  align-items: stretch;
  gap: 0;
  padding: 0;
}
.menu-wrap .menu-icon {
  background-color: #84E9F4;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 13'><rect x='1' y='2' width='18' height='2' fill='%23fff'/><rect x='1' y='6' width='18' height='2' fill='%23fff'/><rect x='1' y='10' width='18' height='2' fill='%23fff'/><rect x='0' y='1' width='18' height='2' fill='%23000'/><rect x='0' y='5' width='18' height='2' fill='%23000'/><rect x='0' y='9' width='18' height='2' fill='%23000'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 20px 13px;
  padding: 10px 12px 13px;
  min-width: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.55),
    inset 0 -5px 0 rgba(0, 70, 90, 0.35);
}
.menu-wrap .cap-select {
  background-color: transparent !important;
  border: none !important;
  box-shadow: none !important;
  padding: 10px 20px 13px 10px !important;
  font-size: inherit !important;
  margin: 0 !important;
  line-height: 1 !important;
}
.menu-wrap .cap-select:focus {
  outline: 2px solid var(--black);
  outline-offset: -2px;
}
.menu-wrap .cap-select:focus:not(:focus-visible) { outline: none; }

@media (min-width: 768px) {
  .menu-wrap .menu-icon {
    padding: 12px 14px 15px;
    min-width: 48px;
    background-size: 22px 14px;
  }
  .menu-wrap .cap-select { padding: 12px 22px 15px 12px !important; }
}
@media (min-width: 1024px) {
  .menu-wrap .menu-icon {
    padding: 13px 16px 16px;
    min-width: 52px;
    background-size: 24px 16px;
  }
  .menu-wrap .cap-select { padding: 13px 24px 16px 14px !important; }
}

/* v=138: only team-dd-trigger keeps the darker #84E9F4 fill; the
   mode + view wrappers inherit the lighter .cap-btn default so only
   their MODE:/VIEW: label text picks up the darker cyan (see rule
   below). */
.tv-dd-trigger.cap-btn {
  background-color: #84E9F4;
}
/* Mode wrap: takes cols 1-2 of the .action-zone grid. v=137 wraps
   the MODE:-labeled select so the label and options are decoupled. */
.mode-wrap { grid-column: 1; justify-self: start; width: 100%; }

/* In-play band + out band + team dd trigger carry .cap-btn so their
   base rules (legacy cyan/grey fills) need to lose to keycap styling.
   We override the specific properties that conflict. */
.tv-inplay-band.cap-btn,
.tv-out-band.cap-btn,
.tv-dd-trigger.cap-btn {
  background-color: var(--ice-light-cyan);
  color: var(--black);
  text-shadow: none;
  border: 3px solid var(--black);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.9),
    inset 0 -5px 0 rgba(0, 70, 90, 0.25),
    3px 3px 0 var(--shadow-drop-deep);
}
.tv-inplay-band.cap-btn { font-size: 0.5rem; padding: 10px 14px 13px; }
.tv-out-band.cap-btn { font-size: 0.5rem; padding: 10px 14px 13px; }
.tv-dd-trigger.cap-btn { padding: 10px 10px 13px 12px; }
@media (min-width: 768px) {
  .tv-inplay-band.cap-btn,
  .tv-out-band.cap-btn { font-size: 0.6rem; padding: 12px 18px 15px; }
  .tv-dd-trigger.cap-btn { padding: 12px 12px 15px 14px; }
}


/* v=133: font-size bump + reduced/unified left padding on every
   non-menu cap dropdown. Menu is exempt since it carries the
   hamburger icon on the left and needs its extra padding to clear
   the icon. Right padding stays generous on cap-select variants so
   the chevron SVG has room; the cap-btn variants (team-dd, inplay,
   out) reuse their existing right padding too. */
.mode-select,
.view-toggle-select,
.tv-dd-trigger.cap-btn,
.tv-inplay-band.cap-btn,
.tv-out-band.cap-btn {
  font-size: 0.6rem;
  padding-left: 10px;
}
.mode-select,
.view-toggle-select {
  padding-right: 20px;
}
.tv-inplay-band.cap-btn,
.tv-out-band.cap-btn {
  padding-right: 8px;
}
.tv-dd-trigger.cap-btn {
  padding-right: 10px;
}
@media (min-width: 768px) {
  .mode-select,
  .view-toggle-select,
  .tv-dd-trigger.cap-btn,
  .tv-inplay-band.cap-btn,
  .tv-out-band.cap-btn {
    font-size: 0.7rem;
    padding-left: 12px;
  }
  .mode-select,
  .view-toggle-select { padding-right: 22px; }
  .tv-inplay-band.cap-btn,
  .tv-out-band.cap-btn { padding-right: 10px; }
  .tv-dd-trigger.cap-btn { padding-right: 12px; }
}
@media (min-width: 1024px) {
  .mode-select,
  .view-toggle-select,
  .tv-dd-trigger.cap-btn,
  .tv-inplay-band.cap-btn,
  .tv-out-band.cap-btn {
    font-size: 0.75rem;
    padding-left: 14px;
  }
}


/* v=137: MODE: / VIEW: label-select wrappers. The wrapper carries the
   .cap-btn keycap chrome; the inner <select> (keeps .cap-select for
   the chevron bg-image but has its other chrome reset to transparent)
   only covers the value portion so the native options panel renders
   directly under it, not under the label. */
.mode-wrap, .view-wrap {
  display: inline-flex;
  align-items: stretch;
  gap: 0;
  padding: 0;
  position: relative;
}
/* v=149: chevron rendered as a pseudo-element anchored to the wrap's
   right edge. Decoupled from the inner <select>'s bg so it's always
   flush right regardless of flex-fill behavior. pointer-events: none
   so clicks still pass through to the select underneath. */
.mode-wrap::after,
.view-wrap::after {
  content: '';
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  width: 14px;
  height: 9px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M1 1l5 6 5-6z'/><path fill='%23000' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-size: 14px 9px;
  pointer-events: none;
}
.mode-wrap .cap-label,
.view-wrap .cap-label {
  font-family: 'Press Start 2P', monospace;
  font-size: inherit;
  color: var(--black);
  /* Two-tone keycap: label half paints the darker draw-strip cyan;
     value half (see .cap-select below) shows the wrapper's lighter
     .cap-btn bg. White pixel shadow keeps the text punchy. */
  background-color: #84E9F4;
  text-shadow: 1.5px 1.5px 0 var(--white);
  flex-shrink: 0;
  white-space: nowrap;
  letter-spacing: 0;
  word-spacing: -0.6em;
  padding: 10px 4px 13px 10px;
  line-height: 1.2;
  display: inline-flex;
  align-items: center;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.55),
    inset 0 -5px 0 rgba(0, 70, 90, 0.35);
}
/* Inner <select>: transparent so the wrapper's lighter .cap-btn bg
   shows through on the value side. Keeps the chevron from .cap-select.
   v=148: flex: 1 on both so the select fills the wrap's remaining
   width, which plants the chevron at the wrapper's far right edge. */
.mode-wrap .cap-select,
.view-wrap .cap-select {
  flex: 1 1 0;
  min-width: 0;
  background-color: transparent !important;
  background-image: none !important;  /* chevron moves to wrap::after */
  border: none !important;
  box-shadow: none !important;
  padding: 10px 24px 13px 6px !important;
  font-size: inherit !important;
  margin: 0 !important;
  line-height: 1 !important;
}
.mode-wrap .cap-select:focus,
.view-wrap .cap-select:focus {
  outline: 2px solid var(--black);
  outline-offset: -2px;
}
.mode-wrap .cap-select:focus:not(:focus-visible),
.view-wrap .cap-select:focus:not(:focus-visible) { outline: none; }

@media (min-width: 768px) {
  .mode-wrap .cap-label, .view-wrap .cap-label { padding: 12px 6px 15px 12px; }
  .mode-wrap .cap-select, .view-wrap .cap-select { padding: 12px 26px 15px 8px !important; }
}
@media (min-width: 1024px) {
  .mode-wrap .cap-label, .view-wrap .cap-label { padding: 13px 8px 16px 14px; }
  .mode-wrap .cap-select, .view-wrap .cap-select { padding: 13px 28px 16px 10px !important; }
}


/* v=147: wrapper font-size so .cap-label (inherit) + .cap-select
   (inherit via !important in wrap scope) both render at the full
   non-menu dropdown size. */
.mode-wrap, .view-wrap {
  font-size: 0.6rem;
}
@media (min-width: 768px) {
  .mode-wrap, .view-wrap { font-size: 0.7rem; }
}
@media (min-width: 1024px) {
  .mode-wrap, .view-wrap { font-size: 0.75rem; }
}


/* v=147: action-zone first column tracks card width at each bp. */
@media (min-width: 768px) {
  .action-zone {
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
    padding: 3px 14px;
  }
}
@media (min-width: 1024px) {
  .action-zone {
    grid-template-columns: repeat(4, 1fr);
    gap: 20px;
    padding: 3px 16px;
  }
}

@media (min-width: 768px) {
  .mode-wrap::after, .view-wrap::after { right: 12px; }
}
@media (min-width: 1024px) {
  .mode-wrap::after, .view-wrap::after { right: 14px; }
}


/* v=153: restore the v=150 pre-v152 shim set. sticky-shell-inner
   keeps its 20px padding at 768+ / 1024+ (untouched). board-header
   + card-hint + btn-start targets card col-1/col-N edges at
   10 / 14 / 16px lottery-padding. mode-wrap + drawing-header get a
   larger right-shift (14 / 20 / 24px) since they live inside
   sticky-shell-inner (padded 20) and need to reach the same card
   col-1 left edge visually — user directive: move them further right. */
/* v=156: land LOTTERY DRAWING and MODE on the exact X where
   LOTTERY ORDER & ODDS (board-header inside main-wrapper) sits.
     main-wrapper has padding 12 at every breakpoint
     sticky-shell-inner has padding 12 / 20 / 20
   So on 768+/1024+ we subtract the 8px container-padding delta via
   negative margin-left. Padding-left is left at the .board-header
   default (4px) for drawing-header so its text sits +4 from element
   edge matching board-header on index.html. */
/* v=157 — land LOTTERY DRAWING and MODE at the same X where the
   cards, TAP hint, and REAL-TIME ODDS sit. Those all sit at
   main-outer + 12 (main-wrapper padding) + 10/14/16 (lottery-card
   padding) = 22/26/28. drawing-header is in sticky-shell-inner
   (padding 12/20/20) with a default 4px padding-left, so margin-left
   compensates:
     mobile : 12 + 6 + 4 = 22
     768+   : 20 + 2 + 4 = 26
     1024+  : 20 + 4 + 4 = 28
   mode-wrap has no default padding-left:
     mobile : 12 + 10 = 22
     768+   : 20 +  6 = 26
     1024+  : 20 +  8 = 28 */
/* v=158 — correct math now that I know main-wrapper has padding:
   0 20px at 768+ AND 1024+ (not 12 like I assumed). Card col-1 left
   at each breakpoint:
     mobile (<768) : main-outer + 12 + 10 =  22
     768+          : main-outer + 20 + 14 =  34
     1024+         : main-outer + 20 + 16 =  36
   drawing-header (inside sticky-inner, sticky padding 12/20/20,
   .board-header default padding-left: 4):
     mobile : 12 +  6 + 4 = 22
     768+   : 20 + 10 + 4 = 34
     1024+  : 20 + 12 + 4 = 36
   mode-wrap (no default padding-left):
     mobile : 12 + 10 = 22
     768+   : 20 + 14 = 34
     1024+  : 20 + 16 = 36  */
/* v=161: drawing-header still needs its margin/padding shims to
   reach card col-1 left (it lives inside sticky-shell-inner directly,
   not in action-zone). mode-wrap drops its shim because action-zone
   now pads and mode-wrap fills col 1 which IS card col-1. */
#drawing-header { margin-left: 6px !important; padding-left: 4px !important; }
.mode-wrap      { margin-left: 0 !important; }
@media (min-width: 768px) {
  #drawing-header { margin-left: 10px !important; }
}
@media (min-width: 1024px) {
  #drawing-header { margin-left: 12px !important; }
}

#board-header { padding-left: 10px; }
@media (min-width: 768px) { #board-header { padding-left: 14px; } }
@media (min-width: 1024px) { #board-header { padding-left: 16px; } }

.card-hint { margin-left: 0 !important; padding: 0 !important; }


/* v=171: top menu (hamburger + LOTTERY select) sized and aligned to
   card col-N. Lives in .header-container which is max-width 1000px
   centered with padding 12. Width calc uses the same formula as the
   VIEW toggle: (100% - lottery_pad*2 - gaps) / N. margin-right pulls
   the wrap in by lottery_pad so the right edge hits card col-N right. */
.menu-wrap {
  width: calc((100% - 32px) / 2);
  margin-right: 10px;
}
@media (min-width: 768px) {
  .menu-wrap {
    width: calc((100% - 60px) / 3);
    margin-right: 14px;
  }
}
@media (min-width: 1024px) {
  .menu-wrap {
    width: calc((100% - 92px) / 4);
    margin-right: 16px;
  }
}

/* v=171: attempts counter matches the start button's footprint (card
   width, right-aligned with card col-N right). */
.attempts-counter {
  display: block;
  width: calc((100% - 32px) / 2);
  margin-left: auto;
  margin-right: 10px;
  text-align: center;
  box-sizing: border-box;
}
@media (min-width: 768px) {
  .attempts-counter {
    width: calc((100% - 60px) / 3);
    margin-right: 14px;
  }
}
@media (min-width: 1024px) {
  .attempts-counter {
    width: calc((100% - 92px) / 4);
    margin-right: 16px;
  }
}


/* v=172: menu dropdown polish — bigger font + chevron flush right via
   ::after pseudo-element (matching mode-wrap / view-wrap pattern). */
.menu-wrap {
  position: relative;
  font-size: 0.6rem;
}
@media (min-width: 768px) {
  .menu-wrap { font-size: 0.7rem; }
}
@media (min-width: 1024px) {
  .menu-wrap { font-size: 0.75rem; }
}

/* Inner menu <select>: kill its own chevron bg (::after handles it),
   let it flex-fill so the chevron lands at the wrap's right edge. */
.menu-wrap .cap-select {
  background-image: none !important;
  flex: 1 1 0;
  min-width: 0;
  font-size: inherit !important;
  padding-right: 24px !important;
}

/* Chevron: same 14x9 SVG used everywhere else, anchored right 10/12/14. */
.menu-wrap::after {
  content: '';
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  width: 14px;
  height: 9px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M1 1l5 6 5-6z'/><path fill='%23000' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-size: 14px 9px;
  pointer-events: none;
}
@media (min-width: 768px) {
  .menu-wrap::after { right: 12px; }
}
@media (min-width: 1024px) {
  .menu-wrap::after { right: 14px; }
}


/* =====================================================================
   v=173 Team View overhaul
   - Card shell in darker cyan (#84E9F4) with symmetric padding.
   - Team dropdown uses keycap wrap (TEAM: label decoupled from value).
   - Stats row: single border around the row, dividers between tiles.
   - IN-PLAY + OUT bands share meta structure (label left / meta+caret right).
   - IN-PLAY grid is a flat grid of .tv-inplay-pair units (pip on top,
     combo text below). 3 cols mobile, 7 cols 768+. Gold on pip only.
   - Drops the "|" separators from both band meta lines.
   ===================================================================== */

/* --- Card shell ---------------------------------------------------- */
.lottery-card.full-card.tv-card {
  background: #84E9F4;
  padding: 14px;
  box-shadow: 3px 3px 0 var(--shadow-drop-deep);
  border: 3px solid var(--black);
}
@media (min-width: 768px) {
  .lottery-card.full-card.tv-card { padding: 18px; }
}
@media (min-width: 1024px) {
  .lottery-card.full-card.tv-card { padding: 22px; }
}

/* --- Team dropdown keycap wrap (mirrors .mode-wrap / .view-wrap) --- */
.team-dd-wrap.cap-btn {
  display: inline-flex;
  align-items: stretch;
  width: 100%;
  min-width: 0;
  gap: 0;
  padding: 0 !important;
  position: relative;
  font-size: 0.6rem;
}
@media (min-width: 768px) {
  .team-dd-wrap.cap-btn { font-size: 0.7rem; }
}
@media (min-width: 1024px) {
  .team-dd-wrap.cap-btn { font-size: 0.75rem; }
}
.team-dd-wrap .cap-label {
  font-family: 'Press Start 2P', monospace;
  font-size: inherit;
  color: var(--black);
  background-color: #84E9F4;
  text-shadow: 1.5px 1.5px 0 var(--white);
  flex-shrink: 0;
  white-space: nowrap;
  letter-spacing: 0;
  word-spacing: -0.6em;
  padding: 10px 4px 13px 10px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.55),
    inset 0 -5px 0 rgba(0, 70, 90, 0.35);
}
@media (min-width: 768px) {
  .team-dd-wrap .cap-label { padding: 12px 6px 15px 12px; }
}
@media (min-width: 1024px) {
  .team-dd-wrap .cap-label { padding: 13px 8px 16px 14px; }
}
/* Inner trigger: transparent chrome, inherits wrap's keycap body.
   Overrides the earlier .tv-dd-trigger.cap-btn rules (no .cap-btn class
   on it anymore), but we still need to beat .tv-dd-trigger's base rules. */
.team-dd-wrap .tv-dd-trigger {
  flex: 1 1 0;
  min-width: 0;
  background: transparent !important;
  background-image: none !important;
  border: none !important;
  box-shadow: none !important;
  padding: 10px 24px 13px 8px !important;
  font-family: 'Press Start 2P', monospace;
  font-size: inherit !important;
  color: var(--black);
  letter-spacing: 0.02em;
  text-align: left;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  line-height: 1 !important;
}
@media (min-width: 768px) {
  .team-dd-wrap .tv-dd-trigger { padding: 12px 26px 15px 10px !important; }
}
@media (min-width: 1024px) {
  .team-dd-wrap .tv-dd-trigger { padding: 13px 28px 16px 12px !important; }
}
/* Chevron pinned to wrap's right edge, same SVG/size as mode+view. */
.team-dd-wrap::after {
  content: '';
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  width: 14px;
  height: 9px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M1 1l5 6 5-6z'/><path fill='%23000' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-size: 14px 9px;
  pointer-events: none;
}
@media (min-width: 768px) {
  .team-dd-wrap::after { right: 12px; }
}
@media (min-width: 1024px) {
  .team-dd-wrap::after { right: 14px; }
}
.team-dd-wrap .tv-dd-trigger:focus {
  outline: 2px solid var(--black);
  outline-offset: -2px;
}
.team-dd-wrap .tv-dd-trigger:focus:not(:focus-visible) { outline: none; }
/* Wrap carries the keycap chrome. Because .cap-btn rules apply to it,
   the base .tv-dd-trigger.cap-btn override block upstream no longer
   matches — we only need to reshape the wrap itself. */

/* --- Stats row: single border around the row with dividers --------- */
.tv-stats-row {
  background: var(--ice-light-cyan);
  border: 3px solid var(--black);
  box-shadow: 3px 3px 0 var(--shadow-drop);
  gap: 0;
}
.tv-stats-row .tv-stat {
  background: transparent;
  border: none;
  box-shadow: none;
  border-right: 2px solid var(--black);
}
.tv-stats-row .tv-stat:last-child { border-right: none; }

/* --- OUT band mirror of IN-PLAY (label / meta / caret) ------------- */
.tv-out-band-right {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.tv-out-meta {
  font-size: 0.45rem;
  opacity: 0.85;
  letter-spacing: 0.04em;
  text-transform: none;
}
@media (min-width: 768px) {
  .tv-out-meta { font-size: 0.5rem; }
}

/* Meta-stat chunks (IN-PLAY + OUT share the same look). */
.tv-meta-stat {
  display: inline-block;
}
.tv-meta-stat + .tv-meta-stat {
  margin-left: 14px;
}
@media (min-width: 768px) {
  .tv-meta-stat + .tv-meta-stat { margin-left: 18px; }
}

/* --- IN-PLAY grid: flat pair grid (pip + combo below) -------------- */
/* Win against the older .tv-inplay-grids flex row (teamView.js no longer
   emits the wrapper, so the legacy rules never match; the new
   .tv-inplay-grid is a direct child of #tv-inplay-body). */
#tv-inplay-body .tv-inplay-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: none;
  grid-auto-flow: row;
  row-gap: 10px;
  column-gap: 6px;
}
@media (min-width: 768px) {
  #tv-inplay-body .tv-inplay-grid {
    grid-template-columns: repeat(7, 1fr);
    column-gap: 6px;
  }
}
.tv-inplay-pair {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 0;
}
.tv-pair-combo {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.38rem;
  letter-spacing: 0;
  color: var(--black);
  opacity: 0.85;
  text-align: center;
  line-height: 1.15;
  white-space: nowrap;
}
@media (min-width: 768px) {
  .tv-pair-combo { font-size: 0.42rem; }
}
@media (min-width: 1024px) {
  .tv-pair-combo { font-size: 0.45rem; }
}


/* =====================================================================
   v=174 Team View tightening
   Sequenced after the v=173 overhaul block so these rules win on
   cascade.
   ===================================================================== */

/* 1+2: Shrink tv-card to draw-strip inner box + add top gap under
   the VIEW dropdown. Draw-strip uses width calc(100% - 20/28/32) and
   margin 10/14/16 horizontally; mirror those exactly. */
.lottery-card.full-card.tv-card {
  width: calc(100% - 20px);
  margin: 10px 10px 14px;
  box-sizing: border-box;
}
@media (min-width: 768px) {
  .lottery-card.full-card.tv-card {
    width: calc(100% - 28px);
    margin: 14px 14px 14px;
  }
}
@media (min-width: 1024px) {
  .lottery-card.full-card.tv-card {
    width: calc(100% - 32px);
    margin: 16px 16px 14px;
  }
}

/* 3: Matched ball pip — gold gradient + white pixel highlight.
   Mirrors .draw-ball and .tv-match-slot.is-gold treatment. */
.tv-ball-pip.is-match {
  background: radial-gradient(circle at 32% 28%, #FFF5C8, var(--ball-gold) 60%, var(--ball-gold-deep) 100%);
  color: var(--black);
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.5);
}

/* 4: Auto-width team dropdown on 768+. Mobile stays 100% so the TEAM
   row stacks nicely below the context line. */
@media (min-width: 768px) {
  .team-dd-wrap.cap-btn {
    width: auto;
    min-width: 280px;
  }
  .tv-dd {
    min-width: 280px;
  }
}
@media (min-width: 1024px) {
  .team-dd-wrap.cap-btn {
    min-width: 300px;
  }
  .tv-dd {
    min-width: 300px;
  }
}
/* Ensure the trigger doesn't force a scroll on small screens when
   the team label ("VANCOUVER CANUCKS") is long. */
.team-dd-wrap .tv-dd-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 5: Popover panel visually matches the other native-looking dropdowns:
   no inner borders between rows, compact padding, light hover highlight
   (same --ice-light-cyan used elsewhere), 2px black outer border to
   keep the pixel-art chrome consistent. */
.tv-dd-panel {
  border: 2px solid var(--black);
  box-shadow: 3px 3px 0 var(--shadow-drop-deep);
  background: var(--white);
}
.tv-dd-option {
  padding: 7px 10px;
  border-bottom: none;
  font-size: 0.5rem;
}
.tv-dd-option:last-child { border-bottom: none; }
.tv-dd-option:hover,
.tv-dd-option:focus,
.tv-dd-option.is-focused {
  background: var(--ice-light-cyan);
}
.tv-dd-option.is-selected {
  background: var(--ice-cyan);
}
@media (min-width: 768px) {
  .tv-dd-option { padding: 9px 12px; font-size: 0.55rem; }
}

/* 6: Remove the vertical dividers inside the stats row. */
.tv-stats-row .tv-stat,
.tv-stats-row .tv-stat:last-child {
  border-right: none;
}

/* 7: IN-PLAY meta renders as single-line textContent with "|" again;
   the tv-meta-stat span rules from v=173 are no-ops now — nothing emits
   those spans. Leave them in place (harmless). */

/* 8: IN-PLAY pair layout — pip on left, count+word stacked on right.
   The count number matches the pip's font-size so the visual weight
   balances side-to-side. The word sits below in a small pixel caption.
   Because .tv-pair-combo is now a flex column (not a text span), we
   override the v=173 color/opacity rules from the overhaul block. */
.tv-inplay-pair {
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  min-width: 0;
}
.tv-pair-combo {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  line-height: 1;
  opacity: 1;
  white-space: nowrap;
  font-size: inherit;
}
.tv-pair-count {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  color: var(--black);
  line-height: 1;
}
.tv-pair-word {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.3rem;
  color: var(--black);
  opacity: 0.7;
  letter-spacing: 0.02em;
  line-height: 1;
}
@media (min-width: 768px) {
  .tv-pair-count { font-size: 0.65rem; }
  .tv-pair-word { font-size: 0.38rem; }
  .tv-inplay-pair { gap: 10px; }
}
@media (min-width: 1024px) {
  .tv-pair-count { font-size: 0.75rem; }
  .tv-pair-word { font-size: 0.42rem; }
  .tv-inplay-pair { gap: 12px; }
}

/* Slight row-gap adjustment so horizontal pairs don't crowd each other
   vertically on mobile. */
#tv-inplay-body .tv-inplay-grid {
  row-gap: 12px;
  column-gap: 10px;
}
@media (min-width: 768px) {
  #tv-inplay-body .tv-inplay-grid { row-gap: 14px; column-gap: 12px; }
}

/* 9: OUT body — left-align pips instead of center. */
.tv-out-body {
  justify-content: flex-start;
}


/* =====================================================================
   v=175 Team View fixes
   Sequenced after v=173 overhaul + v=174 tightening so these win on
   cascade.
   ===================================================================== */

/* 1: VIEW dropdown was getting its top border clipped by the
   sticky-shell content painting above it (sticky-shell has z-index 40).
   Give the row its own stacking context with a higher index so the
   VIEW keycap always paints above the sticky-shell. */
.view-toggle-row {
  position: relative;
  z-index: 50;
}

/* 2+3: pair count font-size bump; matched label styling. */
.tv-pair-count {
  font-size: 0.6rem;
}
@media (min-width: 768px) {
  .tv-pair-count { font-size: 0.8rem; }
}
@media (min-width: 1024px) {
  .tv-pair-count { font-size: 0.9rem; }
}
.tv-pair-word {
  font-size: 0.32rem;
}
@media (min-width: 768px) {
  .tv-pair-word { font-size: 0.42rem; }
}
@media (min-width: 1024px) {
  .tv-pair-word { font-size: 0.48rem; }
}

/* MATCH label: single-line pixel caption. Sized to match the count
   visual weight so matched and alive pairs balance next to each other. */
.tv-pair-match {
  display: inline-flex;
  align-items: center;
}
.tv-pair-match-label {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  color: var(--ball-gold-deep);
  letter-spacing: 0.04em;
  line-height: 1;
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.5);
}
@media (min-width: 768px) {
  .tv-pair-match-label { font-size: 0.65rem; }
}
@media (min-width: 1024px) {
  .tv-pair-match-label { font-size: 0.75rem; }
}

/* 4a+4b: mobile 4 cols, center pair in column so outer gaps stay
   symmetric regardless of pair natural width. */
#tv-inplay-body .tv-inplay-grid {
  grid-template-columns: repeat(4, 1fr);
  row-gap: 14px;
  column-gap: 4px;
}
@media (min-width: 768px) {
  #tv-inplay-body .tv-inplay-grid {
    grid-template-columns: repeat(7, 1fr);
    column-gap: 10px;
  }
}
.tv-inplay-pair {
  justify-self: center;
}

/* 5a+5b: fixed-width team dropdown on 768+ so switching teams does
   not resize the wrap. Width set to fit "COLUMBUS BLUE JACKETS" +
   chevron + TEAM: label comfortably. Extra margin between the team
   label and the chevron comes from the tv-dd-label margin-right. */
@media (min-width: 768px) {
  .team-dd-wrap.cap-btn,
  .tv-dd {
    width: 340px;
    min-width: 340px;
    max-width: 340px;
  }
}
@media (min-width: 1024px) {
  .team-dd-wrap.cap-btn,
  .tv-dd {
    width: 380px;
    min-width: 380px;
    max-width: 380px;
  }
}
.team-dd-wrap .tv-dd-label {
  margin-right: 14px;
}
@media (min-width: 768px) {
  .team-dd-wrap .tv-dd-label { margin-right: 18px; }
}
@media (min-width: 1024px) {
  .team-dd-wrap .tv-dd-label { margin-right: 22px; }
}

/* 5c: panel now lives inside .tv-dd-body — position:relative on body,
   panel pinned to body's left/right so it aligns with the trigger's
   value column (NOT the TEAM: cap-label). Body flex-fills the wrap. */
.tv-dd-body {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: stretch;
}
.tv-dd-body .tv-dd-trigger {
  width: 100%;
}
/* Panel positioned relative to .tv-dd-body (not .tv-dd). Overrides the
   original left: 0; right: 0 on the wrap with the nested body bounds. */
.tv-dd-body .tv-dd-panel {
  left: 0;
  right: 0;
}
/* Option font-size matches the selected team label above (0.6/0.7/0.75). */
.tv-dd-option {
  font-size: 0.6rem;
  padding: 8px 10px;
}
@media (min-width: 768px) {
  .tv-dd-option { font-size: 0.7rem; padding: 10px 12px; }
}
@media (min-width: 1024px) {
  .tv-dd-option { font-size: 0.75rem; padding: 11px 14px; }
}


/* =====================================================================
   v=176 Team View fixes
   ===================================================================== */

/* Widen dropdown so "COLUMBUS BLUE JACKETS" fits at 768+/1024+ without
   text-overflow clipping. Numbers derived empirically from longest
   name (21 chars + logo + gap + chevron + margin + padding). */
@media (min-width: 768px) {
  .team-dd-wrap.cap-btn,
  .tv-dd {
    width: 440px;
    min-width: 440px;
    max-width: 440px;
  }
}
@media (min-width: 1024px) {
  .team-dd-wrap.cap-btn,
  .tv-dd {
    width: 480px;
    min-width: 480px;
    max-width: 480px;
  }
}

/* v=176: killer + post-KO OUT pips carry an extra .is-killed class.
   Leaving them visually identical to .is-out for now; the class hook
   exists so we can dial up the emphasis later if wanted. */
.tv-ball-pip.is-out.is-killed {
  /* reserved — same paint as .is-out today. */
}


/* =====================================================================
   v=177 Team View
   ===================================================================== */

/* Stats row now holds 4 tiles. Tighten text sizing so the labels fit
   at each breakpoint without breaking. */
.tv-stats-row { grid-template-columns: repeat(4, 1fr); }
.tv-stat-label { font-size: 0.35rem; }
@media (min-width: 768px) {
  .tv-stat-label { font-size: 0.4rem; }
}
@media (min-width: 1024px) {
  .tv-stat-label { font-size: 0.45rem; }
}
.tv-stat-num { font-size: 0.7rem; }
@media (min-width: 768px) {
  .tv-stat-num { font-size: 0.85rem; }
}
@media (min-width: 1024px) {
  .tv-stat-num { font-size: 1rem; }
}

/* Dropdown LABEL (closed state): show abbreviation on mobile, full
   city+name on tablet+. Dual <span>s let us toggle via media query
   without touching JS every resize. */
.tv-dd-label-full { display: none; }
.tv-dd-label-abbrev { display: inline; }
@media (min-width: 768px) {
  .tv-dd-label-full { display: inline; }
  .tv-dd-label-abbrev { display: none; }
}

/* Dropdown OPTIONS (open state): each row = logo, name/abbrev, %
   on the right. Flex so the % is right-pinned. */
.tv-dd-option {
  display: flex;
  align-items: center;
  gap: 8px;
}
.tv-dd-option-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tv-dd-option-full { display: none; }
.tv-dd-option-abbrev { display: inline; }
@media (min-width: 768px) {
  .tv-dd-option-full { display: inline; }
  .tv-dd-option-abbrev { display: none; }
}
.tv-dd-option-pct {
  flex-shrink: 0;
  font-family: 'Press Start 2P', monospace;
  color: var(--black);
  font-size: 0.85em;
  opacity: 0.85;
  margin-left: 8px;
}

/* Empty slot: occupies a grid cell but paints nothing. Keeps column
   widths and row heights consistent across the whole sim so balls
   don't shift as they transition. */
.tv-inplay-pair.is-empty {
  visibility: hidden;
  pointer-events: none;
}

/* v=177: killed pips — red fill + white digit. .is-out.is-killed wins
   over the neutral grey .is-out rule earlier in the file because it
   has one more class-selector hit. */
.tv-ball-pip.is-out.is-killed {
  background: radial-gradient(circle at 32% 28%, #FF8A85, #E2231A 55%, #8B0F0F 100%);
  color: var(--white);
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.55);
  opacity: 1;
  border-color: var(--black);
}


/* =====================================================================
   v=178 Team View
   ===================================================================== */

/* 1: Mobile now shows the full city+name in the trigger and options.
   Override the v=177 dual-text toggle so full is always visible and
   abbrev is never rendered. */
.tv-dd-label-full,
.tv-dd-option-full { display: inline !important; }
.tv-dd-label-abbrev,
.tv-dd-option-abbrev { display: none !important; }

/* 2: Stats row labels — tight word-spacing + nowrap on mobile to keep
   "DRAW 1 ODDS", "COMBOS IN PLAY", etc. on one line. Tablet/desktop
   bump the font-size up for readability. */
.tv-stat-label {
  white-space: nowrap;
  word-spacing: -0.18em;
  letter-spacing: 0;
  font-size: 0.32rem;
}
@media (min-width: 768px) {
  .tv-stat-label { font-size: 0.5rem; word-spacing: -0.1em; }
}
@media (min-width: 1024px) {
  .tv-stat-label { font-size: 0.55rem; word-spacing: -0.05em; }
}

/* Value numbers stay aligned visually; nudge down a hair on mobile
   so the tiles don't get too tall with the big figure + caption. */
@media (max-width: 767px) {
  .tv-stat-num { font-size: 0.65rem; }
}

/* 3: empty-slot rule from v=177 is unused now (dynamic entries never
   emit .is-empty). Left in place as a no-op; harmless. */

/* 4: OUT body — grid of 7 columns, pips centered in each column so
   rows are evenly distributed regardless of ball count. Replaces the
   prior flex-wrap layout. */
.tv-out-body {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  justify-items: center;
  align-items: center;
  row-gap: 8px;
  column-gap: 4px;
  /* legacy flex rules are shadowed by grid properties above; gap: 8px
     from the earlier rule is overridden via row-gap/column-gap. */
}
@media (min-width: 768px) {
  .tv-out-body { column-gap: 6px; row-gap: 10px; }
}


/* =====================================================================
   v=180 Team View
   ===================================================================== */

/* 1: IN-PLAY row-to-row pip alignment. Pairs now fill their grid cell
   (justify-self: stretch) and anchor the pip to the cell's left edge.
   Previously pairs were centered inside their 1fr cell, so MATCH pairs
   (narrower) and count pairs (wider) pushed their pip to different
   X positions — pips in row 2 drifted left/right relative to row 1.
   With stretch + pip-at-column-start, every pip sits at the same X
   as the pip directly above it, no matter how wide the combo block is. */
.tv-inplay-pair {
  justify-self: stretch;
  width: 100%;
  justify-content: flex-start;
  min-width: 0;
}
/* Combo block inside the pair can shrink/grow without moving the pip. */
.tv-inplay-pair > .tv-ball-pip { flex-shrink: 0; }
.tv-inplay-pair > .tv-pair-combo {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
}

/* 2: OUT body — ONE row of 14 columns at every breakpoint. Pips shrink
   on mobile so the row fits inside the body's inner width (~240px).
   Grid + justify-items: center keeps pips centered in each column so
   the row reads evenly. */
.tv-out-body {
  display: grid;
  grid-template-columns: repeat(14, 1fr);
  row-gap: 0;
  column-gap: 2px;
  justify-items: center;
  align-items: center;
  padding: 10px 8px;
}
@media (min-width: 768px) {
  .tv-out-body { column-gap: 4px; padding: 12px 10px; }
}
@media (min-width: 1024px) {
  .tv-out-body { column-gap: 6px; padding: 12px; }
}

/* Pip size inside OUT — shrunk on mobile to fit 14 across. */
.tv-out-body .tv-ball-pip {
  width: 18px;
  height: 18px;
  font-size: 0.36rem;
  border-width: 1.5px;
}
@media (min-width: 768px) {
  .tv-out-body .tv-ball-pip {
    width: 26px;
    height: 26px;
    font-size: 0.48rem;
    border-width: 2px;
  }
}
@media (min-width: 1024px) {
  .tv-out-body .tv-ball-pip {
    width: 28px;
    height: 28px;
    font-size: 0.5rem;
  }
}


/* =====================================================================
   v=181 Team View — mobile dropdown polish
   ===================================================================== */

/* 1: Mobile height match with VIEW dropdown. The 26px logo + trigger's
   10/13 vertical padding made team-dd noticeably taller than VIEW.
   Shrink both. */
.team-dd-wrap .tv-dd-logo {
  width: 16px;
  height: 16px;
}
@media (min-width: 768px) {
  .team-dd-wrap .tv-dd-logo { width: 22px; height: 22px; }
}
@media (min-width: 1024px) {
  .team-dd-wrap .tv-dd-logo { width: 24px; height: 24px; }
}
.team-dd-wrap .tv-dd-trigger {
  padding: 7px 22px 10px 6px !important;
  gap: 6px;
}
@media (min-width: 768px) {
  .team-dd-wrap .tv-dd-trigger { padding: 11px 26px 14px 8px !important; gap: 8px; }
}
@media (min-width: 1024px) {
  .team-dd-wrap .tv-dd-trigger { padding: 12px 28px 15px 10px !important; gap: 10px; }
}

/* 2: Tighter word-spacing so "COLUMBUS BLUE JACKETS" fits without
   ellipsis on the trigger AND inside the options panel. */
.team-dd-wrap .tv-dd-label,
.team-dd-wrap .tv-dd-label-full,
.tv-dd-option-label,
.tv-dd-option-full {
  word-spacing: -0.35em;
  letter-spacing: 0;
}
@media (min-width: 768px) {
  .team-dd-wrap .tv-dd-label,
  .team-dd-wrap .tv-dd-label-full,
  .tv-dd-option-label,
  .tv-dd-option-full { word-spacing: -0.2em; }
}

/* Options panel: shrink logo too so row heights feel consistent. */
.tv-dd-option .tv-dd-logo { width: 18px; height: 18px; }
@media (min-width: 768px) {
  .tv-dd-option .tv-dd-logo { width: 22px; height: 22px; }
}


/* =====================================================================
   v=184 — PS2P line-height fix + OUT empty-state single line
   Root cause diagnosis: Press Start 2P glyphs clip at the top when
   line-height is exactly 1. Bumping to 1.2 adds ~1px of half-leading
   above and below the glyph so nothing clips. No padding changes,
   so the glyph's visual center stays where it was.
   ===================================================================== */

/* VIEW + MODE native <select> text — fixes "TEAM" / "FULL SIM" clip. */
.mode-wrap .cap-select,
.view-wrap .cap-select {
  line-height: 1.2 !important;
}

/* IN-PLAY pair count digits — fixes the 63 / 59 / 58 top clip. */
.tv-pair-count,
.tv-pair-word,
.tv-pair-match-label {
  line-height: 1.2;
}

/* OUT body empty state ("ALL REMAINING BALLS IN PLAY"). OUT body is
   a 14-col grid (v=180), so the empty-state span was landing in a
   single ~17px cell and wrapping. Span all columns + nowrap so the
   text reads as one line at every breakpoint. */
.tv-out-body .tv-inplay-empty {
  grid-column: 1 / -1;
  white-space: nowrap;
  text-align: center;
  padding: 8px 4px;
}


/* =====================================================================
   v=185
   ===================================================================== */

/* ---- Chart band: same shell as IN-PLAY/OUT bands ----
   Uses .cap-btn chrome (light-cyan fill, pixel border, inset highlight,
   drop shadow). Label left, meta+caret right. Collapsible body below. */
.tv-chart-band {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  font-family: 'Press Start 2P', monospace;
  cursor: pointer;
  letter-spacing: 0.05em;
  margin-bottom: 10px;
  transition: transform 0.1s, box-shadow 0.1s;
  font-size: 0.5rem;
  padding: 10px 14px 13px;
}
@media (min-width: 768px) {
  .tv-chart-band { font-size: 0.6rem; padding: 12px 18px 15px; }
}
.tv-chart-band:active {
  transform: translate(2px, 2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.9),
    inset 0 -5px 0 rgba(0, 70, 90, 0.25),
    1px 1px 0 var(--shadow-drop-deep);
}
.tv-chart-band-right {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.tv-chart-meta {
  font-size: 0.45rem;
  opacity: 0.85;
  letter-spacing: 0.04em;
  white-space: nowrap;
}
@media (min-width: 768px) {
  .tv-chart-meta { font-size: 0.5rem; }
}
.tv-chart-caret {
  display: inline-block;
  width: 14px;
  height: 9px;
  font-size: 0;
  color: transparent;
  flex-shrink: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M1 1l5 6 5-6z'/><path fill='%23000' d='M0 0l5 6 5-6z'/></svg>");
  background-repeat: no-repeat;
  background-size: 14px 9px;
  background-position: center;
}
.tv-chart-band[aria-expanded="false"] .tv-chart-caret {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 7'><path fill='%23fff' d='M3 1l6 3-6 3z'/><path fill='%23000' d='M2 0l6 3-6 3z'/></svg>");
}
.tv-chart-body {
  background: var(--white);
  border: 3px solid var(--black);
  box-shadow: 3px 3px 0 var(--shadow-drop-deep);
  padding: 12px 10px 10px;
  margin-bottom: 14px;
}
.tv-chart-body.is-hidden { display: none; }

/* Bump the bar % value font size. */
.tv-bar-val { font-size: 0.5rem; }
@media (min-width: 768px) { .tv-bar-val { font-size: 0.6rem; } }
@media (min-width: 1024px) { .tv-bar-val { font-size: 0.65rem; } }

/* Legacy .tv-chart-wrap / .tv-chart-title rules become no-ops now that
   the wrap is gone from the DOM. Left unchanged in the file. */

/* ---- Native <select> option styling — match team popover ---- */
.cap-select option {
  background-color: var(--white);
  color: var(--black);
  font-family: 'Press Start 2P', monospace;
}
.cap-select option:hover,
.cap-select option:focus,
.cap-select option:checked {
  background-color: var(--ice-light-cyan);
  color: var(--black);
}

/* ---- Hamburger menu: hide value text + chevron, keep icon clickable.
   The <select> becomes an invisible overlay on the icon so taps on the
   icon still open the native options list. ---- */
.menu-wrap::after { display: none !important; }
.menu-wrap {
  width: auto;
  min-width: 44px;
}
@media (min-width: 768px) { .menu-wrap { min-width: 48px; } }
@media (min-width: 1024px) { .menu-wrap { min-width: 52px; } }
.menu-wrap .cap-select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  padding: 0 !important;
  margin: 0 !important;
  cursor: pointer;
  z-index: 2;
}


/* =====================================================================
   v=186 — custom popover shared across MODE / VIEW / menu (replaces
   native <select>). Panel + option visuals mirror the team picker.
   ===================================================================== */

.cap-dd-panel {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  /* no min-width — panel sizes to its positioning context */
  background: var(--white);
  border: 2px solid var(--black);
  box-shadow: 3px 3px 0 var(--shadow-drop-deep);
  z-index: 60;
}
.cap-dd-panel.is-open { display: block; }

.cap-dd-option {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem;
  color: var(--black);
  background: var(--white);
  /* v=261: 12px -> 6px horizontal so the inline desc fits 1 line. */
  padding: 10px 6px;
  cursor: pointer;
  line-height: 1.2;
  letter-spacing: 0.02em;
  outline: none;
}
@media (min-width: 768px) {
  .cap-dd-option { font-size: 0.65rem; padding: 11px 14px; }
}
@media (min-width: 1024px) {
  .cap-dd-option { font-size: 0.7rem; padding: 12px 16px; }
}
.cap-dd-option:hover,
.cap-dd-option:focus,
.cap-dd-option.is-focused {
  background: var(--ice-light-cyan);
}
.cap-dd-option[aria-selected="true"] {
  background: var(--ice-cyan);
}

/* v=238: inline two-line option layout. Big label + small grey
   description. Description is mobile-only -- on >=768px the right-
   side hover tooltip carries the explainer instead. */
.cap-dd-option-label {
  display: block;
}
.cap-dd-option-desc {
  display: block;
  margin-top: 5px;
  font-size: 0.4rem;
  color: #5a5a5a;
  letter-spacing: 0.02em;
  /* v=261: pushed to -0.55em paired with the v=261 padding shrink. */
  word-spacing: -0.55em;
  line-height: 1.25;
}
@media (min-width: 768px) {
  .cap-dd-option-desc { display: none; }
}

/* MODE + VIEW: the trigger button sits inside .cap-dd-body next to the
   cap-label — same pattern the team picker uses. Visual chrome mirrors
   the previous .cap-select (transparent, chevron via wrap ::after). */
.cap-dd-body {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: stretch;
}
.cap-dd-trigger {
  flex: 1 1 0;
  min-width: 0;
  background: transparent;
  border: none;
  cursor: pointer;
  font-family: 'Press Start 2P', monospace;
  color: var(--black);
  font-size: inherit;
  /* v=188: match .cap-label vertical padding + flex-center so the
     value sits on the same baseline as the MODE:/VIEW: label. */
  padding: 10px 24px 13px 6px;
  text-align: left;
  line-height: 1.2;
  letter-spacing: 0;
  word-spacing: -0.6em;
  display: inline-flex;
  align-items: center;
}
@media (min-width: 768px) {
  .cap-dd-trigger { padding: 12px 26px 15px 8px; }
}
@media (min-width: 1024px) {
  .cap-dd-trigger { padding: 13px 28px 16px 10px; }
}
.cap-dd-trigger:focus { outline: 2px solid var(--black); outline-offset: -2px; }
.cap-dd-trigger:focus:not(:focus-visible) { outline: none; }

/* Menu trigger: the hamburger icon button inherits the icon bg + click. */
.menu-dd-trigger {
  background-color: #84E9F4;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 13'><rect x='1' y='2' width='18' height='2' fill='%23fff'/><rect x='1' y='6' width='18' height='2' fill='%23fff'/><rect x='1' y='10' width='18' height='2' fill='%23fff'/><rect x='0' y='1' width='18' height='2' fill='%23000'/><rect x='0' y='5' width='18' height='2' fill='%23000'/><rect x='0' y='9' width='18' height='2' fill='%23000'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 20px 13px;
  padding: 10px 12px 13px;
  min-width: 44px;
  border: none;
  cursor: pointer;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.55),
    inset 0 -5px 0 rgba(0, 70, 90, 0.35);
}
@media (min-width: 768px) {
  .menu-dd-trigger {
    padding: 12px 14px 15px;
    min-width: 48px;
    background-size: 22px 14px;
  }
}
@media (min-width: 1024px) {
  .menu-dd-trigger {
    padding: 13px 16px 16px;
    min-width: 52px;
    background-size: 24px 16px;
  }
}
.menu-dd-trigger:focus { outline: 2px solid var(--black); outline-offset: -2px; }
.menu-dd-trigger:focus:not(:focus-visible) { outline: none; }
.menu-dd-trigger[aria-expanded="true"] {
  transform: translate(3px, 3px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.55),
    inset 0 -5px 0 rgba(0, 70, 90, 0.35);
}

/* Menu panel anchors to the wrap's right edge so the popover lines up
   with the hamburger (which sits flush right on the header). */
.menu-wrap {
  position: relative;
}
.menu-wrap .cap-dd-panel {
  left: auto;
  right: 0;
  min-width: 180px;
}


/* =====================================================================
   v=189 — dynamic status footer. Replaces the prior .tv-ko-footer.
   Three variants (is-ko / is-won / is-owns) for KO, draw-win, and
   own-pick-locked states.
   ===================================================================== */
.tv-status-footer {
  /* v=190: footer sits inside .tv-header now (mobile: stacks below team
     selector via the header's column flex; 768+: right of selector via
     the header's row flex). No top margin. */
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 10px 12px;
  /* v=196: 3px border + 3px shadow to match team picker + stats row. */
  border: 3px solid var(--black);
  box-shadow: 3px 3px 0 var(--shadow-drop);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.55rem;
  letter-spacing: 0.02em;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
  width: 100%;
}
@media (min-width: 768px) {
  .tv-status-footer {
    font-size: 0.6rem;
    padding: 11px 14px;
    width: auto;
    min-width: 220px;
    flex-shrink: 0;
    /* v=191: left-align on tablet/desktop. */
    justify-content: flex-start;
    text-align: left;
  }
}
@media (min-width: 1024px) {
  .tv-status-footer { font-size: 0.65rem; padding: 12px 16px; min-width: 260px; }
}
.tv-status-footer.is-hidden { display: none; }

/* Variants */
.tv-status-footer.is-ko {
  /* v=191: black text, white pixel shadow (no red box). */
  background: var(--ice-light-cyan);
  color: var(--black);
  text-shadow: 1px 1px 0 var(--white);
}
/* v=190: champagne/gold — matches .card-wrap.winner .face. */
.tv-status-footer.is-won-gold {
  background: #FFF2B8;
  border-color: #F0C850;
  color: var(--black);
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.55);
}
/* v=190: silver — matches .card-wrap.runner-up .face. */
.tv-status-footer.is-won-silver {
  background: #E6EAF0;
  border-color: #BFC4CE;
  color: var(--black);
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.55);
}
.tv-status-footer.is-owns {
  background: var(--ice-cyan);
  color: var(--black);
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.55);
}


/* =====================================================================
   v=194 — PS2P top-clip fix on team picker. Mirrors the v=184 fix that
   resolved the same issue on the MODE/VIEW selects.
   ===================================================================== */
.team-dd-wrap .tv-dd-trigger,
.team-dd-wrap .tv-dd-label,
.team-dd-wrap .tv-dd-label-full,
.team-dd-wrap .tv-dd-label-abbrev,
.tv-dd-option,
.tv-dd-option-label,
.tv-dd-option-full,
.tv-dd-option-abbrev,
.tv-dd-option-pct {
  line-height: 1.2;
}


/* =====================================================================
   v=195 — z-index, layout, and width fixes
   ===================================================================== */

/* 1: Lift header-container above sticky-shell-inner so the hamburger
   menu's popover paints over PUSH TO DRAW + ATTEMPTS. Old value
   z-index: 0 left the container at the same level as auto-stacked
   siblings, with sticky-shell-inner winning by DOM order. */
.header-container {
  z-index: 50 !important;
}

/* 2: Trim hamburger panel min-width so options sit flush against
   their text (no trailing whitespace after LOTTERY / PROSPECTS / ANALYTICS). */
.menu-wrap .cap-dd-panel {
  min-width: 140px !important;
}

/* 3: TEAM header — stretch flex children on 768+ so the status footer
   ends up the same vertical box as the team picker. Mobile keeps the
   stacked column flow. */
@media (min-width: 768px) {
  .tv-header {
    align-items: stretch;
  }
  .tv-status-footer {
    /* Wider so KNOCKED OUT OF DRAW 1 / OWNS #X OVR / WON DRAW N have
       breathing room next to the (440px) team picker. */
    min-width: 320px;
    /* Match the team picker's vertical anchoring inside the stretched row. */
    align-self: stretch;
    box-sizing: border-box;
  }
}
@media (min-width: 1024px) {
  .tv-status-footer { min-width: 360px; }
}

/* 4: Team picker popover — bump z-index so options stay clickable
   regardless of what bands are rendered below. */
.tv-dd-panel {
  z-index: 100;
}


/* =====================================================================
   v=196 — status footer polish: center text everywhere, gold/silver
   text shadows + blinking on draw winners.
   ===================================================================== */

/* Center text at every breakpoint (undo v=191 left-align on 768+). */
@media (min-width: 768px) {
  .tv-status-footer {
    justify-content: center !important;
    text-align: center !important;
  }
}

/* v=196: gold/silver text shadows on draw winners — match
   .card-wrap.winner / .card-wrap.runner-up treatment. */
.tv-status-footer.is-won-gold {
  text-shadow: 1.5px 1.5px 0 #F0C850;
  border-color: #F0C850;
}
.tv-status-footer.is-won-silver {
  text-shadow: 1.5px 1.5px 0 #BFC4CE;
  border-color: #BFC4CE;
}

/* Status-footer flavored variants of the card blink keyframes — same
   color cadence but only animate border-color + box-shadow so the bg
   stays steady. Reuses the existing card-blink-* keyframes from the
   card section above. */
.tv-status-footer.is-won-gold {
  animation: card-blink-winner 0.7s step-end infinite;
}
.tv-status-footer.is-won-silver {
  animation: card-blink-runner-up 0.7s step-end infinite;
}


/* =====================================================================
   v=197 — panel scroll, footer width, tablet MATCH downsize, menu
   tightening, chart body padding parity.
   ===================================================================== */

/* 1: team picker panel — show all 16 teams without internal scroll on
   any reasonable screen height. min() fall back to 760px on giant
   displays. Keep overflow-y so very short viewports still scroll. */
.tv-dd-panel {
  max-height: min(80vh, 760px) !important;
}

/* 2: status footer width re-tune. Tablet 220px (fit alongside 440px
   team picker inside the tv-card content area), desktop 380px wider. */
@media (min-width: 768px) {
  .tv-status-footer {
    min-width: 220px !important;
    max-width: 100%;
  }
}
@media (min-width: 1024px) {
  .tv-status-footer { min-width: 380px !important; }
}

/* 3: tablet "MATCH" label was getting clipped because pair column is
   narrow (~95px) and 0.65rem PS2P with overflow:hidden cropped the
   "M". Drop down a step. */
@media (min-width: 768px) {
  .tv-pair-match-label { font-size: 0.55rem !important; }
}
@media (min-width: 1024px) {
  .tv-pair-match-label { font-size: 0.65rem !important; }
}

/* 4: menu panel — tighter min-width so options sit close to text. */
.menu-wrap .cap-dd-panel {
  min-width: 110px !important;
}

/* 5: chart body padding matches IN-PLAY body (10px 12px) so the three
   bands feel uniform. */
.tv-chart-body {
  padding: 10px 12px !important;
}


/* =====================================================================
   v=198 — z-index hammer + cursor: pointer on team-dd trigger so click
   targets stay reliable on Safari/iOS where stacking can surprise.
   ===================================================================== */
.tv-dd { position: relative; z-index: 200; }
.tv-dd-body { position: relative; z-index: 200; }
.tv-dd-panel { z-index: 1000 !important; }
.tv-dd-trigger {
  cursor: pointer !important;
  pointer-events: auto !important;
  position: relative;
  z-index: 1;
}
.tv-dd-option {
  cursor: pointer !important;
  pointer-events: auto !important;
}


/* =====================================================================
   v=199 — band-header parity. Chart label matches OUT/IN-PLAY size.
   Meta text bumped + word-spaced for readability.
   ===================================================================== */

/* Chart label catches up to the v=133 OUT/IN-PLAY scaling. */
.tv-chart-band {
  font-size: 0.6rem !important;
  padding: 10px 14px 13px !important;
}
@media (min-width: 768px) {
  .tv-chart-band {
    font-size: 0.7rem !important;
    padding: 12px 18px 15px !important;
  }
}
@media (min-width: 1024px) {
  .tv-chart-band {
    font-size: 0.75rem !important;
    padding: 13px 20px 16px !important;
  }
}

/* Meta text on the right of every band: bump font + open word spacing. */
.tv-inplay-meta,
.tv-out-meta,
.tv-chart-meta {
  font-size: 0.55rem !important;
  word-spacing: 0.15em !important;
  letter-spacing: 0.04em;
}
@media (min-width: 768px) {
  .tv-inplay-meta,
  .tv-out-meta,
  .tv-chart-meta {
    font-size: 0.6rem !important;
  }
}
@media (min-width: 1024px) {
  .tv-inplay-meta,
  .tv-out-meta,
  .tv-chart-meta {
    font-size: 0.65rem !important;
  }
}

/* Labels — open word spacing for "% ODDS BY PICK" etc. */
.tv-out-label,
.tv-inplay-label,
.tv-chart-band-label {
  word-spacing: 0.12em;
}


/* =====================================================================
   v=200 — meta line-height + chart label tighten
   ===================================================================== */

/* PS2P glyphs clip at top with line-height: 1. v=199 bumped meta font
   size and exposed the same issue. Same fix as v=184 — line-height 1.2
   gives the glyph half-leading on top + bottom. */
.tv-inplay-meta,
.tv-out-meta,
.tv-chart-meta {
  line-height: 1.2 !important;
}

/* v=200: tight word-spacing on the chart band label specifically — overrides
   v=199's 0.12em. OUT and IN-PLAY labels keep their breathing room. */
.tv-chart-band-label {
  word-spacing: -0.2em !important;
}


/* =====================================================================
   v=201 — tighten word-spacing on EXPECTED PICK only.
   ===================================================================== */
.tv-chart-meta {
  word-spacing: -0.3em !important;
}


/* =====================================================================
   v=202 — band caret alignment + uniform section spacing.
   ===================================================================== */

/* 1: chart band's right padding now matches OUT/IN-PLAY so the caret
   sits at the same X. v=133 set OUT/IN-PLAY to 8/10/10 right padding;
   force chart to the same. */
.tv-chart-band { padding-right: 8px !important; }
@media (min-width: 768px) {
  .tv-chart-band { padding-right: 10px !important; }
}
@media (min-width: 1024px) {
  .tv-chart-band { padding-right: 10px !important; }
}

/* 2: section gaps unified.
     band -> body  : 10px (every section)
     body -> next  : 14px (every section)
   Removes the legacy -10px on .tv-out-body that gave OUT a tighter
   band-to-body gap than the others. */
.tv-out-body {
  margin-top: 0 !important;
}
.tv-inplay-band,
.tv-out-band,
.tv-chart-band {
  margin-bottom: 10px !important;
}
.tv-inplay-body,
.tv-out-body,
.tv-chart-body {
  margin-bottom: 14px !important;
}

/* 3: the tv-card's last child shouldn't carry its own bottom margin —
   the card's padding-bottom already defines that gap. Without this,
   the chart body's 14px margin-bottom stacks with the card's
   padding-bottom and the gap below ODDS BY PICK ends up wider than
   the gap above the team dropdown. */
.lottery-card.full-card.tv-card > :last-child {
  margin-bottom: 0 !important;
}


/* =====================================================================
   v=203 — chart band padding-left matches OUT/IN-PLAY so labels align.
   ===================================================================== */
.tv-chart-band { padding-left: 10px !important; }
@media (min-width: 768px) {
  .tv-chart-band { padding-left: 12px !important; }
}
@media (min-width: 1024px) {
  .tv-chart-band { padding-left: 14px !important; }
}


/* =====================================================================
   v=204 — view-toggle-row z-index above tv-dd's 200 so the VIEW panel
   doesn't get covered by the team selector when opened.
   ===================================================================== */
.view-toggle-row {
  z-index: 300 !important;
}


/* =====================================================================
   v=205 — LEAGUE card cleanup
   ===================================================================== */

/* FRONT: secondary logo smaller + greyer + slightly more transparent. */
.face.front .trade-secondary {
  width: 22px !important;
  height: 18px !important;
  opacity: 0.4 !important;
}
@media (min-width: 768px) {
  .face.front .trade-secondary {
    width: 26px !important;
    height: 22px !important;
  }
}
.face.front .trade-secondary img {
  filter: url(#retro-posterize)
          saturate(1.6) contrast(1.2) brightness(1.03)
          drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.7))
          grayscale(0.9) !important;
}

/* BACK (QUICK): default cards — slide stats down so they breathe. */
.face.back .stats {
  margin-top: 14px;
}
@media (min-width: 768px) {
  .face.back .stats { margin-top: 18px; }
}

/* v=255: removed BACK QUICK trade-card overrides; trade-pair lives in the strip now. */

/* BACK (FULL): bump number-ball size on every breakpoint. */
.mc-ball {
  width: 20px !important;
  height: 20px !important;
  font-size: 0.42rem !important;
  border-width: 1.5px !important;
}
@media (min-width: 768px) {
  .mc-ball {
    width: 28px !important;
    height: 28px !important;
    font-size: 0.55rem !important;
    border-width: 2px !important;
  }
  .mc-ball-row { gap: 5px; }
}
@media (min-width: 1024px) {
  .mc-ball {
    width: 32px !important;
    height: 32px !important;
    font-size: 0.6rem !important;
  }
  .mc-ball-row { gap: 6px; }
}


/* =====================================================================
   v=206 — push trade footnote tighter to the card bottom edge.
   ===================================================================== */
.face.back:has(.trade-footnote) .trade-footnote {
  bottom: 1px !important;
  line-height: 1 !important;
}
@media (min-width: 768px) {
  .face.back:has(.trade-footnote) .trade-footnote {
    bottom: 2px !important;
  }
}

/* Reduce face padding-bottom on trade cards so there's no dead band
   below the footnote text. */
.face.back:has(.trade-footnote) {
  padding-bottom: 6px !important;
}
@media (min-width: 768px) {
  .face.back:has(.trade-footnote) {
    padding-bottom: 8px !important;
  }
}


/* =====================================================================
   v=207 — unified back-face stats layout (regular + trade cards).
   Stats vertically centered. Trade-pair / trade-footnote are absolute
   overlays that don't shift the stats position.
   ===================================================================== */

/* Center stats inside the back face. .face is display: flex column so
   justify-content: center works on the only flex child (.stats); the
   absolute children (abbrev-tag, trade-pair, trade-footnote) ignore. */
.face.back {
  justify-content: center !important;
}

/* Stats: natural height so centering takes effect (was flex: 1 +
   margin-top: 14/18 from v=205, which made the grid expand to fill). */
.face.back .stats {
  flex: 0 1 auto !important;
  margin-top: 0 !important;
  margin-bottom: 0 !important;
}

/* Trade cards: drop the v=205 abbrev-tag top shift — same placement
   as regular cards now. */
.face.back:has(.trade-footnote) .abbrev-tag {
  top: 6px !important;
}
@media (min-width: 768px) {
  .face.back:has(.trade-footnote) .abbrev-tag {
    top: 8px !important;
  }
}

/* Trade-footnote stays glued near the card's bottom edge. */
.face.back:has(.trade-footnote) .trade-footnote {
  bottom: 1px !important;
  line-height: 1 !important;
}
@media (min-width: 768px) {
  .face.back:has(.trade-footnote) .trade-footnote {
    bottom: 2px !important;
  }
}
.face.back:has(.trade-footnote) {
  padding-bottom: 6px !important;
}
@media (min-width: 768px) {
  .face.back:has(.trade-footnote) {
    padding-bottom: 8px !important;
  }
}


/* =====================================================================
   v=208 — unwind v=207. Stats grid FILLS the card again with rows
   evenly distributed. Padding-bottom unified across regular + trade
   cards so the stats rows end at the same Y on both.
   ===================================================================== */

/* Stats: back to fill behavior. flex: 1 makes the grid container
   expand to fill remaining vertical space; grid-auto-rows: 1fr keeps
   each row equal height. */
.face.back .stats {
  flex: 1 !important;
  margin-top: 0 !important;
  margin-bottom: 0 !important;
}

/* Drop the v=207 face.back centering — flex children now grow with
   flex: 1 instead of being centered with natural height. */
.face.back {
  justify-content: flex-start !important;
}

/* Unified bottom padding so stats row Y's match between regular and
   trade cards. 14px gives the trade-footnote room to sit at bottom: 2
   without colliding with the last stats row. */
.face.back {
  padding-bottom: 14px !important;
}
.face.back:has(.trade-footnote) {
  padding-bottom: 14px !important;
}
@media (min-width: 768px) {
  .face.back,
  .face.back:has(.trade-footnote) {
    padding-bottom: 16px !important;
  }
}

/* Trade-footnote stays close to the bottom edge inside that 14/16px band. */
.face.back:has(.trade-footnote) .trade-footnote {
  bottom: 2px !important;
  line-height: 1 !important;
}
@media (min-width: 768px) {
  .face.back:has(.trade-footnote) .trade-footnote {
    bottom: 3px !important;
  }
}


/* =====================================================================
   v=209 — shift MODE/VIEW chevron right so it sits flush to the
   keycap edge, creating a visible gap from the value text.
   ===================================================================== */
.mode-wrap::after,
.view-wrap::after {
  right: 4px !important;
}
@media (min-width: 768px) {
  .mode-wrap::after,
  .view-wrap::after { right: 6px !important; }
}
@media (min-width: 1024px) {
  .mode-wrap::after,
  .view-wrap::after { right: 8px !important; }
}


/* =====================================================================
   v=210 — .board-header line-height bump (PS2P glyph-top clip).
   Tight line-height: 1.1 was clipping LOTTERY ORDER & ODDS at tablet.
   Pad to 1.3 so the half-leading clears the ascender row on every
   breakpoint without changing the visible vertical center.
   ===================================================================== */
.board-header {
  line-height: 1.3 !important;
}


/* =====================================================================
   v=211 — shrink FULL-card .mc-ball sizes from v=205's overshoot.
   ===================================================================== */
.mc-ball {
  width: 18px !important;
  height: 18px !important;
  font-size: 0.4rem !important;
  border-width: 1.5px !important;
}
@media (min-width: 768px) {
  .mc-ball {
    width: 22px !important;
    height: 22px !important;
    font-size: 0.5rem !important;
    border-width: 2px !important;
  }
  .mc-ball-row { gap: 4px; }
}
@media (min-width: 1024px) {
  .mc-ball {
    width: 24px !important;
    height: 24px !important;
    font-size: 0.55rem !important;
  }
  .mc-ball-row { gap: 5px; }
}


/* =====================================================================
   v=212 — desktop .mc-ball trimmed 24 -> 22.
   ===================================================================== */
@media (min-width: 1024px) {
  .mc-ball {
    width: 22px !important;
    height: 22px !important;
    font-size: 0.5rem !important;
  }
}


/* =====================================================================
   v=213 — REDRAW indicator. Draw-strip label stacks "DRAW 2" + red
   "REDRAW" sub-bar (NHL '94 logo inspired). Status footer takes a red
   "DRAW 2 REDRAW" variant on the team view.
   ===================================================================== */

/* Stacked label inside .draw-strip-label. The redraw sub-bar is hidden
   until .is-redrawing is added by JS. */
.draw-strip-label {
  display: inline-flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  line-height: 1.1;
}
.draw-strip-label-text {
  display: inline-block;
}
.draw-strip-redraw {
  display: none;
  /* v=228: black fill (was --red) per user feedback. */
  background: var(--black);
  color: var(--white);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.45rem;
  letter-spacing: 3px;
  text-align: center;
  padding: 2px 4px;
  line-height: 1;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.45);
  border: 1.5px solid #000;
}
@media (min-width: 768px) {
  .draw-strip-redraw { font-size: 0.55rem; padding: 3px 6px; }
}
@media (min-width: 1024px) {
  .draw-strip-redraw { font-size: 0.6rem; padding: 4px 8px; }
}
.draw-strip-label.is-redrawing .draw-strip-redraw {
  display: inline-block;
}

/* Status footer redraw variant. v=228: black fill (was red). */
.tv-status-footer.is-redraw {
  background: var(--black) !important;
  color: var(--white) !important;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.6) !important;
  border-color: #000 !important;
  animation: none !important;  /* override any winner blink that might be active */
}


/* =====================================================================
   v=214 — keycap-style trade tooltip (replaces native title attr).
   ===================================================================== */

.pn-tooltip {
  position: absolute;
  top: -9999px;
  left: -9999px;
  background: var(--ice-light-cyan);
  color: var(--black);
  border: 3px solid var(--black);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.55),
    inset 0 -5px 0 rgba(0, 70, 90, 0.35),
    3px 3px 0 var(--shadow-drop-deep);
  padding: 6px 10px;
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  letter-spacing: 0.05em;
  line-height: 1.3;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.1s ease, transform 0.1s ease;
  z-index: 9999;
  text-transform: uppercase;
}
.pn-tooltip.is-on {
  opacity: 1;
  transform: translateY(0);
}
@media (min-width: 768px) {
  .pn-tooltip { font-size: 0.55rem; padding: 7px 11px; }
}
.pn-tooltip-text { display: inline-block; }
/* Triangle tail pointing UP toward the source element. Two stacked
   triangles — outer black for the border, inner cyan to match the
   bg so it reads as a continuous shape. */
.pn-tooltip-tail {
  position: absolute;
  top: -8px;
  left: 50%;
  transform: translateX(-50%);
  width: 14px;
  height: 8px;
  pointer-events: none;
}
.pn-tooltip-tail::before,
.pn-tooltip-tail::after {
  content: '';
  position: absolute;
  left: 0;
  width: 0;
  height: 0;
}
.pn-tooltip-tail::before {
  top: 0;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-bottom: 8px solid var(--black);
}
.pn-tooltip-tail::after {
  top: 3px;
  left: 2px;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 5px solid var(--ice-light-cyan);
}

/* Trade overlays no longer use cursor: help (the ?). Use pointer so
   the user knows they're tappable on touch devices. */
.face.front .trade-secondary,
.face.back .trade-pair {
  cursor: pointer !important;
}

/* v=236: right-side tooltip drops the tail entirely. */
.pn-tooltip.is-right .pn-tooltip-tail {
  display: none;
}
/* v=236: right-side tooltip is single-line, left-aligned, with
   tight word-spacing. Height is matched to the source dropdown
   item via JS (style.height); flex-center vertically aligns the
   inner text in that height. Padding-y goes to 0 so the forced
   height is honoured exactly; padding-x preserved for breathing
   room. Tail is hidden (rule above). */
.pn-tooltip.is-right {
  transform: translateX(-4px);
  white-space: nowrap;
  text-align: left;
  word-spacing: -0.15em;
  letter-spacing: 0.02em;
  display: flex;
  align-items: center;
  padding-top: 0;
  padding-bottom: 0;
  max-width: none;
}
.pn-tooltip.is-right .pn-tooltip-text {
  display: inline-block;
  text-align: left;
}
@media (min-width: 768px) {
  .pn-tooltip.is-right { max-width: none !important; }
}
.pn-tooltip.is-right.is-on {
  transform: translateX(0);
}


/* =====================================================================
   v=215 — page label in the header banner, right of PUCKSON.NET on
   every device. Variant 1: darker-cyan fill + black outline.
   ===================================================================== */
.page-label {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  letter-spacing: 1px;
  line-height: 1;
  color: #84E9F4;
  text-shadow:
    -1.5px 0 0 #000,  1.5px 0 0 #000,  0 -1.5px 0 #000,  0 1.5px 0 #000,
    -1.5px -1.5px 0 #000, 1.5px 1.5px 0 #000, -1.5px 1.5px 0 #000, 1.5px -1.5px 0 #000;
  paint-order: stroke fill;
  white-space: nowrap;
  flex-shrink: 1;
  min-width: 0;
}
@media (min-width: 768px) {
  .page-label {
    font-size: 0.85rem;
    letter-spacing: 1.5px;
    text-shadow:
      -2px 0 0 #000,  2px 0 0 #000,  0 -2px 0 #000,  0 2px 0 #000,
      -2px -2px 0 #000, 2px 2px 0 #000, -2px 2px 0 #000, 2px -2px 0 #000;
  }
}
@media (min-width: 1024px) {
  .page-label {
    font-size: 1.05rem;
    letter-spacing: 2px;
  }
}

/* Header container: PUCKSON.NET (left) | page-label (center) | hamburger (right). */
.header-container {
  gap: 12px;
}
@media (min-width: 768px) {
  .header-container { gap: 18px; }
}


/* =====================================================================
   v=216 — page label outline via text-stroke (Variant F).
   Closest match to the reference DRAFT LOTTERY treatment. Replaces
   v=215's 8-direction text-shadow approach.
   ===================================================================== */
.page-label {
  -webkit-text-stroke: 2px #000;
  text-stroke: 2px #000;
  paint-order: stroke fill;
  text-shadow: none !important;
}
@media (min-width: 768px) {
  .page-label {
    -webkit-text-stroke-width: 3px;
    text-stroke-width: 3px;
  }
}
@media (min-width: 1024px) {
  .page-label {
    -webkit-text-stroke-width: 4px;
    text-stroke-width: 4px;
  }
}


/* =====================================================================
   v=217 — page label recipe matches the reference HTML:
   stroke (outline) + bottom-right drop shadow.
   Our color is #84E9F4 (band cyan).
   ===================================================================== */
.page-label {
  -webkit-text-stroke: 2px #000;
  text-stroke: 2px #000;
  paint-order: stroke fill;
  text-shadow: 2px 2px 0 #000 !important;  /* override v=216's `none` */
}
@media (min-width: 768px) {
  .page-label {
    -webkit-text-stroke-width: 3px;
    text-stroke-width: 3px;
    text-shadow: 3px 3px 0 #000 !important;
  }
}
@media (min-width: 1024px) {
  .page-label {
    -webkit-text-stroke-width: 4px;
    text-stroke-width: 4px;
    text-shadow: 4px 4px 0 #000 !important;
  }
}


/* =====================================================================
   v=219 — tooltip polish: white bg, dark-grey bottom strip, max-width
   capped to card-ish, tight word-spacing, two-line support via pre-line.
   ===================================================================== */
.pn-tooltip {
  background: var(--white) !important;
  /* Bottom strip dark grey instead of dark cyan, top stays white. */
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.85),
    inset 0 -6px 0 rgba(60, 60, 60, 0.4),
    3px 3px 0 var(--shadow-drop-deep) !important;
  white-space: pre-line !important;  /* allow \n line breaks */
  text-align: center !important;
  word-spacing: -0.2em !important;
  max-width: 180px !important;
  padding: 6px 10px 9px !important;  /* extra bottom for the dark strip */
}
@media (min-width: 768px) {
  .pn-tooltip { max-width: 240px !important; padding: 7px 11px 10px !important; }
}
@media (min-width: 1024px) {
  .pn-tooltip { max-width: 260px !important; }
}

/* Tail inner color follows new white bg. */
.pn-tooltip-tail::after {
  border-bottom-color: var(--white) !important;
}


/* =====================================================================
   v=221 — locked-first banner (cyan); D1 winner banner stays gold via
   the .card-wrap.winner ancestor.
   ===================================================================== */
.card-wrap.winner .owns-pick-banner {
  background: var(--ball-gold);
  color: #1a1a1a;
}
/* v=222 cache-bump no-op */


/* =====================================================================
   v=227 — LIVE SIM mode. Active slot blinks with an arcade cursor;
   number-picker popover appears on tap.
   ===================================================================== */

/* v=232: the WHOLE ball turns gold and blinks. No inner box, no
   underscore, no halo. Filled slots use the existing .drawn paint;
   only empty/active slots get this rule. */
@keyframes pn-live-ball-blink {
  0%, 49%   { opacity: 1; }
  50%, 100% { opacity: 0.25; }
}

.draw-ball-slot.is-live-active {
  cursor: pointer;
  border-color: var(--black);
  /* Solid gold ball gradient, identical to .draw-ball.drawn. */
  background: radial-gradient(
    circle at 32% 28%,
    #FFF5C8,
    var(--ball-gold) 60%,
    var(--ball-gold-deep) 100%
  );
  /* v=233: 0.6s -> 1.1s, easier blink cadence. */
  animation: pn-live-ball-blink 1.1s step-end infinite;
}
/* v=268: NHL shield stays visible on the active slot (was hidden
   in v=232). Shield + blinking gold ball read together. */

/* Number picker popover. */
.live-num-picker {
  position: absolute;
  background: var(--white);
  border: 3px solid var(--black);
  box-shadow: 4px 4px 0 var(--shadow-drop-deep);
  padding: 10px;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  z-index: 2000;
}
.live-num-btn {
  width: 34px;
  height: 34px;
  border: 2px solid var(--black);
  background: var(--ice-light-cyan);
  color: var(--black);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.6rem;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  box-shadow: 2px 2px 0 var(--shadow-drop);
}
.live-num-btn:hover:not(:disabled) {
  background: var(--ice-cyan);
}
.live-num-btn:active:not(:disabled) {
  transform: translate(2px, 2px);
  box-shadow: none;
}
.live-num-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}
@media (min-width: 768px) {
  .live-num-picker { padding: 12px; gap: 6px; }
  .live-num-btn { width: 40px; height: 40px; font-size: 0.7rem; }
}

/* =====================================================================
   v=242 — band-header chrome refresh.
   IN-PLAY / OUT / ODDS BY PICK band headers repaint to the same
   darker cyan (#84E9F4) as the TEAM: cap-label so they read as one
   keycap-style family. Bodies move from white to --ice-light-cyan.
   ===================================================================== */
.tv-inplay-band.cap-btn,
.tv-out-band.cap-btn,
.tv-chart-band.cap-btn {
  background: #84E9F4;
  color: var(--black);
  text-shadow: 1.5px 1.5px 0 var(--white);
}
.tv-inplay-body,
.tv-out-body,
.tv-chart-body {
  background: var(--ice-light-cyan);
}

/* =====================================================================
   v=252 — option 04 card chrome: WHITE faces + dark-cyan top strip.
   The strip carries the rank (left), abbrev (back-face center) and
   odds (right). Tag elements lose their black pill chrome and become
   plain text on the cyan band. Winner/runner-up cards swap the strip
   to gold / silver while keeping the same text treatment.
   ===================================================================== */

/* 1) White card faces. */
.face,
.face.back {
  background: var(--white) !important;
}

/* 2) Top strip via ::before on every face. Sits inside the card's
      black border; its own bottom 3px black band separates strip
      from content. Keycap insets give it a soft 3D pop. */
.face::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 22px;
  background: #84E9F4;
  border-bottom: 3px solid var(--black);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.55),
    inset 0 -3px 0 rgba(0, 70, 90, 0.25);
  z-index: 0;
  pointer-events: none;
}
@media (min-width: 768px) {
  .face::before { height: 26px; }
}
@media (min-width: 1024px) {
  .face::before { height: 28px; }
}

/* 3) Tag chrome -> plain text on the strip. Wins specificity against
      the v=62 black-pill rules earlier in the file. */
.seed-badge,
.odds-tag,
.abbrev-tag {
  background: transparent !important;
  border: none !important;
  color: var(--black) !important;
  text-shadow: 1.5px 1.5px 0 var(--white) !important;
  z-index: 1;
}

/* 4) Trade overlay (front center) sits on the strip too. Existing
      top: 6px is fine since it's within the 28px strip area. */
.face.front .trade-secondary,
.face.back .trade-pair {
  z-index: 1;
}

/* 5) Winner / runner-up: swap strip paint to medal colours. Text
      stays black + white-shadow (same legibility on every variant). */
.card-wrap.winner .face::before {
  background: radial-gradient(
    circle at 32% 28%,
    #FFF5C8,
    var(--ball-gold) 60%,
    var(--ball-gold-deep) 100%
  );
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.55),
    inset 0 -3px 0 rgba(120, 80, 0, 0.35);
}
.card-wrap.runner-up .face::before {
  background: linear-gradient(to bottom, #F0F3F7, #C9CFD6);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.7),
    inset 0 -3px 0 rgba(60, 60, 70, 0.25);
}
.card-wrap.winner .seed-badge,
.card-wrap.winner .odds-tag,
.card-wrap.winner .abbrev-tag,
.card-wrap.runner-up .seed-badge,
.card-wrap.runner-up .odds-tag,
.card-wrap.runner-up .abbrev-tag {
  color: var(--black) !important;
  text-shadow: 1.5px 1.5px 0 var(--white) !important;
}

/* v=253 — strip shrunk + tags forced to fill strip vertically.
   Existing 'display: inline-flex; align-items: center' on each tag
   centers the text inside its bounding box. */
.seed-badge,
.odds-tag,
.abbrev-tag {
  top: 0 !important;
  height: 22px !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}
@media (min-width: 768px) {
  .seed-badge,
  .odds-tag,
  .abbrev-tag {
    height: 26px !important;
  }
}
@media (min-width: 1024px) {
  .seed-badge,
  .odds-tag,
  .abbrev-tag {
    height: 28px !important;
  }
}

/* trade-secondary (front) and trade-pair (back) ride on the strip too. */
.face.front .trade-secondary,
.face.back .trade-pair {
  top: 0 !important;
  height: 22px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}
@media (min-width: 768px) {
  .face.front .trade-secondary,
  .face.back .trade-pair { height: 26px !important; }
}
@media (min-width: 1024px) {
  .face.front .trade-secondary,
  .face.back .trade-pair { height: 28px !important; }
}

/* v=254 — back-of-card abbrev rendered as a team logo. The wrapping
   .abbrev-tag still positions on the strip; we just swap the text for
   a small image sized to fit comfortably inside the 22/26/28px strip. */
.abbrev-logo {
  width: 18px;
  height: 18px;
  object-fit: contain;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  filter: url(#retro-posterize)
          saturate(1.6) contrast(1.2) brightness(1.03)
          drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.7));
  pointer-events: none;
  user-select: none;
}
@media (min-width: 768px) {
  .abbrev-logo { width: 22px; height: 22px; }
}
@media (min-width: 1024px) {
  .abbrev-logo { width: 24px; height: 24px; }
}
/* Drop the text-shadow that the .abbrev-tag wrapper applies (it was
   meant for text); the image doesn't need it. */
.abbrev-tag:has(> .abbrev-logo) {
  text-shadow: none !important;
  letter-spacing: 0 !important;
}

/* v=258/v=266 — OUT cards: grey strip. v=266 adds :not(.winner) so
   the D1 winner (which carries both .winner AND .is-dead during
   DRAW 2) keeps its gold strip from v=252. */
.card-wrap.is-dead:not(.winner) .face::before {
  background: #C8CED3;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.55),
    inset 0 -3px 0 rgba(0, 0, 0, 0.18);
}

/* =====================================================================
   v=265 — OWNS banner: text matches strip, color depends on win state.
   Actual D1 winner (.card-wrap.winner) keeps the gold strip from v=252.
   Locked-first team (carries OWNS but not .winner) gets the light-grey
   strip like OUT cards. Banner itself stays transparent + flush.
   ===================================================================== */
.card-wrap:has(.owns-pick-banner):not(.winner) .face::before {
  background: #C8CED3;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.55),
    inset 0 -3px 0 rgba(0, 0, 0, 0.18);
}
.owns-pick-banner {
  background: transparent !important;
  top: 0 !important;
  height: 22px !important;
  line-height: 22px !important;
  z-index: 1;
  color: var(--black) !important;
  /* v=265: text matches the % on the strip (size + white pixel shadow). */
  font-size: 0.5rem !important;
  text-shadow: 1.5px 1.5px 0 var(--white) !important;
}
@media (min-width: 768px) {
  .owns-pick-banner {
    height: 26px !important;
    line-height: 26px !important;
    font-size: 0.6rem !important;
  }
}
@media (min-width: 1024px) {
  .owns-pick-banner {
    height: 28px !important;
    line-height: 28px !important;
    font-size: 0.6rem !important;
  }
}

/* =====================================================================
   v=280 — failed-redraw hold. When applyBall trips a redraw the 4 balls
   stay visible for ~1.5s with this red treatment so the user clearly
   sees which combo failed before the slots clear.
   ===================================================================== */
.draw-ball-slot.is-failed {
  border-color: var(--red);
  box-shadow:
    0 0 0 2px var(--red),
    inset 0 -2px 0 rgba(139, 15, 15, 0.35);
  animation: pn-failed-pulse 0.45s ease-in-out 2;
}
@keyframes pn-failed-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.04); }
}


/* ===== v=288: WINNER REVEAL MODAL =====
   Option 04 from realistic mocks. Cyan-banded header on a real
   .card-wrap.winner card body. Pops after each draw resolves.
   Gold = DRAW 1 (default). Add .is-d2 to .winner-modal-card for
   the DRAW 2 silver palette. */
.winner-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: none;
  /* v=291: anchor the card just below the sticky shell so it
     never tucks under the banner on desktop and never slides
     too low on tall tablet/desktop viewports. JS sets
     --winner-modal-top from the sticky-shell's measured height
     on boot / resize / open. Fallback covers the no-JS path. */
  align-items: flex-start;
  justify-content: center;
  padding: var(--winner-modal-top, 150px) 20px 40px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.winner-modal[aria-hidden="false"] {
  display: flex;
}
.winner-modal[aria-hidden="false"] .winner-modal-backdrop {
  animation: wm-backdrop-in 240ms ease-out;
}
.winner-modal[aria-hidden="false"] .winner-modal-card {
  animation: wm-card-in 320ms cubic-bezier(0.3, 1.4, 0.4, 1);
}
@keyframes wm-backdrop-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes wm-card-in {
  from { opacity: 0; transform: translateY(18px) scale(0.96); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.winner-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  cursor: pointer;
}

.winner-modal-card {
  position: relative;
  width: 290px;
  max-width: calc(100vw - 40px);
  border: 3px solid #F0C850;          /* gold (winner border) */
  background: #FFF2B8;                /* gold-face (winner face) */
  box-shadow: 4px 4px 0 var(--shadow-drop-deep);
  z-index: 1;
}

/* v=292: medal-colored header band -- gold for D1, silver for D2
   (was cyan #84E9F4 in v=288). Matches the card border + ball
   palette so the whole modal reads as a single trophy unit. */
.winner-modal-card .wm-band {
  background: #F0C850;            /* gold (winner border) */
  padding: 18px 12px 16px;
  text-align: center;
  border-bottom: 3px solid var(--black);
}
.winner-modal-card .wm-head {
  font-family: 'Press Start 2P', monospace;
  font-size: 1.35rem;
  /* v=289: black per user pref (was --red). */
  color: var(--black);
  letter-spacing: 3px;
  text-shadow: 3px 3px 0 var(--white);
  margin: 0;
  line-height: 1;
}
.winner-modal-card .wm-sub {
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  color: var(--black);
  letter-spacing: 3px;
  margin: 12px 0 0;
}

/* Body: logo + team identity + winning balls */
.winner-modal-card .wm-body {
  padding: 18px 14px 18px;
  text-align: center;
}
.winner-modal-card .wm-logo {
  /* v=289: bigger + force block centering so SVGs with off-axis
     iconography (e.g. shields) sit dead-center in the card. */
  display: block;
  margin: 0 auto;
  /* v=290: another size bump per user pref. */
  width: 170px;
  height: 170px;
  object-fit: contain;
  image-rendering: pixelated;
  filter:
    url(#retro-posterize)
    saturate(1.6) contrast(1.2) brightness(1.03)
    drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.7));
}
.winner-modal-card .wm-name {
  font-family: 'Press Start 2P', monospace;
  /* v=290: bigger + sits BELOW city now. Bottom gap to balls. */
  font-size: 1.0rem;
  color: var(--black);
  letter-spacing: 1px;
  margin: 4px 0 16px;
  text-shadow: 1.5px 1.5px 0 #F0C850;
  line-height: 1.3;
  word-spacing: -0.25em;
}
.winner-modal-card .wm-city {
  font-family: 'Press Start 2P', monospace;
  /* v=290: bigger + sits ABOVE name now. Top gap from logo. */
  font-size: 0.7rem;
  color: var(--black);
  letter-spacing: 1px;
  margin: 16px 0 0;
  text-shadow: 1.5px 1.5px 0 #F0C850;
}

.winner-modal-card .wm-balls {
  display: flex;
  justify-content: center;
  gap: 8px;
}
.winner-modal-card .wm-ball {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #FFE9A0, #F0C850 60%, #B8893A);
  border: 2px solid var(--black);
  box-shadow: inset -2px -2px 0 rgba(0, 0, 0, 0.25);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--black);
}

/* Silver palette for DRAW 2 winner */
.winner-modal-card.is-d2 {
  border-color: #BFC4CE;
  background: #E6EAF0;
}
/* v=292: silver band on D2. */
.winner-modal-card.is-d2 .wm-band {
  background: #BFC4CE;
}
.winner-modal-card.is-d2 .wm-name,
.winner-modal-card.is-d2 .wm-city {
  text-shadow: 1.5px 1.5px 0 #BFC4CE;
}
.winner-modal-card.is-d2 .wm-ball {
  background: radial-gradient(circle at 35% 30%, #F2F4F8, #BFC4CE 60%, #6E7480);
}

/* Close button: matches site button language (black + white border + drop sink). */
.winner-modal-card .wm-close {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 28px;
  height: 28px;
  background: var(--black);
  color: var(--white);
  border: 2px solid var(--white);
  box-shadow: 2px 2px 0 var(--shadow-drop-deep);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.65rem;
  cursor: pointer;
  z-index: 4;
  padding: 0;
  line-height: 1;
}
.winner-modal-card .wm-close:active {
  transform: translate(2px, 2px);
  box-shadow: 0 0 0 transparent;
}

@media (min-width: 768px) {
  .winner-modal-card { width: 340px; }
  .winner-modal-card .wm-head { font-size: 1.6rem; }
  .winner-modal-card .wm-sub { font-size: 0.6rem; }
  /* v=290: tablet bumps to match base bumps. */
  .winner-modal-card .wm-name { font-size: 1.2rem; }
  .winner-modal-card .wm-city { font-size: 0.85rem; }
  .winner-modal-card .wm-logo { width: 195px; height: 195px; }
  .winner-modal-card .wm-ball { width: 32px; height: 32px; font-size: 0.55rem; }
}

/* Reduced motion: skip the card slide-in. */
@media (prefers-reduced-motion: reduce) {
  .winner-modal[aria-hidden="false"] .winner-modal-backdrop,
  .winner-modal[aria-hidden="false"] .winner-modal-card {
    animation: none;
  }
}


/* ===== v=293: FEEDBACK STRIP =====
   Mirrors .cap-btn / hamburger chrome at a smaller scale:
     - 3px black border
     - cyan #84E9F4 background
     - inner top white highlight + bottom dark inset
     - 3x3 outer drop shadow (the missing piece)
   Hover/active match the .cap-btn translate + shadow-shrink
   pattern. Envelope strokes get a white pixel drop-shadow
   (mimics the hamburger bars' paired-rect highlight). */
.feedback-strip-wrap {
  text-align: center;
  padding: 14px 12px 4px;
}
.feedback-strip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: #84E9F4;
  color: var(--black);
  font-family: 'Press Start 2P', monospace;
  font-size: 0.4rem;
  padding: 6px 10px 9px;
  border: 3px solid var(--black);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.9),
    inset 0 -5px 0 rgba(0, 70, 90, 0.25),
    3px 3px 0 var(--shadow-drop-deep);
  letter-spacing: 2px;
  line-height: 1;
  text-decoration: none;
  text-shadow: 1.5px 1.5px 0 var(--white);
  transition: transform 0.1s, box-shadow 0.1s;
}
@media (hover: hover) {
  .feedback-strip:hover {
    transform: translate(1px, 1px);
    box-shadow:
      inset 0 2px 0 rgba(255, 255, 255, 0.9),
      inset 0 -5px 0 rgba(0, 70, 90, 0.25),
      2px 2px 0 var(--shadow-drop-deep);
  }
}
.feedback-strip:active {
  transform: translate(2px, 2px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.9),
    inset 0 -5px 0 rgba(0, 70, 90, 0.25),
    1px 1px 0 var(--shadow-drop-deep);
}
.feedback-strip:active .env-icon-pixel {
  /* matches hamburger bars losing their shadow on press */
  filter: none;
}
.feedback-strip:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 2px;
}
.env-icon-pixel {
  display: inline-block;
  width: 12px;
  height: 9px;
  vertical-align: -1px;
  image-rendering: pixelated;
  shape-rendering: crispEdges;
  /* white pixel drop-shadow -- mirrors the hamburger bars'
     white-rect-behind-black highlight. */
  filter: drop-shadow(1px 1px 0 var(--white));
}
@media (min-width: 768px) {
  .feedback-strip {
    font-size: 0.5rem;
    padding: 8px 12px 11px;
    letter-spacing: 2.5px;
  }
  .env-icon-pixel { width: 14px; height: 10px; }
  .feedback-strip-wrap { padding: 18px 12px 6px; }
}


/* ===== v=294: PUCKSON.NET wordmark as a real link =====
   Anchor (was span) so keyboard users can tab to it, right-click for
   new tab, etc. Visual stays identical -- inherit color, no underline,
   default cursor was pointer for <a>. Focus ring scoped to keyboard
   nav only via :focus-visible. */
a.nhl-text {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  outline: none;
}
a.nhl-text:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 4px;
}
