/* ==========================================================================
   mobile.css — canonical mobile rules for rps-logistics
   --------------------------------------------------------------------------
   This file is loaded AFTER /css/style.css on every HTML page (see the
   <link> tag in each public/*.html). All rules here are wrapped in
   @media queries so the existing desktop layout is untouched at
   >= 1025px (and table card-view stays off at >= 641px so tablets keep
   their horizontal-scroll tables).

   Three named tiers (kept as CSS custom properties for greppability):
     --bp-phone:  640px   (phones: card-view tables, full-screen modals,
                           stacked forms, 44px touch targets)
     --bp-drawer: 900px   (phones + portrait tablets: slide-in sidebar)
     --bp-tablet: 1024px  (anything narrower than this is "mobile-ish")

   Rule of thumb:
     - Drawer behaviour fires at <= --bp-drawer (so iPad portrait gets it).
     - Card-view tables / full-screen modals / stacked forms fire at
       <= --bp-phone (tablets keep tables horizontal-scroll, modals
       centered).
   ========================================================================== */

:root {
  --bp-phone:  640px;
  --bp-tablet: 1024px;
  --bp-drawer: 900px;
}

/* --------------------------------------------------------------------------
   Drawer sidebar (<=900px)
   --------------------------------------------------------------------------
   At drawer-tier viewports the sidebar becomes a slide-in panel. The
   .app grid collapses to a single column so main fills the width; the
   sidebar is fixed-position, translated off-screen by default, and
   slides in when <body> gets the .drawer-open class.

   See public/js/app.js Drawer state machine for the JS side.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
  /* Main fills the width — sidebar becomes an overlay, not a column. */
  .app { grid-template-columns: 1fr; }

  /* Sidebar = fixed-position drawer, slid off-screen by default. */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    height: 100vh;
    width: min(86vw, 320px);
    z-index: 200;
    transform: translateX(-100%);
    transition: transform .22s ease-out;
    box-shadow: 0 20px 60px rgba(0, 0, 0, .35);
    will-change: transform;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* Reset any inline-strip styling from style.css legacy rule. */
    flex-direction: column;
    align-items: stretch;
    flex-wrap: nowrap;
    padding: 18px 14px;
    gap: 0;
  }
  body.drawer-open .sidebar { transform: translateX(0); }

  /* Restore the desktop look INSIDE the drawer (the legacy 780px rule
     converted these to a horizontal strip — undo that). */
  .sidebar-user { display: flex; }
  .sidebar .nav { flex-direction: column; gap: 4px; padding: 0; min-width: 0; overflow: visible; }
  .sidebar .nav-label { display: block; }
  .sidebar .nav a { padding: 10px 12px; font-size: 14px; white-space: normal; }
  .sidebar-footer { flex-direction: column; gap: 8px; margin-top: 12px; flex: 0 0 auto; }

  /* Backdrop covers everything except the drawer when open. */
  .drawer-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, .5);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s, visibility .2s;
    z-index: 150;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
  }
  body.drawer-open .drawer-backdrop { opacity: 1; visibility: visible; }

  /* Hamburger: 44x44 touch target inside the topbar, shown only here. */
  .hamburger-btn {
    display: inline-grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: 10px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    margin-right: 4px;
    cursor: pointer;
    flex: 0 0 auto;
  }
  .hamburger-btn:focus-visible {
    outline: 2px solid var(--accent, #4f46e5);
    outline-offset: 2px;
  }

  /* Close-X inside the drawer header (visible only when drawer open). */
  .sidebar .sidebar-logo { position: relative; }
  .drawer-close {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 36px;
    height: 36px;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    display: inline-grid;
    place-items: center;
    cursor: pointer;
  }
  .drawer-close:focus-visible {
    outline: 2px solid var(--accent, #4f46e5);
    outline-offset: 2px;
  }

  /* Sticky topbar so the hamburger is always reachable while scrolling. */
  .topbar {
    position: sticky;
    top: 0;
    z-index: 80;
    background: var(--bg);
  }
}
/* Desktop: hide the drawer chrome entirely. */
@media (min-width: 901px) {
  .hamburger-btn { display: none; }
  .drawer-backdrop { display: none; }
  .drawer-close { display: none; }
}

/* Reduced motion: no slide animation. */
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .sidebar { transition: none; }
  .drawer-backdrop { transition: none; }
}

/* --------------------------------------------------------------------------
   Card-view tables (<=640px, phone tier only)
   --------------------------------------------------------------------------
   On phones, every row in a data-heavy table becomes a stacked card with
   label/value pairs. The label comes from each <td>'s data-label attr
   (which the renderer must set — see source-page.js for the pattern).

   Class hooks covered:
     .src-tbl      (source-page.js / hk-bidding-page.js)
     .data-table   (drivers / companies / vehicles / etc.)
     .tours-table  (dashboard / driver detail modals)
     .nd-tbl       (dashboard Next Deliveries)
     .card-table   (generic class new code can opt-in via)

   If a <td> has no data-label, the ::before pseudo collapses so the value
   takes the full width — no orphan empty-label column.
   -------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .src-tbl, .data-table, .tours-table, .nd-tbl, .card-table { display: block; min-width: 0; }
  .src-tbl thead, .data-table thead, .tours-table thead, .nd-tbl thead, .card-table thead { display: none; }
  .src-tbl tbody, .data-table tbody, .tours-table tbody, .nd-tbl tbody, .card-table tbody { display: block; }

  .src-tbl tr, .data-table tr, .tours-table tr, .nd-tbl tr, .card-table tr {
    display: block;
    padding: 12px 14px;
    margin-bottom: 10px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 10px);
    box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
  }

  .src-tbl td, .data-table td, .tours-table td, .nd-tbl td, .card-table td {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px;
    padding: 6px 0;
    border: 0;
    text-align: right;
    min-height: 0;
    white-space: normal;
    word-break: break-word;
  }

  .src-tbl td::before, .data-table td::before,
  .tours-table td::before, .nd-tbl td::before, .card-table td::before {
    content: attr(data-label);
    flex: 0 0 40%;
    text-align: left;
    font-size: 11px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-muted);
    font-weight: 700;
  }

  /* If a <td> has no data-label, suppress the empty pseudo so the value
     gets the whole row. Renderers should still set data-label everywhere
     for consistency. */
  .src-tbl td:not([data-label])::before,
  .data-table td:not([data-label])::before,
  .tours-table td:not([data-label])::before,
  .nd-tbl td:not([data-label])::before,
  .card-table td:not([data-label])::before { content: none; display: none; }

  /* Action cells span both columns so buttons get full width. */
  .src-tbl td.col-actions, .data-table td.col-actions,
  .src-tbl td[data-label="Actions"], .data-table td[data-label="Actions"],
  .tours-table td.col-actions, .card-table td.col-actions {
    flex-direction: column;
    align-items: stretch;
    text-align: left;
    gap: 8px;
  }
  .src-tbl td.col-actions::before, .data-table td.col-actions::before,
  .tours-table td.col-actions::before, .card-table td.col-actions::before {
    display: none;
  }

  /* "No data" empty-row pattern (single <td colspan="N">). Collapse to a
     centered single-line message so we don't render a weird tall card. */
  .src-tbl tr.empty-row, .data-table tr.empty-row,
  .tours-table tr.empty-row, .nd-tbl tr.empty-row,
  .card-table tr.empty-row {
    text-align: center;
    padding: 14px;
  }
  .src-tbl tr.empty-row td, .data-table tr.empty-row td,
  .tours-table tr.empty-row td, .nd-tbl tr.empty-row td,
  .card-table tr.empty-row td {
    display: block;
    text-align: center;
  }
  .src-tbl tr.empty-row td::before, .data-table tr.empty-row td::before,
  .tours-table tr.empty-row td::before, .nd-tbl tr.empty-row td::before,
  .card-table tr.empty-row td::before { display: none; }

  /* Override style.css min-width:720px on tours-table / data-table so the
     card view actually fits the viewport. */
  table.tours-table, table.data-table { min-width: 0; }
  .table-wrap { overflow-x: visible; }
}

/* --------------------------------------------------------------------------
   Full-screen modals (<=640px)
   --------------------------------------------------------------------------
   On phones, modals stop being centered cards and become full-screen
   sheets. Header stays at the top, footer at the bottom, body scrolls.
   Applies to the shared .modal/.modal-backdrop plus the inline variants
   used by source-page.js (.src-modal) and assignments.js (.rps-modal).
   -------------------------------------------------------------------------- */
@media (max-width: 640px) {
  .modal-backdrop, .src-modal-backdrop, .rps-modal-backdrop {
    padding: 0;
    align-items: stretch;
    justify-content: stretch;
  }

  .modal, .src-modal, .rps-modal {
    width: 100vw;
    max-width: 100vw;
    height: 100vh;
    max-height: 100vh;
    min-height: 100vh;
    border-radius: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  .modal .modal-head, .src-modal .src-modal-head,
  .rps-modal .rps-modal-head, .modal-head {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--surface);
    flex: 0 0 auto;
  }

  .modal .modal-body, .src-modal .src-modal-body,
  .rps-modal .rps-modal-body, .modal-body {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  .modal .modal-foot, .src-modal .src-modal-foot,
  .rps-modal .rps-modal-foot, .modal-foot {
    position: sticky;
    bottom: 0;
    z-index: 2;
    background: var(--surface);
    flex: 0 0 auto;
    /* iOS Safari: clear the home-indicator bar so the footer buttons stay tappable. */
    padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  }
}

/* --------------------------------------------------------------------------
   Form stacking + 44px touch targets (<=640px)
   --------------------------------------------------------------------------
   On phones, flex-row form groups stack to one column so inputs get the
   full width. Buttons / selects / inputs respect a 44px min touch target
   (WCAG 2.5.5 target size, iOS HIG, Material).

   Add the class .stack-form to any container that needs explicit stacking
   beyond the catch-all rules below.
   -------------------------------------------------------------------------- */
@media (max-width: 640px) {
  /* Catch-all: any explicit "row" of inputs collapses to a column. */
  .form-row, .filters, .flex-row, .input-row,
  .book-cols-2, .book-cols-3, .stack-form,
  .form-grid, .field-row {
    flex-direction: column !important;
    grid-template-columns: 1fr !important;
    gap: 10px;
  }

  /* Inputs go full width. */
  .form-row > *, .filters > *, .flex-row > *,
  .input-row > *, .stack-form > *,
  .field-row > *, .form-grid > * { width: 100%; }

  /* 44px touch targets — the WCAG / iOS HIG minimum.
     Scoped to .btn / form controls only. Bare <button> elements like
     .icon-btn (topbar action chips, 38x38), .pill-btn (freshness pill,
     26x26), and .login-lang-btn (login page, 28px) declare their own
     explicit dimensions; applying min-height:44px globally to every
     <button> would inflate the height without inflating the width,
     producing awkward tall-narrow chips that still fail WCAG 2.5.5
     because the WIDTH stays below 44px. Pages that DO want the 44px
     minimum on a bare button can opt in with the .btn class. */
  .btn, button.btn, input[type="text"], input[type="email"],
  input[type="password"], input[type="search"], input[type="number"],
  input[type="tel"], input[type="url"], input[type="date"],
  input[type="time"], input[type="datetime-local"], select, textarea {
    min-height: 44px;
  }
  /* Compact "xs" buttons stay smaller — they live inside dense rows like
     the notification dropdown and we don't want them ballooning. */
  .btn-xs { min-height: 32px; }

  /* Number-input chevrons are tiny by default — make the field roomy. */
  input[type="number"] { font-size: 16px; /* avoid iOS zoom-on-focus */ }
  input[type="text"], input[type="email"], input[type="password"],
  input[type="search"], input[type="tel"], input[type="url"],
  select, textarea { font-size: 16px; /* avoid iOS zoom-on-focus */ }

  /* Main padding shrinks on phone so cards get edge-to-edge room. */
  .main { padding: 14px; }
  .topbar { padding: 12px 14px; gap: 8px; }

  /* Page header stacks (title + actions). */
  .page-header { flex-direction: column; align-items: flex-start; gap: 10px; }

  /* KPI grid drops to single column on phones (style.css already does this
     at 780px, but our phone tier is 640 — kept explicit so the rule fires
     even if the legacy rule is removed later). */
  .kpis { grid-template-columns: 1fr; }
  .grid-equal-2 { grid-template-columns: 1fr; }
  .grid-2 { grid-template-columns: 1fr; }

  /* Mini-stat grids inside the tour / vehicle detail modals — class hooks
     replace inline `style="display:grid;grid-template-columns:repeat(4,1fr)"`
     so phones get a single column instead of crushed 4-up tiles. Desktop
     rules below restore the original repeat(N,1fr) layout. */
  .mini-stat-grid { grid-template-columns: 1fr !important; }
}

/* Mini-stat grids — desktop / tablet sizing. Class hooks for the previously
   inline-styled `repeat(4,1fr)` / `repeat(2,1fr)` mini-stat rows in
   app.js's openTourDetail / openVehicleDetail. */
.mini-stat-grid { display: grid; gap: 10px; }
.mini-stat-grid.grid-4 { grid-template-columns: repeat(4, 1fr); }
.mini-stat-grid.grid-2 { grid-template-columns: repeat(2, 1fr); }

/* Narrow modal variant: above the phone tier (>=641px) cap the .src-modal
   width so wider phones / tablets / desktops see a centered 480px card
   instead of an edge-to-edge sheet. Below 641px the phone-tier rule above
   (.modal, .src-modal, .rps-modal { width: 100vw; ... }) wins and the
   modal stays full-screen. */
@media (min-width: 641px) {
  .src-modal.src-modal-narrow { max-width: 480px; }
}

/* Body scroll lock while the drawer is open. The JS Drawer state machine
   ALSO sets <html style="overflow:hidden"> directly (Drawer.open() in
   app.js), so this rule is a belt-and-braces fallback for the body
   element specifically. The legacy html.drawer-scroll-lock selector was
   removed because nothing sets that class — open()/close() write the
   inline style synchronously, atomically with the body class toggle. */
body.drawer-open { overflow: hidden; }

/* Body remains scrollable as normal when drawer is closed — we DO NOT
   set overflow:hidden on body globally. */
