*{
margin:0;
padding:0;
box-sizing:border-box;
font-family:Poppins,sans-serif;
}

body{

background:#f5f6fa;

/* Every navigation here is a real full-page reload (no SPA routing), which
   otherwise reads as a stark, un-web-like snap between pages — this fades
   the freshly-loaded page in instead. Pure CSS (no JS class-toggle needed,
   so it can never get stuck at opacity:0 if some other script errors),
   kept short so it smooths the transition without adding perceptible
   delay of its own. See public/js/pageLoading.js for the matching
   top-loading-bar that covers the OTHER half of this — the wait while the
   next page is still on its way over the network. */
animation:pageFadeIn .18s ease-out;

}

@keyframes pageFadeIn{

from{opacity:0;}

to{opacity:1;}

}

/* Top loading bar (public/js/pageLoading.js) — shown the instant a link is
   clicked or a form submitted, since a full-page navigation gives the
   browser nothing to paint until the new page arrives; this is the only
   feedback a user gets in that gap otherwise, which is exactly what read
   as "did my tap even register?" lag. */
#pageLoadingBar{

position:fixed;

top:0;

left:0;

height:3px;

width:0;

background:#D4AF37;

z-index:2000;

transition:width .3s ease-out,opacity .2s ease-in;

box-shadow:0 0 8px rgba(212,175,55,.6);

}

.layout{

display:flex;

min-height:100vh;

}

.sidebar{

width:260px;

background:#212529;

color:white;

padding:20px;

}

.logo{

text-align:center;

margin-bottom:30px;

color:#D4AF37;

}

.sidebar-menu{

list-style:none;

padding:0;

margin:0;

}

.sidebar-menu>li{

margin-bottom:6px;

}

.sidebar-menu a{

display:flex;

align-items:center;

gap:12px;

padding:12px 16px;

color:#d8d8d8;

text-decoration:none;

border-radius:10px;

transition:.25s;

font-weight:500;

}

.sidebar-menu a:hover{

background:#343a40;

color:#fff;

}

.sidebar-menu a.active{

background:#D4AF37;

color:#111;

font-weight:600;

}

.content{

flex:1;

/* Real bug found 2026-08-06: a flex item defaults to min-width:auto, which
   lets it grow past its own allotted space to fit an intrinsically-wide
   child instead of shrinking/clipping it — exactly what a data-heavy
   Orders table (10+ columns with real data) does on desktop, dragging
   this ENTIRE flex item (and so the whole page) wider than the viewport,
   with .card:has(table)'s own overflow-x:auto below powerless to help
   since there was nothing constraining the width it was supposed to
   scroll within. min-width:0 lets this shrink to its real flex-assigned
   width, so a wide table properly scrolls inside its own card instead of
   stretching the page — confirmed this was also silently pushing a
   flex-positioned element (Orders' own justify-content-between page-title
   row) off past the right edge of the screen entirely on desktop. */
min-width:0;

}

/* Real bug found 2026-08-06 (same investigation as the min-width fix just
   above): confirmed via computed-style inspection that this exact rule
   already exists elsewhere in this file (".card:has(table){overflow-x:
   auto}"), but it's declared INSIDE the @media(max-width:900px) block
   further down, so it only ever applied on small screens. On desktop,
   overflow-x stayed at the browser default (visible) — so even with
   .content's own min-width:0 fix above letting this card shrink to its
   rightful width, a data-heavy table (10+ columns with real order data)
   still just rendered past the card's own right edge instead of scrolling
   within it. Deliberately NOT duplicating the mobile block's companion
   ".card table{min-width:640px}" here — that exists to keep a table's
   columns from getting too cramped on a narrow screen, which doesn't apply
   on desktop, where a table is usually already wider than 640px on its own. */
.card:has(table){
overflow-x:auto;
}


.dashboard-card{

padding:25px;

border:none;

border-radius:15px;

display:flex;

justify-content:space-between;

align-items:center;

box-shadow:0 8px 20px rgba(0,0,0,.08);

transition:.3s;

cursor:pointer;

}

.dashboard-card:hover{

transform:translateY(-5px);

}

.dashboard-card h2{

font-weight:700;

margin-top:8px;

}

.card-icon{

font-size:45px;

opacity:.25;

}

.green{

background:#d1f7df;

}

.blue{

background:#d9ebff;

}

.gold{

background:#fff3cd;

}

.purple{

background:#e8dcff;

}

.card{

border:none;

border-radius:15px;

box-shadow:0 8px 20px rgba(0,0,0,.06);

}
.logo-area{

text-align:center;

padding-bottom:20px;

border-bottom:1px solid rgba(255,255,255,.08);

}

.logo{

width:70px;

height:70px;

margin-bottom:10px;

/* A seller's own uploaded logo (partials/sidebar.ejs's user.hasLogo branch)
   is rarely a perfect square — without this it was forced to fill 70x70
   and came out stretched/awkwardly cropped instead of a clean round avatar.
   Same object-fit:cover + border-radius:50% treatment as the bottom nav's
   own logo FAB (.mbn-fab-logo img) for a consistent look. Harmless for the
   default square Peeptoon logo too. */
border-radius:50%;

object-fit:cover;

}

.logo-area h4{

color:#D4AF37;

margin:0;

}

.logo-area small{

color:#999;

}

.profile-box{

display:flex;

align-items:center;

margin:20px 0;

padding:15px;

background:#2d3238;

border-radius:12px;

}

.avatar{

width:45px;

height:45px;

background:#D4AF37;

color:black;

font-weight:bold;

display:flex;

align-items:center;

justify-content:center;

border-radius:50%;

margin-right:12px;

}

.menu-title{

font-size:12px;

color:#888;

margin:20px 0 10px;

letter-spacing:1px;

}
.topbar{

height:75px;

background:white;

display:flex;

justify-content:space-between;

align-items:center;

padding:0 25px;

box-shadow:0 3px 12px rgba(0,0,0,.08);

}

.left-section{

display:flex;

align-items:center;

gap:15px;

}

.menu-btn{

width:45px;

height:45px;

border:none;

background:#f5f6fa;

border-radius:10px;

font-size:20px;

}

.search-box{

display:flex;

align-items:center;

background:#f5f6fa;

padding:12px 15px;

border-radius:12px;

width:420px;

position:relative;

}

/* Instant search-preview card — per explicit request 2026-08-13, modeled on
   a courier-aggregator's hover-preview: typing an AWB/order id/reference/
   phone into the topbar search box shows the single latest matching
   order's key details without a full page reload. Anchored to .search-box
   (position:relative above) so it sits directly under the input on both
   desktop and the mobile topbar layout. */
.topbar-search-preview{
position:absolute;
top:calc(100% + 6px);
left:0;
right:0;
background:#fff;
border:1px solid #e5e7eb;
border-radius:12px;
box-shadow:0 10px 30px rgba(0,0,0,.15);
padding:14px 16px;
z-index:1050;
color:#1a1a1a;
}
.topbar-search-preview .tsp-row1{
display:flex;
justify-content:space-between;
align-items:flex-start;
gap:10px;
}
.topbar-search-preview .tsp-ref{
font-weight:600;
font-size:0.95rem;
}
.topbar-search-preview .tsp-meta{
color:#6c757d;
font-size:0.82rem;
margin-top:2px;
}
.topbar-search-preview .tsp-more{
color:#6c757d;
font-size:0.78rem;
margin-top:8px;
padding-top:8px;
border-top:1px solid #eee;
}
.topbar-search-preview .tsp-empty{
color:#6c757d;
font-size:0.85rem;
}

.search-box input{

border:none;

outline:none;

background:none;

width:100%;

margin-left:10px;

}

.right-section{

display:flex;

align-items:center;

gap:15px;

}

.icon-btn{

width:45px;

height:45px;

border:none;

background:#f5f6fa;

border-radius:12px;

font-size:20px;

position:relative;

display:flex;

align-items:center;

justify-content:center;

text-decoration:none;

color:inherit;

}

.notification span{

position:absolute;

top:-5px;

right:-5px;

background:red;

color:white;

width:22px;

height:22px;

border-radius:50%;

font-size:12px;

display:flex;

justify-content:center;

align-items:center;

}

.wallet-btn{

background:#D4AF37;

border:none;

padding:12px 22px;

font-weight:600;

border-radius:12px;

display:inline-block;

text-decoration:none;

color:#000;

}

.profile{

display:flex;

align-items:center;

gap:12px;

padding:8px 15px;

background:#f5f6fa;

border-radius:12px;

cursor:pointer;

}

.status-box{

padding:8px 15px;

border-radius:50px;

font-size:13px;

display:flex;

align-items:center;

gap:10px;

}

.status-box span{

width:10px;

height:10px;

background:#2ecc71;

border-radius:50%;

}

.online{

background:#e8fff0;

color:#2ecc71;

}

.status-box.gold{

background:#fdf3d9;

color:#a67c00;

}

.status-box.gold span{

background:#D4AF37;

}
.sidebar{

transition:.3s;

}

.sidebar.close{

width:80px;

overflow:hidden;

}

/* Collapsed state previously just shrank the sidebar's width with
   overflow:hidden, leaving every label's text still rendered and simply
   clipped mid-word (e.g. "Peep", "Order...") instead of a clean icon-only
   rail — this hides each label properly and centers the icons instead. */
.sidebar.close .logo-area h4,
.sidebar.close .logo-area small,
.sidebar.close .profile-box > div:not(.avatar),
.sidebar.close .menu-title{
    display:none;
}

.sidebar.close .profile-box{
    justify-content:center;
    padding:10px;
}

.sidebar.close .avatar{
    margin-right:0;
}

.sidebar.close .sidebar-menu a{
    justify-content:center;
    font-size:0;
    padding:12px 0;
}

.sidebar.close .sidebar-menu a i{
    font-size:1.1rem;
}

.sidebar.close .menu-toggle{
    justify-content:center;
}

.sidebar.close .menu-toggle span{
    font-size:0;
}

.sidebar.close .menu-toggle span i{
    font-size:1.1rem;
}

.sidebar.close .menu-toggle .arrow,
.sidebar.close .menu-item.open .submenu{
    display:none;
}

.sidebar.close{
    padding:20px 8px;
}

.sidebar.close .logo-area{
    padding-bottom:15px;
}

.sidebar.close .logo{
    width:36px;
    height:36px;
    margin-bottom:0;
}

.dark{

background:#111827;

color:white;

}

.dark .topbar{

background:#1f2937;

color:white;

}

.dark .card{

background:#1f2937;

color:white;

}

.dark .sidebar-menu a,
.dark .text-muted,
.dark small {
color:#9ca3af !important;
}

.dark table {
color:#e5e7eb;
}

.dark .form-control,
.dark .form-select,
.dark textarea {
background:#111827;
color:white;
border-color:#374151;
}

.dark .form-control::placeholder {
color:#6b7280;
}

.dark .modal-content,
.dark .dropdown-menu {
background:#1f2937;
color:white;
}

.dark .dropdown-item {
color:#e5e7eb;
}

.dark .dropdown-item:hover {
background:#374151;
color:white;
}

.dark .table-hover>tbody>tr:hover>* {
background:#273449;
color:white;
}

.dark .btn-outline-dark {
color:#e5e7eb;
border-color:#6b7280;
}

.dark hr,
.dark .dropdown-divider {
border-color:#374151;
}
.stepper{

display:flex;

align-items:center;

justify-content:space-between;

}

.step{

width:70px;

height:70px;

background:#e9ecef;

border-radius:50%;

display:flex;

align-items:center;

justify-content:center;

flex-direction:column;

font-weight:600;

}

.step.active{

background:#D4AF37;

color:black;

}

/* Bootstrap's stock nav-tabs default to its own blue for the active tab and
   every link — overridden here to the same peeptoon gold (#D4AF37) already
   used for .sidebar-menu a.active/.step.active, so every tab strip in the
   app (Orders' Fresh/Pending/Picked/etc.) reads as ours, not generic
   Bootstrap. Applies site-wide, not just one page, since this is a one-off
   .nav-tabs rule rather than a per-view override. */
.nav-tabs .nav-link{

color:#6c757d;

}

.nav-tabs .nav-link:hover{

color:#D4AF37;

border-color:transparent;

}

.nav-tabs .nav-link.active{

color:#111;

background:#D4AF37;

border-color:#D4AF37;

}

/* Real complaint 2026-08-08 ("all in one line for mobile too... it break") —
   a 5-tab strip (Orders' All/Pending/Picked/Delivered/Cancelled, same
   pattern on Local/Tickets/Seller Requests) doesn't fit one line on a phone
   screen, and Bootstrap's default flex-wrap dropped the overflow tabs onto
   a second, visually broken row instead. Site-wide (same reasoning as the
   gold-branding rule above — every .nav-tabs strip in the app gets this,
   not just Orders'), scrolls sideways instead of wrapping below this
   breakpoint — a swipe reveals the rest, same pattern most apps already use
   for a tab bar that doesn't fit. Desktop is untouched (wrapping was never
   a problem there). */
@media (max-width:767.98px){
.nav-tabs{
flex-wrap:nowrap;
overflow-x:auto;
overflow-y:hidden;
-webkit-overflow-scrolling:touch;
flex-shrink:0;
}
.nav-tabs .nav-item{
flex-shrink:0;
}
.nav-tabs .nav-link{
white-space:nowrap;
}
}

.step p{

font-size:12px;

margin-top:5px;

}

.line{

flex:1;

height:3px;

background:#ddd;

margin:0 10px;

}

.submenu-link{

color:#bbb;

text-decoration:none;

display:block;

width:100%;

}

.submenu-link:hover{

color:white;

}
.submenu{

    display:none;

    list-style:none;

    padding-left:20px;

    margin:0;

}

.submenu {

    display: none;

    list-style: none;

    margin: 0;

    padding-left: 20px;

}

.menu-item.open .submenu {

    display: block;

}

.arrow {

    transition: .3s;

}

.menu-item.open .arrow {

    transform: rotate(180deg);

}

.menu-toggle{

display:flex;

justify-content:space-between;

align-items:center;

padding:12px 16px;

border-radius:10px;

cursor:pointer;

color:#d8d8d8;

transition:.25s;

}

.menu-toggle:hover{

background:#343a40;

}

.submenu{

display:none;

list-style:none;

padding-left:20px;

margin-top:5px;

}

.menu-item.open .submenu{

display:block;

}

.submenu li{

margin:2px 0;

padding:0;

}

.submenu a{

padding:9px 15px;

font-size:14px;

color:#bdbdbd;

}

.submenu a:hover{

background:#2e3238;

color:#fff;

}
.sidebar a{

text-decoration:none !important;

}

.login-page{

min-height:100vh;

display:flex;

align-items:center;

justify-content:center;

}

.login-card{

width:380px;

background:white;

padding:35px;

border-radius:15px;

box-shadow:0 8px 20px rgba(0,0,0,.08);

text-align:center;

}

.login-logo{

width:70px;

margin-bottom:10px;

}

.login-card h4{

margin-bottom:20px;

}

.login-card form{

text-align:left;

}

/* ==========================================================================
   Interface polish pass — 2026-08-04 ("every page so old and basic... make
   it look classic and bold"). Deliberately touches ONLY weight/spacing/
   shadow/radius/transform — never a color/background value — so it can
   never fight the .dark overrides above (dark mode) or get silently undone
   by the mobile @media block below (which only ever tunes size/padding for
   small screens, never weight/shadow/radius), and layers cleanly on top of
   both instead of replacing anything. Unscoped (not inside a media query)
   on purpose: applies to the app AND the Android/iOS build identically,
   since both are just this same CSS rendered in a WebView — no native
   change needed for a visual update. */

h1,h2,h3,h4,h5,h6{
font-weight:700;
letter-spacing:-.01em;
}

/* Every page's own title is a bare <h3> right at the top of .content (see
   views/dashboard.ejs, orders.ejs, tickets.ejs, etc.) — a small gold
   underline turns that one consistent element into a real masthead across
   all 50 views at once, without touching any individual view's markup. */
.content h3{
font-weight:700;
letter-spacing:-.015em;
padding-bottom:14px;
margin-bottom:22px;
position:relative;
}

.content h3::after{
content:"";
position:absolute;
left:0;
bottom:0;
width:46px;
height:4px;
border-radius:2px;
background:#D4AF37;
}

/* Layered shadow (soft ambient + tighter definition) reads as real depth
   instead of the previous single flat blur — same "raise on hover" this app
   already had on .dashboard-card, now shared by every plain .card too. */
.card{
border-radius:16px;
box-shadow:0 12px 28px rgba(0,0,0,.08),0 2px 6px rgba(0,0,0,.05);
transition:box-shadow .25s ease,transform .25s ease;
}

.dashboard-card{
border-radius:16px;
box-shadow:0 12px 28px rgba(0,0,0,.09),0 2px 6px rgba(0,0,0,.05);
}

.dashboard-card:hover{
box-shadow:0 18px 36px rgba(0,0,0,.13),0 3px 8px rgba(0,0,0,.06);
}

.dashboard-card h2{
font-size:2.1rem;
letter-spacing:-.02em;
}

/* The small label above each dashboard number ("Total Orders", "Delivered"
   etc.) — a bold, spaced-out uppercase treatment reads as a deliberate
   masthead label instead of plain paragraph text sitting above a number. */
.dashboard-card > div > small{
font-weight:600;
letter-spacing:.03em;
text-transform:uppercase;
font-size:.72rem;
}

/* Buttons — bolder weight and a touch more shape everywhere, regardless of
   which Bootstrap variant/color a given page already uses (this pass is
   about weight/shape, not re-coloring any button). */
.btn{
font-weight:600;
border-radius:10px;
letter-spacing:.01em;
transition:transform .15s ease,box-shadow .15s ease;
}

.btn:not(.btn-sm):not(.btn-link):active{
transform:translateY(1px);
}

.wallet-btn{
font-weight:700;
box-shadow:0 6px 16px rgba(212,175,55,.35);
transition:transform .2s ease,box-shadow .2s ease;
}

.wallet-btn:hover{
transform:translateY(-2px);
box-shadow:0 10px 22px rgba(212,175,55,.45);
}

/* Sidebar — bolder baseline nav weight, and a real lifted-tab shadow on the
   active item instead of a flat gold fill, so the current page reads as
   clearly "selected," not just differently colored. */
.sidebar-menu a{
font-weight:600;
}

.sidebar-menu a.active{
font-weight:700;
box-shadow:0 6px 16px rgba(212,175,55,.35);
}

.profile-box b{
font-weight:700;
letter-spacing:-.01em;
}

.profile b{
font-weight:700;
}

/* Table headers — bold, spaced, uppercase small caps is the classic
   "admin ledger" masthead look; scoped to real data tables only (not modal
   headers etc., which never use <thead>/<th> here anyway). Untouched on
   mobile's .table-mobile-cards view, which hides <thead> entirely already. */
.table thead th,
table thead th{
font-weight:700;
letter-spacing:.03em;
text-transform:uppercase;
font-size:.72rem;
color:#495057;
border-bottom-width:2px;
}

body.dark .table thead th,
body.dark table thead th{
color:#adb5bd;
}

/* Status pills (Booked/Delivered/Cancelled/Draft/etc. badges) — bolder and
   a touch more spaced-out, same "confident, not flat" intent as everything
   above. Font-size deliberately untouched here (the mobile @media block
   already owns that at .7rem on small screens). */
.badge{
font-weight:600;
letter-spacing:.02em;
}

/* Filter inputs (Orders' From/To/Courier/Warehouse/Seller row, etc.) — a
   crisper focus ring in the brand gold instead of Bootstrap's default blue
   glow, so keyboard/tap focus itself reads as "ours." */
.form-control:focus,
.form-select:focus{
border-color:#D4AF37;
box-shadow:0 0 0 .2rem rgba(212,175,55,.25);
}

/* Real gap found live 2026-08-10 ("we click but not visible click") —
   the Create Shipment wizard's courier list (both B2C and B2B) checked
   the radio input itself on click, but the ROW (the actual <label>
   that's visible) never got any styling for that — a selected courier
   looked identical to every other row aside from a tiny filled radio
   dot easy to miss on a long list. Brand gold, not Bootstrap's default
   blue .active treatment, matching every other selected/active state
   in this app. */
.courier-row-selected{
border-color:#D4AF37 !important;
background:rgba(212,175,55,.1);
box-shadow:inset 0 0 0 1px #D4AF37;
}

.login-card{
border-radius:20px;
box-shadow:0 20px 50px rgba(0,0,0,.12),0 4px 12px rgba(0,0,0,.06);
}

/* Login/Sign Up switcher — per explicit request 2026-08-05 ("new user
   confused after visit our page, mention clearly... sign up"): the only
   previous way to find Sign Up from Login was a small plain-text link
   buried below the whole form, PLUS a one-time bonus banner that never
   shows again once a browser's seen it once (localStorage-gated) — a
   returning/confused visitor had no permanent, obvious affordance at all.
   This sits right under the logo/title on both login.ejs and signup.ejs,
   unconditional (no JS/localStorage dependency), so "which page am I on,
   and how do I get to the other one" is answered before anything else on
   the page. */
.auth-toggle{
display:flex;
gap:6px;
background:#f5f6fa;
border-radius:12px;
padding:4px;
margin-bottom:20px;
}

.auth-toggle a,
.auth-toggle span{
flex:1;
text-align:center;
padding:10px 0;
border-radius:9px;
font-weight:700;
text-decoration:none;
color:#6c757d;
}

.auth-toggle a:hover{
color:#212529;
}

.auth-toggle span.active{
background:#D4AF37;
color:#111;
box-shadow:0 4px 10px rgba(212,175,55,.35);
}

/* Unified "alternate sign-in method" button — per explicit request
   2026-08-14 ("login with whatsapp and continue with google both in a
   same align, this design is so husky... make simple and classy, same as
   signup"). Continue with Google and Login/Sign Up with WhatsApp OTP used
   Bootstrap's stock btn-outline-dark/btn-outline-success (a harsh black
   border on one, a green border on the other) — read as two unrelated
   buttons instead of a matched pair of alternate sign-in options. One
   shared neutral style for both now, on both login.ejs and signup.ejs;
   the WhatsApp icon keeps a small brand-green accent (set inline in the
   view, not here) so the two are still tellable apart at a glance —
   everything else about the button (border, background, text weight,
   radius) matches. */
.auth-alt-btn{
display:flex;
align-items:center;
justify-content:center;
gap:8px;
width:100%;
padding:11px 0;
border-radius:12px;
border:1.5px solid #e1e4e8;
background:#fff;
color:#3c4043;
font-weight:600;
transition:background .15s ease,border-color .15s ease;
}

.auth-alt-btn:hover{
background:#f8f9fa;
border-color:#c7cbd1;
color:#212529;
}

.auth-alt-btn:disabled{
opacity:.65;
}

.login-card h4{
font-weight:700;
letter-spacing:-.015em;
}

/* Mobile responsiveness (added — this app previously had zero breakpoints) */

@media (max-width: 900px) {

/* Per explicit request 2026-08-12 — extends the same compact, native-app-
   style sizing (WhatsApp/Facebook, per the user's own comparison) that
   fixed Local's pickup buttons out to every plain-sized button and form
   label/control site-wide on mobile. Bootstrap's own defaults read as a bit
   "webpage-sized" rather than "app-sized" on a phone. Deliberately leaves
   .btn-sm/.btn-lg alone — those are ALREADY a deliberate size choice at
   each call site (a small icon-action button vs. a large primary CTA like
   "Submit Booking"/"Recharge Wallet"), not the plain, no-size-class buttons
   this is actually about. Loaded after bootstrap.min.css (see
   partials/header.ejs's own <link> order) so this wins ties on specificity
   — the :not() exclusions are what stop it from also shrinking .btn-lg (see
   this rule's own comment for why that matters) or re-inflating .btn-sm
   past its own already-smaller Bootstrap default. */
.btn:not(.btn-sm):not(.btn-lg) {
font-size: 0.875rem;
padding: .375rem .9rem;
}

.form-label,
.form-check-label,
label {
font-size: 0.85rem;
}

.form-control,
.form-select {
font-size: 0.9rem;
}

/* Per explicit request 2026-08-12: the top .menu-btn (topbar.ejs) and the
   new bottom nav's own Menu button (partials/bottomNav.ejs) both open the
   exact same sidebar drawer — redundant to show both on a phone. Hidden
   here (mobile only, this same 900px breakpoint) rather than removed from
   the DOM entirely: mobileBottomNav.js's Menu button calls this button's
   own .click() programmatically, which still works fine on a
   display:none element (only a real tap is disabled, not a JS-triggered
   click) — see that script's own comment for why it reuses this rather
   than reimplementing the drawer toggle. Desktop keeps it — no bottom nav
   there, and it's also desktop's only way to collapse/expand the sidebar
   (app.js's own isMobile() branch), a function nothing else replicates.
   */
.menu-btn {
display: none;
}

.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100vh;
z-index: 1050;
width: 260px;
transform: translateX(-100%);
transition: transform .3s;
overflow-y: auto;
}

.sidebar.mobile-open {
transform: translateX(0);
}

.sidebar.close {
width: 260px;
overflow-y: auto;
}

.sidebar-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,.4);
z-index: 1040;
}

.sidebar-backdrop.show {
display: block;
}

.content {
width: 100%;
}

.topbar {
height: auto;
flex-wrap: wrap;
gap: 10px;
padding: 12px 15px;
}

.left-section {
flex: 1 1 auto;
min-width: 0;
}

.search-box {
width: 100%;
order: 3;
}

.right-section {
flex-wrap: wrap;
gap: 8px;
}

.profile > div {
display: none;
}

/* Per explicit instruction (2026-07-26): "make everything small... not
   zoom view" — Bootstrap's default form-control/btn/card sizing is built
   for desktop and reads oversized/"zoomed in" on a phone. Global (not
   per-page) so every page gets it at once instead of needing individual
   fixes. Deliberately does NOT touch input/select font-size below 16px —
   iOS Safari auto-zooms the whole page in when a focused text input/select
   has a computed font-size under 16px, which would make the exact "zoom
   view" complaint worse, not better. Shrinking padding/height/labels/
   buttons/headings gets the compact feel without ever triggering that. */
.form-control,
.form-select {
padding: 0.375rem 0.65rem;
font-size: 1rem;
}

.form-label {
font-size: 0.8rem;
margin-bottom: 0.25rem;
}

.btn {
padding: 0.35rem 0.75rem;
font-size: 0.85rem;
}

.btn-sm {
padding: 0.2rem 0.5rem;
font-size: 0.78rem;
}

h3 {
font-size: 1.25rem;
}

h5 {
font-size: 1.05rem;
}

.card {
border-radius: 10px;
}

.card.p-3 {
padding: 0.75rem !important;
}

.badge {
font-size: 0.7rem;
}

/* Every explicit inline gap-2 (0.5rem) between filter fields felt oversized
   stacked vertically on a narrow phone — halved here, still comfortable to
   tap. */
.d-flex.flex-wrap.gap-2 {
gap: 0.35rem !important;
}

/* Every data table on this app sits inside a .card — scrolling that
   container instead of touching every view's table markup individually.
   Scoped to :has(table) so a card with no table (e.g. Create Shipment's
   plain form) never becomes horizontally scrollable — confirmed this was
   the real cause of the Create Shipment page looking cut off/shifted on a
   real phone: the blanket ".card" rule made that non-table card scrollable
   too, and the mobile browser was auto-scrolling it sideways to bring a
   focused/filled input into view, dragging every label off-screen with it. */
.card:has(table) {
overflow-x: auto;
}

.card table {
min-width: 640px;
}

/* Per explicit instruction (2026-07-26): "classy", Instagram/Facebook-feed-
   style layout on mobile instead of a wide table forcing a sideways scroll
   — degrades a normal <table> into one bordered card per row, no header
   row, no horizontal scroll, everything in one vertical read. Opt-in via
   .table-mobile-cards (overrides the generic .card table min-width above
   for just this table) so it never affects any other table in the app —
   apply it to a specific <table> to convert it, one at a time. Each <td>
   needs data-label="<column header text>" (see views/orders.ejs for the
   reference implementation) — shown as a small bold label beside its
   value, replacing the header row this hides entirely at this width. Rows
   that aren't real data (a section-divider row, an expandable detail
   panel) are excluded via :not() below so they still just span full width
   plainly, undecorated.

   Real bug found 2026-07-26: this was written as plain ".table-mobile-cards"
   (specificity 0,1,0), which is LESS specific than ".card table" above
   (0,1,1 — a class plus an element) — the override never actually won
   regardless of source order, so the table stayed forced to 640px wide no
   matter what. Every value span, being right-aligned inside that oversized
   row, was pushed off past the right edge of the phone screen — reading as
   "labels show, values are just gone" when they were actually sitting
   off-screen the whole time, only reachable by scrolling the whole page
   sideways. Qualifying the selector with the element AND the .card ancestor
   below matches (and beats) ".card table"'s specificity for real. */
.card table.table-mobile-cards {
min-width: 0;
}

.table-mobile-cards thead {
display: none;
}

.table-mobile-cards, .table-mobile-cards tbody {
display: block;
width: 100%;
}

/* Real bug found 2026-07-26 ("too much gap and scroll left/right"): a
   .table-card-exempt row (seller-name divider, expandable track-result row —
   both a single <td colspan="N">) never got a display override at all, so it
   kept the browser default display:table-row. A table-row directly inside a
   tbody that's forced to display:block is invalid table structure — engines
   patch it up inconsistently (an anonymous table wrapper some places, raw
   leftover table-layout sizing/gaps in others), which is exactly the stray
   blank space and horizontal scroll seen on real devices. These rows were
   only ever meant to skip the CARD styling (background/border/shadow) below,
   not skip becoming a normal block element — every row needs display:block
   under a display:block parent, exempt or not.
   */
.table-mobile-cards tbody tr.table-card-exempt {
display: block;
width: 100%;
}

.table-mobile-cards tbody tr.table-card-exempt > td {
display: block;
width: 100%;
white-space: normal;
}

.table-mobile-cards tbody tr:not(.table-card-exempt) {
display: block;
background: #fff;
border: 1px solid #e3e3e3;
border-radius: 10px;
margin-bottom: 10px;
padding: 10px 12px;
box-shadow: 0 1px 3px rgba(0,0,0,.06);
}

/* Real bug found 2026-07-26 ("gap in between text and output, box expand
   out of range"): with flex-wrap left at its default (nowrap), a value long
   enough to not fit next to its label — a full address, a long courier
   name, a nowrap Bootstrap badge/link that refuses to break — had nowhere
   to go but push the row (and the whole card, and on some devices the
   whole page) wider than the phone screen. flex-wrap: wrap lets a value
   that doesn't fit drop to its own full-width line below the label instead
   of ever forcing extra width. Paired with .td-value's overflow-wrap below
   and the badge/link override further down so nothing inside can hold a
   nowrap line wider than the screen either.

   Second real bug found 2026-07-26 ("nice on Android, still gap in the
   middle on iPhone"): justify-content: space-between pushes the label to
   the left edge and the value to the right edge of the FULL row width —
   whenever label+value together are shorter than that width (almost
   always), everything in between is blank space. That's barely visible on
   a narrow Android screen but stretches into an obvious gap on a wider
   iPhone, since it's genuinely more empty pixels, not a rendering
   difference between the two. Switched to flex-start with a small fixed
   gap so label and value always sit right next to each other — no gap on
   ANY screen width, and consistent across devices. */
.table-mobile-cards tbody tr:not(.table-card-exempt) > td {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
gap: 4px 6px;
border: none;
border-bottom: 1px solid #f2f2f2;
padding: 6px 0;
font-size: 0.86rem;
line-height: 1.3;
}

.table-mobile-cards tbody tr:not(.table-card-exempt) > td:last-child {
border-bottom: none;
}

.table-mobile-cards tbody tr td[data-label]::before {
content: attr(data-label) ":";
font-weight: 600;
color: #6c757d;
flex-shrink: 0;
}

/* Real bug found 2026-07-26: the actual cell value was a bare text node
   sitting next to the ::before label inside a flex container — some
   WebView/browser engines don't reliably turn a raw text node into its own
   flex item alongside a ::before pseudo-element, so the label showed but
   the value silently didn't (every field looked blank except AWB, which
   already had a real <a> element instead of bare text). Every cell's real
   content is now explicitly wrapped in <span class="td-value"> (see
   views/orders.ejs) — a real element is unambiguous everywhere. */
.table-mobile-cards .td-value {
flex: 0 1 auto;
min-width: 0;
text-align: left;
overflow-wrap: anywhere;
}

/* Bootstrap's .badge and plain links default to white-space: nowrap —
   fine for a short status word, but a long one (the weight-issue mismatch
   badge, a full courier/warehouse name as a link) refuses to break and
   forces the row wider than the screen no matter what the flex rules
   above allow. Anything sitting inside a value must be allowed to wrap. */
.table-mobile-cards .td-value .badge,
.table-mobile-cards .td-value a {
white-space: normal;
}

/* Action/checkbox cells read better right-aligned as a whole (a dropdown
   button, a lone checkbox) than split into a label/value pair like every
   other field. */
.table-mobile-cards tbody tr > td.table-card-full-width {
justify-content: flex-end;
}

body.dark .table-mobile-cards tbody tr:not(.table-card-exempt) {
background: #2b3035;
border-color: #3a3f44;
}

body.dark .table-mobile-cards tbody tr:not(.table-card-exempt) > td {
border-bottom-color: #3a3f44;
}

body.dark .table-mobile-cards tbody tr td[data-label]::before {
color: #adb5bd;
}

.login-card {
width: 92%;
max-width: 380px;
}

}

/* First-time Create Shipment guided tour (public/js/createShipmentTour.js) —
   deliberately unscoped by any @media block, shown on any screen size. A
   single highlight box + tooltip pair, repositioned via inline top/left/
   width/height in JS (computed from the real target's getBoundingClientRect,
   so it can't be precomputed here) — this only holds the static visual
   styling. box-shadow with a huge spread is the classic no-library
   "spotlight" trick: it dims the whole page except the transparent hole
   exactly where the highlight box sits. */
.tour-highlight {
position: fixed;
display: none;
z-index: 2000;
border-radius: 8px;
box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.55);
border: 2px solid #D4AF37;
pointer-events: none;
transition: top 0.25s ease, left 0.25s ease, width 0.25s ease, height 0.25s ease;
}

.tour-tooltip {
position: fixed;
display: none;
z-index: 2001;
max-width: 320px;
background: #fff;
border-radius: 10px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
padding: 14px 16px;
}

.tour-tooltip-step {
font-size: 0.72rem;
font-weight: 600;
color: #D4AF37;
text-transform: uppercase;
letter-spacing: 0.04em;
margin-bottom: 4px;
}

.tour-tooltip-title {
font-size: 0.95rem;
font-weight: 700;
margin-bottom: 6px;
}

.tour-tooltip-text {
font-size: 0.85rem;
color: #495057;
margin-bottom: 12px;
line-height: 1.4;
}

.tour-tooltip-actions {
display: flex;
justify-content: space-between;
align-items: center;
}

body.dark .tour-tooltip {
background: #2b3035;
color: #f1f1f1;
}

body.dark .tour-tooltip-text {
color: #ced4da;
}

/* Per explicit request 2026-08-12 — small pill-style action buttons (Local
   booking's "Use My Location"/"Add Pickup Number"), sized/weighted like a
   native app's own secondary actions (WhatsApp/Facebook), not a full-size
   Bootstrap button crammed inline into a form label's own text flow (the
   real bug this was fixing — see local.ejs's own comment on that button
   row). */
.pickup-action-btn {
font-size: 0.75rem;
padding: 4px 12px;
line-height: 1.4;
}

.pickup-action-btn i {
font-size: 0.8rem;
}

/* ============================================================
   Mobile bottom navigation bar — per explicit request 2026-08-12
   ("menu option for site and app in below... fixed and smooth").
   Customer-only (see partials/footer.ejs), mobile-only (hidden above the
   same 900px breakpoint the sidebar's own off-canvas drawer already uses,
   so desktop keeps using the sidebar exactly as before). Icon-led, like
   Amazon's own app bottom bar, not text-heavy.
   ============================================================ */
.mobile-bottom-nav {
display: none;
}

/* Per-person Start Trip toggle (topbar.ejs) — per explicit instruction
   2026-08-15: a real GPS trip is a phone-in-hand action, hidden entirely on
   tablet/laptop, not just tucked into the dropdown. Same 900px breakpoint
   every other mobile-only control on this page already uses. */
.mobile-only-trip-toggle {
display: none;
}

@media (max-width: 900px) {
.mobile-only-trip-toggle {
display: block;
}
}

/* Real bug found 2026-08-12: these two sheets (Orders/Create slide-up
   panels) only had their display:none/position:fixed/off-screen-transform
   styling INSIDE the @media block below — on a desktop-width screen none of
   that ever applied, so the browser's plain default block-level div fell
   into normal page flow instead, showing as stray unstyled text ("Orders /
   All Orders Booked Today..." etc) at the bottom of the page. Hidden by
   default here at every width, same as .mobile-bottom-nav above; the media
   query below re-enables them (display: block) only under 900px, where the
   .show-toggled transform can then actually slide them on/off screen. */
.mbn-sheet-backdrop,
.mbn-sheet {
display: none;
}

@media (max-width: 900px) {

.mobile-bottom-nav {
display: flex;
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 1030; /* below the sidebar drawer (1050) and its backdrop (1040)
                   so opening Menu visually sits on top of this, but above
                   ordinary page content. */
align-items: flex-end;
justify-content: space-between;
background: #fff;
border-top: 1px solid #e9ecef;
padding: 6px 6px calc(6px + env(safe-area-inset-bottom, 0px));
box-shadow: 0 -2px 10px rgba(0,0,0,.06);
/* Instagram-style hide-on-scroll-down/reveal-on-scroll-up, per explicit
   request 2026-08-15 — public/js/mobileBottomNav.js toggles .mbn-hidden.
   prefers-reduced-motion below turns this into an instant snap instead. */
transition: transform 0.22s ease;
transform: translateY(0);
}

.mobile-bottom-nav.mbn-hidden {
transform: translateY(100%);
}

@media (prefers-reduced-motion: reduce) {
.mobile-bottom-nav {
transition: none;
}
}

body.dark .mobile-bottom-nav {
background: #1e2126;
border-top-color: #343a40;
}

/* Real bug this specifically guards against ("when user try to book order
   and scroll dont stuck or difficult") — a fixed bar with no matching page
   padding covers the last chunk of any long scrollable form (exactly the
   Local booking form this was reported from), making its own final fields/
   submit button unreachable. */
body.has-mobile-bottom-nav .content {
padding-bottom: 78px;
}

.mbn-item {
flex: 1 1 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2px;
background: none;
border: none;
padding: 6px 2px;
color: #6c757d;
font-size: 0.65rem;
line-height: 1.1;
}

body.dark .mbn-item {
color: #adb5bd;
}

.mbn-item i {
font-size: 1.25rem;
}

.mbn-item.active {
color: #D4AF37;
}

.mbn-fab-wrap {
flex: 1 1 0;
display: flex;
justify-content: center;
}

.mbn-fab {
width: 52px;
height: 52px;
border-radius: 50%;
background: #D4AF37;
color: #212529;
border: 4px solid #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.4rem;
margin-top: -26px;
box-shadow: 0 2px 8px rgba(0,0,0,.25);
flex-shrink: 0;
}

body.dark .mbn-fab {
border-color: #1e2126;
}

/* Admin's own FAB variant — a bigger round Peeptoon logo instead of a plain
   "+" icon, per explicit request 2026-08-13 ("big stylish round Peeptoon
   symbol"). Wider gold ring + a bit larger than the seller's plain FAB so it
   reads as a brand mark, not just a bigger button. */
.mbn-fab-logo {
width: 60px;
height: 60px;
padding: 3px;
background: #fff;
border-width: 3px;
box-shadow: 0 3px 12px rgba(212,175,55,.45);
}

body.dark .mbn-fab-logo {
background: #1e2126;
}

.mbn-fab-logo img {
width: 100%;
height: 100%;
border-radius: 50%;
object-fit: cover;
}

/* Shown only via the logo <img>'s own onerror handler (bottomNav.ejs) when
   that image fails to load — a plain gold "+" glyph filling the same
   circle, instead of the browser's broken-image icon + alt text. */
.mbn-fab-fallback-icon {
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
font-size: 1.4rem;
color: #D4AF37;
}

/* India flag badge — Independence Day season only (services/seasonalFeatures.js
   gates Aug 1-16 IST, every year, no manual toggle). Plain CSS tricolor
   circle, no image asset, so it renders identically anywhere a logo does.
   Parent must be position:relative. */
.india-flag-badge {
position: absolute;
right: -3px;
bottom: -3px;
width: 22px;
height: 22px;
border-radius: 50%;
border: 2px solid #fff;
box-shadow: 0 1px 3px rgba(0,0,0,.3);
background: linear-gradient(to bottom, #FF9933 0%, #FF9933 33.33%, #fff 33.33%, #fff 66.66%, #138808 66.66%, #138808 100%);
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
}

.india-flag-badge::after {
content: "";
width: 6px;
height: 6px;
border-radius: 50%;
border: 1px solid #0d47a1;
background: #fff;
}

.india-flag-badge-sm {
width: 15px;
height: 15px;
border-width: 1.5px;
right: -2px;
bottom: -2px;
}

.india-flag-badge-sm::after {
width: 4px;
height: 4px;
}

/* Lightweight custom slide-up sheet (Orders / Create) — deliberately NOT a
   Bootstrap modal: no backdrop-fade JS dependency chain, no risk of
   colliding with an already-open modal elsewhere on the page, and opens
   purely via a CSS transition with zero network/JS work — see the "smooth
   open... without any network error" part of the same request. */
.mbn-sheet-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,.35);
z-index: 1031;
}

.mbn-sheet-backdrop.show {
display: block;
}

.mbn-sheet {
display: block;
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 1032;
background: #fff;
border-radius: 16px 16px 0 0;
padding: 8px 8px calc(12px + env(safe-area-inset-bottom, 0px));
transform: translateY(100%);
transition: transform .25s ease;
max-height: 70vh;
overflow-y: auto;
}

.mbn-sheet.show {
transform: translateY(0);
}

body.dark .mbn-sheet {
background: #1e2126;
color: #f1f1f1;
}

.mbn-sheet-handle {
width: 40px;
height: 4px;
border-radius: 2px;
background: #dee2e6;
margin: 6px auto 10px;
}

body.dark .mbn-sheet-handle {
background: #495057;
}

.mbn-sheet-title {
font-weight: 600;
font-size: 0.9rem;
padding: 0 10px 8px;
color: #6c757d;
text-transform: uppercase;
letter-spacing: .03em;
}

/* Per explicit request 2026-08-23 — admin/staff's own National section in
   the Create Shipment sheet groups Create Shipment alongside quick order-
   status links; this labels that group without competing with the sheet's
   own top-level .mbn-sheet-title. */
.mbn-sheet-subtitle {
font-weight: 600;
font-size: 0.75rem;
padding: 10px 10px 4px;
color: #adb5bd;
text-transform: uppercase;
letter-spacing: .03em;
border-top: 1px solid #eee;
margin-top: 6px;
}

body.dark .mbn-sheet-subtitle {
border-top-color: #343a40;
}

.mbn-sheet a.mbn-sheet-option {
display: flex;
align-items: center;
gap: 10px;
padding: 12px 14px;
border-radius: 10px;
color: inherit;
text-decoration: none;
font-size: 0.92rem;
}

.mbn-sheet a.mbn-sheet-option:active {
background: #f5f6fa;
}

body.dark .mbn-sheet a.mbn-sheet-option:active {
background: #2b3035;
}

.mbn-sheet a.mbn-sheet-option i {
font-size: 1.1rem;
color: #D4AF37;
width: 22px;
text-align: center;
}

}