/* Blue / Inter design language (2026-09-15 redesign) — replaces the app's original warm/orange
   palette with the palette+type system from the user's Figma Make reference upload ("Web UI/UX
   Design": Inter + JetBrains Mono, --color-primary #2563eb, navy sidebar, soft-blue surfaces).
   Deliberately kept as a drop-in swap of the SAME variable names the whole app already
   references (--brand/--green/--red/--line/--card/... — every screen's CSS and every JS file's
   generated HTML already goes through these tokens, never a hardcoded hex) so the whole app
   reskins from this one block without touching per-screen markup. Two names stay defined but
   unused elsewhere (--navy2, --blue/--blue-soft) — kept for any future use, not removed since
   removing an unreferenced var risks nothing but also helps nothing. */
:root{
  --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --bg: #f0f4ff; --card: #ffffff;
  --ink: #0f172a; --ink-soft: #64748b; --ink-faint: #94a3b8;
  --line: #dbeafe;
  --brand: #2563eb; --brand-dark: #1d4ed8; --brand-soft: #eff6ff;
  --green: #16a34a; --green-soft: #dcfce7;
  --red: #dc2626; --red-soft: #fee2e2;
  --amber: #d97706; --amber-soft: #fef9c3;
  --purple: #7c3aed; --purple-soft: #ede9fe;
  --navy: #1e3a8a; --navy2: #1e40af;
  --blue: #2563eb; --blue-soft: #dbeafe;
  --radius:16px; --shadow:0 1px 2px #1e3a8a0d,0 4px 14px #2563eb14; --shadow-md:0 10px 28px #2563eb1f;
}
*{box-sizing:border-box}
/* Defensive safety-net (2026-09-24) — every on-screen table is already wrapped in
   .tablewrap{overflow-x:auto} (see below) and voucher tables never render on-screen (they live
   in the hidden #printArea, only shown via @media print), so this shouldn't normally trigger —
   but this stops ANY future stray element with an accidental fixed/oversized width from pushing
   the whole page sideways, without affecting each table's own intentional horizontal scroll. */
html{overflow-x:hidden}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;overflow-x:hidden}

/* Boot loading screen (2026-09-26) -- see index.html's #bootLoadingScreen comment for the full
   context. Full-viewport, sits above literally everything else (z-index 9999, the highest used
   anywhere in this file) so it fully covers whatever #authScreen/#appShell paint underneath it
   while booting. .boothide is added by app.js's hideBootScreen() right before removing the
   element -- a quick opacity fade instead of an abrupt disappearance. */
#bootLoadingScreen{position:fixed;inset:0;z-index:9999;background:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center;transition:opacity .25s ease}
#bootLoadingScreen.boothide{opacity:0;pointer-events:none}
#bootLoadingScreen .bootlogo{width:88px;height:88px;margin-bottom:16px}
#bootLoadingScreen .bootlogo img{width:100%;height:100%;display:block;object-fit:contain}
#bootLoadingScreen .bootwordmark{font-size:26px;font-weight:900;color:var(--brand);letter-spacing:-.02em;line-height:1.2}
#bootLoadingScreen .boottagline{font-size:13px;font-weight:600;color:var(--green);margin:2px 0 26px}
#bootLoadingScreen .bootspinner{width:44px;height:44px;border-radius:50%;margin-bottom:16px;background:conic-gradient(from 0deg,var(--brand) 0%,var(--green) 55%,transparent 78%,transparent 100%);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 5px),#000 calc(100% - 5px));mask:radial-gradient(farthest-side,transparent calc(100% - 5px),#000 calc(100% - 5px));animation:bootspin .85s linear infinite}
@keyframes bootspin{to{transform:rotate(360deg)}}
#bootLoadingScreen .bootstatus{font-size:13px;color:var(--ink-soft);font-weight:500}
.wrap{max-width:420px;margin:0 auto;min-height:100vh;display:flex;flex-direction:column;justify-content:center;padding:24px 18px}
.wrap.wide{max-width:920px}

/* ============================================================================
   App Shell — persistent left sidebar (ported from the offline app's own
   #topnav/#navList/#main layout, same idea: one sidebar always on screen
   instead of a single Home menu you have to return to between modules).
   Screens inside #screensHost keep their existing .wrap/.wrap.wide markup —
   only their outer centering is turned off here so they fill the content
   area beside the sidebar instead of floating centered in a narrow column.
   ============================================================================ */
#appShell{display:flex;flex-direction:row;min-height:100vh}
/* Sidebar switched from position:sticky to position:fixed (2026-09-30, per user report
   "sidebar ko fix karo ... sidebar scroll/sticky nahi ho raha"). sticky's containing block was
   #appShell, a normal-flow flex row -- it should have worked, but body/html both carry
   overflow-x:hidden (2026-09-24's horizontal-scroll safety net, style.css's own note above),
   and per the CSS overflow spec setting one axis to non-visible computes the OTHER axis to auto
   too -- so body silently became an explicit scroll container instead of using the page's
   default viewport scrolling, which is a well-known way for position:sticky to stop sticking,
   especially inconsistently across the Android WebView vs. desktop/mobile Chrome this app runs
   in (see the many other WebView-vs-browser quirks already documented elsewhere in this file).
   position:fixed has no such dependency on which element ends up "the" scroll container -- it's
   always relative to the viewport, full stop. #mainArea below gets a matching margin-left so
   the now-out-of-flow sidebar doesn't sit on top of the page content; the max-width:860px
   block further down (mobile off-canvas drawer) already used position:fixed for its own reasons
   and is unaffected. */
#sidebarNav{background:var(--navy);color:#dbeafe;display:flex;flex-direction:column;align-items:stretch;gap:16px;padding:22px 14px;flex:none;width:224px;position:fixed;top:0;left:0;bottom:0;overflow-y:auto;z-index:30;border-right:1px solid var(--navy2)}
#sidebarNav .brandblock{display:flex;align-items:center;gap:10px;padding:0 8px 4px}
#sidebarNav .logo{width:28px;height:28px;border-radius:9px;background:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;flex:none}
#sidebarNav .brandtext b{display:block;font-size:15px;color:#fff;font-weight:800}
#sidebarNav .brandtext span{display:block;font-size:10px;color:#93c5fd;margin-top:1px}
#navList{list-style:none;display:flex;flex-direction:column;gap:2px;margin:0;padding:0;align-items:stretch}
#navList li{margin:0}
#navList a{display:flex;align-items:center;gap:10px;color:#bfdbfe;padding:9px 12px;border-radius:10px;font-size:12.5px;font-weight:600;white-space:nowrap;text-decoration:none;cursor:pointer;border-left:3px solid transparent}
#navList a:hover{background:rgba(255,255,255,.08);color:#fff}
#navList a.active{background:var(--navy2);color:#fff;border-left:3px solid #93c5fd}
#navList a .navicon{flex:none;display:block}
#navList li.navgroup-label{padding:14px 12px 5px;font-size:10px;font-weight:800;letter-spacing:.07em;color:#7ea8e0;text-transform:uppercase;white-space:nowrap}
#navList li.navgroup-label:first-child{padding-top:2px}
#sidebarBackdrop{display:none}
#bottomNav{display:none}
#mainArea{flex:1;min-width:0;display:flex;flex-direction:column;margin-left:224px}
#topbar{background:var(--card);border-bottom:1px solid var(--line);padding:12px 20px;display:flex;gap:12px;align-items:center;position:sticky;top:0;z-index:20}
#impersonateBar{background:var(--navy);color:#fff;padding:8px 20px;display:flex;gap:12px;align-items:center;flex-wrap:wrap;font-size:12.5px;font-weight:600;position:sticky;top:57px;z-index:19}
#impersonateBar .btn{width:auto;background:transparent;border-color:rgba(255,255,255,.4);color:#fff;padding:5px 12px;font-size:12px;margin-left:auto}
/* Guest Mode banner (2026-09-20, see app.js renderGuestBar()) — amber/warning tone, same
   sticky-below-topbar treatment as #impersonateBar (they never show at the same time). */
#guestBar{background:#92400e;color:#fff;padding:8px 20px;display:flex;gap:12px;align-items:center;flex-wrap:wrap;font-size:12.5px;font-weight:600;position:sticky;top:57px;z-index:19}
#guestBar .btn{width:auto;background:transparent;border-color:rgba(255,255,255,.5);color:#fff;padding:5px 12px;font-size:12px;margin-left:auto}
/* "Viewing an Owner's fleet" banner (2026-09-23, see app.js renderManagerViewBar()) —
   brand-blue tone (distinct from navy Admin View / amber Guest Mode), same
   sticky-below-topbar treatment; never shows at the same time as those two. */
#managerViewBar{background:var(--brand);color:#fff;padding:8px 20px;display:flex;gap:12px;align-items:center;flex-wrap:wrap;font-size:12.5px;font-weight:600;position:sticky;top:57px;z-index:19}
#impersonateBar .btn:hover{background:rgba(255,255,255,.12)}
#topbar #topbarTitle{flex:1;font-weight:800;font-size:15px}
#fleetSwitcherSelect{max-width:180px;padding:7px 10px;border:1px solid var(--line);border-radius:999px;background:var(--brand-soft);color:var(--ink);font-size:12.5px;font-weight:700;cursor:pointer;flex:none}
#hamburgerBtn{display:none;background:none;border:1px solid var(--line);border-radius:8px;width:34px;height:34px;font-size:16px;cursor:pointer;color:var(--ink);flex:none}

/* Notification bell (2026-09-19, per user's own spec) — see public/notifications.js.
   Badge styling mirrors .filterbtn .filterbadge above; icon box mirrors #hamburgerBtn.
   2026-09-19 (2nd addition): #adminNotifBellWrap/Btn/Badge/Panel are the Super Admin
   screen's own separate bell instance (same markup shape, different ids since the
   Admin screen doesn't share #topbar) — every rule below is shared by both. */
#notifBellWrap,#adminNotifBellWrap{position:relative;flex:none}
#notifBellBtn,#adminNotifBellBtn{position:relative;display:flex;align-items:center;justify-content:center;background:none;border:1px solid var(--line);border-radius:8px;width:34px;height:34px;cursor:pointer;color:var(--ink);padding:0}
#notifBellBtn:hover,#adminNotifBellBtn:hover{background:var(--brand-soft);border-color:var(--brand)}
#notifBadge,#adminNotifBadge{position:absolute;top:-5px;right:-5px;background:var(--red);color:#fff;font-size:10px;font-weight:800;min-width:16px;height:16px;border-radius:99px;display:flex;align-items:center;justify-content:center;padding:0 3px;line-height:1;border:2px solid var(--card)}
#notifPanel,#adminNotifPanel{position:absolute;top:42px;right:0;width:340px;max-width:88vw;max-height:70vh;overflow-y:auto;background:var(--card);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-md);z-index:50;padding:6px}
.notif-head{padding:8px 10px 10px;font-weight:800;font-size:13px;color:var(--ink);border-bottom:1px solid var(--line);margin-bottom:4px;position:sticky;top:0;background:var(--card)}
.notif-item{display:flex;gap:10px;padding:9px 8px;border-radius:8px}
.notif-item:hover{background:var(--brand-soft)}
.notif-ic{flex:none;width:30px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:14px}
.notif-ic.warn{background:var(--amber-soft)}
.notif-ic.urgent{background:var(--red-soft)}
.notif-body{flex:1;min-width:0}
.notif-title{font-size:12.5px;font-weight:700;color:var(--ink);overflow-wrap:anywhere}
.notif-sub{font-size:11.5px;color:var(--ink-soft);margin-top:1px}
.notif-empty{padding:26px 10px;text-align:center;color:var(--ink-soft);font-size:12.5px}
@media(max-width:480px){#notifPanel,#adminNotifPanel{position:fixed;top:56px;left:12px;right:12px;width:auto;max-width:none}}
#screensHost{flex:1}
#screensHost .wrap{max-width:100%;margin:0;min-height:0;display:block;padding:20px 24px}
#screensHost .wrap .authcard{max-width:920px}
#screensHost .wrap .authcard.wide{max-width:100%}

@media(max-width:860px){
  #appShell{flex-direction:column}
  #sidebarNav{position:fixed;top:0;left:0;bottom:0;width:78%;max-width:280px;height:100vh;
    padding:70px 14px 20px;box-shadow:8px 0 28px rgba(0,0,0,.25);
    transform:translateX(-100%);transition:transform .28s ease;z-index:65}
  #sidebarNav.open{transform:translateX(0)}
  /* Cancel the desktop #mainArea{margin-left:224px} above -- on this breakpoint the sidebar is
     an off-canvas drawer (translateX'd out of view by default), not a permanent left column, so
     content must use the full width, not leave a blank 224px gap on the left. */
  #mainArea{margin-left:0}
  #sidebarBackdrop{display:none;position:fixed;inset:0;background:rgba(8,12,26,.5);z-index:55}
  #sidebarBackdrop.open{display:block}
  #hamburgerBtn{display:flex;align-items:center;justify-content:center}
  /* Bottom padding clears the fixed #bottomNav bar below so it never covers the last
     card/row of whichever screen is showing (offline-app pattern, same value). */
  #screensHost .wrap{padding:14px 14px calc(78px + env(safe-area-inset-bottom,0px))}

  /* 2026-09-23, per user request ("dashboard vendors ya kisi bhi page me white window
     bani hoi hai, mobile k fullscreen me ho white window na bni ho"): every app screen
     (Dashboard/Vehicles/Trips/Vendors/etc.) wraps its content in .authcard — a
     bordered, rounded, drop-shadowed white "card" (see the base .authcard rule above).
     That's the right look on desktop, where it visibly floats over the lavender
     (--bg) page background beside the sidebar, but on a phone screen (this same
     media query the bottom tab bar/hamburger menu switch on at) it reads as a
     separate boxed-in "window" with a colored margin around it rather than the
     screen's real content filling the device edge-to-edge, most noticeable in the
     Android app where there's no browser chrome around it to explain the framing.
     Flattening the card styling here AND matching the page background to the same
     white as the card (instead of the lavender --bg) makes the content span the
     full width with nothing left to show a boundary. #authScreen (the actual
     login/signup screen) sets its own explicit background and lives entirely
     outside #screensHost, so it's unaffected by the body override below. */
  body{background:var(--card)}
  #screensHost .wrap .authcard{background:transparent;border:none;border-radius:0;box-shadow:none;padding:0}

  /* Fixed bottom tab bar (2026-09-09) — ported from the offline app's own #bottomNav,
     same 5-tab set/order/icons/labels (Menu/Trips/Dashboard/Vendors/Vehicles), same
     flat card-background bar with a soft brand-tinted rounded highlight behind the
     active tab's icon. "Menu" just opens the existing sidebar drawer (toggleSidebar())
     and is never shown as active itself; the other 4 tabs' active state is kept in
     sync by setActiveNav() (see app.js) rather than tracked separately. Deliberately
     below #sidebarBackdrop's z-index (55) so it stays non-interactive while the
     drawer is open, same as offline. */
  #bottomNav{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:40;background:var(--card);border-top:1px solid var(--line);box-shadow:var(--shadow-md);padding:9px 6px calc(12px + env(safe-area-inset-bottom,0px))}
  #bottomNav a{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;color:var(--ink-faint);text-decoration:none}
  #bottomNav a .bn-icon{width:34px;height:26px;display:flex;align-items:center;justify-content:center;border-radius:10px;line-height:1}
  #bottomNav a.active{color:var(--brand)}
  #bottomNav a.active .bn-icon{background:color-mix(in oklch, var(--brand) 15%, var(--card))}
  #bottomNav a .bn-label{font-size:10px;font-weight:600}
}
/* "Filters" button + popup (2026-09-09) — ported from the offline app's own
   filterbtn/filterbadge pattern; see openFilterModal()/closeFilterModal() in
   app.js and the shared #filterModal markup in index.html. */
.filterbtn-row{margin-bottom:14px}
.filterbtn{display:inline-flex;align-items:center;gap:8px;background:var(--card);border:1px solid var(--line);border-radius:10px;padding:10px 16px;font-weight:600;font-size:12.5px;color:var(--ink);cursor:pointer;box-shadow:var(--shadow)}
.filterbtn:hover{border-color:var(--brand)}
.filterbtn .filterbadge{background:var(--brand);color:#ffffff;font-size:11px;font-weight:800;min-width:20px;height:20px;border-radius:99px;display:inline-flex;align-items:center;justify-content:center;padding:0 5px}

.authcard{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow-md);padding:28px 24px}

/* Language switcher (2026-09-19, i18n stage 1 — public/i18n.js) */
.langswitcher{display:flex;gap:6px;justify-content:center;margin-bottom:16px}
.langbtn{padding:5px 12px;border-radius:999px;border:1px solid var(--line);background:transparent;color:var(--ink-soft);font-size:11.5px;font-weight:600;cursor:pointer;width:auto}
.langbtn.active{background:var(--brand);border-color:var(--brand);color:#ffffff}
.langbtn:hover:not(.active){border-color:var(--brand);color:var(--brand-dark)}
/* Urdu script needs its own font (Inter has no Urdu glyphs) — scoped to
   body.lang-ur so English/Roman Urdu are completely unaffected. Right-aligned
   text on the two pre-login screens is handled by their own [dir] attribute
   (see i18n.js applyTranslations()), not here.
   2026-09-28, per user request ("urdu font Noto Naskh Arabic ye kro") —
   switched from Noto Nastaliq Urdu (calligraphic, sloped) to Noto Naskh
   Arabic (upright, more legible at small UI sizes) — see index.html's
   Google Fonts <link> for the matching swap of which family is loaded. */
body.lang-ur, body.lang-ur input, body.lang-ur button, body.lang-ur select, body.lang-ur textarea{
  font-family:'Noto Naskh Arabic', 'Inter', system-ui, sans-serif;
}
body.lang-ur .field label{text-align:right}
body.lang-ur .authswitch, body.lang-ur .authcopyright{text-align:center}
.brandrow{display:flex;align-items:center;gap:10px;margin-bottom:22px;justify-content:center}
.brandrow .logo{width:38px;height:38px;border-radius:10px;background:var(--brand-soft);display:flex;align-items:center;justify-content:center;font-size:20px}
.brandrow b{font-size:17px}
h1.title{font-size:18px;margin:0 0 4px;text-align:center}
p.sub{color:var(--ink-soft);font-size:13px;text-align:center;margin:0 0 20px}
.field{margin-bottom:14px}
.field label{display:block;font-size:12.5px;font-weight:600;color:var(--ink-soft);margin-bottom:5px}
.field input,.field select,.field textarea{width:100%;padding:11px 12px;border:1px solid var(--line);border-radius:10px;background:#f8faff;color:var(--ink);font-size:14px;font-family:inherit}
.field textarea{min-height:70px;resize:vertical}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--brand)}
.tab{padding:6px 14px;border-radius:6px;border:none;font-size:12px;font-weight:600;cursor:pointer;background:transparent;color:var(--ink-soft);transition:all .15s}
.tab.active{background:var(--line);color:var(--brand-dark)}
.tab:hover:not(.active){color:var(--brand-dark);background:#f0f7ff}
.field-inline{padding:9px 10px;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink);font-size:13px}
.rolepill{padding:5px 10px;border-radius:6px;font-size:11.5px;font-weight:700;background:var(--brand-soft);color:var(--ink)}
.rolepill.inactive{background:var(--line);color:var(--ink-soft)}
.section-heading{font-size:12.5px;text-transform:uppercase;letter-spacing:.4px}
.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:11px 16px;border-radius:10px;border:1px solid var(--line);background:var(--card);color:var(--ink);font-weight:700;font-size:13.5px;cursor:pointer;width:100%}
.btn.primary{background:var(--brand);border-color:var(--brand);color:#ffffff}
.btn.primary:hover{background:var(--brand-dark);color:#fff}
.btn.ghost{background:none;border:1px solid var(--line);color:var(--brand-dark);font-weight:600}
.btn.ghost:hover{background:var(--brand-soft);border-color:var(--brand)}
/* 2026-09-29 -- generic confirm-dialog system (app.js confirmDialog()/#confirmDialogModal in
   index.html), first wired into Trip Delete. .btn.primary is brand-blue everywhere else, but a
   destructive Confirm button (delete, etc.) needs to read as dangerous at a glance -- this
   modifier stacks on top of .btn.primary (same class order as the HTML: class="btn primary
   danger") and just swaps the color to --red/--red-soft, keeping .btn's shared sizing/shape. */
.btn.primary.danger{background:var(--red);border-color:var(--red)}
.btn.primary.danger:hover{background:#b91c1c}
/* 2026-09-30 -- no generic disabled-button look existed outside #authScreen's own spinner
   variant; needed for the Vehicle Delete confirm modal's Delete button, which starts disabled
   and only enables once the typed text matches the vehicle's number (vehicleAccount.js's
   checkVehicleDeleteConfirmInput()). Generic on .btn so any future disabled button gets it too. */
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn.primary.danger:disabled:hover{background:var(--red)}
.note{background:var(--amber-soft);color:var(--brand-dark);border-radius:10px;padding:9px 11px;font-size:12px;margin-top:10px}
.error{background:var(--red-soft);color:var(--red);border-radius:10px;padding:9px 11px;font-size:12px;margin-top:10px}

/* ---- Auth screen (Login/Sign Up) — Figma Make AuthScreen, 2026-09-15.
   Everything here is scoped under #authScreen so it never touches .authcard
   / .brandrow / .btn.primary etc. used elsewhere (Dashboard's .authcard.wide,
   Forgot Password's plain .authcard, and so on). */
#authScreen.wrap{max-width:100%;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:32px 18px;background:linear-gradient(135deg,#0f172a 0%,#1e3a8a 50%,#2563eb 100%);position:relative;overflow:hidden}
#authScreen.wrap::before,#authScreen.wrap::after{content:'';position:absolute;border-radius:50%;background:rgba(255,255,255,.06);pointer-events:none}
#authScreen.wrap::before{width:420px;height:420px;top:-160px;right:-120px}
#authScreen.wrap::after{width:320px;height:320px;bottom:-140px;left:-100px}
.authhero{position:relative;z-index:1;width:100%;max-width:400px;display:flex;flex-direction:column;align-items:center}
.authhero-brand{text-align:center;margin-bottom:24px;color:#fff}
.authhero-logo{width:56px;height:56px;margin:0 auto 14px;border-radius:16px;overflow:hidden;box-shadow:0 8px 24px rgba(0,0,0,.35)}
.authhero-logo img{width:100%;height:100%;display:block;object-fit:cover}
.authhero-brand h1{font-size:28px;font-weight:900;line-height:1.15;margin:0;color:#fff;letter-spacing:-.02em}
.authhero-brand h1.accent{color:#93c5fd;margin:0 0 8px}
.authhero-brand p{font-size:13px;color:#bfdbfe;margin:0;font-weight:500}
/* 2026-09-30 (per user request) — the logo+wordmark link back to "/" (welcome.html);
   reset link defaults so it looks identical to the plain text/logo it replaces. */
.authhero-brand-link{display:block;text-decoration:none;color:inherit;cursor:pointer}
.authhero-brand-link:hover .authhero-logo{box-shadow:0 8px 24px rgba(0,0,0,.5)}
/* The card itself — scoped override of the shared .authcard rule (line ~104)
   so Dashboard/Trips/Vehicles/Drivers' .authcard.wide keeps its own look. */
#authScreen .authcard{width:100%;border:none;border-radius:20px;box-shadow:0 24px 64px rgba(0,0,0,.35);padding:28px 26px}
#authScreen .brandrow,#authScreen #authTitle{display:none}
.authtabs{display:flex;gap:4px;background:#f1f5f9;border-radius:10px;padding:4px;margin-bottom:18px}
.authtab{flex:1;padding:9px 0;border:none;border-radius:8px;background:transparent;color:var(--ink-soft);font-weight:700;font-size:13px;cursor:pointer;transition:all .15s}
.authtab.active{background:#fff;color:var(--brand-dark);box-shadow:0 1px 4px rgba(0,0,0,.12)}
#authScreen p.sub{margin-bottom:18px}
.pwfieldwrap{position:relative}
.pwfieldwrap input{padding-right:42px}
.pweye{position:absolute;top:0;right:0;height:100%;width:42px;display:flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;font-size:15px;padding:0}
.authrow-between{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:-4px 0 16px;flex-wrap:wrap}
.authrow-between #forgotPasswordRow{margin:0;font-size:12.5px}
#authScreen .btn.primary{background:linear-gradient(135deg,var(--brand) 0%,var(--brand-dark) 100%);position:relative}
#authScreen .btn.primary:disabled{color:transparent;opacity:.85}
#authScreen .btn.primary:disabled::before{content:'';position:absolute;width:16px;height:16px;border-radius:50%;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;animation:authspin .7s linear infinite}
@keyframes authspin{to{transform:rotate(360deg)}}
.authswitch{text-align:center;font-size:12.5px;color:var(--ink-soft);margin:16px 0 0}
.authswitch a{color:var(--brand-dark);font-weight:700}
.authcopyright{position:relative;z-index:1;text-align:center;font-size:11.5px;color:#bfdbfe;margin:22px 0 0}
@media (max-width:480px){
  .authhero-brand h1{font-size:24px}
  #authScreen .authcard{padding:22px 18px;border-radius:16px}
}

.muted{color:var(--ink-soft);font-size:12.5px}
.center{text-align:center}
.hidden{display:none!important}

/* App Updates (2026-09-30, public/adminBuilds.js) — drag/drop zone for the .apk build file on
   the Super Admin "Publish Update" form. */
.ab-dropzone{border:1.5px dashed var(--line);border-radius:10px;padding:22px 14px;text-align:center;font-size:13px;color:var(--ink-soft);font-weight:600;cursor:pointer;background:#f8faff}
.ab-dropzone.dragover{border-color:var(--brand);background:var(--brand-soft)}

/* Package / plan cards */
.plangrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;margin:18px 0}
.plancard{background:var(--card);border:1.5px solid var(--line);border-radius:14px;padding:18px;text-align:center;position:relative}
.plancard.featured{border-color:var(--brand);box-shadow:var(--shadow-md)}
.plancard .badge{position:absolute;top:-11px;left:50%;transform:translateX(-50%);background:var(--brand);color:#ffffff;font-size:10.5px;font-weight:800;padding:3px 10px;border-radius:99px}
.plancard h3{margin:6px 0 2px;font-size:15px}
.plancard .price{font-size:24px;font-weight:800;margin:8px 0 2px}
.plancard .price span{font-size:12px;font-weight:600;color:var(--ink-soft)}
.plancard .save{color:var(--green);font-size:11.5px;font-weight:700;margin-bottom:10px}

/* Link request rows / admin fleet rows */
.reqrow{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px;border:1px solid var(--line);border-radius:10px;margin-bottom:8px}
.reqrow .who{font-weight:700;font-size:13.5px}
.reqrow .phone{color:var(--ink-soft);font-size:12px}
.pillrow{display:flex;gap:8px}
.pillrow .btn{width:auto;padding:8px 12px;font-size:12.5px}

/* Super Admin dashboard (2026-09-15) — search+filter toolbar and color-coded
   subscription-status pills, on top of .statgrid/.stat (Dashboard's own
   headline-card look) and .reqrow (the same list-row pattern every other
   screen already uses) so the console reads as part of the app rather than
   a bolted-on settings form. */
.admin-toolbar{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:14px}
.admin-searchwrap{flex:1;min-width:200px;display:flex;align-items:center;gap:8px;padding:10px 14px;border:1px solid var(--line);border-radius:10px;background:var(--card)}
.admin-searchwrap input{border:none;outline:none;background:transparent;flex:1;font-size:14px;font-family:inherit;color:var(--ink);padding:0;min-width:0}
.admin-tabs{display:flex;gap:4px;flex-wrap:wrap;background:var(--muted,#f1f5f9);border:1px solid var(--line);border-radius:8px;padding:4px}
/* Distinct from .rolepill (a plain 2-state active/inactive look used
   elsewhere) — Pending needs its own color from Expired so the Super Admin
   can scan the list at a glance. */
.statuspill{padding:5px 10px;border-radius:6px;font-size:11.5px;font-weight:700;white-space:nowrap}
.statuspill.active{background:var(--green-soft);color:var(--green)}
.statuspill.pending{background:var(--amber-soft);color:var(--brand-dark)}
.statuspill.expired{background:var(--red-soft);color:var(--red)}
/* Trip status pill variants (Trips Ledger redesign, 2026-09-15) — reuses the same .statuspill
   shape as Admin's subscription-status pills: Active Trip (still running/unsettled) reads as
   "in progress" (amber, same tint as .pending), Complete Trip as "done" (green). */
.statuspill.trip-ongoing{background:var(--amber-soft);color:var(--brand-dark)}
.statuspill.trip-done{background:var(--green-soft);color:var(--green)}
/* Vehicle status pill variants (Vehicles/Fleet redesign, 2026-09-15) — Active reads as
   healthy (green), Repair needs attention (amber), Inactive is neutral/parked (gray, same
   tint as .rolepill.inactive), Sold is a soft red so it still stands out in the list without
   reading as urgent the way Repair does. */
.statuspill.veh-active{background:var(--green-soft);color:var(--green)}
.statuspill.veh-repair{background:var(--amber-soft);color:var(--brand-dark)}
.statuspill.veh-inactive{background:var(--line);color:var(--ink-soft)}
.statuspill.veh-sold{background:var(--red-soft);color:var(--red)}
.planpill{padding:5px 10px;border-radius:6px;font-size:11px;font-weight:700;background:var(--navy);color:#fff;white-space:nowrap}
.admin-meta{color:var(--ink-soft);font-size:11.5px;display:flex;gap:14px;flex-wrap:wrap;margin-top:4px}

/* Realtime online/offline presence dot (2026-09-28, per user request —
   "green dot ... jo abhi online betha hai, gray dot jo offline ho"). Green +
   a soft pulsing glow ring while online, a plain flat gray dot otherwise —
   see public/admin.js's isUserOnline()/adminPresenceDotHtml() for what
   "online" means (a heartbeat_at ping within the last 3 minutes) and
   lib/db.js's touchHeartbeat() for where that timestamp comes from. The
   pulse ring is only ever added for .online so an offline dot never runs
   the animation at all. inline-block + vertical-align so it sits inline
   right before a name/label (.who, .admin-presence-text) without needing
   its own flex wrapper. */
.onlinedot{display:inline-block;width:9px;height:9px;border-radius:50%;vertical-align:middle;margin-right:6px;position:relative;background:var(--ink-faint);flex:none}
.onlinedot.online{background:var(--green)}
.onlinedot.online::after{content:'';position:absolute;inset:-3px;border-radius:50%;background:var(--green);opacity:.35;animation:onlinedot-pulse 1.8s ease-out infinite}
@keyframes onlinedot-pulse{0%{transform:scale(.6);opacity:.5}100%{transform:scale(1.8);opacity:0}}
/* The admin-meta line's "Online now" text (adminPresenceMetaHtml()) — green
   and bold so it reads as a distinct, good-news state next to the plain
   gray "Last Seen ..." text it replaces while the user is online. */
.admin-presence-text.online{color:var(--green);font-weight:700}

/* QR login */
.qrbox{background:#fff;padding:14px;border-radius:12px;display:inline-block;box-shadow:var(--shadow)}
.qrbox img,.qrbox canvas{display:block;width:220px;height:220px}

/* Trips — segment cards, form grids, ledger table (Phase 3) */
.card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:16px;margin-bottom:14px}
.card h3,.card h4{margin:0 0 10px}
.card h4{font-size:13.5px;color:var(--brand-dark)}
.formgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px 14px;margin-bottom:10px}
.formgrid .field{margin-bottom:0}
.tablewrap{overflow-x:auto;margin-top:8px}
.tablewrap table{width:100%;border-collapse:collapse;font-size:12.5px}
.tablewrap th,.tablewrap td{padding:8px 10px;border-bottom:1px solid var(--line);text-align:left;white-space:nowrap}
.tablewrap thead tr{background:#f8faff}
.tablewrap th{color:var(--ink-soft);font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.06em}
/* 2026-09-27, user-reported — Vehicle/Manager Performance table headers (e.g.
   "KIRAYA"/"EXPENSES") stayed left-aligned while their own column's values sat
   right-aligned below them, even though every such <th> already had class="right"
   — same visual symptom as the earlier column-width bug, but a DIFFERENT root
   cause found on closer look: CSS specificity. Line above (.tablewrap th,
   .tablewrap td{text-align:left}) targets th at specificity (0,1,1) — one
   type-selector (th) beats the bare ".right" class alone at (0,1,0), so it was
   silently overriding "right" on th (but not on td, since ".tablewrap td.right"
   is itself more specific there). Adding ".tablewrap th.right" here explicitly
   gives header cells the same winning specificity as data cells — this is a
   pre-existing app-wide rule (.tablewrap is used by every table in the app), so
   the fix isn't scoped to just the Dashboard's two performance tables. */
.tablewrap td.right,.tablewrap th.right,.right{text-align:right}
.tablewrap tbody tr.clickrow{cursor:pointer;transition:background .1s}
.tablewrap tbody tr.clickrow:hover{background:var(--brand-soft)}
/* Vehicle/Manager Performance tables (dashboard.js, 2026-09-27) — user-reported
   bug: columns looked unevenly spaced, with big gaps before Expenses/Profit-Loss.
   .tablewrap table's default table-layout:auto sizes each column off its own
   widest cell including header text, so a short numeric column (e.g. Trips: "2")
   next to a long-header column (Profit/Loss) got a much wider box than its
   content needed, and the right-aligned value sat far to the right of it,
   reading as a random gap. table-layout:fixed + each row's own <colgroup>
   (set inline per-table in dashboard.js, since Vehicle/Manager Performance have
   a different column count) makes column widths predictable instead of
   content-driven. min-width keeps columns from squishing unreadable-thin on a
   narrow phone — .tablewrap's own overflow-x:auto scrolls the table sideways
   below that width instead (same fix applies inside the Android app, which
   loads this same site). */
.perftable{table-layout:fixed;min-width:480px}
/* First column (vehicle number / manager name) is the only one whose text length
   really varies row to row — with table-layout:fixed's box now strict, an
   unusually long one would otherwise visually bleed into the next column
   instead of wrapping (still nowrap by design, for row height consistency);
   ellipsis it instead so it always stays inside its own cell. */
.perftable td:first-child,.perftable th:first-child{overflow:hidden;text-overflow:ellipsis}
/* 2026-09-27, per user request (not a bug report) — Vehicle/Manager Performance table
   values (Vehicle/Trips/Kiraya/Expenses/Profit-Loss) should sit CENTERED in their columns
   instead of left/right. Scoped to .perftable only, so no other table in the app is
   touched. !important used deliberately, not out of laziness: these same cells are
   already targeted by two other rules above (.tablewrap th,.tablewrap td{text-align:left}
   and .tablewrap td.right,.tablewrap th.right,.right{text-align:right}) -- this exact
   stylesheet just showed real specificity fragility between those two (see the
   ".tablewrap th.right" comment above), so a plain .perftable th,.perftable td selector
   would need to out-rank whichever of the two applies to a given cell, which differs by
   column (.right or not). !important sidesteps that specificity math entirely instead of
   risking the same silent-loss bug a third time. */
.perftable th,.perftable td{text-align:center!important}
.progress-item.clickable{cursor:pointer}
.progress-item.clickable:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:6px}
.btn.sm{width:auto;padding:7px 12px;font-size:12.5px}
.btn.red{color:var(--red);border-color:var(--red-soft)}
/* Chip action button (Figma "Ledger"/"Khata →" row-action style) — filled pale-blue pill,
   distinct from .btn.ghost (transparent bg). Used for the primary per-row action in list
   tables (Trips/Drivers/Vendors/... row actions) to match the reference design exactly. */
.btn.chip{width:auto;background:var(--brand-soft);border:1px solid var(--line);color:var(--brand);font-weight:600;padding:5px 12px;font-size:11px;border-radius:6px}
.btn.chip:hover{background:var(--line);border-color:var(--brand)}

/* ============================================================================
   New Trip Entry modal — reskinned 2026-09-16 to match the Figma Make
   design's own modal language (ModalShell: light icon-box header + title/
   subtitle + ghost X close, white card, `0 24px 64px #2563eb20` shadow —
   same tokens as .modalbox above) instead of the old offline-app navy-header
   look. Only the CHROME changed (header/shadow/footer/buttons) — every
   field, section box, pill, combo box and the calculator input underneath
   is untouched, per user request: "sirf look badlo, functionality wahi
   rahe" (keep all real business logic, restyle only). Header markup reuses
   .modalbox-head/-head-left/-ic/-title/-sub/-close directly (see trips.js's
   renderTripFormScreen) rather than duplicating those rules here. */
/* "+ Add Vehicle/Company/Contractor/Vendor" quick-add links (2026-09-20, New Trip page —
   see quickAdd.js). 2026-09-24: moved from sitting inline with the field's own label to
   stacked BELOW the field's input/select, inside the same .field column (.qa-add-below). */
.qa-add-link{color:var(--brand);font-size:11.5px;font-weight:700;cursor:pointer;white-space:nowrap}
.qa-add-link:hover{text-decoration:underline}
.qa-add-below{display:block;margin-top:6px}
.modal-overlay{position:fixed;inset:0;background:rgba(16,28,61,.6);z-index:200;display:flex;align-items:flex-start;justify-content:center;padding:26px 14px;overflow-y:auto}
.modal-box{background:var(--card);border:1px solid var(--line);border-radius:16px;max-width:920px;width:100%;box-shadow:0 24px 64px #2563eb20;overflow:hidden;margin:auto 0}
.modal-header{background:var(--card);border-bottom:1px solid var(--line);padding:18px 22px;position:sticky;top:0;z-index:2}
.modal-header .modalbox-head{margin-bottom:0}
.trip-sticky-summary{position:fixed;top:16px;right:16px;z-index:250;background:var(--card);border:1px solid var(--line);border-radius:12px;padding:9px 14px;display:flex;flex-direction:column;gap:3px;min-width:168px;box-shadow:var(--shadow-md)}
.trip-sticky-summary .tss-item{display:flex;justify-content:space-between;align-items:baseline;gap:12px;font-size:11px;color:var(--ink-soft);white-space:nowrap}
.trip-sticky-summary .tss-item b{font-size:12.5px;color:var(--ink)}
.trip-sticky-summary .tss-item.tss-netpl{border-top:1px dashed var(--line);padding-top:4px;margin-top:1px}
.trip-sticky-summary .tss-item.tss-netpl b{font-size:14.5px}
@media(max-width:1050px){.trip-sticky-summary{display:none}}
@media(max-width:640px){.trip-sticky-summary{display:flex;position:static;flex-direction:row;flex-wrap:wrap;gap:4px 16px;margin:0;box-shadow:none;border:none;border-bottom:1px solid var(--line);border-radius:0;min-width:0}
.trip-sticky-summary .tss-item.tss-netpl{border-top:none;padding-top:0;margin-top:0}}
.modal-body{padding:20px}
/* Step-tabs bar (2026-09-16) — exact Figma Make structure: 3 flex-equal tabs under a 2px line,
   a numbered circle (upcoming=brand-soft/faint, active=brand/white, done=green/check) plus label,
   active tab's own bottom border overlaps the shared line. Clicking any tab jumps straight to it,
   same as Figma's own onClick={() => setStep(i)} — no gating, all steps write into one tripDraft. */
.tripstep-tabs{display:flex;border-bottom:2px solid var(--line);margin-bottom:20px}
.tripstep-tab{flex:1;padding:10px 4px;background:none;border:none;border-bottom:2px solid transparent;margin-bottom:-2px;font-size:12px;font-weight:500;color:var(--ink-faint);cursor:pointer;transition:all .15s;display:flex;align-items:center;justify-content:center;gap:6px;font-family:inherit}
.tripstep-tab.active{border-bottom-color:var(--brand);color:var(--brand);font-weight:700}
.tripstep-tab.done{color:var(--ink-soft)}
.tripstep-num{width:20px;height:20px;border-radius:50%;background:var(--brand-soft);color:var(--ink-faint);font-size:10px;font-weight:800;display:inline-flex;align-items:center;justify-content:center;flex:none}
.tripstep-tab.active .tripstep-num{background:var(--brand);color:#fff}
.tripstep-tab.done .tripstep-num{background:var(--green);color:#fff}
@media(max-width:640px){.tripstep-tab{flex-direction:column;gap:3px;font-size:9.5px;padding:8px 2px;text-align:center}}
.modal-footer{padding:14px 22px;border-top:1px solid var(--line);display:flex;justify-content:flex-end;gap:10px;background:var(--card);position:sticky;bottom:0}
.modal-footer .btn{width:auto}
body.modal-open{overflow:hidden}
@media(max-width:640px){.modal-overlay{padding:0}.modal-box{border-radius:0;min-height:100vh}}

.box{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);padding:20px 22px;margin-bottom:16px}
.box-title{font-size:13px;font-weight:700;color:var(--ink);margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid var(--line);display:flex;align-items:center;flex-wrap:wrap;gap:6px 8px}
.box.highlight{background:var(--brand-soft);border-color:var(--brand)}
.box.highlight .box-title{border-bottom-color:var(--brand)}
.box.highlight .field label{color:var(--brand-dark);font-weight:700}
.box-2col{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:800px){.box-2col{grid-template-columns:1fr}}

.fieldpills{display:flex;gap:6px;flex-wrap:wrap;margin-top:2px}
.fieldpill{padding:7px 13px;border-radius:99px;font-weight:700;font-size:12px;color:var(--ink-soft);background:var(--card);border:1px solid var(--line);cursor:pointer;transition:all .15s;white-space:nowrap}
.fieldpill:hover{border-color:var(--brand);color:var(--brand-dark)}
.fieldpill.active{background:var(--brand);color:#fff;border-color:var(--brand)}
/* Pills got tabindex="0" (2026-09-12, Tab-navigation fix — see trips.js's tripPillHtml) so they're
   now reachable by keyboard; give that keyboard focus the same visible ring every plain input/
   select/textarea gets on focus (.field input:focus etc., above) instead of no indicator at all. */
.fieldpill:focus{outline:2px solid var(--brand);outline-offset:1px}

.combo{position:relative}
.combo-dropdown{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:60;background:var(--card);border:1px solid var(--line);border-radius:9px;box-shadow:0 10px 30px rgba(16,28,61,.18);max-height:220px;overflow-y:auto;padding:4px}
.combo-opt{padding:7px 10px;border-radius:6px;cursor:pointer;font-size:12.5px}
.combo-opt:hover{background:var(--brand-soft)}
/* Arrow-key highlight (2026-09-12, keyboard navigation — see trips.js's comboKeyDown/
   comboSetHighlight) — same tint as the existing mouse :hover so keyboard and mouse read
   identically regardless of which one picked the option. */
.combo-opt.highlighted{background:var(--brand-soft)}
.combo-opt.combo-addnew{color:var(--brand-dark);font-weight:700;border-top:1px solid var(--line);margin-top:4px;padding-top:9px}

/* Peshgi/Fixed-Expense Amount inline calculator (2026-09-15) — popup panel, same positioning as
   .combo-dropdown above (it reuses that class) plus its own live-result line and button grid. */
.calc-dropdown{max-height:none;overflow:visible;padding:8px}
.calc-preview{font-size:13px;font-weight:800;color:var(--brand-dark);text-align:right;padding:2px 4px 8px;min-height:18px}
.calc-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.calc-grid button{padding:11px 0;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink);font-size:15px;font-weight:700;cursor:pointer;font-family:inherit}
.calc-grid button:active{background:var(--brand-soft)}
.calc-grid .calc-op{color:var(--brand-dark)}
.calc-grid .calc-clear{color:var(--red)}
.calc-grid .calc-back{grid-column:span 1}
.calc-grid .calc-equals{grid-column:span 1;background:var(--brand-soft);color:var(--brand-dark);border-color:var(--brand)}
.calc-grid .calc-ok{grid-column:span 2;background:var(--brand);color:#fff;border-color:var(--brand)}

/* Diesel section grid: 1 column on phones, 2 from small screens up, 5 on desktop, with the 3
   Diesel Payment Mode pills forced to span the full row above the numeric fields. */
.diesel-formgrid{grid-template-columns:1fr}
.diesel-formgrid .field.diesel-mode-field{grid-column:1 / -1}
@media(min-width:640px){.diesel-formgrid{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1024px){.diesel-formgrid{grid-template-columns:repeat(5,1fr)}}
.diesel-formgrid .fieldpills{gap:8px}
.diesel-formgrid .fieldpill{flex:1 1 170px;text-align:center;padding:9px 13px}
@media(max-width:479px){.diesel-formgrid .fieldpill{flex:1 1 100%}}

.expense-row{display:grid;grid-template-columns:1.3fr 1fr 1fr 1fr 1.3fr auto;gap:8px;align-items:end;margin-bottom:10px;background:var(--card);padding:10px 12px;border-radius:var(--radius);border-left:3px solid var(--brand);box-shadow:var(--shadow)}
.expense-row .btn.red{justify-self:end}
.expense-row-credit{grid-column:1/-1;text-align:right;font-size:11px}
.expense-row-parts{background:var(--card);border-left:3px solid var(--brand);box-shadow:var(--shadow);border-radius:var(--radius)}
@media(max-width:900px){.expense-row{grid-template-columns:1fr 1fr}}

.summary-line{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px dashed var(--line);font-size:12px}
.summary-line b{font-weight:700}
.summary-line.total{border-top:2px solid var(--ink);border-bottom:none;padding-top:6px;margin-top:3px;font-size:13.5px}

.fc-amount{background:var(--navy);color:#fff;font-weight:800;font-size:13px;padding:6px 12px;border-radius:99px;display:inline-flex;align-items:center;gap:4px;white-space:nowrap;font-variant-numeric:tabular-nums;font-family:var(--font-mono)}
.fc-amount.red{background:var(--red)}
.fc-amount.green{background:var(--green)}

/* Dashboard — headline stat cards, small category-badge cards, per-vehicle
   feed cards. Simplified from the offline app's own .statgrid/.ministat/
   .feedcard (same visual language — rounded card, soft-tint accent). */
/* 2026-09-25, per user request ("4 columns [Total Expenses / Net Profit-Loss /
   Total Payable / Contractor Receivable] ka text size aur width bilkul fix aur
   ek jitni honi chahiye"): there are always exactly 4 Dashboard stat cards (see
   STAT_DEFS in dashboard.js), so this is pinned to a literal repeat(4,1fr) —
   four equal-width columns, full stop — instead of the old auto-fit/minmax
   trick, which sized columns off a 180px minimum and could drift uneven
   depending on how many cards fit per row at a given screen width. */
.statgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:16px}
.stat{border-radius:10px;padding:20px;background:var(--card);border:1px solid var(--line);transition:box-shadow .15s,border-color .15s;min-width:0}
.stat:hover{border-color:#93c5fd;box-shadow:0 4px 24px #2563eb12}
/* line-height/min-height reserve exactly 2 lines of label text on every card, so
   "Total Expenses"/"Total Payable" (1 line) and "Net Profit/Loss"/"Contractor
   Receivable" (which wrap to 2 lines) still end up the same card height instead
   of the row looking jagged — the width and font-size were already identical
   across all 4 cards (shared .stat/.lbl/.val classes, no per-card override). */
.stat .lbl{font-size:11px;line-height:1.35;min-height:30px;font-weight:700;color:var(--ink-soft);text-transform:uppercase;letter-spacing:.05em;display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
.stat .val{font-size:24px;font-weight:800;margin-top:10px;letter-spacing:-.02em;font-variant-numeric:tabular-nums;font-family:var(--font-mono)}
.stat .val.green{color:var(--green)}
.stat .val.red{color:var(--red)}
/* Owner Ledger's "Owner Drawing" KPI (2026-09-15 redesign, ported from the offline app's
   .kpi.purple) — a neutral third color so a drawing total doesn't read as a red "problem"
   the way Reclassified Vehicle Debt does. */
.stat .val.purple{color:var(--purple)}
.stat .val.amber{color:var(--amber)}
/* Unused since 2026-09-15 (per-card eye buttons replaced by one page-wide "Show All"/
   "Hide All" toggle, itself removed from the Dashboard header 2026-09-19 — see
   dashboard.js's dashHidden comment) — left defined in case a future screen, or a
   rebuilt hide-all toggle, wants this same small pill-button look. */
.eyebtn{flex:0 0 auto;background:var(--bg);border:1px solid var(--line);border-radius:99px;padding:2px 7px;font-size:9.5px;font-weight:700;color:var(--ink-soft);cursor:pointer;white-space:nowrap}
.eyebtn:hover{background:var(--brand-soft);color:var(--brand-dark)}
.minirow{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:16px}
.ministat{background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);padding:12px 14px}
.ministat .lbl{font-size:11px;color:var(--ink-soft);font-weight:600}
.ministat .val{font-size:15px;font-weight:800;margin-top:6px;font-variant-numeric:tabular-nums;font-family:var(--font-mono)}
.ministat.brand{border-left:3px solid var(--brand)}
.ministat.green{border-left:3px solid var(--green)}
.ministat.purple{border-left:3px solid var(--purple)}
.ministat.amber{border-left:3px solid var(--amber)}
.ministat.red{border-left:3px solid var(--red)}
/* Vendor Snapshot rows that tap/click through to that party's Khata (2026-09-15,
   public/dashboard.js's goToVendorCategory()/showDriversScreen() calls) — same
   hover language as .feedcard so it reads as tappable like the cards below it. */
.ministat.clickable{cursor:pointer;transition:transform .1s,box-shadow .1s}
.ministat.clickable:hover{box-shadow:var(--shadow-md);transform:translateY(-1px);border-color:var(--brand)}
.ministat.clickable:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* Dashboard headline stat cards + Vendor Snapshot mini cards on phone widths
   (2026-09-12, matching the offline app's own mobile rule and the Owner's
   reference screenshot) — force a fixed 2-up grid instead of leaving it to
   auto-fit, which collapses to a single column once the screen's own side
   padding eats into the 180px/150px per-card minimum on real phones. Placed
   after the base .statgrid/.minirow rules above (same selector specificity,
   so source order decides) rather than inside the earlier #bottomNav media
   block, which this would otherwise lose to. */
@media(max-width:860px){
  .statgrid{grid-template-columns:repeat(2,1fr);gap:10px;margin-bottom:14px}
  .stat{padding:14px}
  /* 2026-09-27, per user report (mobile app screenshot) — "Rs." was breaking onto its
     own line above the number (e.g. "Rs." / "160,500") on the 2 stat cards with larger
     6-digit values (Total Expenses/Net Profit-Loss), while the 2 cards with shorter
     5-digit values (Total Payable/Contractor Receivable) stayed on one line right next
     to them — same card, same font-size, just less horizontal room left over once the
     longer number's width didn't fit beside the 38px icon box in .stat-top's flex row,
     so it wrapped at the space after "Rs.". white-space:nowrap alone would just push the
     overflow outside the card instead of fixing it, so this frees up room three ways
     instead: a smaller value font, a smaller icon box, and a tighter icon gap — combined
     that's enough slack for a 6-digit "Rs. 160,500"-length value to fit on one line. */
  .stat .val{font-size:15.5px;white-space:nowrap}
  .stat-top{gap:6px}
  .stat-ic{width:30px;height:30px}
  .minirow{grid-template-columns:repeat(2,1fr);gap:10px}
  .ministat{padding:12px}
}
.feedrow{display:flex;flex-direction:column;gap:10px;margin-bottom:16px}
.feedcard{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:16px 18px;cursor:pointer;transition:box-shadow .15s,border-color .15s;display:flex;flex-direction:column;gap:12px;min-width:0}
.feedcard:hover{box-shadow:0 4px 24px #2563eb12;border-color:#93c5fd}
.feedcard .fc-top{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap}
.feedcard .fc-title{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}
.feedcard .fc-title b{font-size:15px;font-weight:700}
.feedcard .fc-badge{background:color-mix(in oklch, var(--brand) 16%, white);color:var(--brand-dark);font-size:10.5px;font-weight:700;padding:3px 9px;border-radius:99px;white-space:nowrap}
.feedcard .fc-amount{background:var(--navy);color:#fff;font-weight:800;font-size:13px;padding:6px 12px;border-radius:99px;display:flex;align-items:center;gap:4px;white-space:nowrap;flex:none;font-variant-numeric:tabular-nums;font-family:var(--font-mono)}
.feedcard .fc-amount.red{background:var(--red)}
.feedcard .fc-amount.green{background:var(--green)}
.feedcard .fc-amount .chev{font-size:15px;opacity:.75;line-height:1}
.feedcard .fc-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px 14px;font-size:12px;border-top:1px solid var(--line);padding-top:10px}
.feedcard .fc-lbl{color:var(--ink-soft);font-weight:600}

/* ============================================================================
   Dashboard / Vehicles structural layout (2026-09-15, Figma Make redesign —
   this block ports the mockup's actual LAYOUT (icon-boxed stat cards, a
   2-column dashboard grid with a table-like left panel + summary panels on
   the right, illustrated vehicle grid cards) on top of the app's real data —
   not just a color swap. See dashboard.js/vehicles.js for the markup that
   uses these classes.
   ============================================================================ */
.screen-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:18px;flex-wrap:wrap}
.screen-head h1{font-size:20px;font-weight:800;color:var(--ink);letter-spacing:-.02em;margin:0}
.screen-head .sub{color:var(--ink-soft);font-size:13px;margin-top:3px}
.screen-head .actions{display:flex;gap:10px;flex-wrap:wrap;align-items:center}
/* Dashboard's screen-head actions row (2026-09-19, per user: "dashborad button ki aligment
   kro or buttons ko figma style me or size m banao") — Dashboard is the only screen that puts
   the shared Filters button (.filterbtn-row/.filterbtn, from filterButtonHtml() in app.js)
   directly next to an ordinary .btn inside .screen-head .actions; .filterbtn-row's own
   margin-bottom:14px (meant for when Filters sits alone above a list) threw off vertical
   alignment here, and .filterbtn's slightly smaller padding/font-size made it look like a
   different button size than "+ Add Trip". Scoped to this one row so every other screen's
   Filters button (Vehicles, Vendors, Trips, ...) keeps its original spacing/size. */
.screen-head .actions .filterbtn-row{margin-bottom:0}
.screen-head .actions .filterbtn{padding:11px 16px;font-size:13.5px;box-shadow:none}

.stat-top{display:flex;justify-content:space-between;align-items:flex-start;gap:10px}
.stat-ic{width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;flex:none}
.stat-ic svg{display:block}

.dash-grid{display:grid;grid-template-columns:1fr 320px;gap:18px;align-items:start}
/* Grid-blowout fix (2026-09-25, user-reported — "dashboard ka columns fix karo") — a CSS Grid
   item's default min-width is `auto` (sized to fit its content), not 0. Vehicle/Manager
   Performance's .tablewrap tables have wide nowrap columns, so without this the grid column
   (and with it .dash-grid, #mainArea, and the whole page) was being forced wider than the
   screen on mobile — the ENTIRE dashboard scrolled sideways, cutting off unrelated content
   like Account Summary's Rs. amounts even though that panel has no table of its own. Setting
   min-width:0 on both direct grid children lets each column shrink to the container's actual
   width, so .tablewrap's own overflow-x:auto finally does its job (only the table scrolls). */
.dash-grid > div{min-width:0}
@media(max-width:860px){.dash-grid{grid-template-columns:1fr}}

.panel{background:var(--card);border:1px solid var(--line);border-radius:10px;overflow:hidden;margin-bottom:16px;transition:box-shadow .15s,border-color .15s}
.panel:hover{border-color:#93c5fd;box-shadow:0 4px 24px #2563eb12}
.panel-head{padding:14px 18px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center;gap:10px}
.panel-head .t{font-size:14px;font-weight:700;color:var(--ink)}
.panel-head .s{font-size:12px;color:var(--ink-soft);margin-top:1px}
.panel-body{padding:16px 18px}

.balance-box{display:flex;justify-content:space-between;align-items:center;padding:12px 14px;border-radius:8px;margin-bottom:10px}
.balance-box.green{background:var(--green-soft);border:1px solid #bbf7d0}
.balance-box.red{background:var(--red-soft);border:1px solid #fecaca}
.balance-box .bl{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}
.balance-box.green .bl{color:#166534}
.balance-box.red .bl{color:#991b1b}
.balance-box .bs{font-size:11px;opacity:.75;margin-top:1px}
.balance-box .bv{font-family:var(--font-mono);font-size:15px;font-weight:800}
.balance-box.green .bv{color:var(--green)}
.balance-box.red .bv{color:var(--red)}
.balance-divider{height:1px;background:var(--line);margin:12px 0}
.balance-net{display:flex;justify-content:space-between;align-items:center}
.balance-net .nl{font-size:12px;color:var(--ink-soft);font-weight:600}
.balance-net .nv{font-family:var(--font-mono);font-size:14px;font-weight:800}

.progress-item{margin-bottom:13px}
.progress-item:last-child{margin-bottom:0}
.progress-item .pr-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}
.progress-item .pr-lbl{font-size:12.5px;color:var(--ink);font-weight:600}
.progress-item .pr-val{font-family:var(--font-mono);font-size:12px;font-weight:700;padding:1px 8px;border-radius:4px}
.progress-track{height:6px;background:var(--bg);border-radius:4px;overflow:hidden}
.progress-fill{height:6px;border-radius:4px;opacity:.85}

.vehiclegrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}
.vehcard{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:16px;overflow:hidden;transition:box-shadow .15s,border-color .15s}
.vehcard:hover{border-color:#93c5fd;box-shadow:0 4px 24px #2563eb12}
/* Whole-card click target -> Khata (2026-09-19, per user request — the old 5-button actions
   footer, .vehcard-actions/.vehcard-divider below, is no longer used but left defined). */
.vehcard-clickable{cursor:pointer}
.vehcard-clickable:active{box-shadow:0 1px 6px #2563eb1f}
/* Card header (2026-09-16 rebuild — exact match to the Figma Make design's VehiclesPage
   card: a small icon-box + mono plate number/make-year on the left, status+type+wheels
   stacked right-aligned on the right — replaces the earlier illustrated-truck banner
   version, see vehicles.js's header comment for why. */
.vehcard-head{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:12px}
.vehcard-head-left{display:flex;gap:12px;align-items:center}
.vehcard-ic{width:46px;height:46px;border-radius:12px;background:var(--brand-soft);border:1px solid #bfdbfe;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.vehcard-plate{font-family:var(--font-mono);font-size:17px;font-weight:800;color:var(--ink);letter-spacing:.04em}
.vehcard-sub{font-size:12px;color:var(--ink-soft);margin-top:1px}
.vehcard-head-right{text-align:right}
.vehcard-typepill{font-size:11px;font-weight:700;color:var(--brand);background:var(--brand-soft);padding:2px 8px;border-radius:4px;margin-top:4px;display:inline-block}
.vehcard-wheels{font-size:11px;color:var(--ink-faint);margin-top:3px}
.vehcard-infogrid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:0}
.vehcard-infogrid .vi{background:#f8faff;border-radius:6px;padding:8px 10px}
.vehcard-infogrid .vi .vl{font-size:10px;color:var(--ink-faint);font-weight:600;text-transform:uppercase;letter-spacing:.05em;margin-bottom:3px}
.vehcard-infogrid .vi .vv{font-size:12px;color:var(--ink-soft);font-weight:600}
.vehcard-divider{height:1px;background:var(--line);margin-bottom:12px}
.vehcard-actions{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}

/* Vehicle Account (Khata) header — back button, plate-number title, status pill and the "..."
   kebab menu (Edit/Tyres/Maintenance) — Figma rebuild, 2026-09-19, per user: "ye figma jesa
   page banao or active k sath ... button banao jis me edit tyres & mentanince button add kro". */
.vaheader{display:flex;align-items:center;gap:12px;margin-bottom:18px;flex-wrap:wrap}
.vaback{flex:none;width:36px;height:36px;border-radius:10px;border:1px solid var(--line);background:var(--card);color:var(--ink);font-size:17px;cursor:pointer;display:flex;align-items:center;justify-content:center}
.vaback:hover{background:var(--brand-soft);border-color:var(--brand)}
.vaheader-title{flex:1;min-width:120px}
.vaheader-plate{font-family:var(--font-mono);font-size:19px;font-weight:800;color:var(--ink);letter-spacing:.03em}
.vaheader-sub{font-size:12.5px;color:var(--ink-soft);margin-top:2px}
.vamenu{position:relative;flex:none}
.vamenu-btn{width:36px;height:36px;border-radius:10px;border:1px solid var(--line);background:var(--card);color:var(--ink);font-size:18px;cursor:pointer;line-height:1}
.vamenu-btn:hover{background:var(--brand-soft);border-color:var(--brand)}
.vamenu-dropdown{position:absolute;top:42px;right:0;min-width:180px;background:var(--card);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-md);z-index:30;padding:6px;display:flex;flex-direction:column;gap:2px}
.vamenu-dropdown button{width:100%;text-align:left;background:none;border:none;border-radius:8px;padding:9px 10px;font-size:13px;font-weight:600;color:var(--ink);cursor:pointer}
.vamenu-dropdown button:hover{background:var(--brand-soft)}
/* 2026-09-30 -- Delete Vehicle menu item (vehicleAccount.js) reads as destructive at a glance,
   same reasoning as .btn.primary.danger above. */
.vamenu-dropdown button.danger{color:var(--red)}
.vamenu-dropdown button.danger:hover{background:var(--red-soft)}

/* Generic per-row "..." action menu (2026-09-23) — same visual language as .vamenu above, but
   safe to render many times on one screen (each row gets its own wrapper/dropdown pair instead
   of sharing one fixed id) — see app.js's rowMenuHtml()/toggleRowMenu(). */
.rowmenu{position:relative;display:inline-flex}
.rowmenu-btn{width:30px;height:30px;border-radius:8px;border:1px solid var(--line);background:var(--card);color:var(--ink);font-size:16px;cursor:pointer;line-height:1;display:flex;align-items:center;justify-content:center}
.rowmenu-btn:hover{background:var(--brand-soft);border-color:var(--brand)}
.rowmenu-dropdown{position:absolute;top:calc(100% + 4px);right:0;min-width:160px;background:var(--card);border:1px solid var(--line);border-radius:12px;box-shadow:var(--shadow-md);z-index:30;padding:6px;display:flex;flex-direction:column;gap:2px}
.rowmenu-dropdown button{width:100%;text-align:left;background:none;border:none;border-radius:8px;padding:9px 10px;font-size:13px;font-weight:600;color:var(--ink);cursor:pointer;white-space:nowrap}
.rowmenu-dropdown button:hover{background:var(--brand-soft)}
.rowmenu-dropdown button.danger{color:var(--red)}
.rowmenu-dropdown button.danger:hover{background:var(--red-soft)}

/* Maintenance History card rows (Khata screen, Figma rebuild). */
.va-maint-row{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid var(--line)}
.va-maint-row:last-child{border-bottom:none}

/* Ledger table's Net Balance strip — Payable (dr, amber) / Receivable (cr, green). */
.va-netbalance{margin-top:10px;padding:10px 14px;border-radius:10px;font-size:13px;background:var(--brand-soft);color:var(--ink)}
.va-netbalance.dr{background:var(--amber-soft);color:#92400e}
.va-netbalance.cr{background:var(--green-soft);color:var(--green)}

/* Add/Edit record modal windows — Vehicle/Driver/Vendor/Contractor/Vehicle-Owner (2026-09-16,
   user request: "add karny ka tareka or window figma ui/ux k style me banao jese window choti
   or attractive hai same isi tarha banao"). Replaces the old full-width "authcard wide"
   overlay (single-column stacked fields, plain bold title, no icon/subtitle, full-width
   Cancel+Save) with the Figma Make design's own small ModalShell pattern: a compact
   ~500px-wide card, icon-box + title + subtitle header with an X close button, fields
   grouped two-per-row where they fit, and a right-aligned Cancel(ghost)/Save(primary) bar —
   exact spacing/sizing from the Figma source's `.modal`/`.modal-overlay` CSS. Only the
   window's chrome changed — every field id, option list and open/save/close function is
   untouched, so no JS needed updating. */
.modalbox{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:28px;width:520px;max-width:95vw;max-height:90vh;overflow-y:auto;box-shadow:0 24px 64px rgba(37,99,235,.14)}
.modalbox-head{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:22px}
.modalbox-head-left{display:flex;gap:12px;align-items:center}
.modalbox-ic{width:40px;height:40px;border-radius:10px;background:var(--brand-soft);border:1px solid #bfdbfe;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.modalbox-title{font-size:17px;font-weight:800;color:var(--ink)}
.modalbox-sub{font-size:12px;color:var(--ink-soft);margin-top:1px}
.modalbox-close{background:none;border:none;color:var(--ink-faint);cursor:pointer;padding:4px;display:flex;border-radius:6px}
.modalbox-close:hover{color:var(--ink-soft);background:var(--bg)}
.formrow{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:14px}
.formrow.cols1{grid-template-columns:1fr}
.formrow .field,.modalbox>.field{margin-bottom:0}
.modalbox>.field{margin-bottom:14px}
/* Scoped to these modals only (never the global .field) — Figma's Field label is small,
   uppercase and letter-spaced; the rest of the app's .field labels stay exactly as-is. */
.modalbox .field label{text-transform:uppercase;letter-spacing:.04em;font-size:11.5px}
.modalbox-savebar{display:flex;gap:10px;margin-top:20px;justify-content:flex-end}
.modalbox-savebar .btn{width:auto}

/* Print — Trip Voucher / Ledger (Khata) — see printLedgerVoucher() in ledger.js and
   printTripVoucher() in trips.js. Neither one prints the on-screen app card directly
   (colored, rounded, app-styled) — each builds a clean black & white .voucher document
   into the always-in-DOM #printArea (see index.html, just before </body>) and only THAT
   prints, same idea as the offline app's own #printArea/.voucher pattern. */
#printArea{display:none}
@media print{
  html, body{height:auto !important; margin:0 !important; padding:0 !important; background:#fff !important}
  body > *:not(#printArea){display:none !important}
  #printArea{display:block !important; width:auto}
  @page{size:A4; margin:10mm}
}
.voucher{width:100%;font-size:11.5px;color:#000}
.voucher .vhead{text-align:center;border-bottom:2px solid #000;padding-bottom:6px;margin-bottom:8px}
.voucher .vhead h1{font-size:17px;margin:0}
.voucher .vhead div{font-size:11px}
/* Company Address/Phone/Email line under the company name (2026-09-23) — see trips.js's
   voucherContactLine(). Slightly smaller/muted than the doc-title line below it. */
.voucher .vhead .vcontact{font-size:9.5px;color:#444 !important;margin-top:2px}
.voucher table{width:100%;border-collapse:collapse;font-size:11px;margin-top:6px}
.voucher th,.voucher td{padding:3px 6px;border:1px solid #999;color:#000 !important;text-align:left}
.voucher th{background:#f0f0f0}
.voucher td.right,.voucher th.right{text-align:right}
.voucher .meta{display:grid;grid-template-columns:1fr 1fr;gap:2px 16px;margin-bottom:8px;font-size:11.5px}
.voucher .meta div{padding:2px 0;border-bottom:1px dotted #ccc}
.voucher .sig{display:flex;justify-content:space-between;margin-top:26px;font-size:11.5px}
/* App attribution footer (2026-09-23) — see trips.js's voucherFooterHtml(). Left-aligned, small,
   muted — sits after the signature line as the last thing on the printed page, independent of
   whether the header above shows the app's own brand or a paid fleet's own Company Name. */
.voucher .vfoot{margin-top:18px;padding-top:6px;border-top:1px solid #ccc;text-align:left;font-size:9.5px;color:#888 !important}
.voucher .totalrow td{font-weight:700;background:#f0f0f0}
.voucher h3{font-size:12.5px;margin:12px 0 4px}
.voucher h4{font-size:11.5px;margin:10px 0 3px;color:#000}
.voucher p.muted,.voucher .muted{color:#555 !important}

/* ============================================================================
   Home screen — section header icon boxes + invite/QR card (2026-09-15,
   conservative Figma "QRConnectPage" visual polish applied to the REAL
   invite-link/QR feature only — see public/index.html's homeScreen and
   app.js's renderInviteUI(). No fictional mobile-pairing or RBAC-role UI
   from the mockup was ported; see project doc for why.
   ============================================================================ */
.sectionhead-ic{display:flex;align-items:center;gap:12px;margin-bottom:14px}
.sectionhead-ic .ic{width:40px;height:40px;border-radius:11px;background:linear-gradient(135deg,var(--brand) 0%,var(--brand-dark) 100%);display:flex;align-items:center;justify-content:center;flex:none;font-size:18px;box-shadow:0 4px 14px #2563eb30}
.sectionhead-ic .t{font-size:14px;font-weight:800;color:var(--ink)}
.sectionhead-ic .s{font-size:12px;color:var(--ink-soft);margin-top:1px}

.invitecard{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:20px;text-align:center}
.invitecard .qrwrap{display:inline-block;background:#fff;padding:12px;border-radius:12px;box-shadow:0 4px 24px #1e3a8a18;margin:6px 0 14px}
.invitecard .codebox{background:#f8faff;border:1px solid #dbeafe;border-radius:10px;padding:12px 18px;margin-bottom:14px}
.invitecard .codebox .cl{font-size:10.5px;color:var(--ink-soft);font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:4px}
.invitecard .codebox .cv{font-family:var(--font-mono);font-size:13px;font-weight:700;color:var(--brand);word-break:break-all}

.steplist{display:flex;flex-direction:column}
.stepitem{display:flex;gap:12px;padding:10px 0;border-bottom:1px solid var(--bg)}
.stepitem:last-child{border-bottom:none}
.stepitem .num{width:26px;height:26px;border-radius:99px;background:var(--brand-soft);border:1px solid #bfdbfe;display:flex;align-items:center;justify-content:center;flex:none}
.stepitem .num span{font-size:11px;font-weight:800;color:var(--brand)}
.stepitem .txt b{font-size:12.5px;color:var(--ink);display:block}
.stepitem .txt p{font-size:11.5px;color:var(--ink-soft);margin-top:1px}

.memberrow{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:8px;margin-bottom:8px;background:var(--card)}
.memberrow:last-child{margin-bottom:0}
.memberrow .mr-left{display:flex;align-items:center;gap:10px;min-width:0}
.memberrow .mr-ic{width:32px;height:32px;border-radius:50%;background:var(--brand-soft);color:var(--brand-dark);display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:800;flex:none}
.memberrow .mr-name{font-size:13px;font-weight:700;color:var(--ink)}
.memberrow .mr-sub{font-size:11.5px;color:var(--ink-soft)}

/* Manager Permissions modal (2026-09-23) -- managerPermsModal in index.html, filled by
   app.js's renderManagerPermsForm() from lib/permissions.js's PERMISSION_LABELS grouping. */
.permslist{max-height:52vh;overflow-y:auto;margin:4px 0 8px}
.permgroup{margin-bottom:14px}
.permgroup:last-child{margin-bottom:0}
.permgroup-title{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.03em;color:var(--ink-soft);margin-bottom:6px}
.permrow{display:flex;align-items:center;gap:10px;padding:8px 4px;border-bottom:1px solid var(--line);cursor:pointer}
.permrow:last-child{border-bottom:none}
.permrow input[type="checkbox"]{width:17px;height:17px;flex:none;accent-color:var(--brand)}
.permrow span{font-size:13px;color:var(--ink)}

/* ============================================================================
   Settings + My Profile screens (2026-09-15) — Figma "SettingsPage"/"UserPanel"
   ported as a STATIC/MOCKUP UI only (user's explicit choice — real screens
   don't exist in this app at all yet): toggles/inputs are local-only (no
   server persistence, same as Figma's own React demo state), Save buttons
   show a cosmetic "✓ Saved" the same way Figma's mockup does. See
   settings.js/profile.js file-header comments and claude/next-steps.md for
   exactly what was intentionally left out (fake activity log, fake device
   list, fake org-chart/manager, fake RBAC roles/permissions) because those
   would show fabricated claims about the REAL logged-in person, not just an
   unstyled feature.
   ============================================================================ */
.settingsgrid{display:grid;grid-template-columns:210px 1fr;gap:20px;align-items:start}
@media(max-width:760px){.settingsgrid{grid-template-columns:1fr}}
.settingsnav{display:flex;flex-direction:column;gap:2px}
.settingsnav button{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;border-radius:8px;border:none;background:transparent;color:var(--ink-soft);font-weight:600;font-size:13px;text-align:left;cursor:pointer;border-left:3px solid transparent}
.settingsnav button:hover{background:var(--bg)}
.settingsnav button.active{background:var(--brand-soft);color:var(--brand-dark);font-weight:700;border-left-color:var(--brand)}

.togswitch{width:46px;height:26px;border-radius:13px;background:var(--line);border:none;cursor:pointer;position:relative;flex:none;transition:background .15s;padding:0}
.togswitch.on{background:var(--brand)}
.togswitch .knob{position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:0 1px 4px rgba(0,0,0,.25);transition:left .15s}
.togswitch.on .knob{left:23px}

.settingsrow{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:13px 0;border-bottom:1px solid var(--bg)}
.settingsrow:last-child{border-bottom:none}
.settingsrow .sr-label{font-size:13px;font-weight:600;color:var(--ink)}
.settingsrow .sr-desc{font-size:11.5px;color:var(--ink-soft);margin-top:2px}

.themepresetgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.themepreset{padding:12px;border-radius:10px;border:2px solid var(--line);background:#fff;cursor:pointer;text-align:left;position:relative}
.themepreset.active{border-color:var(--brand);background:var(--brand-soft)}
.themepreset .swatches{display:flex;gap:5px;margin-bottom:8px}
.themepreset .sw{width:18px;height:18px;border-radius:5px}
.themepreset .plabel{font-size:11px;font-weight:700;color:var(--ink)}
.themepreset.active .plabel{color:var(--brand-dark)}
.themepreset .check{position:absolute;top:6px;right:6px;width:16px;height:16px;border-radius:50%;background:var(--brand);color:#fff;display:flex;align-items:center;justify-content:center;font-size:9px}

.settings-sublabel{font-size:11px;font-weight:700;color:var(--ink-soft);text-transform:uppercase;letter-spacing:.06em;margin:0 0 12px}
.settings-savedtag{font-size:12px;color:var(--green);font-weight:700}

.profilebanner{background:linear-gradient(135deg,var(--navy) 0%,var(--brand-dark) 60%,var(--brand) 100%);border-radius:16px;padding:26px 28px;margin-bottom:20px;position:relative;overflow:hidden;color:#fff}
.profilebanner::before{content:'';position:absolute;top:-30px;right:-30px;width:160px;height:160px;border-radius:50%;background:rgba(255,255,255,.05)}
.profilebanner-row{display:flex;align-items:center;gap:18px;position:relative;flex-wrap:wrap}
.profilebanner .pb-avatar{width:64px;height:64px;border-radius:18px;background:linear-gradient(135deg,var(--brand) 0%,var(--purple) 100%);display:flex;align-items:center;justify-content:center;flex:none;box-shadow:0 4px 18px rgba(124,58,237,.35)}
.profilebanner .pb-avatar span{font-size:21px;font-weight:900;color:#fff}
.profilebanner .pb-name{font-size:20px;font-weight:900;letter-spacing:-.02em}
.profilebanner .pb-sub{font-size:12.5px;color:#bfdbfe;margin-top:2px}
.profilebanner .pb-badges{display:flex;gap:8px;margin-top:10px;flex-wrap:wrap}
.profilebanner .pb-badge{font-size:11px;font-weight:800;padding:4px 11px;border-radius:6px;background:rgba(255,255,255,.12);color:#e0e7ff}
.profilebanner .pb-badge.role{background:rgba(124,58,237,.3);color:#ddd6fe;border:1px solid rgba(124,58,237,.4)}

.rolecard{background:var(--brand-soft);border:1px solid var(--line);border-radius:12px;padding:18px 20px}
.rolecard .rc-top{display:flex;align-items:center;gap:14px;margin-bottom:6px}
.rolecard .rc-ic{width:44px;height:44px;border-radius:12px;background:#fff;display:flex;align-items:center;justify-content:center;font-size:19px;flex:none}
.rolecard .rc-title{font-size:15px;font-weight:800;color:var(--ink)}
.rolecard .rc-sub{font-size:11.5px;color:var(--ink-soft);margin-top:2px}

/* ---- First-login guided tour (2026-09-30, migration 026 — see
   public/onboarding.js's header for the full design). #tourChrome sits at
   z-index 9000+ -- above everything in the app (sidebar 30, topbar/bars
   19-20, bottomNav 40, sidebarBackdrop 55, notif/dropdown panels 50-60,
   modal-overlay 200) except #bootLoadingScreen's one-off 9999, which is
   never on-screen at the same time as the tour. Four separate .tour-mask
   divs (not one box-shadow "donut") dim the page around the highlighted
   button while leaving its own real rect completely uncovered, so the
   button underneath stays natively clickable and nothing else on the
   dimmed page is -- see positionSpotlight() in onboarding.js. */
#tourChrome{position:fixed;inset:0;z-index:9000}
.tour-mask{position:fixed;background:rgba(9,14,32,.62);pointer-events:auto;transition:top .18s ease,left .18s ease,right .18s ease,bottom .18s ease,height .18s ease,width .18s ease}
.tour-ring{position:fixed;border-radius:10px;box-shadow:0 0 0 3px var(--brand),0 0 22px rgba(37,99,235,.55);pointer-events:none;z-index:9001;transition:top .18s ease,left .18s ease,width .18s ease,height .18s ease}
.tour-tooltip{position:fixed;z-index:9002;background:#fff;border-radius:14px;box-shadow:0 18px 44px rgba(9,14,32,.35);padding:18px 20px;max-width:320px;width:calc(100vw - 28px)}
.tour-tooltip.tour-tooltip-center{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);max-width:360px;text-align:center}
.tour-tooltip .tour-progress{font-size:10.5px;font-weight:800;color:var(--brand);text-transform:uppercase;letter-spacing:.07em;margin-bottom:6px}
.tour-tooltip h3{font-size:15.5px;font-weight:800;color:var(--ink);margin-bottom:6px}
.tour-tooltip p{font-size:13px;color:var(--ink-soft);line-height:1.5;margin-bottom:16px}
.tour-tooltip .tour-btnrow{display:flex;gap:10px;justify-content:flex-end}
.tour-tooltip-center .tour-btnrow{justify-content:center}
.tour-tooltip .tour-btn-skip{margin-right:auto}
.tour-tooltip-center .tour-btn-skip{margin-right:0}

/* ---- Dark Mode (2026-09-30, per user report "app ka dark mode or compact mode work nhi kr
   rhy") — Settings > Appearance's Dark Mode toggle, made real (public/app.js's applyAppTheme()
   puts a 'dark-mode' class on <html> when this fleet's saved appearance.darkMode is true — see
   that function's own header). The whole app already runs on the --bg/--card/--ink/--ink-soft/
   --ink-faint/--line tokens defined in :root above (that block's own comment: "every screen's
   CSS ... already goes through these tokens, never a hardcoded hex"), so overriding just those
   here re-skins every screen the same way a theme-color change does — no per-screen edits
   needed. --brand-soft/--navy2/--purple-soft stay JS-driven (documentElement.style, which wins
   over any class selector here since inline style has higher specificity) — applyAppTheme()
   itself computes dark-appropriate versions of those when darkMode is on, see its comment.
   Five spots use a literal `background:#f8faff` instead of a variable (pre-dating this dark-mode
   work) -- overridden individually below rather than converting all five to a new CSS variable,
   to keep this a scoped addition. Pre-login screens (#authScreen/#forgotPasswordScreen/
   #qrLoginScreen) are untouched by design -- this class is only ever added post-login (see
   loadAndApplyAppTheme()), and those screens were separately made permanently English/LTR and
   decoupled from theming entirely (2026-09-26). Voucher/print output (.voucher, @media print) is
   also untouched -- printed paper should always be plain black-on-white regardless of the
   on-screen theme. */
:root.dark-mode{
  --bg:#0b1220; --card:#121b2e;
  --ink:#e7ebf5; --ink-soft:#9aa7c2; --ink-faint:#6b7794;
  --line:#253248;
  --green-soft:#0f2b1c; --red-soft:#3a1a1a; --amber-soft:#332910; --blue-soft:#16233f;
  --shadow:0 1px 2px rgba(0,0,0,.35),0 4px 14px rgba(0,0,0,.28); --shadow-md:0 10px 28px rgba(0,0,0,.4);
}
:root.dark-mode body{background:var(--bg);color:var(--ink)}
:root.dark-mode .field input,
:root.dark-mode .field select,
:root.dark-mode .field textarea,
:root.dark-mode .ab-dropzone,
:root.dark-mode .tablewrap thead tr,
:root.dark-mode .vehcard-infogrid .vi,
:root.dark-mode .invitecard .codebox{background:#182338;border-color:var(--line)}
:root.dark-mode .tour-tooltip{background:var(--card);color:var(--ink)}
:root.dark-mode ::placeholder{color:var(--ink-faint)}
/* Sidebar/topbar/navy surfaces already use --navy/--navy2 (dark by design in both modes) so
   need no override; #bootLoadingScreen is pre-theme-class (boots white before login) and
   intentionally untouched. */

/* ---- Compact Mode (2026-09-30, same user report as Dark Mode above) — "Reduce padding for
   more data on screen". This codebase's padding is mostly hardcoded per-component rather than
   on a shared spacing variable (see this file's own long-standing convention), so rather than
   the much bigger job of converting every single padding value to a var() first, this overrides
   the small set of high-traffic containers that account for most of the app's visible density:
   cards/auth-cards, modals, stat tiles, table cells, settings rows, the sidebar and topbar, and
   buttons. Not literally every pixel of padding in the app, but the containers a user actually
   notices when judging "is this dense or spacious". */
:root.compact-mode .authcard{padding:18px 16px}
:root.compact-mode .card{padding:11px;margin-bottom:10px}
:root.compact-mode .modal-body{padding:13px}
:root.compact-mode .modal-header{padding:12px 15px}
:root.compact-mode .modal-footer{padding:10px 15px}
:root.compact-mode .stat{padding:13px}
:root.compact-mode .screen-head{margin-bottom:12px}
:root.compact-mode .field{margin-bottom:9px}
:root.compact-mode .formrow{gap:9px;margin-bottom:9px}
:root.compact-mode .settingsrow{padding:8px 0}
:root.compact-mode .btn{padding:8px 13px}
:root.compact-mode .tablewrap th,
:root.compact-mode .tablewrap td{padding:5px 7px}
:root.compact-mode #sidebarNav{padding:14px 10px;gap:10px}
:root.compact-mode #topbar{padding:8px 14px}
:root.compact-mode .pillrow{gap:5px}
