/* ==========================================================================
   pos_mobile.css — phone/tablet layer for the COMPILED POS SPA.

   Injected by run.py's _SpaPatch into the React shell (the bundle and its
   stylesheet /assets/index-A6yxq7Mn.css are never edited). Everything here is
   an override of that stylesheet, so it must load after it — the injected
   <link> sits at the end of <body>, which satisfies that.

   The compiled CSS already had a @media (max-width:768px) block, but it was
   incomplete in three ways that made the SPA unusable on a phone:

     1. NO WAY TO OPEN THE NAV. It parks .sidebar off-canvas and defines
        .sidebar.open to slide it back, but the bundle renders no hamburger and
        nothing ever sets .open — so below 768px there was no navigation at all.
        pos_mobile.js injects the button; the drawer rules live here, keyed off
        a class on <body> (React re-renders can't clobber that).

     2. .main-content is a flex child of .app-layout and kept its default
        min-width:auto, so a wide table stretched .main-content — and therefore
        the whole page — past the viewport. That ALSO defeated .table-wrap's own
        overflow-x:auto, because the wrap grew with the table instead of
        clipping it. One `min-width:0` fixes Products / Inventory / Bills /
        Customers at once. Deliberately NOT inside a media query: it is correct
        at every width.

     3. .pos-layout (billing) was switched to one column for mobile but kept its
        desktop height:calc(100vh - 73px), so the Order Summary column was
        forced back on top of the product search instead of stacking under it.

   Layout contract this file assumes (all from the compiled bundle):
     .app-layout > .sidebar + .main-content > .page-header + .page-body
     .pos-layout > .pos-main + .pos-sidebar        (billing screen)
     .table-wrap > table                           (every data table)
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Root containment fix — see note 2 above. All widths, on purpose.
   -------------------------------------------------------------------------- */
.main-content { min-width: 0; }
.page-header, .page-body { min-width: 0; max-width: 100%; }

/* Same defect one level down: flex AND grid children both default to
   min-width:auto, so a nowrap table inside a .grid-2 cell pushes the cell —
   and the page — wide again. Containment has to hold all the way down. */
.grid-2 > *, .grid-3 > *, .stats-grid > *, .card { min-width: 0; }

/* Tables scroll inside their wrapper instead of stretching the page. */
.table-wrap { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* The same defect in the billing grid. .pos-layout is a grid, and a grid track
   sized 1fr still takes min-width:auto for its item — so the widest thing
   inside .pos-main sets the track width. The size x colour picker renders a
   display:table matrix (565px for 8 colours), which dragged the track, the
   page, and therefore the entire screen sideways: adding an item scrolled the
   whole UI right instead of scrolling just the matrix.

   With the track contained, .wwpk-matwrap's own overflow-x:auto finally does
   its job and only the matrix pans left/right, which is the intended gesture.

   This also repairs position:fixed on this screen. In mobile browsers a
   horizontally overflowing page widens the layout viewport, and fixed elements
   resolve against THAT — so the checkout bar and the offline pill were being
   pinned to a 646px-wide phantom viewport and pushed off-screen. They are only
   correct while the page does not overflow. */
.pos-main, .pos-sidebar { min-width: 0; }
/* Belt and braces: the popup can never outgrow the column that now bounds it. */
.wwpk-pop { max-width: 100%; }

/* mountBurger() injects the hamburger at every width (it cannot know the
   breakpoint), and ALL of its styling lives in the 768px block below — so above
   the breakpoint it was rendering as a default-styled <button> in the header.
   Hide it here and let the media query turn it back on. */
.ww-burger { display: none; }

@media (max-width: 768px) {

  /* ------------------------------------------------------------------------
     2. Nav drawer. The compiled sheet already has the off-canvas transform and
        a .sidebar.open rule; we drive it from <body> instead so a React
        re-render of the sidebar (which rewrites className="sidebar") can never
        strip the open state mid-interaction.
     ------------------------------------------------------------------------ */
  body.ww-nav-open .sidebar { transform: translate(0); }
  body.ww-nav-open { overflow: hidden; }          /* no scroll-through */

  .ww-nav-backdrop {
    position: fixed; inset: 0; z-index: 99;
    background: rgba(0, 0, 0, .55);
    opacity: 0; pointer-events: none; transition: opacity .3s;
  }
  body.ww-nav-open .ww-nav-backdrop { opacity: 1; pointer-events: auto; }

  /* Injected hamburger. Styled as a .btn-icon sibling so it inherits the
     bundle's own button language rather than looking bolted on. */
  .ww-burger {
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 40px; width: 40px; height: 40px; padding: 0;
    margin-right: 2px;
    background: transparent; color: var(--text-secondary);
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    cursor: pointer; transition: all .15s;
  }
  .ww-burger:active { border-color: var(--accent); color: var(--accent); }
  .ww-burger svg { width: 20px; height: 20px; }

  /* Sidebar is a full-height drawer; give its own nav comfortable touch rows. */
  .sidebar { box-shadow: var(--shadow); }
  .sidebar .nav-item { padding: 13px 14px; }

  /* ------------------------------------------------------------------------
     3. Page header. Was a single non-wrapping flex row (title on the left,
        search + actions on the right) that simply ran off the screen.
        Title claims row 1 next to the burger; every other control block wraps
        onto its own full-width row below.
     ------------------------------------------------------------------------ */
  .page-header {
    padding: 11px 14px;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
  }
  .page-header > h2 {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 18px;
    /* keep clear of the fixed offline-status pill parked top-right below */
    padding-right: 104px;
  }
  /* any control cluster the page puts beside the title drops to its own row */
  .page-header > *:not(h2):not(.ww-burger) { flex: 1 1 100%; min-width: 0; }
  .page-header .flex { flex-wrap: wrap; gap: 8px; }
  .page-header .flex > * { min-width: 0; }

  /* ------------------------------------------------------------------------
     4. Page body + the fixed-pixel inputs the pages set inline
        (width:220px / 280px / 160px / 200px, and max-width:400px form-groups).
        Inline styles need !important to beat.
     ------------------------------------------------------------------------ */
  .page-body { padding: 14px 12px; }
  .page-body > .flex, .page-body .flex-between { flex-wrap: wrap; gap: 8px; }
  .page-body > .flex > * { min-width: 0; }

  .page-header input.form-control,
  .page-header select.form-control,
  .page-body input.form-control,
  .page-body select.form-control { width: 100% !important; min-width: 0; }
  .page-body .form-group[style] { max-width: none !important; flex: 1 1 100% !important; }

  /* Report-type / filter button rows: wrap instead of running off-screen. */
  .page-body > .flex .btn { flex: 0 1 auto; }

  /* ------------------------------------------------------------------------
     5. Billing screen (/pos). Root cause of the Order Summary panel landing on
        top of the product search: the one-column mobile grid inherited the
        desktop viewport-locked height.
     ------------------------------------------------------------------------ */
  .pos-layout { height: auto !important; min-height: 0; }
  .pos-main { padding: 14px 12px; overflow: visible; }
  .pos-sidebar {
    height: auto !important;
    border-left: none;
    border-top: 1px solid var(--border);
  }
  .pos-sidebar-body { overflow: visible; }
  .pos-sidebar-header, .pos-sidebar-footer { padding: 14px 14px; }

  /* Cart rows: keep name / qty / price on one line at 390px. */
  .cart-item { padding: 11px 14px; gap: 9px; }
  .cart-item-info .name { font-size: 13.5px; }
  .cart-item-price { min-width: 62px; font-size: 13.5px; }
  .cart-item-qty button { width: 32px; height: 32px; }

  /* ------------------------------------------------------------------------
     6. Data tables. With the wrap finally bounded (rule 1) it scrolls, but the
        cells were wrapping product names onto 3 lines, making rows ~200px tall.
        Nowrap + a sane min-width trades that for a horizontal swipe.
     ------------------------------------------------------------------------ */
  .table-wrap table { min-width: 620px; }
  .table-wrap thead th, .table-wrap tbody td { padding: 10px 12px; white-space: nowrap; }
  .table-wrap { position: relative; }

  /* ------------------------------------------------------------------------
     7. Cards, stat tiles, modals.
     ------------------------------------------------------------------------ */
  .card { padding: 15px 14px; }
  .card-header { flex-wrap: wrap; gap: 8px; }
  .stats-grid { gap: 12px; }
  .stats-grid > * { min-width: 0; }
  .stat-card { padding: 15px 14px; }
  .stat-card .value { font-size: clamp(19px, 6vw, 28px); overflow-wrap: anywhere; }
  .stat-card .label { font-size: 11px; letter-spacing: .6px; }

  .modal-overlay { padding: 12px; align-items: flex-end; }
  .modal { max-height: 90vh; border-radius: 14px; }
  .modal-header, .modal-footer { padding: 15px 16px; }
  .modal-body { padding: 16px; }
  .modal-footer { flex-wrap: wrap; }
  .modal-footer .btn { flex: 1 1 auto; justify-content: center; }
  .grid-2, .grid-3 { gap: 12px; }

  /* ------------------------------------------------------------------------
     8. Touch targets + the iOS focus-zoom trap.
        Safari zooms the page whenever a focused input's font-size is < 16px;
        the bundle uses 14px, so every tap into the barcode box rescaled the
        whole till screen. 16px is the fix — it is a threshold, not a taste.
     ------------------------------------------------------------------------ */
  .form-control { font-size: 16px; padding: 11px 13px; }
  select.form-control { background-position: right 12px center; }
  .btn { min-height: 42px; padding: 10px 18px; }
  .btn-sm { min-height: 36px; padding: 8px 13px; font-size: 13px; }
  .btn-lg { min-height: 48px; }
  .btn-icon { width: 38px; height: 38px; flex: 0 0 38px; }

  /* ------------------------------------------------------------------------
     9. Checkout bar (/pos only — .pos-sidebar exists on no other screen).

        Rule 5 stacks the Order Summary under the product search, which is the
        right reading order but puts the two controls that end every sale —
        the Total and "Complete Sale" — off the bottom of the page. Measured on
        a 390x844 phone: 151px below the fold with an EMPTY cart, 312-355px once
        items are in it. So the cashier scrolled ~40% of a screen to read the
        total, scrolled back up to add the next item, and repeated that for
        every line of every sale.

        Fix: pin the footer the bundle already renders. We move the REAL
        element — same summary rows, same <button> — so React keeps its state
        and its click handler; nothing here duplicates or re-implements the
        cart. Two columns: the money stacks on the left, the action sits on the
        right, so the bar costs ~90px instead of the 180px it takes in flow.
     ------------------------------------------------------------------------ */
  .pos-sidebar-footer {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
    display: grid; grid-template-columns: 1fr auto;
    align-items: center; gap: 2px 12px;
    background: var(--bg-secondary);
    border-top: 1px solid var(--border);
    box-shadow: 0 -8px 24px rgba(0, 0, 0, .4);
    /* env() keeps the button clear of the iPhone home indicator. */
    padding: 9px 14px calc(9px + env(safe-area-inset-bottom, 0px));
    /* Tax/discount rows appear conditionally — never let the bar eat the page. */
    max-height: 45vh; overflow-y: auto;
  }

  /* Item count, mirrored onto the footer by pos_mobile.js from the sidebar
     header (which scrolls away with the cart). attr() means an empty/missing
     value simply renders nothing — if the JS never runs, the bar still works. */
  .pos-sidebar-footer::before {
    content: attr(data-ww-items);
    grid-column: 1; line-height: 1.2;
    font-size: 10.5px; letter-spacing: .7px; text-transform: uppercase;
    color: var(--text-muted);
  }
  .pos-sidebar-footer:not([data-ww-items])::before { display: none; }

  .pos-sidebar-footer .summary-row { grid-column: 1; padding: 0; font-size: 12.5px; }
  .pos-sidebar-footer .summary-row.total {
    font-size: 17px; border-top: none; padding-top: 1px; margin-top: 1px;
  }
  /* Inline width/margin on the button (see markup) needs !important to beat. */
  .pos-sidebar-footer .btn {
    grid-column: 2; grid-row: 1 / -1;
    width: auto !important; margin-top: 0 !important;
    min-height: 50px; padding: 12px 20px; white-space: nowrap;
  }

  /* Reserve the bar's height so the last of the cart is never trapped under it.
     pos_mobile.js keeps --ww-cartbar-h in sync with the real rendered height;
     the fallback covers the window before the first measurement lands. */
  .pos-layout { padding-bottom: var(--ww-cartbar-h, 112px); }

  /* ------------------------------------------------------------------------
     10. Offline-status pill (#ww-offline-widget, mounted by pos_offline.js with
        inline styles — hence !important). Bottom-left put it straight on top of
        the full-width "Complete Sale" button. Park it in the sticky header's
        right edge, which rule 3 reserves space for, and flip its popover to
        open downward.
     ------------------------------------------------------------------------ */
  #ww-offline-widget {
    top: 12px !important; bottom: auto !important;
    right: 12px !important; left: auto !important;
    z-index: 60 !important;
  }
  #ww-offline-widget button { min-height: 32px; }
  #ww-offline-widget > div {          /* the status popover */
    top: 38px !important; bottom: auto !important;
    right: 0 !important; left: auto !important;
    width: min(276px, calc(100vw - 28px)) !important;
  }
  /* while the drawer is open the pill must not float above the scrim */
  body.ww-nav-open #ww-offline-widget { display: none !important; }
}

/* Narrow phones (<=400px): the 2-up stat grid gets cramped past ~360px. */
@media (max-width: 400px) {
  .stats-grid { grid-template-columns: 1fr; }
  .page-header > h2 { font-size: 17px; }
}
