/* _astoler-mobile.css — every mobile-only override across the A. S. Toler
 * Portal. Loaded LAST in every panel's <head> so it wins the cascade
 * against panel-local CSS without specificity wars.
 *
 * Hard rule: EVERY rule in this file lives inside
 *   @media (max-width: 768px) { ... }
 * Desktop must remain untouched.
 *
 * iPhone 14 / 15 = 390-430px wide. Breakpoint at 768 covers all phones
 * + small tablets (iPad mini portrait). Larger tablets get desktop.
 *
 * Per the project_mobile_responsive_pass brief 2026-05-21.
 *
 * Sections, in shipping order:
 *   §A Global page primitives (safe area, viewport scroll)
 *   §B FAB clearance (chat bubble + Ask AI overlap)
 *   §C Tab bars (horizontal scroll + right-edge fade)
 *   §D Tap targets (44×44 floor)
 *   §E Main Panel ( / )
 *   §F Ops Panel ( /ops-panel/ )
 *   §G Field Panel ( /field-panel/ )
 *   §H Admin Panel ( /admin/ )
 *   §I PM Panel ( /pm-panel/ )
 *   §J Bay PowerBid ( /bay-bid-list/ )
 *   §K Bid Panel ( /bid-panel/ )
 *   §L AI Takeoff ( /takeoff/ )
 */

@media (max-width: 768px) {

  /* ─── §A Global ────────────────────────────────────────────────── */
  /* Real-iPhone scroll fix 2026-05-21: forcing overflow-y:auto on
   * BOTH html and body creates two competing scroll containers and
   * iOS WebKit can lock touch scroll entirely. Just unset height
   * caps and let the document scroll naturally — the overflow:hidden
   * that was the original problem is now fixed at the source on the
   * Main Panel (commit 664eee5). No other panel sets overflow on
   * html/body inline. */

  html, body {
    height: auto;
    overscroll-behavior-y: contain;
  }

  body {
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
  }

  /* Particle canvas on Main Panel is a fixed full-viewport <canvas>
   * with its own touchmove listener. Real mobile browsers (iOS Safari,
   * Android Chrome) sometimes route touchscroll through whatever was
   * touched first — even pointer-events:none isn't always enough to
   * defer it cleanly. Hide it entirely on phones. The page already
   * has the gradient background; sparks are a nice-to-have not a
   * core feature. */
  #particles {
    display: none !important;
  }

  /* ─── §B FAB clearance ─────────────────────────────────────────── */
  /* Chat bubble lives at bottom-left, Ask AI / astoler-suggestions
   * at bottom-right. Lift both above the home indicator + force the
   * page content to leave a clear gutter so the last scroll item
   * isn't trapped under either FAB. */

  .fchat-bubble {
    bottom: calc(16px + env(safe-area-inset-bottom)) !important;
    left:   calc(16px + env(safe-area-inset-left))   !important;
  }
  .fchat-drawer {
    bottom: calc(80px + env(safe-area-inset-bottom)) !important;
    left:   calc(12px + env(safe-area-inset-left))   !important;
    right:  calc(12px + env(safe-area-inset-right))  !important;
  }

  /* Generic scrollable containers — leaves 80px clear for the FAB +
   * the iPhone home indicator. Panels can override with a smaller
   * value if they have no FAB. */
  .wrap,
  .app,
  main,
  .content,
  .tab-panel,
  .field-tab-content,
  .ops-tab-content,
  .admin-tab-content,
  .panel-cards-container {
    padding-bottom: calc(80px + env(safe-area-inset-bottom));
  }

  /* ─── §C Tab bars: right-edge fade ─────────────────────────────── */
  /* Most panels have horizontal tab strips that scroll on overflow
   * but give zero visual hint there are more tabs off-screen.
   * Wrap each tab-bar in a positioned parent and overlay a fade. */

  .tab-bar,
  .tabs,
  .palette-tabs,
  #tab-bar {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scroll-behavior: smooth;
    position: relative;
  }
  /* The fade itself — uses currentColor on the parent's bg via
   * mix-blend-mode workaround. Approximated with --bg if available
   * else falls back to a dark-tolerant rgba. */
  .tab-bar::after,
  .tabs::after,
  #tab-bar::after {
    content: '';
    position: sticky;
    right: 0;
    top: 0;
    width: 48px;
    height: 100%;
    margin-left: -48px;
    background: linear-gradient(to right, transparent, var(--panel3, #121212));
    pointer-events: none;
    flex-shrink: 0;
  }

  /* ─── §D Tap targets ───────────────────────────────────────────── */
  /* 44×44 minimum on interactive surfaces. Small icons + tightly
   * packed buttons go from 24-32px → 44px so they're thumb-friendly. */

  input[type="checkbox"],
  input[type="radio"] {
    width: 20px;
    height: 20px;
    min-width: 20px;
  }
  /* Single-tap text links that act as buttons (e.g. "View Email",
   * "View all bids →") get a tap padding. Use a small selector that
   * matches the pattern across panels. */
  a.tap-link,
  .view-all-link,
  .prequal-view-email,
  .pm-view-all-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 8px 12px;
  }

  /* ─── §E Main Panel ( / ) ─────────────────────────────────────── */
  /* Scroll fix — .stage uses justify-content:center + min-height:100vh
   * which, when content exceeds the viewport on mobile (5 panel-btns
   * + logo + title easily clears 1000px on a 430×932 iPhone), centers
   * the overflow symmetrically and prevents reaching the bottom.
   * Top-anchor the column and let it grow naturally instead.
   *
   * Also swaps 100vh → 100dvh because iOS Safari's 100vh = layout
   * viewport (URL bar collapsed), which is taller than what the user
   * actually sees → content gets cropped on first paint. */
  .stage {
    justify-content: flex-start !important;
    min-height: 100dvh !important;
    padding: 24px 14px 80px !important;
    gap: 16px !important;
  }
  /* Particle canvas stays fixed; nothing else holds the page captive. */

  /* Legacy selectors below — keep for panels that use these class
   * names (Field/PM headers). Main Panel uses .stage above. */
  body.main-panel-page .hero-section,
  body.main-panel-page .logo-banner,
  .main-panel .hero-section,
  .main-panel .logo-banner {
    min-height: 120px !important;
    height: 120px !important;
  }
  /* Sign-out button — let it flow with the header instead of
   * floating outside the safe area. */
  .main-panel .sign-out-btn,
  body.main-panel-page .sign-out-btn {
    position: static !important;
    margin-left: auto;
  }

  /* ─── §F Ops Panel ( /ops-panel/ ) ───────────────────────────── */
  /* The "ADMIN ← Main Sign out" cram-fest — stack vertically. */

  .ops-panel-page .f-page-header,
  .ops-panel-page #topbar {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 12px 16px !important;
  }
  .ops-panel-page .f-page-brand {
    width: 100%;
  }
  .ops-panel-page .f-page-nav {
    width: 100%;
    justify-content: flex-end;
  }
  /* Tab bar already covered by §C global fade. */
  /* Tables horiz-scroll. */
  .ops-panel-page table {
    min-width: 540px;
  }
  .ops-panel-page .card {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* ─── §G Field Panel ( /field-panel/ ) ────────────────────────── */
  /* User-name in header clipping → ellipsis at 100px. */
  .field-panel-page .header-user,
  .field-panel-page #whoName {
    max-width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: inline-block;
    vertical-align: middle;
  }
  /* Consent screen bigger checkbox + padded label. */
  .field-panel-page .consent-checkbox input[type="checkbox"] {
    width: 22px;
    height: 22px;
    min-width: 22px;
  }
  .field-panel-page .consent-checkbox label {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 0;
    cursor: pointer;
  }
  /* Roster duplicate header bug — hide any nested .field-panel-header
   * that lives INSIDE a tab panel (the real one is above the tabs). */
  .field-panel-page .tab-panel .field-panel-header,
  .field-panel-page .tab-panel .panel-title-section,
  .field-panel-page #tab-roster .field-panel-header,
  .field-panel-page #tab-roster .panel-title-section {
    display: none !important;
  }
  /* Inline code in roster — break long paths. */
  .field-panel-page #tab-roster code,
  .field-panel-page #tab-roster .code-ref {
    word-break: break-word;
    white-space: normal;
  }
  /* Receipts: stack amount + status vertically. */
  .field-panel-page .receipt-row-right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
  }
  /* Admin (Users) form — stack side-by-side fields. */
  .field-panel-page .user-form .field-pair,
  .field-panel-page .field-pair {
    flex-direction: column;
    gap: 8px;
  }
  .field-panel-page .user-form .field-pair input,
  .field-panel-page .user-form .field-pair select,
  .field-panel-page .field-pair input,
  .field-panel-page .field-pair select {
    width: 100%;
  }

  /* ─── §H Admin Panel ( /admin/ ) ─────────────────────────────── */
  /* Tables overflow — wrap container, sticky first column. */
  body[data-page="admin"] .card,
  .admin-panel .card,
  #tab-activity table,
  #tab-livenow table,
  #tab-wipes table,
  #tab-cron table {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  /* Hide TAB OPENS + LAST PING columns on mobile — they're the most
   * disposable in the Activity / Live Now tables. */
  .activity-table .col-tab-opens,
  #tab-activity th:nth-child(4),
  #tab-activity td:nth-child(4) {
    display: none;
  }
  /* RANGE selector → scrollable chip row. */
  .range-chips {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
    padding-bottom: 4px;
  }
  .range-chips .chip {
    flex-shrink: 0;
    min-height: 36px;
    padding: 0 14px;
  }
  /* Long workflow names in Cron Health */
  #tab-cron td:nth-child(2) {
    max-width: 180px;
    white-space: normal;
    word-break: break-word;
  }

  /* ─── §I PM Panel ( /pm-panel/ ) ─────────────────────────────── */
  /* Date line de-emphasized. */
  .pm-panel-page .pm-date-display,
  .pm-date-display {
    font-size: 10px;
    color: var(--muted, #888);
    text-align: center;
    margin: 4px 0;
  }
  /* Bottom nav safe-area. */
  .pm-bottom-nav,
  .pm-nav-bar {
    padding-bottom: env(safe-area-inset-bottom);
  }
  /* Tables horiz-scroll. */
  .pm-panel-page table {
    min-width: 480px;
  }
  .pm-panel-page .card,
  .pm-panel-page .table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* ─── §J Bay PowerBid ( /bay-bid-list/ ) ─────────────────────── */
  /* Stat-card labels + values get readable. */
  .stat-card .label,
  .bbl-kpi .label,
  .f-kpi-label {
    font-size: 11px !important;
  }
  .stat-card .value,
  .bbl-kpi .value,
  .f-kpi-value {
    font-size: 24px !important;
  }

  /* Bid card compaction — desktop's 4-stat side column (Quotes In,
   * Bid Due, Job Walk, Addenda) becomes a 4-row vertical stack on
   * mobile, leaving a giant dead zone next to the scope tags. Flex-
   * wrap the head: title gets its own row, then the stats lay out
   * side-by-side underneath. Each stat keeps its own label-over-value
   * column so dates + times still read correctly. */
  .bid-head {
    display: flex !important;
    flex-wrap: wrap;
    gap: 8px 14px !important;
    padding: 10px 12px !important;
    align-items: flex-start !important;
  }
  .bid-title {
    flex: 1 1 100%;
    min-width: 0;
  }
  .bid-stat {
    align-items: flex-start !important;
    margin-left: 0 !important;
    padding-left: 0 !important;
    border-left: none !important;
    min-width: 0 !important;
    gap: 1px !important;
  }
  .bid-stat-label {
    font-size: 9px !important;
    letter-spacing: .4px;
  }
  .bid-stat-value {
    font-size: 14px !important;
  }
  /* Scope description: drop the 90ch desktop cap and tighten line-
   * height so the 4-line clamp shows more in less vertical space. */
  .bid-scope {
    max-width: none !important;
    font-size: 11.5px !important;
    line-height: 1.35 !important;
  }

  /* Ask-AI floating panel — desktop locks it to 620px tall with
   * overflow:hidden, which on phones cuts off the answer below the
   * input bar. Drop the fixed cap and let content scroll vertically
   * inside the panel. 100dvh accounts for iOS Safari's URL bar so
   * the panel doesn't extend behind the home indicator. */
  .bbl-ai-panel {
    height: auto;
    max-height: calc(100dvh - 16px);
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
  }

  /* Toolbar (.toolbar + .toolbar-group) is the shared filter row pattern
   * used by every Bay PowerBid view: Bay Bid List (STATUS / SEARCH / SORT
   * / VIEW), Analytics (DIVISION / YEAR), Bid Radar, SBX Watchlist
   * (SOURCE / COUNTY / FUTURE-DUE / ELECTRICAL / C10), Prequal List.
   *
   * Desktop has each group with min-width:170px on its select/input which
   * means on a 390px viewport they stack vertically and consume ~300px
   * before the user sees any cards. We:
   *   - Drop min-width so inputs shrink to their slot
   *   - Lay groups out in a 2-col CSS grid so dropdowns sit side-by-side
   *     by default
   *   - Inputs span the full grid cell
   *   - Drop sticky-top so the filter row doesn't eat the top of the
   *     viewport while scrolling cards
   */
  .toolbar {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 8px 10px !important;
    position: static !important;
    padding: 10px !important;
  }
  .toolbar > .toolbar-group {
    min-width: 0;
  }
  /* The "View" chip row (data-display chips) is the wide one -- give it
   * the full grid width so chips don't wrap awkwardly. Caught by either
   * the chip-row sibling OR the bblViewToggle id. */
  .toolbar > .toolbar-group:has(.f-chip-row),
  .toolbar > .toolbar-group:has(#bblViewToggle) {
    grid-column: 1 / -1;
  }
  .toolbar-group select,
  .toolbar-group input {
    min-width: 0 !important;
    width: 100%;
    font-size: 14px !important;  /* >=14 stops iOS Safari from zooming-in on focus */
  }
  .toolbar-group label {
    font-size: 10px;
  }

  /* SBX Watchlist filter checkboxes (#sbxFutureOnly / Electrical / C10)
   * are 13-14px native checkboxes -- below tap-target minimum. Bump to
   * 20×20 with generous row padding so the whole label is tappable. */
  #sbxFutureOnly,
  #sbxElectricalOnly,
  #sbxC10Only {
    width: 20px !important;
    height: 20px !important;
    cursor: pointer;
  }
  .toolbar-group:has(#sbxFutureOnly),
  .toolbar-group:has(#sbxElectricalOnly),
  .toolbar-group:has(#sbxC10Only) {
    padding: 6px 0;
    flex-direction: row !important;
    align-items: center !important;
    gap: 8px !important;
  }

  /* Bid Radar select-all toolbar — wraps poorly on phones because the
   * Remove-selected button + selected count + checkbox label all want
   * to share one row. Flex-wrap + tap-friendly checkbox. */
  #radarToolbar {
    flex-wrap: wrap;
    gap: 8px 12px !important;
    padding: 10px !important;
  }
  #radarSelectAll {
    width: 20px !important;
    height: 20px !important;
  }
  #radarDismissBtn {
    padding: 8px 14px !important;
    min-height: 36px;
    font-size: 12px !important;
  }
  /* Per-row Bid Radar checkboxes — keep them centered with the card text
   * but big enough to tap. */
  .radar-check {
    width: 20px !important;
    height: 20px !important;
    margin-top: 8px !important;
  }

  /* Prequal "View Email" links sit inline in table cells and are 11px
   * with no padding. Pull them up to 44px tap target. */
  .prequal-email-link,
  a[href*="mail.google.com"][data-prequal-thread],
  #view-prequal a[href*="mail.google.com"] {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 8px 12px;
  }

  /* ─── §K Bid Panel ( /bid-panel/ ) ───────────────────────────── */
  /* Nav buttons on one row. */
  .bid-panel-page .f-page-nav,
  .bid-panel-page .nav-links {
    flex-wrap: nowrap;
    gap: 8px;
  }
  .bid-panel-page .f-page-nav .f-btn-ghost,
  .bid-panel-page .nav-links .nav-link {
    flex: 1;
    text-align: center;
  }
  /* View toggle full width. */
  .bid-panel-page #viewToggle,
  .view-toggle {
    display: flex;
    width: 100%;
  }
  .bid-panel-page #viewToggle .f-chip,
  .view-toggle button {
    flex: 1;
  }

  /* ─── §L AI Takeoff ( /takeoff/ ) ────────────────────────────── */
  /* Per-Alex: the BAY/SAC/ALL + Due/EST#/A–Z + List/Month chip strip
   * was pushing the whole page wider than the viewport, causing
   * horizontal page scroll. Wanted behavior: header alone swipes
   * left-right, page body fits viewport. */

  /* Stop the page itself from scrolling sideways. */
  body.takeoff-page {
    overflow-x: hidden;
  }

  /* Page header stacks: title row, then the nav strip on its own row. */
  body.takeoff-page .f-page-header {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3) !important;
  }

  /* Nav becomes a single-row horizontal scroller. flex-wrap:nowrap so
   * everything stays on one line; overflow-x:auto so the user can
   * swipe; -webkit-overflow-scrolling:touch keeps iOS momentum. */
  body.takeoff-page .f-page-nav {
    width: 100%;
    flex-wrap: nowrap !important;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    justify-content: flex-start;
    gap: 8px;
    padding-bottom: 4px;
    /* Hide the native scrollbar — swipe + edge fade communicate
     * scrollability without stealing 14px of height. */
    scrollbar-width: none;
  }
  body.takeoff-page .f-page-nav::-webkit-scrollbar {
    display: none;
  }

  /* Don't let chip groups, buttons, or the search input shrink — that
   * would re-collapse them into a single overlapping mess. */
  body.takeoff-page .f-page-nav > * {
    flex-shrink: 0;
  }
  body.takeoff-page #bid-search {
    width: 160px !important;
  }

  /* Right-edge fade hint — same pattern as §C global tab fades, scoped
   * here because the nav is a sibling layer above .f-page-header. */
  body.takeoff-page .f-page-header {
    position: relative;
  }
  body.takeoff-page .f-page-header::after {
    content: "";
    position: absolute;
    right: 0;
    bottom: 4px;
    width: 32px;
    height: 38px;
    background: linear-gradient(90deg, transparent, var(--bg) 80%);
    pointer-events: none;
  }

  /* Card pills wrap (unchanged from prior pass). */
  body.takeoff-page .bid-meta,
  body.takeoff-page .meta-chip {
    flex-wrap: wrap;
    gap: 4px;
  }

}  /* end @media (max-width: 768px) */
