/* =====================================================================
   WBL MOBILE LAYER  —  css/mobile.css
   ---------------------------------------------------------------------
   Loaded by index.html, league-office.html, projections.html,
   all-time-teams.html and scouting_history.html, AFTER every other
   stylesheet.

   RULES OF THE ROAD
   -----------------
   1. Everything here lives inside a max-width media query. Nothing in
      this file may apply at desktop widths. If you add a rule outside a
      media query, you have broken the desktop site.
   2. `!important` is used deliberately and often: almost all of the
      site's layout comes from Tailwind utility classes and inline
      `style=""` attributes written by app_slim.js. A stylesheet rule
      marked !important beats an inline style; an unmarked one does not.
   3. Class hooks prefixed `wbl-m-` are applied at runtime by
      js/wbl-mobile.js. Don't rename one without changing the other.

   BREAKPOINTS
     <= 820px   tablets held in portrait and every phone
     <= 640px   phones
     <= 400px   small phones (iPhone SE / mini)
   ===================================================================== */


/* =====================================================================
   1. FOUNDATION  (<= 820px)
   ===================================================================== */
@media (max-width: 820px) {

  /* A single stray wide child used to drag the whole document sideways,
     which on a phone means every page scrolls horizontally and the
     header never lines up. Contain it at the root. */
  html {
    overflow-x: hidden;
    -webkit-text-size-adjust: 100%;
            text-size-adjust: 100%;
  }
  body {
    overflow-x: hidden;
    /* room for the docked control bars added in section 6 */
    padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)) !important;
  }

  /* Flex and grid children default to min-width:auto, which refuses to
     shrink below their content. That is the single most common cause of
     a blown-out row on this site. */
  .wbl-m-on * {
    min-width: 0;
  }

  /* Reclaim the side gutters. body carries Tailwind's p-4 sm:p-8. */
  body.wbl-m-on {
    padding-left: 12px !important;
    padding-right: 12px !important;
  }

  /* Cards and panels: less padding, tighter radius, so content gets the
     width instead of the chrome. */
  .wbl-m-on .rounded-lg,
  .wbl-m-on .rounded-xl,
  .wbl-m-on .rounded-2xl {
    border-radius: 10px;
  }
  .wbl-m-on .p-6  { padding: 0.875rem !important; }
  .wbl-m-on .p-8  { padding: 1rem !important; }
  .wbl-m-on .px-6 { padding-left: 0.875rem !important; padding-right: 0.875rem !important; }
  .wbl-m-on .px-8 { padding-left: 1rem !important; padding-right: 1rem !important; }

  /* Long unbroken strings (player slugs, URLs, team names) must wrap
     rather than push the layout. */
  .wbl-m-on h1, .wbl-m-on h2, .wbl-m-on h3,
  .wbl-m-on h4, .wbl-m-on p, .wbl-m-on li {
    overflow-wrap: break-word;
    word-break: normal;
  }

  /* Images never exceed their box. */
  .wbl-m-on img,
  .wbl-m-on svg,
  .wbl-m-on canvas,
  .wbl-m-on video,
  .wbl-m-on iframe {
    max-width: 100%;
    height: auto;
  }
}


/* =====================================================================
   2. TYPE  —  a legibility floor
   ---------------------------------------------------------------------
   Several tables render at 9-10px, which is unreadable on a phone and
   is what made the ZiPS projections page (844 sub-11px text nodes)
   effectively unusable. CSS cannot express "raise anything below 11px",
   so js/wbl-mobile.js tags the offenders with .wbl-m-type and this rule
   lifts them.
   ===================================================================== */
@media (max-width: 820px) {

  .wbl-m-on .wbl-m-type {
    font-size: 11.5px !important;
    line-height: 1.35 !important;
  }

  /* Page titles set in px or large rem run off the screen. Scale them
     with the viewport instead, with a hard ceiling so they stay sane. */
  .wbl-m-on h1 { font-size: clamp(1.35rem, 6.4vw, 2rem) !important; }
  .wbl-m-on h2 { font-size: clamp(1.15rem, 5.2vw, 1.6rem) !important; }
  /* Only the sizes that actually overflow. text-2xl (24px) reads fine
     on a phone and is left alone — same mobile-first reasoning as the
     grid note in section 5. */
  .wbl-m-on .text-4xl { font-size: clamp(1.5rem, 7vw, 2.25rem) !important; }
  .wbl-m-on .text-3xl { font-size: clamp(1.35rem, 6vw, 1.875rem) !important; }
}

@media (max-width: 400px) {
  .wbl-m-on .wbl-m-type { font-size: 11px !important; }
}


/* =====================================================================
   3. TAP TARGETS
   ---------------------------------------------------------------------
   Audit found buttons at 22-29px tall across every page. Apple's floor
   is 44px, Google's 48; 40px is the compromise that doesn't wreck the
   denser toolbars. Buttons inside table cells are excluded — a 40px
   sort header would double the height of every stats table.
   ===================================================================== */
@media (max-width: 820px) {

  .wbl-m-on button,
  .wbl-m-on select,
  .wbl-m-on input[type="button"],
  .wbl-m-on input[type="submit"],
  .wbl-m-on .tab,
  .wbl-m-on .filter-btn {
    min-height: 40px;
    touch-action: manipulation;
  }

  /* ...but not inside data tables, and not where the element is
     deliberately an icon chip. */
  .wbl-m-on td button,
  .wbl-m-on th button,
  .wbl-m-on td select,
  .wbl-m-on th select,
  .wbl-m-on .wbl-m-nostretch,
  .wbl-m-on .wbl-m-nostretch button {
    min-height: 0;
  }

  /* Text inputs at less than 16px make iOS Safari zoom the whole page on
     focus and then leave it zoomed. 16px is the threshold, not a style
     choice. */
  .wbl-m-on input[type="text"],
  .wbl-m-on input[type="search"],
  .wbl-m-on input[type="number"],
  .wbl-m-on input[type="email"],
  .wbl-m-on input[type="password"],
  .wbl-m-on select,
  .wbl-m-on textarea {
    font-size: 16px !important;
    min-height: 40px;
  }

  /* Kill the grey flash on tap. */
  .wbl-m-on a,
  .wbl-m-on button,
  .wbl-m-on .tab,
  .wbl-m-on [onclick] {
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0.06);
  }
}


/* =====================================================================
   4. SWIPE TABLES WITH A FROZEN NAME COLUMN
   ---------------------------------------------------------------------
   A 16-column batting table is 700px wide. It cannot fit a 390px phone
   and must not be squeezed into one — squeezing is what produced the
   9px text. So it scrolls sideways inside its card, and the first
   column (the player or team name) is pinned to the left edge so you
   always know whose row you are reading.

   js/wbl-mobile.js wraps each too-wide table in .wbl-xscroll and, for
   tables with enough columns to be worth pinning, adds .wbl-m-stick and
   writes each sticky cell's own opaque background inline (rows
   alternate, so one shared colour would show seams).
   ===================================================================== */
@media (max-width: 820px) {

  /* Grids that wbl-mobile.js measured and found too narrow to read.
     collapseGrids() and relieveCrampedTables() only set the count; the
     declaration itself lives here, inside the media query. */
  .wbl-m-on [data-wbl-m-grid="1"] {
    grid-template-columns: repeat(var(--wbl-m-cols, 1), minmax(0, 1fr)) !important;
  }

  .wbl-xscroll {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    /* stop a swipe that reaches the end of the table from triggering
       Safari's back-navigation gesture */
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
    position: relative;
    /* The measured fallback, for the cases where "100% of what?" resolves
       to something wider than the screen. Set by wrapTable(). */
    max-width: var(--wbl-m-maxw, 100%);
  }

  .wbl-xscroll > table {
    /* the table keeps its natural width; the wrapper does the scrolling */
    width: auto;
    min-width: 100%;
  }

  /* Visible scrollbar — an invisible one gives no hint that there is
     more to the right. */
  .wbl-xscroll::-webkit-scrollbar { height: 5px; }
  .wbl-xscroll::-webkit-scrollbar-track { background: rgba(127, 127, 127, 0.12); border-radius: 3px; }
  .wbl-xscroll::-webkit-scrollbar-thumb { background: rgba(127, 127, 127, 0.45); border-radius: 3px; }

  /* Fade on whichever edge still has content beyond it. The state
     classes are maintained by the scroll handler in wbl-mobile.js. */
  .wbl-xscroll::after,
  .wbl-xscroll::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 22px;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.18s ease;
    z-index: 3;
  }
  .wbl-xscroll::after  { right: 0; background: linear-gradient(to left,  rgba(0,0,0,0.30), transparent); }
  .wbl-xscroll::before { left: 0;  background: linear-gradient(to right, rgba(0,0,0,0.30), transparent); }
  .wbl-xscroll.wbl-m-more-right::after { opacity: 1; }
  .wbl-xscroll.wbl-m-more-left::before { opacity: 1; }

  /* On a light card the dark fade reads as dirt; flip it. */
  .wbl-xscroll.wbl-m-light::after  { background: linear-gradient(to left,  rgba(255,255,255,0.95), transparent); }
  .wbl-xscroll.wbl-m-light::before { background: linear-gradient(to right, rgba(255,255,255,0.95), transparent); }

  /* ---- the frozen columns ----
     NOT simply :first-child. A roster table reads
     `# | B | Player | Pos | G | AB | ...`, so freezing the first column
     would freeze the jersey number and let the name scroll away —
     exactly the thing the frozen column exists to prevent. Sticky
     offsets are cumulative, so wbl-mobile.js finds the column that
     actually names the row, pins everything up to it, and writes each
     cell's own `left` and background inline. This rule only supplies
     the behaviour those cells share. */
  .wbl-xscroll .wbl-m-pin {
    position: sticky;
    /* wbl-mobile.js measures these per cell and writes them as custom
       properties rather than as real inline styles, so that everything
       it computes stops applying the moment this media query stops
       matching — even if the script never notices the viewport changed.
       It didn't, once: a 360 -> 1440 resize delivered no matchMedia
       change, and an earlier version that wrote `style.background`
       directly left 153 cells painted at desktop width. */
    left: var(--wbl-pin-left, 0);
    background: var(--wbl-pin-bg, transparent);
    z-index: 2;
  }
  .wbl-xscroll thead .wbl-m-pin {
    z-index: 4;
  }
  /* One hairline at the right edge of the frozen block, not between
     each of its columns. */
  .wbl-xscroll .wbl-m-pin-last {
    box-shadow: 1px 0 0 rgba(127, 127, 127, 0.28);
  }
  /* A name long enough to fill the screen defeats the point. */
  .wbl-xscroll .wbl-m-pin-last {
    max-width: 42vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Cells inside a swipe table: tighter, and never wrapping — wrapping
     is what makes a 16-column table 900px tall. */
  .wbl-xscroll table th,
  .wbl-xscroll table td {
    white-space: nowrap;
    padding-left: 7px !important;
    padding-right: 7px !important;
  }

  /* Sticky column headers on tall tables (scouting history already does
     this; make it consistent). */
  .wbl-m-on table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
  }
}

@media (max-width: 400px) {
  .wbl-xscroll .wbl-m-pin-last {
    max-width: 38vw;
  }
  .wbl-xscroll table th,
  .wbl-xscroll table td {
    padding-left: 5px !important;
    padding-right: 5px !important;
  }
}


/* =====================================================================
   5. STACKING  —  multi-column layouts collapse to one
   ===================================================================== */
@media (max-width: 820px) {

  /* NOTE — there is deliberately no blanket `.grid-cols-4 { 1fr }` rule
     here, and there must never be one. Tailwind is mobile-first: in
     `grid-cols-2 sm:grid-cols-3 lg:grid-cols-5` the UNPREFIXED class is
     already the phone value, chosen by whoever wrote the view. An
     earlier draft of this file overrode them all and turned the 20-team
     picker on the home page — correctly 2-up — into one team per
     screenful. CSS cannot tell a deliberate mobile choice from a
     desktop-only one, so the decision is made at runtime instead:
     wbl-mobile.js measures each grid and only intervenes when the
     columns are genuinely too narrow to read. See collapseGrids(). */

  /* Rows of unrelated blocks that were never meant to be columns. */
  .wbl-m-on .wbl-m-stack {
    display: block !important;
  }
  .wbl-m-on .wbl-m-stack > * {
    width: 100% !important;
    max-width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
  }

  /* Nav button grid — styles.css already steps 6 -> 3 -> 2. Keep 2 but
     let the labels breathe. */
  .wbl-nav-grid > button {
    min-height: 42px;
    font-size: 0.8rem;
  }
}

@media (max-width: 640px) {

  /* --- Standings: the two leagues sit side by side with the sim date
     wedged between them. At 390px that renders as three crushed
     columns with "May 19, 2025" broken over three lines. Stack. --- */
  .wbl-m-on .wbl-m-leaguehdr {
    display: block !important;
    text-align: center;
  }
  .wbl-m-on .wbl-m-leaguehdr > * {
    display: block !important;
    width: 100% !important;
    margin: 0.15rem 0 !important;
    white-space: normal !important;
  }

  /* --- Team home page: the inner panels already collapse at 768 via
     team_home.js, but its lineup (8 cols, 408px) and injury (4 cols,
     600px) tables sit inside overflow:hidden parents, so every column
     past the fourth was simply unreachable on a phone — not squeezed,
     gone. The runtime wrapper gives each table its own scroller inside
     these panels; all this rule has to do is stop the panels from
     refusing to shrink. Note it does NOT set overflow:visible: that
     would let the table escape the card, and html{overflow-x:hidden}
     would then clip it with no scrollbar at all — the same data loss
     wearing a different hat. --- */
  .wbl-m-on #th-lineups,
  .wbl-m-on #th-2col,
  .wbl-m-on #th-lineups > div,
  .wbl-m-on #th-2col > div {
    min-width: 0 !important;
  }
}

/* (no grid overrides at 400px either — same reason as above) */


/* =====================================================================
   6. THE FLOATING CONTROL BARS
   ---------------------------------------------------------------------
   #wbl-nav-btns (back/forward, app_slim.js) and #wbl-omni-bar
   (search/watchlist/My Club, wbl-watchlist.js) are both position:fixed
   at the TOP of the screen. On a phone they land squarely on the WBL
   logo and the page title.

   Dock them to the bottom instead, which is where a thumb is anyway.
   Both carry inline styles, hence !important on every property.
   ===================================================================== */
@media (max-width: 820px) {

  #wbl-nav-btns {
    top: auto !important;
    bottom: calc(10px + env(safe-area-inset-bottom, 0px)) !important;
    left: calc(10px + env(safe-area-inset-left, 0px)) !important;
    z-index: 9990 !important;
  }

  #wbl-omni-bar {
    top: auto !important;
    bottom: calc(10px + env(safe-area-inset-bottom, 0px)) !important;
    right: calc(10px + env(safe-area-inset-right, 0px)) !important;
    z-index: 9991 !important;
  }

  /* Both bars get a readable lift off the page behind them. */
  #wbl-nav-btns > button,
  #wbl-omni-bar > button {
    box-shadow: 0 3px 12px rgba(0, 0, 0, 0.35) !important;
  }
  #wbl-omni-bar > button {
    min-height: 40px !important;
    padding: 8px 13px !important;
    font-size: 0.8rem !important;
  }
  #wbl-nav-btns > button {
    width: 42px !important;
    height: 42px !important;
  }

  /* Anything else the app pins to the top-right would collide with the
     omni bar's old position; nothing does today, but if something is
     added later it will show up in the audit rather than silently
     overlapping. */
}


/* =====================================================================
   7. MODALS AND OVERLAYS  —  bottom sheets on a phone
   ===================================================================== */
@media (max-width: 640px) {

  .wbl-m-on .modal,
  .wbl-m-on .wbl-m-sheet {
    width: 100% !important;
    max-width: 100% !important;
    max-height: 92dvh !important;
    margin: 0 !important;
    border-radius: 14px 14px 0 0 !important;
    padding: 1rem !important;
    padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px)) !important;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Anchor the sheet to the bottom of its overlay. */
  .wbl-m-on .wbl-m-sheet-host {
    align-items: flex-end !important;
    padding: 0 !important;
  }

  /* The player card and other generated overlays use fixed pixel
     widths. Tagged at runtime. */
  .wbl-m-on .wbl-m-fixedw {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
  }

  /* Close buttons are typically 22px. */
  .wbl-m-on .modal-close,
  .wbl-m-on .popup-close {
    min-width: 40px;
    min-height: 40px;
    font-size: 1.5rem !important;
  }
}


/* =====================================================================
   8. PAGE-SPECIFIC
   ===================================================================== */
@media (max-width: 820px) {

  /* --- Team tab bar (index.html): 959px of tabs in a 326px strip.
     It scrolls, but gave no sign that it did. --- */
  .team-tab-bar {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
    padding-bottom: 4px;
  }
  .team-tab-bar > * {
    scroll-snap-align: start;
    flex: 0 0 auto;
  }
  .team-tab-bar::-webkit-scrollbar { height: 4px; }
  .team-tab-bar::-webkit-scrollbar-thumb { background: rgba(127,127,127,0.45); border-radius: 2px; }

  /* --- all-time-teams.html: same treatment for #tabs (550px in 366). --- */
  #tabs {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
  }
  #tabs > * { flex: 0 0 auto; }

  /* --- scouting_history.html --- */
  .tabs {
    padding-left: 12px !important;
    padding-right: 12px !important;
    overscroll-behavior-x: contain;
  }
  .search-box {
    flex-wrap: wrap;
    gap: 8px;
  }
  .search-box input,
  .search-box select {
    flex: 1 1 100%;
    min-width: 0 !important;
  }
  .trait-grid,
  .stat-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }

  /* --- projections.html --- */
  #batting-table-wrapper,
  #pitching-table-wrapper {
    overscroll-behavior-x: contain;
  }
  .filter-btn {
    font-size: 0.8rem;
    padding: 8px 12px !important;
  }

  /* --- league-office.html --- */
  .lo-tab,
  .lo-tabs > button {
    min-height: 42px;
  }

  /* --- Defense: the defensive alignment diagram ---
     app_slim.js already has a phone rule for this (around line 1624):
     it narrows the field to a 0.58 aspect ratio and shrinks the player
     cards' text to 8px, with games played at 7px. That does make nine
     overlapping cards fit a 390px screen, but 7px is below what anyone
     can read — the type floor can't help either, because lifting the
     text inside a 90px card would just make the names collide.

     The diagram is a picture, so treat it the way the wide tables are
     treated: give it room and let the phone pan across it, rather than
     shrinking it past the point of being worth looking at. The field
     gets its desktop proportions and card sizes back, and the container
     scrolls.

     To go back to the squeezed-but-whole version, delete this block —
     app_slim's own rules take over again with nothing else to undo. */
  .wbl-m-on #defense-field-container {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .wbl-m-on #defense-field-container .def-field-wrap {
    min-width: 600px;
    aspect-ratio: 0.967 / 1 !important;
    background-size: contain !important;
    background-position: center !important;
    margin-top: 12px !important;
  }
  .wbl-m-on #defense-field-container .def-card-inner,
  .wbl-m-on #defense-field-container .def-card-empty {
    min-width: 108px !important;
    max-width: none !important;
    padding: 5px 7px !important;
    border-radius: 8px !important;
  }
  .wbl-m-on #defense-field-container .def-pos-label { font-size: 11px !important; margin-bottom: 2px !important; }
  .wbl-m-on #defense-field-container .def-name      { font-size: 12px !important; line-height: 1.2 !important; }
  .wbl-m-on #defense-field-container .def-games     { font-size: 11px !important; }
}


/* =====================================================================
   9. PRINT / REDUCED MOTION HOUSEKEEPING
   ===================================================================== */
@media (max-width: 820px) and (prefers-reduced-motion: reduce) {
  .wbl-xscroll::after,
  .wbl-xscroll::before {
    transition: none;
  }
}
