/* ============================================================
   AssetTrack v2 — School Inventory Management System
   Enhanced CSS: transitions, confirm dialogs, tags, sorting,
   procurement cart, bill upload, dashboard quick-review panel
   ============================================================ */
/* Fonts are now loaded with <link> tags in the page <head> (preconnect + stylesheet) instead of a render-blocking @import.
   The "Fallback" faces are Arial scaled to Inter's / Sora's proportions, so the text keeps its size and line breaks when the web font swaps in. */
@font-face { font-family:'Inter Fallback'; src:local('Arial'), local('Helvetica'); size-adjust:107.4%; ascent-override:90.2%; descent-override:22.5%; line-gap-override:0%; }
@font-face { font-family:'Sora Fallback'; src:local('Arial'), local('Helvetica'); size-adjust:105%; ascent-override:92%; descent-override:23%; line-gap-override:0%; }

:root {
  --navy-900: #0C1633;
  --navy-800: #12204A;
  --navy-700: #182C5E;
  --navy-600: #22397A;
  --navy-500: #2E4A93;
  --navy-400: #3A5BAD;
  /* Semantic "accent ink" — used for links, focus rings, active borders and
     small emphasis text/icons. Defaults to navy-600 (matches the original
     design exactly in light mode) but gets a brighter, more legible blue
     in dark mode, since navy-600 text is close to unreadable against a
     dark surface. Kept separate from --navy-600 itself so branded solid
     fills (gradients, logo tiles) that intentionally use navy-600 as a
     *background* stay exactly as designed in both themes. */
  --accent: var(--navy-600);

  --brass: #5FA82E;
  --brass-light: #8CC63F;
  --brass-soft: #DCF0C4;
  --brass-tint: #EFF9E4;

  --ink: #101526;
  --ink-soft: #29304A;
  --muted: #666F8C;
  --line: #DCE2F0;
  --line-soft: #EEF1F8;
  --canvas: #EEF2FA;
  --surface: #FFFFFF;
  --surface-soft: #F6F8FD;

  --success: #2F8F5B;  --success-tint: #E4F4EB;
  --danger:  #C0463A;  --danger-tint:  #FBEAE8;  --danger-tint-hover: #F8E0DC;
  --late:    #C2841F;  --late-tint:    #FBF1DF;  --late-tint-hover:   #F7EDCF;
  --info:    #2C6FA8;  --info-tint:    #E6F0F8;
  --purple:  #7B4FC0;  --purple-tint:  #F1ECFA;
  --violet:  #6B4FA0;  --violet-tint:  #EEE7F8;
  --brass-ink: #4A7A22;

  --display: 'Sora', 'Sora Fallback', 'Inter', sans-serif;
  --body:    'Inter', 'Inter Fallback', -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --mono:    'JetBrains Mono', monospace;

  --radius-sm: 8px;
  --radius:    14px;
  --radius-lg: 22px;
  --shadow-sm: 0 1px 2px rgba(12,22,51,.06),  0 1px 1px  rgba(12,22,51,.04);
  --shadow:    0 8px 24px -8px rgba(12,22,51,.16), 0 2px 6px rgba(12,22,51,.06);
  --shadow-lg: 0 24px 60px -20px rgba(12,22,51,.35);
  --transition: .18s cubic-bezier(.4,0,.2,1);
  color-scheme: light;
}

/* ============================================================
   Dark mode — overrides the same semantic tokens :root defines
   above, so every component that already reads var(--ink),
   var(--surface), var(--line), a status tint, etc. re-themes
   automatically with no per-component CSS needed. Branded solid
   fills that are meant to stay constant in both themes (the navy
   sidebar, primary/gold buttons, the auth marketing panel) use
   --navy-800/--navy-900/--brass directly rather than a semantic
   token, so they're deliberately untouched here — see the
   comments on --accent above for why that split exists.
   Toggled by setting data-theme="dark" on <html> (theme.js). */
:root[data-theme="dark"] {
  --ink: #E9ECF7;
  --ink-soft: #C7CEE8;
  --muted: #8A93BD;
  --line: #323C68;
  --line-soft: #232B4E;
  --canvas: #0B1226;
  --surface: #141B33;
  --surface-soft: #1B2340;

  --accent: #7FA8E8;

  --brass-tint: #1D2C14;
  --brass-soft: #23331A;
  --brass-ink: #9AD467;

  --success: #4FCB8C;  --success-tint: #163625;
  --danger:  #E88A7E;  --danger-tint:  #3B211E;  --danger-tint-hover: #4A2B27;
  --late:    #E6B85C;  --late-tint:    #3A2E15;  --late-tint-hover:   #4A3A1C;
  --info:    #7FB3E0;  --info-tint:    #17293D;
  --purple:  #B79CE8;  --purple-tint:  #251C3E;
  --violet:  #C0A8EC;  --violet-tint:  #241C3A;

  --shadow-sm: 0 1px 2px rgba(0,0,0,.28),  0 1px 1px  rgba(0,0,0,.2);
  --shadow:    0 8px 24px -8px rgba(0,0,0,.45), 0 2px 6px rgba(0,0,0,.3);
  --shadow-lg: 0 24px 60px -20px rgba(0,0,0,.65);
  color-scheme: dark;
}
/* Smooth, app-wide cross-fade when the toggle is used, without adding a
   transition to every single element (which would make already-animated
   things like the toast or the confirm dialog feel sluggish). */
body, .sidebar, .card, .topbar, .modal, .confirm-dialog, .filter-bar, .auth-split, .auth-right, input, select, textarea, .btn {
  transition: background-color var(--transition), color var(--transition), border-color var(--transition), box-shadow var(--transition);
}

*,*::before,*::after { box-sizing:border-box; }
html, body { height:100%; }
body { margin:0; font-family:var(--body); background:var(--canvas); color:var(--ink); -webkit-font-smoothing:antialiased; }
.hidden { display:none !important; }
a { color:inherit; text-decoration:none; }
button { font-family:inherit; cursor:pointer; }
input, select, textarea { font-family:inherit; font-size:14px; }

/* ── Checkbox row ── */
.checkbox-row { display:flex; gap:10px; align-items:flex-start; margin:14px 0; cursor:pointer; }
.checkbox-row input { margin-top:3px; flex-shrink:0; width:16px; height:16px; accent-color:var(--brass); }
.checkbox-row span { font-size:12.5px; color:var(--muted); line-height:1.5; }

/* ── Footer ── */
.app-footer { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; padding:14px 28px; margin-top:auto; border-top:1px solid var(--line); font-size:12px; color:var(--muted); background:var(--surface); }
@media (max-width:640px) {
  /* space-between only reads correctly with both items on one line — once
     they wrap to their own lines on a narrow screen it left-aligns each
     one instead, which looks unbalanced. Stack and center them instead,
     matching the already-centered footer on the login page. */
  .app-footer { flex-direction:column; justify-content:center; text-align:center; gap:6px; padding:16px; }
}
.app-footer-credit strong { color:var(--ink-soft); font-weight:700; }
.app-footer-auth { max-width:420px; width:100%; margin:14px auto 0; padding:12px 4px; border-top:none; background:transparent; color:#B9C2E6; justify-content:center; gap:18px; }
.app-footer-auth .app-footer-credit strong { color:#EAEEFB; }

/* ── Auth screen ── */
.auth-shell { min-height:100vh; min-height:100dvh; display:flex; flex-direction:column; align-items:center; justify-content:center; background:#081026; padding:24px; }
.auth-split { width:100%; max-width:1040px; min-height:600px; display:flex; border-radius:20px; overflow:hidden; box-shadow:0 30px 80px rgba(4,8,24,.55); background:var(--surface); }
.auth-left { flex:1.1; position:relative; padding:40px 44px; display:flex; flex-direction:column; justify-content:space-between; background:radial-gradient(circle at 15% 8%,#1B2F63 0%,#101E45 45%,#081026 100%); color:#fff; overflow:hidden; min-width:0; }
.auth-left-noise { position:absolute; inset:0; opacity:.5; pointer-events:none; background-image:radial-gradient(rgba(255,255,255,.05) 1px,transparent 1px); background-size:16px 16px; }
.auth-left > * { position:relative; z-index:1; }
.auth-left-mid { max-width:440px; }
.auth-left .eyebrow { font-size:11.5px; font-weight:700; letter-spacing:.08em; color:#8CC63F; margin-bottom:14px; }
.auth-left h1 { font-family:var(--display); font-size:clamp(26px,3vw,34px); line-height:1.2; margin:0 0 16px; color:#fff; }
.auth-left-mid p { font-size:14px; line-height:1.65; color:#B9C2E6; margin:0; }
.auth-left-stats { display:flex; gap:36px; flex-wrap:wrap; }
.auth-left-stats .num { font-family:var(--display); font-size:26px; font-weight:700; color:#fff; }
.auth-left-stats .lbl { font-size:10.5px; letter-spacing:.06em; color:#8B96C2; margin-top:2px; }
.auth-right { flex:1; min-width:0; display:flex; align-items:center; justify-content:center; padding:44px 36px; background:var(--surface); }
.auth-card { width:100%; max-width:360px; }
.auth-brand { display:flex; align-items:center; gap:12px; }
.auth-brand > div:last-child { display:flex; flex-direction:column; justify-content:center; min-width:0; }
.auth-left .auth-brand .name { color:#fff; }
.auth-left .auth-brand .sub  { color:#9BA6D1; }
.mark {
  position: relative; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg,var(--navy-800),var(--navy-600));
  color: #fff; font-family: var(--display); font-weight: 700;
  overflow: hidden; flex-shrink: 0; text-align: center; line-height: 1;
}
.mark img { width:100%; height:100%; object-fit:cover; display:block; border-radius:inherit; }
/* Reference style: logo sits on a clean white rounded card, fully contained
   (never cropped) with a little breathing room — matches how the mark
   should look consistently across the sidebar, login screen and anywhere
   else it appears, regardless of the uploaded logo's own shape/colors.
   This class is only ever added once the image has actually finished
   loading (see applyBranding) — never pre-emptively — so a broken or
   still-loading logo never leaves a blank white box on screen. */
.mark.has-logo { background:#fff; box-shadow:0 1px 3px rgba(16,24,56,.12); border:1px solid var(--line-soft); }
/* The logo <img> itself (mark-logo-img) is only ever inserted by
   setBrandMarks() in common.js once fully loaded, and carries its own
   inline sizing/position/background so it can never be silently defeated
   by a stylesheet rule elsewhere — see that function for why. */
/* .sidebar .brand .mark / .auth-brand .mark are more specific (3 classes)
   than the plain .mark.has-logo rule above (2 classes), so without these
   they'd win and silently override the white has-logo background with the
   navy fallback gradient — restated here at matching specificity so the
   white card actually applies everywhere the mark appears. */
.sidebar .brand .mark.has-logo,
.auth-brand .mark.has-logo { background:#fff; box-shadow:0 1px 3px rgba(16,24,56,.12); }
.auth-brand .name { font-family:var(--display); font-weight:700; font-size:18px; color:var(--ink); line-height:1.25; margin:0; }
.auth-brand .sub  { font-size:11.5px; color:var(--muted); letter-spacing:.02em; line-height:1.3; margin-top:2px; }
.auth-card h2 { font-family:var(--display); font-size:24px; margin:22px 0 4px; color:var(--ink); }
.auth-card .sub { font-size:13.5px; color:var(--muted); margin-bottom:26px; }
.auth-card-foot { font-size:11.5px; color:var(--muted); text-align:center; margin:22px 0 0; }
.auth-error { display:none; background:var(--danger-tint); color:var(--danger); font-size:13px; padding:10px 14px; border-radius:var(--radius-sm); margin-bottom:16px; border:1px solid rgba(192,70,58,.2); }
.auth-error.show { display:block; animation:fadeIn var(--transition); }
.auth-success { display:none; background:var(--success-tint); color:var(--success); font-size:13px; padding:10px 14px; border-radius:var(--radius-sm); margin-bottom:16px; border:1px solid rgba(47,143,91,.2); }
.auth-success.show { display:block; }
/* OTP flow steps */
.auth-step { display:none; }
.auth-step.active { display:block; animation:fadeIn var(--transition); }
.otp-resend { font-size:12.5px; color:var(--muted); margin-top:10px; text-align:center; }
.otp-resend a { color:var(--accent); cursor:pointer; font-weight:600; }
.auth-back-link { display:inline-flex; align-items:center; gap:6px; font-size:13px; color:var(--muted); cursor:pointer; margin-bottom:18px; }
.auth-back-link:hover { color:var(--ink); }

/* ── Form fields ── */
.field { margin-bottom:18px; min-width:0; }
.field label { display:block; font-size:12.5px; font-weight:600; color:var(--ink-soft); margin-bottom:7px; letter-spacing:.01em; }
.field input, .field select, .field textarea { width:100%; padding:11px 13px; border-radius:10px; border:1.5px solid var(--line); background:var(--surface); color:var(--ink); transition:border-color var(--transition), box-shadow var(--transition); box-sizing:border-box; }
/* Checkboxes/radios inside a .field must not inherit the full-width text-input
   styling above — that's what stretched them into a long bar. */
.field input[type="checkbox"], .field input[type="radio"] { width:auto; flex:0 0 auto; padding:0; margin:0; border-radius:4px; box-shadow:none; accent-color:var(--accent); }
.field label.check-row { display:flex; align-items:center; gap:10px; cursor:pointer; margin-bottom:0; }
.field input:focus, .field select:focus, .field textarea:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 4px rgba(46,74,147,.1); }
.field textarea { min-height:80px; resize:vertical; }
.field-row { display:flex; gap:12px; flex-wrap:wrap; }
.field-row .field { flex:1 1 160px; }
/* A full AD+BS date-picker pair (~380px) doesn't fit in a 160px field
   column — cramming three of them across one row (e.g. Reports' From/
   To/Value-as-of) made each pair wrap AD onto one line and BS onto
   another *independently*, and since all three wrapped at the same
   point, the halves lined up into what looked like one merged row with
   overlapping borders. Giving any field-row that contains a date picker
   one field per row instead removes the squeeze entirely — each pair
   gets the full row width, so it lays out AD/BS side by side cleanly
   with no cross-field interference. */
.field-row:has(.bs-date-wrap) .field { flex-basis:100%; }
.field-hint { font-size:11.5px; color:var(--muted); margin-top:5px; }
.select { padding:10px 12px; border-radius:9px; border:1.5px solid var(--line); background:var(--surface); flex-shrink:0; }
.checkbox-list { display:flex; flex-direction:column; gap:2px; max-height:180px; overflow-y:auto; border:1.5px solid var(--line); border-radius:10px; padding:8px 10px; background:var(--surface); }
.checkbox-list label { display:flex; align-items:center; gap:9px; font-size:13.5px; font-weight:500; color:var(--ink); padding:6px 4px; margin:0; cursor:pointer; border-radius:6px; }
.checkbox-list label:hover { background:var(--surface-soft); }
.checkbox-list input[type="checkbox"] { width:auto; flex-shrink:0; accent-color:var(--accent); }
.checkbox-list .empty { font-size:13px; color:var(--muted); padding:6px 4px; }

/* Tags input */
.tags-input-wrap { border:1.5px solid var(--line); border-radius:10px; padding:6px 10px; background:var(--surface); display:flex; flex-wrap:wrap; gap:6px; align-items:center; min-height:44px; cursor:text; transition:border-color var(--transition), box-shadow var(--transition); }
.tags-input-wrap:focus-within { border-color:var(--accent); box-shadow:0 0 0 4px rgba(46,74,147,.1); }
.tag-chip { display:inline-flex; align-items:center; gap:5px; background:var(--info-tint); color:var(--info); border-radius:999px; padding:3px 10px 3px 12px; font-size:12px; font-weight:600; }
.tag-chip .tag-remove { background:none; border:none; padding:0; cursor:pointer; color:inherit; opacity:.7; display:flex; align-items:center; line-height:1; }
.tag-chip .tag-remove:hover { opacity:1; }
.tags-input-wrap input { border:none; outline:none; font-size:13px; padding:3px 4px; min-width:100px; flex:1; background:transparent; }

/* Quantity stepper */
.qty-stepper { display:inline-flex; align-items:center; gap:0; border:1.5px solid var(--line); border-radius:10px; overflow:hidden; }
.qty-stepper button { border:none; background:var(--surface-soft); padding:8px 14px; font-size:16px; font-weight:600; color:var(--ink-soft); cursor:pointer; transition:background var(--transition); }
.qty-stepper button:hover { background:var(--line-soft); }
.qty-stepper input { border:none; border-left:1.5px solid var(--line); border-right:1.5px solid var(--line); width:72px; text-align:center; font-size:14px; font-weight:600; color:var(--ink); padding:8px 6px; }
.qty-stepper input:focus { outline:none; }

/* ── Buttons ── */
.btn { border:none; border-radius:10px; padding:11px 20px; font-size:14px; font-weight:600; transition:transform .1s var(--ease-out), box-shadow var(--transition), background var(--transition), opacity var(--transition); }
.btn:active:not(:disabled) { transform:scale(.97); }
.btn-primary  { background:var(--navy-800); color:#fff; }
.btn-primary:hover:not(:disabled)  { background:var(--navy-700); }
.btn-gold     { background:var(--brass);    color:#fff; }
.btn-gold:hover:not(:disabled)     { background:#54962A; }
.btn-ghost    { background:var(--surface-soft); color:var(--ink-soft); }
.btn-ghost:hover:not(:disabled)    { background:var(--line-soft); }
.btn-danger-ghost { background:var(--danger-tint); color:var(--danger); }
.btn-danger-ghost:hover:not(:disabled) { background:var(--danger-tint-hover); }
.btn-outline   { background:transparent; color:var(--accent); border:1.5px solid var(--accent); }
.btn-outline:hover:not(:disabled)  { background:var(--accent); color:#fff; }
.btn-sm   { padding:7px 14px; font-size:12.5px; border-radius:8px; }
.btn-xs   { padding:4px 10px; font-size:11.5px; border-radius:7px; }
.btn:disabled { opacity:.55; cursor:not-allowed; }
.btn-spinner { display:inline-block; width:12px; height:12px; margin-right:7px; vertical-align:-1.5px; border:2px solid currentColor; border-right-color:transparent; border-radius:50%; animation:btn-spin .6s linear infinite; opacity:.85; }
@keyframes btn-spin { to { transform:rotate(360deg); } }
.btn-block { width:100%; }

/* ── Confirm dialog (themed, replaces browser confirm()) ── */
.confirm-backdrop { position:fixed; inset:0; z-index:500; background:rgba(12,22,51,.56); display:flex; align-items:center; justify-content:center; padding:20px; animation:fadeIn .14s linear; }
.confirm-dialog { background:var(--surface); border-radius:var(--radius-lg); padding:28px 28px 24px; max-width:400px; width:100%; box-shadow:var(--shadow-lg); animation:modalIn .2s var(--ease-out); }
.confirm-dialog .icon { width:44px; height:44px; border-radius:12px; display:flex; align-items:center; justify-content:center; margin-bottom:14px; }
.confirm-dialog.danger .icon  { background:var(--danger-tint); color:var(--danger); }
.confirm-dialog.warning .icon { background:var(--late-tint);   color:var(--late);   }
.confirm-dialog.info .icon    { background:var(--info-tint);   color:var(--info);   }
.confirm-dialog h4 { font-family:var(--display); font-size:17px; margin:0 0 7px; color:var(--ink); }
.confirm-dialog p  { font-size:13.5px; color:var(--muted); margin:0 0 22px; line-height:1.55; }
.confirm-actions { display:flex; gap:10px; }
.confirm-actions .btn { flex:1; }

/* ── App shell ── */
.app-shell { display:flex; min-height:100vh; min-height:100dvh; }
/* Fixed rather than sticky — a sticky sidebar inside a flex layout can
   visually shift/jerk as the page's own content height changes between
   views (a short Overview vs. a long Inventory table), because that
   changes the height of the flex row it's sticking within. Fixed removes
   that dependency entirely: the sidebar's position is computed purely
   from the viewport, never from sibling content, so switching pages can
   never move it. .main's margin-left keeps the layout looking identical
   to the old flex-item approach. */
.sidebar { width:252px; flex-shrink:0; background:linear-gradient(180deg,var(--navy-900),#0F1B3D); color:#fff; display:flex; flex-direction:column; padding:22px 16px; position:fixed; left:0; top:0; height:100vh; height:100dvh; overflow-y:auto; overflow-x:hidden; z-index:40; transition:width .22s cubic-bezier(.4,0,.2,1), left .2s ease; }
.sidebar .brand { display:flex; align-items:center; gap:11px; padding:6px 8px 22px; transition:justify-content var(--transition); }
.sidebar .brand .mark { width:36px; height:36px; border-radius:10px; background:linear-gradient(135deg,var(--navy-800),var(--navy-600)); display:flex; align-items:center; justify-content:center; font-family:var(--display); font-weight:700; font-size:14px; overflow:hidden; flex-shrink:0; }
.sidebar .brand .name { font-family:var(--display); font-weight:700; font-size:15.5px; line-height:1.2; }
.sidebar .brand .sub  { font-size:10.5px; color:#9AA6CC; }
.nav-section-label { font-size:10.5px; letter-spacing:.08em; color:#8B96C2; text-transform:uppercase; padding:18px 12px 6px; margin-top:6px; border-top:1px solid rgba(255,255,255,.08); white-space:nowrap; }
.nav-item { display:flex; align-items:center; gap:11px; padding:10px 12px; border-radius:10px; font-size:13.5px; font-weight:500; color:#C6CEE8; cursor:pointer; margin-bottom:2px; position:relative; transition:background var(--transition), color var(--transition), justify-content var(--transition); }
.nav-item svg { width:17px; height:17px; flex-shrink:0; }
.nav-item:hover  { background:rgba(255,255,255,.06); color:#fff; }
.nav-item.active { background:rgba(95,168,46,.18); color:#fff; }
.nav-item.active svg { color:var(--brass-light); }
.nav-label { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.nav-badge { margin-left:auto; background:var(--danger); color:#fff; font-size:10.5px; font-weight:700; padding:1.5px 7px; border-radius:999px; flex-shrink:0; }
.sidebar .spacer { flex:1; }
.sidebar-foot { border-top:1px solid rgba(255,255,255,.1); padding-top:14px; margin-top:10px; }
.sidebar-user { display:flex; align-items:center; gap:10px; padding:8px; border-radius:10px; cursor:pointer; position:relative; transition:justify-content var(--transition); }
.sidebar-user:hover { background:rgba(255,255,255,.06); }
.sidebar-user-text { min-width:0; overflow:hidden; }
.sidebar-user .nm   { font-size:13px;   font-weight:600; color:#fff; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.sidebar-user .role { font-size:10.5px; color:#9AA6CC; line-height:1.4; }
.logout-link { display:flex; align-items:center; gap:9px; padding:9px 10px; font-size:12.5px; color:#9AA6CC; cursor:pointer; border-radius:8px; position:relative; transition:background var(--transition), color var(--transition), justify-content var(--transition); }
.logout-link:hover { background:rgba(255,255,255,.06); color:#fff; }

/* ── Desktop collapse ── */
.sidebar-topbar { display:flex; justify-content:flex-end; margin-bottom:2px; }
.sidebar-collapse-btn { width:26px; height:26px; border-radius:50%; background:var(--surface); border:1.5px solid var(--line); color:var(--ink-soft); display:flex; align-items:center; justify-content:center; cursor:pointer; flex-shrink:0; box-shadow:var(--shadow-sm); transition:background var(--transition), color var(--transition); }
.sidebar-collapse-btn:hover { background:var(--surface-soft); color:var(--accent); }
.sidebar-collapse-btn svg { transition:transform .22s ease; }
html.sidebar-collapsed .sidebar-collapse-btn svg { transform:rotate(180deg); }
html.sidebar-collapsed .sidebar-topbar { justify-content:center; }
html.sidebar-collapsed .sidebar { width:76px; }
html.sidebar-collapsed .sidebar .brand,
html.sidebar-collapsed .sidebar .nav-item,
html.sidebar-collapsed .sidebar .sidebar-user,
html.sidebar-collapsed .sidebar .logout-link { justify-content:center; }
html.sidebar-collapsed .sidebar .brand-text,
html.sidebar-collapsed .sidebar .nav-label,
html.sidebar-collapsed .sidebar .nav-badge,
html.sidebar-collapsed .sidebar .sidebar-user-text { display:none; }
/* Rather than display:none like the labels above, the Setup divider stays
   in the layout as a thin line (text pushed off-screen, not removed —
   still reachable by screen readers) so there's still a visual grouping
   cue between the day-to-day items and the admin-only ones even with no
   room for the "SETUP" word itself. */
html.sidebar-collapsed .sidebar .nav-section-label { height:0; padding:0; margin:10px 16px; border-top:1px solid rgba(255,255,255,.14); text-indent:-9999px; }
html.sidebar-collapsed .main { margin-left:76px; }

/* Hover tooltips render as a JS-positioned popup appended to <body>
   (initSidebarTooltips() in common.js), not a CSS ::after pseudo-element
   confined inside .sidebar. A pseudo-element positioned to escape the
   sidebar's own box only "works" if the sidebar allows horizontal
   overflow to paint outside it — but overflow-x can't be visible on one
   axis while overflow-y is auto on the other (the spec forces the
   "visible" axis to behave as auto too), so that approach either clipped
   the tooltip or produced a stray horizontal scrollbar on the sidebar
   itself depending on which way it was tuned. A tooltip that lives
   outside the sidebar's DOM subtree entirely sidesteps the problem.
   overflow-x stays hidden below so the sidebar can never scroll
   sideways. */
.sidebar-tooltip { position:fixed; z-index:70; background:var(--navy-900); color:#fff; padding:6px 11px; border-radius:7px; font-size:12px; font-weight:600; white-space:nowrap; box-shadow:var(--shadow-lg); pointer-events:none; opacity:0; transform:translateY(-50%) translateX(-4px); transition:opacity .12s ease, transform .12s ease; }
.sidebar-tooltip.visible { opacity:1; transform:translateY(-50%) translateX(0); }
.sidebar-tooltip::before { content:''; position:absolute; left:-6px; top:50%; transform:translateY(-50%); border:6px solid transparent; border-right-color:var(--navy-900); }

.main { flex:1; min-width:0; display:flex; flex-direction:column; min-height:100vh; min-height:100dvh; margin-left:252px; transition:margin-left .22s cubic-bezier(.4,0,.2,1); }
.topbar { display:flex; align-items:center; justify-content:space-between; padding:20px 32px; background:var(--surface); border-bottom:1px solid var(--line-soft); position:sticky; top:0; z-index:5; gap:16px; }
.topbar-left h1 { font-family:var(--display); font-size:20px; margin:0; color:var(--ink); }
.topbar-left .sub { font-size:12.5px; color:var(--muted); margin-top:2px; }
.topbar h1 { font-family:var(--display); font-size:20px; margin:0; color:var(--ink); }
.topbar .sub { font-size:12.5px; color:var(--muted); margin-top:2px; }
.menu-toggle { display:none; background:none; border:none; padding:6px; flex-shrink:0; }
.theme-toggle-btn { background:var(--surface-soft); border:1px solid var(--line-soft); color:var(--ink-soft); width:38px; height:38px; border-radius:10px; display:flex; align-items:center; justify-content:center; flex-shrink:0; cursor:pointer; transition:background var(--transition), color var(--transition), border-color var(--transition), transform .15s; }
.theme-toggle-btn:hover { background:var(--line-soft); color:var(--ink); }
.theme-toggle-btn:active { transform:scale(.92); }
.theme-toggle-btn .theme-icon-sun  { display:none; }
.theme-toggle-btn .theme-icon-moon { display:block; }
:root[data-theme="dark"] .theme-toggle-btn .theme-icon-sun  { display:block; }
:root[data-theme="dark"] .theme-toggle-btn .theme-icon-moon { display:none; }
.content { padding:28px 32px 60px; max-width:1400px; width:100%; box-sizing:border-box; overflow-x:clip; }
/* On wide monitors the 1400px cap left a large dead gutter on the right,
   especially once the sidebar is collapsed (76px vs 252px reclaims another
   176px that the fixed cap was throwing away). Let content grow with the
   viewport instead of stopping at a fixed number, with a sane upper bound
   so lines of text/cards don't get absurdly wide on ultra-wide displays. */
@media (min-width:1400px) {
  .content { max-width:min(1600px, calc(100vw - 252px - 64px)); }
}
@media (min-width:1700px) {
  .content { max-width:min(1800px, calc(100vw - 252px - 64px)); }
}
html.sidebar-collapsed .content { max-width:min(1760px, calc(100vw - 76px - 64px)); }
@media (min-width:1900px) {
  html.sidebar-collapsed .content { max-width:min(1960px, calc(100vw - 76px - 64px)); }
}

/* ── Sorting / filtering toolbar ── */
.filter-bar { display:flex; align-items:flex-start; gap:10px; flex-wrap:wrap; margin-bottom:18px; padding:12px 16px; background:var(--surface); border-radius:var(--radius); border:1px solid var(--line-soft); box-shadow:var(--shadow-sm); }
.filter-bar .filter-group { display:flex; align-items:center; gap:8px; flex-wrap:wrap; flex:1; min-width:0; }
.filter-bar select, .filter-bar .search-input { font-size:13px; padding:8px 12px; border:1.5px solid var(--line); border-radius:9px; background:var(--surface); color:var(--ink); height:40px; box-sizing:border-box; }
.filter-bar select:focus, .filter-bar .search-input:focus { outline:none; border-color:var(--accent); }
.filter-bar .search-input { min-width:190px; flex:1; }
/* Sits alongside .filter-group as a sibling, not inside it — flex-start
   above keeps it pinned to the top of row 1 instead of centering against
   .filter-group's full height once that group wraps onto a second row on
   narrower screens, which is what made it look vertically misaligned. */
.sort-select-wrap { display:flex; align-items:center; gap:6px; }
.sort-dir-btn { border:1.5px solid var(--line); border-radius:8px; background:var(--surface); color:var(--ink-soft); padding:0 10px; height:40px; box-sizing:border-box; font-size:14px; cursor:pointer; transition:background var(--transition); }
.sort-dir-btn:hover { background:var(--line-soft); }
.filter-tags { display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.filter-tag-chip { display:inline-flex; align-items:center; gap:4px; background:var(--navy-800); color:#fff; padding:3px 10px; border-radius:999px; font-size:11.5px; font-weight:600; }
.filter-tag-chip button { background:none; border:none; color:inherit; opacity:.7; cursor:pointer; padding:0 0 0 2px; line-height:1; }
.filter-tag-chip button:hover { opacity:1; }
.filter-results-count { font-size:12px; color:var(--muted); white-space:nowrap; }

/* ── Avatar ── */
.avatar { width:38px; height:38px; border-radius:50%; display:flex; align-items:center; justify-content:center; color:#fff; font-weight:700; font-size:13.5px; flex-shrink:0; overflow:hidden; }
.avatar img { width:100%; height:100%; object-fit:cover; }
.avatar-lg { width:72px; height:72px; font-size:22px; border-radius:50%; }
.avatar-wrap { position:relative; display:inline-block; }
.avatar-wrap .avatar-remove-btn { position:absolute; bottom:-2px; right:-2px; background:var(--danger); border:none; border-radius:50%; width:20px; height:20px; display:flex; align-items:center; justify-content:center; cursor:pointer; opacity:0; transition:opacity var(--transition); }
.avatar-wrap:hover .avatar-remove-btn { opacity:1; }

/* ── Cards / grids ── */
.card { background:var(--surface); border-radius:var(--radius); box-shadow:var(--shadow-sm); border:1px solid var(--line-soft); }
.card-pad { padding:24px; }
.grid-stats { display:grid; grid-template-columns:repeat(5,1fr); gap:16px; margin-bottom:24px; }
.grid-stats > * { min-width:0; }
/* Stocking Plans' summary row only ever has 4 cards, not 5 — same
   responsive cascade as .grid-stats below (5→3→2→2 as viewport shrinks),
   just starting from 4 columns on desktop instead of 5. Deliberately a
   class, not an inline style: an inline grid-template-columns would beat
   every @media breakpoint below regardless of screen width, which is
   exactly what caused this to overflow on mobile before. */
.stocking-stats-grid { grid-template-columns:repeat(4,1fr); margin-bottom:18px; }
@media (max-width: 900px) { .stocking-stats-grid { grid-template-columns:repeat(2,1fr); } }
@media (max-width: 420px) { .stocking-stats-grid { grid-template-columns:1fr; } }
.stat-card { padding:20px; cursor:pointer; transition:box-shadow var(--transition), transform .12s; }
.stat-card:hover { box-shadow:var(--shadow); transform:translateY(-1px); }
.stat-card .ic { width:34px; height:34px; border-radius:9px; display:flex; align-items:center; justify-content:center; margin-bottom:12px; }
.stat-card .num { font-family:var(--display); font-size:26px; font-weight:700; color:var(--ink); }
.stat-card .lbl { font-size:12px; color:var(--muted); margin-top:2px; }
.grid-2 { display:grid; grid-template-columns:1.4fr 1fr; gap:20px; }
/* Grid tracks default to min-width:auto (the content's intrinsic minimum),
   so a single long unbreakable value anywhere inside either card — a
   vendor name, a purchase-history line, a table row — can silently force
   its whole column, and therefore the page, wider than the viewport. This
   is what actually causes the "have to zoom out" mobile bug, not the grid
   sizing itself. min-width:0 lets each card shrink to its track's real
   width and rely on its own internal wrapping/overflow instead. */
.grid-2 > * { min-width:0; }
.grid-3 { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; }
.grid-3 > * { min-width:0; }

/* Dashboard quick review panel */
.quick-review-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin-bottom:24px; }
.quick-review-grid > * { min-width:0; }
.quick-review-card { background:var(--surface); border-radius:var(--radius); border:1px solid var(--line-soft); box-shadow:var(--shadow-sm); overflow:hidden; }
.quick-review-card .qr-head { display:flex; align-items:center; justify-content:space-between; padding:14px 16px 12px; border-bottom:1px solid var(--line-soft); }
.quick-review-card .qr-title { font-size:13px; font-weight:700; color:var(--ink); }
.quick-review-card .qr-badge { font-size:11px; font-weight:700; background:var(--danger-tint); color:var(--danger); padding:2px 8px; border-radius:999px; }
.qr-item { display:flex; align-items:flex-start; justify-content:space-between; gap:10px; padding:10px 16px; border-bottom:1px solid var(--line-soft); transition:background var(--transition); cursor:pointer; }
.qr-item:last-child { border-bottom:none; }
.qr-item:hover { background:var(--surface-soft); }
.qr-item .qr-name { font-size:13px; font-weight:600; color:var(--ink); }
.qr-item .qr-sub  { font-size:11.5px; color:var(--muted); margin-top:1px; }
.qr-item .qr-actions { display:flex; gap:6px; flex-shrink:0; }
.qr-empty { padding:18px 16px; text-align:center; font-size:13px; color:var(--muted); }
.qr-view-all { display:block; text-align:center; padding:10px; font-size:12.5px; font-weight:600; color:var(--accent); cursor:pointer; border-top:1px solid var(--line-soft); }
.qr-view-all:hover { background:var(--surface-soft); }

/* ── Section headings ── */
.section-head { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; margin-bottom:18px; flex-wrap:wrap; }
.section-head h3 { font-family:var(--display); font-size:16.5px; margin:0 0 3px; color:var(--ink); }
.section-head .sub { font-size:12.5px; color:var(--muted); }

/* ── Tables ── */
.table-wrap { overflow-x:auto; -webkit-overflow-scrolling:touch; }

/* ── Item detail: Quick actions + Activity Log/Purchase History/Stock
   Batches/Consumption tabs ── */
.item-tab-scroll {
  max-height:480px; overflow-y:auto; overflow-x:hidden;
  /* Long unbroken values (a vendor name, a location path) inside the log
     entries wrap instead of forcing this panel — and with it the whole
     page, since it sits in a CSS Grid track (see .grid-2 > *) — wider
     than the viewport. */
  overflow-wrap:anywhere;
}
/* The Stock Batches table sits inside the same narrow panel. Vendor/person
   names used to break mid-letter under `overflow-wrap:anywhere` above
   ("Rajesh Shrestha" → "Ra/je/sh"); cells now stay on one line instead —
   but rather than ellipsis-truncating (which hid the rest of the value
   with no way to read it), the enclosing .table-wrap already scrolls
   horizontally, so the full text stays reachable by scrolling. */
.item-tab-scroll table td, .item-tab-scroll table th { white-space:nowrap; }
@media (max-width:900px) {
  .item-tab-scroll { max-height:360px; }
}
@media (max-width:640px) {
  /* Tighter Quick actions row and card padding so the button set reads
     as 2–3 short rows instead of pushing the card taller/wider than it
     needs to be on a phone. */
  #view-item .card-pad { padding:14px; }
  #view-item .flex.gap-8[style*="flex-wrap"] { gap:6px; margin-bottom:16px !important; }
  #view-item .btn-sm { padding:6px 11px; font-size:12px; }
  .item-tab-scroll { max-height:320px; }
  .section-tabs { margin-bottom:14px; }
}
table { width:100%; border-collapse:collapse; font-size:13px; table-layout:auto; }
thead th { text-align:left; font-size:11px; letter-spacing:.04em; text-transform:uppercase; color:var(--muted); padding:10px 12px; border-bottom:1px solid var(--line); white-space:nowrap; user-select:none; }
thead th[data-sort-key] { cursor:pointer; }
thead th[data-sort-key]:hover { color:var(--ink-soft); }
thead th .sort-icon { margin-left:4px; opacity:.4; font-size:10px; }
thead th.sorted .sort-icon { opacity:1; color:var(--accent); }
tbody td { padding:12px; border-bottom:1px solid var(--line-soft); vertical-align:middle; color:var(--ink-soft); white-space:nowrap; }
tbody tr:last-child td { border-bottom:none; }
tbody tr:hover { background:var(--surface-soft); }

/* Action columns (row buttons — Approve/Decline/Receive/Update/icon-only
   bill toggle) should hug their content instead of stretching edge-to-edge
   on wide monitors, which is what made buttons look oversized/adrift with
   huge gaps around them once the table's other columns ran out of real
   content to fill a 1400–1960px wide row. Shrinking these columns to fit
   pushes the extra width into the text columns instead, where it's
   actually useful. */
thead th:empty,
tbody td:has(> .btn):last-child,
tbody td:has(> .btn-icon):last-child,
tbody td:has(> .flex):last-child,
tbody td:has(> .row-actions):last-child { white-space:nowrap; width:1%; }

/* Long free-text values (issue descriptions, transfer reasons, purposes,
   justifications) truncate to a single line with an ellipsis — a fixed
   pixel width on the inner span makes this reliable inside a table cell,
   since a table in auto-layout mode largely ignores max-width on the <td>
   itself. A small "view" button sits next to it and opens the full text
   in a modal (see #cell-text-modal) rather than trying to cram a
   multi-line clamp into a table row, which doesn't render predictably. */
.cell-truncate-wrap { display:inline-flex; align-items:center; gap:6px; max-width:100%; }
.cell-truncate { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:inline-block; vertical-align:middle; }
.btn-icon.cell-view-btn { width:24px; height:24px; }
.cell-view-btn svg { width:13px; height:13px; }

/* Compact icon-only row action (bill attach/view toggle etc.) — sized and
   colored to match .btn-ghost/.btn-xs so it reads as the same button
   language, just without a text label eating column width. */
.btn-icon {
  display:inline-flex; align-items:center; justify-content:center;
  width:30px; height:30px; border:none; border-radius:8px;
  background:var(--surface-soft); color:var(--ink-soft); cursor:pointer;
  transition:background var(--transition), color var(--transition);
  flex-shrink:0;
}
.btn-icon:hover { background:var(--line-soft); color:var(--accent); }
.btn-icon svg { width:15px; height:15px; }

/* Reserved-height rows so navigating to a shorter last page doesn't
   collapse the table and yank the pager (and everything below it)
   upward — this was the source of the pagination "jerk". */
tr.filler-row td { padding:0; border-bottom:none; height:45px; }
tr.filler-row:hover { background:transparent; }
.mono  { font-family:var(--mono); font-size:12px; }
.muted { color:var(--muted); }
/* Small muted meta text (row dates, secondary labels) — repeated as an
   inline `class="muted" style="font-size:12px;"` combo at 11 call sites;
   promoted to its own class so the same look is defined once. */
.muted-sm { color:var(--muted); font-size:12px; }
.row-person { display:flex; align-items:center; gap:10px; }
.row-person .nm  { font-weight:600; font-size:13px; color:var(--ink); }
.row-person .sub { font-size:11px; color:var(--muted); }
.item-thumb { width:34px; height:34px; border-radius:8px; object-fit:contain; object-position:center; padding:3px; box-sizing:border-box; background:var(--surface-soft); flex-shrink:0; }
.item-thumb-ph { width:34px; height:34px; border-radius:8px; background:var(--surface-soft); display:flex; align-items:center; justify-content:center; color:var(--muted); flex-shrink:0; }

/* ── Badges ── */
.badge { display:inline-block; padding:4px 11px; border-radius:999px; font-size:11.5px; font-weight:700; letter-spacing:.01em; white-space:nowrap; }
.badge-good,.badge-new,.badge-approved,.badge-completed,.badge-repaired,.badge-active { background:var(--success-tint); color:var(--success); }
.badge-fair,.badge-under_repair,.badge-in_repair,.badge-in_review { background:var(--late-tint); color:var(--late); }
.badge-damaged,.badge-rejected,.badge-not_repairable { background:var(--danger-tint); color:var(--danger); }
.badge-pending,.badge-reported { background:var(--info-tint); color:var(--info); }
.badge-disposed,.badge-cancelled,.badge-neutral { background:var(--surface-soft); color:var(--muted); }
.badge-not_required { background:var(--surface-soft); color:var(--muted); }
.badge-asset  { background:var(--violet-tint); color:var(--violet); }
.badge-stock  { background:var(--brass-tint); color:var(--brass-ink); }
.badge-low    { background:var(--late-tint); color:var(--late); }
.badge-urgent,.badge-high { background:var(--danger-tint); color:var(--danger); }
.badge-medium { background:var(--late-tint); color:var(--late); }
.badge-inactive { background:var(--surface-soft); color:var(--muted); }
.badge-tag { background:var(--info-tint); color:var(--info); font-size:11px; padding:2px 8px; }
.badge-code { background:var(--surface-soft); color:var(--accent); font-family:var(--mono); font-size:10.5px; font-weight:700; padding:2px 8px; border:1px solid var(--line-soft); letter-spacing:.02em; }

/* Search summary — grouped totals so items with the same name across
   different locations show as one at-a-glance total (see inv-search-summary). */
.search-summary { background:var(--surface-soft); border:1px solid var(--line-soft); border-radius:var(--radius); padding:12px 14px; margin-bottom:14px; }
.search-summary .ss-totals { font-size:13px; font-weight:600; margin-bottom:6px; }
.search-summary .ss-group { display:flex; justify-content:space-between; gap:10px; font-size:12.5px; padding:4px 0; border-top:1px dashed var(--line-soft); }
.search-summary .ss-group:first-of-type { border-top:none; }
.search-summary .ss-group-name { font-weight:600; }
.search-summary .ss-group-meta { color:var(--muted); }

/* Scraps */
.scrap-value-input { width:110px; }

/* Reports — full-width responsive grid, preview sits below (never beside) */
.reports-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); gap:16px; }
.report-card { cursor:pointer; display:flex; flex-direction:column; transition:border-color .15s, box-shadow .15s; }
.report-card:hover { border-color:var(--accent); box-shadow:0 2px 10px rgba(16,24,56,.08); }
.report-card.active { border-color:var(--accent); box-shadow:0 0 0 1px var(--accent) inset; }
.report-card-title { font-weight:700; margin-bottom:6px; }
.report-card-desc { font-size:12.5px; margin-bottom:14px; flex:1; }

/* ── Tabs ── */
.tab-row { display:flex; gap:4px; background:var(--surface-soft); padding:4px; border-radius:11px; width:fit-content; margin-bottom:22px; flex-wrap:wrap; }
.tab-row .tab { padding:9px 16px; border-radius:8px; font-size:13px; font-weight:600; color:var(--muted); cursor:pointer; transition:background var(--transition), color var(--transition), box-shadow var(--transition); }
.tab-row .tab.active { background:var(--surface); color:var(--ink); box-shadow:var(--shadow-sm); }

/* ── Modals ── */
.modal-backdrop { position:fixed; inset:0; background:rgba(12,22,51,.56); display:flex; align-items:center; justify-content:center; z-index:100; padding:20px; animation:fadeIn .14s linear; }
.modal { background:var(--surface); border-radius:var(--radius-lg); width:100%; max-width:440px; padding:28px; box-shadow:var(--shadow-lg); animation:modalIn .22s var(--ease-out); max-height:calc(100vh - 40px); max-height:calc(100dvh - 40px); overflow-y:auto; }
.modal-wide   { max-width:640px; }
.modal-narrow { max-width:380px; }
.modal h3  { font-size:19px; margin-bottom:6px; font-family:var(--display); color:var(--ink); }
.modal .sub { font-size:13px; color:var(--muted); margin-bottom:20px; }
.modal-close-btn { border:none; background:var(--surface-soft); border-radius:50%; width:30px; height:30px; display:flex; align-items:center; justify-content:center; cursor:pointer; color:var(--muted); transition:background var(--transition), color var(--transition); }
.modal-close-btn:hover { background:var(--line); color:var(--ink); }
@keyframes modalIn { from { opacity:0; transform:translateY(12px) scale(.965); } to { opacity:1; transform:none; } }
@keyframes fadeIn  { from { opacity:0; } to { opacity:1; } }
.modal-actions { display:flex; gap:10px; margin-top:20px; }
.modal-actions .btn { flex:1; }
.modal-section-sep { border:none; border-top:1px solid var(--line-soft); margin:20px 0; }

/* ── Procurement cart ── */
.cart-wrap { border:1.5px solid var(--line); border-radius:var(--radius); overflow:hidden; margin-bottom:18px; }
.cart-head { display:flex; align-items:center; justify-content:space-between; padding:10px 14px; background:var(--surface-soft); border-bottom:1px solid var(--line); }
.cart-head h4 { font-size:13px; font-weight:700; color:var(--ink); margin:0; }
.cart-item-row { display:flex; align-items:center; gap:10px; padding:10px 14px; border-bottom:1px solid var(--line-soft); }
.cart-item-row:last-child { border-bottom:none; }
.cart-item-name { flex:1; font-size:13px; font-weight:600; color:var(--ink); }
.cart-item-meta { font-size:11.5px; color:var(--muted); }
.cart-item-qty  { display:flex; align-items:center; gap:6px; }
.cart-item-qty button { border:1.5px solid var(--line); border-radius:6px; background:var(--surface); color:var(--ink-soft); width:26px; height:26px; display:flex; align-items:center; justify-content:center; cursor:pointer; font-size:15px; transition:background var(--transition); }
.cart-item-qty button:hover { background:var(--line-soft); }
.cart-item-qty .qty-val { font-size:13.5px; font-weight:700; min-width:28px; text-align:center; }
.cart-empty { padding:18px; text-align:center; color:var(--muted); font-size:13px; }

/* ── Bill/receipt upload ── */
.bill-upload-area { border:2px dashed var(--line); border-radius:var(--radius); padding:20px; text-align:center; cursor:pointer; transition:border-color var(--transition), background var(--transition); }
.bill-upload-area:hover { border-color:var(--accent); background:var(--surface-soft); }
.bill-upload-area.has-file { border-color:var(--success); background:var(--success-tint); border-style:solid; }
.bill-upload-area .upload-icon { color:var(--muted); margin-bottom:8px; }
.bill-upload-area p { font-size:13px; color:var(--muted); margin:0 0 6px; }
.bill-upload-area small { font-size:11.5px; color:var(--muted); }
.bill-preview-row { display:flex; align-items:center; gap:12px; margin-top:12px; padding:10px 14px; background:var(--surface); border:1.5px solid var(--line); border-radius:10px; }

/* ── Info list ── */
.info-list { display:flex; flex-direction:column; }
.info-row { display:flex; justify-content:space-between; padding:11px 0; border-bottom:1px solid var(--line-soft); font-size:13.5px; }
.info-row:last-child { border-bottom:none; }
.info-row .k { color:var(--muted); flex-shrink:0; }
.info-row .v { font-weight:600; color:var(--ink); text-align:right; min-width:0; word-break:break-word; }

/* Profile page */
/* ── Signed-in devices (profile page + admin "manage sessions" modal) ── */
.device-row { display:flex; align-items:center; gap:14px; padding:14px 2px; border-bottom:1px solid var(--line-soft); }
.device-row:last-child { border-bottom:none; }
.device-icon { width:42px; height:42px; border-radius:11px; background:var(--surface-soft); color:var(--ink-soft); display:flex; align-items:center; justify-content:center; flex-shrink:0; }
.device-icon svg { width:20px; height:20px; }
.device-info { min-width:0; flex:1; }
.device-info .device-name { display:flex; align-items:center; gap:9px; flex-wrap:wrap; font-weight:700; font-size:13.5px; color:var(--ink); }
.device-info .device-sub  { font-size:12px; color:var(--muted); margin-top:2px; }
.device-current-badge { display:inline-flex; align-items:center; gap:5px; }
.device-current-badge::before { content:''; width:6px; height:6px; border-radius:50%; background:var(--success); }
.device-row .btn { flex-shrink:0; }
.device-list-empty { padding:18px 2px; color:var(--muted); font-size:13px; }
.device-list-loading { padding:18px 2px; color:var(--muted); font-size:13px; }
@media (max-width:520px) {
  .device-row { flex-wrap:wrap; }
  .device-row .btn { margin-left:56px; }
}

.profile-name { font-family:var(--display); font-size:18px; font-weight:700; color:var(--ink); }
.profile-header-row { flex-wrap:wrap; }
.card-section-title { font-family:var(--display); font-size:16px; margin-bottom:18px; }
@media (max-width: 640px) {
  .avatar-lg { width:56px; height:56px; font-size:17px; }
  .profile-name { font-size:15.5px; }
  .info-row { font-size:12.5px; padding:9px 0; }
  .card-section-title { font-size:14.5px; margin-bottom:14px; }
}

/* ── Misc ── */
.flex { display:flex; } .center { align-items:center; } .between { justify-content:space-between; }
.gap-8 { gap:8px; } .gap-12 { gap:12px; } .gap-16 { gap:16px; }
.empty-state { text-align:center; color:var(--muted); font-size:13.5px; padding:30px; }
.empty-state svg { opacity:.3; margin-bottom:10px; }
.search-input { padding:9px 13px; border-radius:9px; border:1.5px solid var(--line); background:var(--surface); font-size:13px; min-width:220px; }
.progress-bar { height:8px; border-radius:999px; background:var(--line-soft); overflow:hidden; }
.progress-bar .fill { height:100%; background:var(--brass); border-radius:999px; transition:width .4s ease; }
.chip { display:inline-flex; align-items:center; gap:4px; padding:4px 10px; border-radius:8px; font-size:12px; font-weight:600; background:var(--surface-soft); color:var(--ink-soft); }

/* Activity feed */
.activity-feed { display:flex; flex-direction:column; gap:0; }
.activity-item { display:flex; align-items:flex-start; gap:12px; padding:12px 0; border-bottom:1px solid var(--line-soft); cursor:pointer; transition:background var(--transition); border-radius:8px; padding:10px 8px; }
.activity-item:hover { background:var(--surface-soft); }
.activity-item:last-child { border-bottom:none; }
.activity-dot { width:8px; height:8px; border-radius:50%; flex-shrink:0; margin-top:5px; }
.activity-dot.transfer   { background:var(--info); }
.activity-dot.procurement { background:var(--brass); }
.activity-dot.repair     { background:var(--late); }
.activity-text { flex:1; font-size:13px; color:var(--ink-soft); line-height:1.45; }
.activity-date { font-size:11.5px; color:var(--muted); white-space:nowrap; }

/* ── Toast ── */
.toast { position:fixed; bottom:24px; right:24px; background:var(--navy-900); color:#fff; padding:13px 20px; border-radius:11px; font-size:13.5px; box-shadow:var(--shadow-lg); z-index:200; animation:toastIn .22s var(--ease-out); max-width:360px; }
.toast.error   { background:var(--danger); }
.toast.success { background:var(--success); }
@keyframes toastIn { from { opacity:0; transform:translateY(14px) scale(.98); } to { opacity:1; transform:none; } }

/* Procurement source toggle */
.source-toggle { display:flex; gap:0; background:var(--surface-soft); border-radius:9px; overflow:hidden; border:1.5px solid var(--line); margin-bottom:18px; }
.source-toggle button { flex:1; border:none; background:none; padding:9px 14px; font-size:13px; font-weight:600; color:var(--muted); cursor:pointer; transition:background var(--transition), color var(--transition); }
.source-toggle button.active { background:var(--navy-800); color:#fff; }

/* Low stock & warranty alert cards */
.alert-card { display:flex; align-items:center; gap:12px; padding:14px 16px; border-radius:10px; background:var(--late-tint); border:1px solid rgba(194,132,31,.2); cursor:pointer; transition:background var(--transition), transform .12s; }
.alert-card + .alert-card { margin-top:10px; }
.alert-card:hover { background:var(--late-tint-hover); transform:translateX(2px); }
.alert-card.danger { background:var(--danger-tint); border-color:rgba(192,70,58,.2); }
.alert-card.danger:hover { background:var(--danger-tint-hover); }
.alert-card .alert-name { font-size:13px; font-weight:600; color:var(--ink); line-height:1.4; }
.alert-card .alert-meta { font-size:11.5px; color:var(--muted); margin-top:3px; line-height:1.4; }

/* ── Responsive ── */
@media (max-width:1180px) {
  .grid-stats { grid-template-columns:repeat(3,1fr); }
  .grid-2     { grid-template-columns:1fr; }
  .grid-3     { grid-template-columns:repeat(2,1fr); }
  .quick-review-grid { grid-template-columns:repeat(2,1fr); }
}
@media (max-width:820px) {
  .auth-left { display:none; }
  .auth-split { box-shadow:none; background:transparent; }
  .auth-right { background:var(--surface); border-radius:20px; box-shadow:0 20px 60px rgba(4,8,24,.4); }
}
@media (max-width:900px) {
  /* Drawer slides with transform (GPU) instead of animating `left` (layout every frame). While closed it is also
     visibility:hidden, so its links can't be tabbed to off-screen and its shadow can't peek in at the edge. */
  .sidebar { left:0; transform:translateX(-100%); visibility:hidden; z-index:50; box-shadow:none; width:252px !important;
             transition:transform .26s var(--ease-out), visibility 0s linear .26s; }
  .sidebar.open { transform:none; visibility:visible; box-shadow:var(--shadow-lg); transition:transform .26s var(--ease-out), visibility 0s; }
  /* The desktop icon-only collapse is a desktop-only feature — mobile
     already has its own show/hide via the hamburger menu, so a stored
     "collapsed" preference from a desktop session should never affect
     the mobile menu. Width alone isn't enough to undo the collapse
     though: it also hides every label and centers every icon, and those
     rules need their own explicit override here too, or the mobile menu
     ends up full-width but still rendering as an unreadable icon-only
     strip with all its text missing. */
  html.sidebar-collapsed .sidebar { width:252px !important; }
  html.sidebar-collapsed .sidebar .brand,
  html.sidebar-collapsed .sidebar .nav-item,
  html.sidebar-collapsed .sidebar .sidebar-user,
  html.sidebar-collapsed .sidebar .logout-link { justify-content:flex-start !important; }
  html.sidebar-collapsed .sidebar .brand-text,
  html.sidebar-collapsed .sidebar .nav-label,
  html.sidebar-collapsed .sidebar .nav-badge,
  html.sidebar-collapsed .sidebar .sidebar-user-text { display:block !important; }
  html.sidebar-collapsed .sidebar .nav-section-label { height:auto !important; padding:18px 12px 6px !important; text-indent:0 !important; }
  html.sidebar-collapsed .sidebar-topbar { justify-content:flex-end !important; }
  .sidebar-collapse-btn { display:none; } /* mobile uses the hamburger menu-toggle instead */
  html.sidebar-collapsed .main { margin-left:0; }
  .main { margin-left:0; }
  .menu-toggle { display:block; }
  .content  { padding:20px 16px 60px; }
  .topbar   { padding:16px; }
  .search-input { min-width:0; width:100%; }
  .quick-review-grid { grid-template-columns:1fr; }
}
@media (max-width:560px) {
  .grid-stats { grid-template-columns:repeat(2,1fr); }
  .grid-3     { grid-template-columns:1fr; }
  /* The old approach here was letting the search box and four selects
     wrap organically inside a flex row, which under real-world content
     widths (long location/category names, the BS date picker's own
     buttons elsewhere on the page competing for the same breakpoint)
     could leave the search box squeezed down to almost nothing with its
     placeholder clipped invisible, and selects overlapping unpredictably.
     A fixed grid removes that ambiguity: search always gets its own full
     row, the four selects always sit in a tidy, predictable 2-column
     grid, and the sort row always spans full width with the direction
     button pinned to a fixed size next to it. */
  .filter-bar { flex-direction:column; align-items:stretch; gap:10px; }
  .filter-bar .filter-group { display:grid; grid-template-columns:1fr 1fr; gap:8px; width:100%; }
  .filter-bar .filter-group .search-input { grid-column:1 / -1; width:100%; min-width:0; }
  .filter-bar .filter-group select.select { width:100%; min-width:0; }
  .filter-bar .sort-select-wrap { width:100%; gap:8px; }
  .filter-bar .sort-select-wrap select { flex:1; min-width:0; }
}
@media (max-width:480px) {
  .field-row .field { flex-basis:100%; }
}
@media (max-height:820px) {
  .content  { padding-top:18px; padding-bottom:24px; }
  .grid-stats { gap:12px; margin-bottom:16px; }
  .stat-card  { padding:14px; }
  .card-pad   { padding:18px; }
}

/* ============================================================
   AssetTrack v3 — UI Fixes & New Components
   Logo, spacing, grid/list views, stocking plans, petty expenses,
   purchase history, FIFO/LIFO display, error/warning messages
   ============================================================ */

/* ── Logo — bigger, clearer in sidebar ── */
.sidebar .brand { padding: 8px 8px 26px; gap: 14px; align-items: center; }
.sidebar .brand .mark {
  width: 52px; height: 52px; border-radius: 14px; font-size: 19px;
  font-weight: 800; letter-spacing: -.5px; flex-shrink: 0;
  box-shadow: 0 4px 14px rgba(0,0,0,.3);
}
.sidebar .brand .name { font-size: 16px; font-weight: 800; letter-spacing: -.2px; }
.sidebar .brand .sub  { font-size: 10px; color: #8B96C2; margin-top: 2px; }
.auth-brand .mark { width: 52px; height: 52px; border-radius: 15px; font-size: 19px; }

/* ── Dashboard stat cards — better gaps & sizing ── */
.grid-stats { gap: 18px; margin-bottom: 22px; }
.stat-card { padding: 22px 20px; }
.stat-card .ic { width: 38px; height: 38px; border-radius: 10px; margin-bottom: 14px; }
.stat-card .num { font-size: 28px; line-height: 1; margin-bottom: 4px; }
.stat-card .lbl { font-size: 12.5px; color: var(--muted); }

/* ── Quick review cards — internal spacing ── */
.quick-review-card .qr-head { padding: 14px 18px 12px; gap: 12px; }
.qr-item { padding: 11px 18px; gap: 14px; }
.qr-item .qr-name { font-size: 13.5px; font-weight: 600; }
.qr-item .qr-sub  { font-size: 12px; color: var(--muted); margin-top: 3px; }

/* ── Inventory view toggle ── */
.view-toggle { display: flex; gap: 4px; background: var(--surface-soft); border-radius: 10px; padding: 4px; border: 1.5px solid var(--line); }
.view-toggle-btn { border: none; background: none; border-radius: 7px; padding: 7px 11px; cursor: pointer; color: var(--muted); transition: background var(--transition), color var(--transition); display: flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; }
.view-toggle-btn:hover { background: var(--line-soft); color: var(--ink); }
.view-toggle-btn.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm); }
.view-toggle-btn svg { width: 15px; height: 15px; }

/* ── Grid view cards ── */
.inv-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 16px; }
.inv-grid-card { background: var(--surface); border-radius: var(--radius); border: 1px solid var(--line-soft); box-shadow: var(--shadow-sm); overflow: hidden; cursor: pointer; transition: box-shadow var(--transition), transform .12s; }
.inv-grid-card:hover { box-shadow: var(--shadow); transform: translateY(-2px); }
.inv-grid-card .card-img { width: 100%; height: 148px; object-fit: contain; object-position: center; padding: 16px; box-sizing: border-box; display: block; background: var(--surface-soft); }
.inv-grid-card .card-img-ph { width: 100%; height: 148px; background: var(--surface-soft); display: flex; align-items: center; justify-content: center; color: var(--line); }
.inv-grid-card .card-body { padding: 13px 14px 14px; }
.inv-grid-card .card-name { font-size: 13.5px; font-weight: 700; color: var(--ink); margin-bottom: 4px; line-height: 1.3; }
.inv-grid-card .card-sub  { font-size: 11.5px; color: var(--muted); margin-bottom: 8px; }
.inv-grid-card .card-foot { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; }
.inv-grid-card .card-qty  { font-size: 12px; font-weight: 600; color: var(--ink-soft); background: var(--surface-soft); padding: 3px 9px; border-radius: 7px; }

/* ── Error & warning message styles ── */

.alert-banner { display: flex; align-items: flex-start; gap: 12px; padding: 13px 16px; border-radius: 10px; margin-bottom: 16px; font-size: 13px; line-height: 1.5; }
.alert-banner.danger  { background: var(--danger-tint); border: 1px solid rgba(192,70,58,.2); color: var(--danger); }
.alert-banner.warning { background: var(--late-tint);   border: 1px solid rgba(194,132,31,.2); color: var(--late); }
.alert-banner.success { background: var(--success-tint);border: 1px solid rgba(47,143,91,.2);  color: var(--success); }
.alert-banner.info    { background: var(--info-tint);   border: 1px solid rgba(44,111,168,.2); color: var(--info); }
.alert-banner .ab-icon { flex-shrink: 0; font-size: 16px; }
.alert-banner strong  { font-weight: 700; }

/* ── Stocking plans ── */
.plan-card { background: var(--surface); border-radius: var(--radius); border: 1px solid var(--line-soft); box-shadow: var(--shadow-sm); padding: 18px 20px; transition: box-shadow var(--transition); }
.plan-card:hover { box-shadow: var(--shadow); }
.plan-card .plan-type-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 700; letter-spacing: .04em; padding: 3px 10px; border-radius: 999px; margin-bottom: 10px; }
.plan-card .plan-title { font-size: 15px; font-weight: 700; color: var(--ink); margin-bottom: 5px; }
.plan-card .plan-sub   { font-size: 12px; color: var(--muted); margin-bottom: 12px; }
.budget-labels { display: flex; justify-content: space-between; font-size: 11.5px; color: var(--muted); margin-top: 5px; }
.budget-labels .spent { font-weight: 600; color: var(--ink-soft); }
.plan-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }

/* ── Petty expenses table ── */
/* Previously: bold 15px accent-colored amount + a bespoke grey category
   pill — the only table in the app styling its money and category cells
   differently from plain text / .badge-tag, which made this section look
   visually disconnected from Transfers/Procurement/Repairs/Consumption
   right next to it. Kept the same font, weight and size as every other
   data cell (see `tbody td`) for a consistent look across the app. */
.expense-category { background:var(--info-tint); color:var(--info); padding:2px 8px; border-radius:6px; font-size:11px; font-weight:600; }

/* ── Section tabs (full-width style) ── */
.section-tabs { display: flex; border-bottom: 2px solid var(--line-soft); margin-bottom: 20px; gap: 0; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.section-tabs::-webkit-scrollbar { display: none; }
.section-tabs .stab { padding: 10px 18px; font-size: 13px; font-weight: 600; color: var(--muted); cursor: pointer; border-bottom: 2.5px solid transparent; margin-bottom: -2px; transition: color var(--transition), border-color var(--transition); white-space: nowrap; flex-shrink: 0; }
.section-tabs .stab:hover { color: var(--ink); }
.section-tabs .stab.active { color: var(--accent); border-bottom-color: var(--accent); }

/* ── Pagination ── */
.pager { display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap; padding:16px 2px 4px; }
.pager-info { font-size:12.5px; color:var(--muted); }
.pager-controls { display:flex; align-items:center; gap:4px; flex-wrap:wrap; }
.pager-btn { min-width:32px; height:32px; padding:0 8px; border:none; border-radius:8px; background:var(--surface-soft); color:var(--ink-soft); font-size:13px; font-weight:600; cursor:pointer; transition:background var(--transition), color var(--transition); }
.pager-btn:hover:not(:disabled):not(.active) { background:var(--line-soft); }
.pager-btn.active { background:var(--navy-800); color:#fff; }
.pager-btn:disabled { opacity:.4; cursor:not-allowed; }
.pager-ellipsis { padding:0 4px; color:var(--muted); font-size:13px; }
@media (max-width: 640px) {
  .pager { padding-top:12px; }
  .pager-btn { min-width:28px; height:28px; font-size:12px; }
}
@media (max-width: 640px) {
  .section-tabs .stab { padding: 9px 13px; font-size: 12px; }
}

/* ── Spacing fixes across views ── */
.content { padding: 26px 28px 80px; }
.card-pad { padding: 22px 24px; }
.topbar { padding: 16px 28px; }
.filter-bar { gap: 10px; padding: 12px 14px; flex-wrap: wrap; }
.filter-bar select, .filter-bar .search-input { font-size: 13px; padding: 8px 11px; }
.section-head { margin-bottom: 16px; }
.section-head h3 { font-size: 16px; margin: 0 0 3px; }

/* ── Table spacing ── */
thead th { padding: 10px 14px; }
tbody td  { padding: 11px 14px; }

/* ── Modal improvements ── */
.modal { padding: 26px 28px; }
.modal h3 { font-size: 18px; }
.modal .sub { font-size: 13px; margin-bottom: 18px; }
.field { margin-bottom: 16px; }
.field label { font-size: 12.5px; margin-bottom: 6px; }
.field-row { gap: 14px; }

/* ── Nav item spacing ── */
.nav-item { padding: 10px 13px; margin-bottom: 1px; font-size: 13px; }
.nav-section-label { padding: 18px 13px 5px; font-size: 10px; }

/* ── Responsive tweaks ── */
@media (max-width: 1280px) { .grid-stats { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 900px)  { .content { padding: 16px 14px 60px; } .topbar { padding: 14px 14px; } .card-pad { padding: 16px; } }
@media (max-width: 640px)  { .grid-stats { grid-template-columns: repeat(2, 1fr); } .inv-grid { grid-template-columns: repeat(2, 1fr); } .plan-grid { grid-template-columns: 1fr; } }
@media (max-width: 420px)  { .grid-stats { grid-template-columns: 1fr 1fr; } .stat-card .num { font-size: 22px; } }

/* ── Nepali (BS) date picker — public/js/nepaliDatePicker.js ── */
/* Both the AD and BS fields share the exact same .bs-input-group shell
   (height, border, border-radius, background) — the AD input is wrapped
   in it too now — so their sizes can't drift apart the way they would if
   each were sized independently by browser-default vs custom CSS. Fixed
   widths throughout are deliberate: neither field's size changes between
   empty/placeholder, mid-typing, or holding a full date, so picking or
   typing a date never shifts the +Request/+Add button sitting next to it.
   Widths are generous on purpose — a native date input needs real room
   for "mm/dd/yyyy" plus its own built-in icon before mobile browsers
   start clipping their own UI inside it, which is what caused the
   cut-off "08/17/2(" rendering this is fixing. */
.bs-date-wrap { display:inline-flex; align-items:center; gap:12px; row-gap:10px; max-width:100%; flex-wrap:wrap; margin:2px 0; }
/* From/To captions for filter bars that don't otherwise have a <label>
   above their date fields (Transfers, Procurement, Repairs, Consumption)
   — see data-bs-label on those inputs. Keeps label+boxes together as one
   flex item so the row-level flex-wrap can't separate a caption from its
   own date pair. */
.bs-field-block { display:inline-flex; flex-direction:column; gap:6px; align-items:flex-start; }
.bs-field-label { font-size:11px; font-weight:700; letter-spacing:.03em; text-transform:uppercase; color:var(--muted); padding-left:2px; }
/* Rows that mix date-picker pairs with other controls (the +Request/
   +Add button, in particular) need more breathing room than the generic
   8px .gap-8 utility gives — each pair is now a wider AD+BS group, not a
   single narrow native input, so the old tight gap read as cramped and
   made things look like they were overlapping once the row wrapped. */
/* Without this, `.flex`'s default align-items:stretch forces the
   "+ Request Transfer" / "+ New ..." button sitting next to the AD+BS
   date-filter pair to stretch to match the pair's height (label row +
   40px input), so the button visibly grows or shrinks depending on
   whether the filters wrap onto their own line at a given viewport
   width. Bottom-align everything to the inputs' baseline instead, so
   the button stays a fixed, predictable size regardless of layout. */
.flex.gap-8:has(.bs-date-wrap) { gap:14px; row-gap:14px; align-items:flex-end; }
.bs-input-group { display:inline-flex; align-items:stretch; flex-shrink:0; height:40px; border:1.5px solid var(--line); border-radius:9px; background:var(--surface-soft); overflow:hidden; transition:border-color var(--transition); }
.bs-input-group:focus-within { border-color:var(--accent); }
.bs-input-group:has(.bs-text-input.invalid) { border-color:var(--danger); }
.bs-input-tag { display:flex; align-items:center; padding:0 8px; font-size:10.5px; font-weight:800; letter-spacing:.03em; color:var(--muted); background:var(--surface); border-right:1px solid var(--line-soft); flex-shrink:0; }
/* The native AD input keeps its own border/background/focus-outline
   everywhere else in the app (.field, .select, etc.) — but inside this
   shared shell that would double up into a border-within-a-border (and,
   on focus, the browser's own default outline drawing a second visible
   rectangle on top of it — the "unwanted border" this removes). The
   group's single outer border stands in for both, including the focus
   state via :focus-within above. */
.ad-input-group input[type="date"] {
  border:none !important; outline:none !important; background:transparent !important; box-shadow:none !important;
  -webkit-appearance:none; appearance:none;
  padding:0 10px; width:148px; min-width:0; height:100%; color:var(--ink); font-size:13px;
}
.ad-input-group input[type="date"]:focus { border:none !important; outline:none !important; box-shadow:none !important; }
.bs-text-input { width:140px !important; min-width:0; border:none !important; outline:none !important; background:transparent !important; box-shadow:none !important; color:var(--ink); font-size:13px; padding:0 10px !important; font-family:inherit; }
.bs-text-input::placeholder { color:var(--muted); }
.bs-text-input:focus { border:none !important; outline:none !important; box-shadow:none !important; }
.bs-text-input.has-value { color:var(--accent); font-weight:600; }
.bs-text-input.invalid { color:var(--danger); }
.bs-text-input.loading { opacity:.6; }
.bs-date-btn { display:flex; align-items:center; justify-content:center; flex-shrink:0; width:36px; border:none; border-left:1px solid var(--line-soft); background:transparent; color:var(--muted); cursor:pointer; transition:background var(--transition), color var(--transition); }
.bs-date-btn:hover { background:var(--line-soft); color:var(--accent); }
@media (max-width:480px) {
  /* Still comfortably wide enough for "mm/dd/yyyy" / "DD Mon YYYY" to
     render in full on a phone — narrower than desktop, but not so narrow
     the native control has to start clipping its own text/icon. */
  .ad-input-group input[type="date"] { width:126px !important; }
  .bs-text-input { width:118px !important; }
  .bs-date-wrap { gap:10px; row-gap:12px; }
}

.bs-datepicker-popup { position:absolute; z-index:300; width:272px; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow-lg); padding:14px; font-size:13px; }
.bs-dp-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:10px; }
.bs-dp-title { font-weight:700; color:var(--ink); font-size:14px; }
.bs-dp-nav { width:28px; height:28px; border-radius:8px; border:none; background:var(--surface-soft); color:var(--ink-soft); font-size:16px; line-height:1; cursor:pointer; transition:background var(--transition); }
.bs-dp-nav:hover { background:var(--line-soft); }
.bs-dp-weekdays { display:grid; grid-template-columns:repeat(7,1fr); text-align:center; font-size:10.5px; font-weight:700; color:var(--muted); margin-bottom:4px; }
.bs-dp-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }
.bs-dp-grid .bs-dp-pad { height:30px; }
.bs-dp-day { height:30px; border:none; border-radius:8px; background:transparent; color:var(--ink); font-size:12.5px; cursor:pointer; transition:background var(--transition), color var(--transition); }
.bs-dp-day:hover { background:var(--surface-soft); }
.bs-dp-day.today { font-weight:700; color:var(--accent); }
.bs-dp-day.selected { background:var(--navy-800); color:#fff; }
.bs-dp-day.loading { opacity:.5; pointer-events:none; }
.bs-dp-error { grid-column:1/-1; text-align:center; color:var(--muted); font-size:12px; padding:16px 4px; }
.bs-dp-foot { display:flex; justify-content:space-between; margin-top:10px; padding-top:10px; border-top:1px solid var(--line-soft); }
.bs-dp-foot button { background:none; border:none; color:var(--accent); font-size:12.5px; font-weight:600; cursor:pointer; padding:4px 6px; }
.bs-dp-foot button:hover { text-decoration:underline; }
@media (max-width:480px) {
  .bs-date-wrap { flex-wrap:wrap; }
  .bs-datepicker-popup { width:calc(100vw - 32px); max-width:272px; }
}

/* ── Native scrollbars, themed to match light/dark mode ──
   Firefox uses scrollbar-color/-width; Chrome/Safari/Edge use the
   ::-webkit-scrollbar family. Applied globally via `*` so every
   scrollable area (the sidebar, modals, the item detail tab panel,
   tables) gets a consistent, theme-aware scrollbar rather than each
   browser's stark default — light grey-on-white in light mode, a muted
   version of the same tokens in dark mode, instead of an OS-default
   white scrollbar glaring against a dark page. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
*::-webkit-scrollbar { width:10px; height:10px; }
*::-webkit-scrollbar-track { background:transparent; }
*::-webkit-scrollbar-thumb { background-color:var(--line); border-radius:8px; border:2px solid transparent; background-clip:padding-box; }
*::-webkit-scrollbar-thumb:hover { background-color:var(--muted); }
*::-webkit-scrollbar-corner { background:transparent; }
/* The sidebar sits on its own permanent dark navy background in both
   themes (see .sidebar's comment above) — a scrollbar using the page's
   --line token would be near-invisible against it in light mode, so it
   gets its own always-dark-appropriate color instead of following theme. */
.sidebar { scrollbar-color: rgba(255,255,255,.25) transparent; }
.sidebar::-webkit-scrollbar-thumb { background-color:rgba(255,255,255,.25); }
.sidebar::-webkit-scrollbar-thumb:hover { background-color:rgba(255,255,255,.4); }

/* ── Desktop density fix ──
   The button/pill sizes here were tuned for smaller viewports and read as
   oversized on a real monitor at 100% OS scaling (e.g. "+ Request Transfer",
   topbar icon buttons). Trim them slightly once there's real desktop width
   to work with, without touching the mobile/tablet sizes above. */
@media (min-width:1024px) {
  .btn          { padding:9px 16px; font-size:13.5px; }
  .btn-sm       { padding:6px 12px; font-size:12px; }
  .btn-xs       { padding:4px 10px; font-size:11.5px; }   /* must follow .btn above, or it is overridden and looks full-size */
  .topbar       { padding:16px 28px; }
  .theme-toggle-btn, .sidebar-collapse-btn { width:34px; height:34px; }
}

/* Depreciation fields locked to an automatically-applied policy */
input.dep-auto, input.dep-auto:disabled { background:var(--surface-soft); color:var(--muted, #6b7280); cursor:not-allowed; -webkit-text-fill-color:currentColor; opacity:1; }

/* ── Permissions (user dialog + user-group editor) ────────────────────────
   Scoped under .perm-list so the generic ".field input / .field label" form
   styles (full-width boxed inputs, block labels) can't leak into the switches. */
.perm-list { max-height:360px; overflow:auto; border:1px solid var(--line); border-radius:12px; background:var(--surface); }
.perm-list .perm-group-title { position:sticky; top:0; z-index:2; padding:8px 14px; font-size:11px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); background:var(--surface-soft); border-bottom:1px solid var(--line-soft); }
.perm-list .perm-row { display:flex; align-items:center; justify-content:space-between; gap:16px; padding:11px 14px 11px 11px; border-bottom:1px solid var(--line-soft); border-left:4px solid transparent; cursor:pointer; user-select:none; }
.perm-list .perm-row:last-child { border-bottom:0; }
.perm-list .perm-row:hover { background:var(--surface-soft); }
.perm-list .perm-row.state-on  { border-left-color:var(--success); }
.perm-list .perm-row.state-off { border-left-color:var(--danger); background:var(--danger-tint); }
.perm-list .perm-row.state-off:hover { background:var(--danger-tint-hover); }
.perm-list .perm-row.state-inherit { border-left-color:var(--line); cursor:default; }
.perm-list .perm-row.locked { cursor:not-allowed; }
.perm-list .perm-text { display:block; min-width:0; flex:1 1 auto; }
.perm-list .perm-label { display:block; font-size:13.5px; font-weight:700; color:var(--ink); line-height:1.35; margin:0; letter-spacing:0; }
.perm-list .perm-desc { display:block; margin-top:2px; font-size:12px; font-weight:400; color:var(--muted); line-height:1.4; }
.perm-list .perm-defaults { display:block; margin-top:3px; font-size:11px; color:var(--muted); }
.perm-tag { display:inline-block; margin-left:6px; padding:1px 8px; border-radius:999px; font-size:10px; font-weight:800; letter-spacing:.02em; vertical-align:middle; }
.perm-tag.tag-custom { background:var(--info); color:#fff; }
.perm-tag.tag-group  { background:#7A5AC8; color:#fff; }
.perm-tag.tag-locked { background:var(--line); color:var(--ink-soft); }
.perm-list .perm-control { display:flex; align-items:center; gap:10px; flex:0 0 auto; }
.perm-state { display:inline-block; min-width:34px; text-align:center; padding:2px 8px; border-radius:999px; font-size:11px; font-weight:800; letter-spacing:.03em; }
.perm-state.on  { background:var(--success-tint); color:var(--success); }
.perm-state.off { background:var(--danger-tint);  color:var(--danger); border:1px solid var(--danger); }
.perm-legend { display:flex; align-items:center; flex-wrap:wrap; gap:6px 10px; margin:2px 0 8px; font-size:12px; color:var(--muted); }
.perm-legend .perm-tag { margin-left:0; }

/* on/off switch — drawn from a hidden checkbox */
.perm-list .perm-switch { position:relative; display:inline-block; flex:0 0 auto; width:44px; height:24px; }
.perm-list .perm-switch input[type="checkbox"] { position:absolute; inset:0; width:100%; height:100%; margin:0; padding:0; opacity:0; border:0; pointer-events:none; }
.perm-list .perm-track { position:absolute; inset:0; border-radius:999px; background:var(--danger-tint); border:1.5px solid var(--danger); transition:background .15s, border-color .15s; }
.perm-list .perm-track::after { content:''; position:absolute; top:2px; left:2px; width:17px; height:17px; border-radius:50%; background:var(--danger); transition:transform .15s, background .15s; }
.perm-list .perm-switch input:checked + .perm-track { background:var(--success); border-color:var(--success); }
.perm-list .perm-switch input:checked + .perm-track::after { transform:translateX(20px); background:#fff; }
.perm-list .perm-row.locked .perm-switch { opacity:.55; }

/* three-way choice used by the group editor: Role default / On / Off */
.perm-list .perm-seg { display:inline-flex; border:1px solid var(--line); border-radius:9px; overflow:hidden; flex:0 0 auto; }
.perm-list .perm-seg button { appearance:none; border:0; background:var(--surface); color:var(--muted); font:inherit; font-size:11.5px; font-weight:700; padding:6px 10px; cursor:pointer; border-right:1px solid var(--line); white-space:nowrap; }
.perm-list .perm-seg button:last-child { border-right:0; }
.perm-list .perm-seg button:hover { background:var(--surface-soft); }
.perm-list .perm-seg button.sel-inherit { background:var(--surface-soft); color:var(--ink); }
.perm-list .perm-seg button.sel-on  { background:var(--success); color:#fff; }
.perm-list .perm-seg button.sel-off { background:var(--danger);  color:#fff; }
@media (max-width:560px) { .perm-list .perm-row { flex-direction:column; align-items:flex-start; } }

/* ── Inline field validation (showFieldError in common.js) ───────────────── */
.field.has-error > input, .field.has-error > select, .field.has-error > textarea,
.field.has-error .bs-input-group { border-color:var(--danger); background:var(--danger-tint); box-shadow:0 0 0 3px color-mix(in srgb, var(--danger) 16%, transparent); }
.field.has-error > label { color:var(--danger); }
.field-error { display:flex; align-items:flex-start; gap:6px; margin-top:7px; font-size:12.5px; font-weight:600; line-height:1.4; color:var(--danger); animation:field-error-in .18s ease-out; }
.field-error svg { flex:0 0 auto; margin-top:1px; }
.field.has-error > input, .field.has-error > select, .field.has-error > textarea { animation:field-shake .28s ease-in-out; }
.field label .req { color:var(--danger); font-weight:800; margin-left:2px; }
@keyframes field-error-in { from { opacity:0; transform:translateY(-3px); } to { opacity:1; transform:none; } }
@keyframes field-shake { 0%,100% { transform:translateX(0); } 25% { transform:translateX(-4px); } 75% { transform:translateX(4px); } }
@media (prefers-reduced-motion: reduce) { .field-error, .field.has-error > input, .field.has-error > select, .field.has-error > textarea { animation:none; } }


/* ============================================================
   Support — user guide / licence viewer and developer contact.
   Built only from existing tokens, so dark mode and the navy/
   green brand carry over with no theme-specific rules.
   ============================================================ */
#view-support .tab-row { max-width:100%; }

.support-doc { padding:0; overflow:hidden; }
.support-doc-head { display:flex; align-items:flex-start; gap:14px; padding:20px 24px; flex-wrap:wrap; }
.support-doc-ic { width:44px; height:44px; border-radius:12px; display:flex; align-items:center; justify-content:center; background:var(--info-tint); color:var(--info); flex-shrink:0; }
.support-doc-ic.is-licence { background:var(--brass-tint); color:var(--brass-ink); }
.support-doc-title { flex:1; min-width:220px; }
.support-doc-title h3 { font-family:var(--display); font-size:16.5px; margin:0 0 4px; color:var(--ink); }
.support-doc-title .sub { font-size:12.5px; color:var(--muted); line-height:1.55; }
.support-doc-title .meta { font-size:12px; color:var(--muted); margin-top:6px; }
.support-doc-actions { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
.support-doc-actions .btn, .support-actions .btn { display:inline-flex; align-items:center; justify-content:center; gap:7px; text-decoration:none; }

.support-facts { display:grid; grid-template-columns:repeat(4,1fr); border-top:1px solid var(--line-soft); border-bottom:1px solid var(--line-soft); background:var(--surface-soft); }
.support-fact { padding:12px 24px; min-width:0; }
.support-fact + .support-fact { border-left:1px solid var(--line-soft); }
.support-fact .k { font-size:11.5px; color:var(--muted); margin-bottom:2px; }
.support-fact .v { font-size:14px; font-weight:600; color:var(--ink); overflow-wrap:anywhere; }

.support-viewer { position:relative; height:clamp(480px, calc(100vh - 340px), 920px); background:var(--surface-soft); }
.support-viewer iframe { position:absolute; inset:0; width:100%; height:100%; border:0; background:transparent; }
.support-viewer-note { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:13px; color:var(--muted); pointer-events:none; }
.support-viewer:fullscreen { height:100vh; background:var(--canvas); }

.support-empty { display:flex; flex-direction:column; align-items:center; text-align:center; gap:6px; padding:56px 24px 60px; }
.support-empty .support-doc-ic { width:56px; height:56px; border-radius:16px; margin-bottom:10px; }
.support-empty h3 { font-family:var(--display); font-size:16px; margin:0; color:var(--ink); }
.support-empty p { font-size:13px; color:var(--muted); max-width:460px; line-height:1.6; margin:0; }
.support-empty code { font-family:var(--mono); font-size:12px; background:var(--surface-soft); border:1px solid var(--line-soft); border-radius:6px; padding:1px 6px; color:var(--ink-soft); }
.support-empty .btn { margin-top:14px; }

.support-grid { display:grid; grid-template-columns:1fr 1.25fr; gap:20px; }
.support-grid > * { min-width:0; }
.support-dev { display:flex; align-items:center; gap:14px; margin-bottom:18px; }
.support-dev-mark { width:56px; height:56px; border-radius:16px; background:linear-gradient(135deg,var(--navy-800),var(--navy-600)); color:#fff; display:flex; align-items:center; justify-content:center; font-family:var(--display); font-weight:700; font-size:18px; flex-shrink:0; }
#view-support .info-row { align-items:center; gap:16px; }
#view-support .card-section-title { margin-top:0; }
.support-dev .muted { font-size:13px; margin-top:2px; }
.support-link { color:var(--accent); font-weight:600; }
.support-link:hover { text-decoration:underline; }
.support-copy { display:inline-flex; align-items:center; justify-content:center; width:26px; height:26px; margin-left:6px; vertical-align:middle; border:none; border-radius:7px; background:var(--surface-soft); color:var(--muted); transition:background var(--transition), color var(--transition); }
.support-copy:hover { background:var(--line-soft); color:var(--ink); }
.support-actions { display:flex; gap:10px; flex-wrap:wrap; }

:is(.support-doc-actions .btn, .support-actions .btn, .support-copy, #support-tabs .tab):focus-visible { outline:2px solid var(--accent); outline-offset:2px; }

@media (max-width:1180px) { .support-grid { grid-template-columns:1fr; } }
@media (max-width:640px) {
  .support-doc-head { padding:16px; }
  .support-doc-actions { width:100%; }
  .support-doc-actions .btn { flex:1; }
  .support-facts { grid-template-columns:repeat(2,1fr); }
  .support-fact { padding:10px 16px; }
  .support-fact:nth-child(3) { border-left:none; }
  .support-fact:nth-child(n+3) { border-top:1px solid var(--line-soft); }
  .support-viewer { height:72vh; min-height:420px; }
  .support-empty { padding:40px 18px 44px; }
}
@media (max-width:520px) {
  #support-tabs { width:100%; flex-wrap:nowrap; }
  #support-tabs .tab { flex:1 1 auto; text-align:center; padding:9px 6px; font-size:12.5px; white-space:nowrap; }
  .support-actions .btn { flex:1; }
}


/* ─────────────────────────────────────────────────────────────────────────
   Rejection reasons, request edit log, "Edited" pill, report filters
   ───────────────────────────────────────────────────────────────────────── */
/* Reason dialog = the confirm dialog with a text box in it */
.confirm-dialog.with-field { max-width:440px; }
.confirm-dialog.with-field p { margin-bottom:16px; }
.confirm-dialog.with-field .field { margin-bottom:20px; text-align:left; }
.confirm-dialog.with-field textarea { min-height:96px; }

/* "Edited ×2" marker under an item name — opens that request's edit log */
.edited-pill { display:inline-flex; align-items:center; gap:4px; margin:3px 0 0 6px; padding:1px 8px; border:0; border-radius:999px; font:inherit; font-size:10.5px; font-weight:800; letter-spacing:.02em; vertical-align:middle; background:var(--late-tint); color:var(--late); cursor:pointer; }
.edited-pill:hover { filter:brightness(.96); }
.cell-badge-wrap { display:inline-flex; align-items:center; gap:6px; }

/* Edit modal */
.re-section.hidden { display:none; }
.re-lock-note { margin-bottom:16px; }
.field input:disabled, .field select:disabled, .field textarea:disabled { background:var(--surface-soft); color:var(--muted); cursor:not-allowed; }

/* Edit log */
.edit-log { display:flex; flex-direction:column; gap:12px; max-height:60vh; overflow-y:auto; overflow-x:hidden; min-width:0; }
.edit-log-entry { border:1px solid var(--line); border-radius:12px; padding:13px 14px; background:var(--surface); min-width:0; max-width:100%; flex:none; }
.edit-log-head { display:flex; align-items:baseline; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-bottom:6px; }
.edit-log-who { font-weight:700; font-size:13.5px; color:var(--ink); }
.edit-log-when { font-size:12px; color:var(--muted); }
.edit-log-note { font-size:12.5px; color:var(--ink-soft); background:var(--surface-soft); border-radius:8px; padding:7px 10px; margin-bottom:8px; white-space:pre-wrap; word-break:break-word; }
.edit-log-changes { width:100%; border-collapse:collapse; font-size:12.5px; table-layout:fixed; }
.edit-log-changes td { padding:6px 0; vertical-align:top; border-top:1px solid var(--line-soft); white-space:normal; overflow-wrap:anywhere; word-break:break-word; min-width:0; }
.edit-log-changes td:first-child { width:30%; color:var(--muted); font-weight:700; padding-right:10px; }
@media (max-width:560px) { .edit-log-changes td:first-child { width:36%; } }
.edit-log-from { color:var(--danger); text-decoration:line-through; text-decoration-color:rgba(192,70,58,.5); }
.edit-log-to { color:var(--success); font-weight:600; }
.edit-log-arrow { color:var(--muted); margin:0 6px; }

/* Report filters — same controls as the rest of the app (.field + select / .select) */
.rep-filters-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(190px, 1fr)); gap:12px 14px; }
.rep-filters-grid .field { margin:0; }
.rep-filters-grid .field.hidden { display:none; }
.rep-filters-foot { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-top:14px; }
.rep-filter-chips { display:flex; flex-wrap:wrap; gap:6px; }
.rep-chip { display:inline-block; padding:3px 10px; border-radius:999px; font-size:11.5px; font-weight:700; background:var(--info-tint); color:var(--info); }

/* ── Inventory Excel import ── */
.imp-btn { display:inline-flex; align-items:center; gap:7px; border:1.5px solid var(--line); background:var(--surface); color:var(--ink-soft); }
.imp-btn:hover:not(:disabled) { background:var(--surface-soft); border-color:var(--line); }
.imp-btn.hidden { display:none; }
.modal-xwide { max-width:1120px; }
.imp-toolbar { display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin-bottom:12px; }
.imp-chips { display:flex; flex-wrap:wrap; gap:8px; }
.imp-chip { display:inline-flex; align-items:center; gap:7px; border:1.5px solid transparent; border-radius:999px; padding:5px 13px; font-size:12px; font-weight:700; letter-spacing:.03em; text-transform:uppercase; cursor:pointer; background:var(--surface-soft); color:var(--muted); font-family:inherit; }
.imp-chip::before { content:''; width:7px; height:7px; border-radius:50%; background:currentColor; }
.imp-chip.active { border-color:currentColor; }
.imp-chip.create { background:var(--success-tint); color:var(--success); }
.imp-chip.update { background:var(--info-tint); color:var(--info); }
.imp-chip.error  { background:var(--danger-tint); color:var(--danger); }
.imp-chip.warn   { background:var(--late-tint); color:var(--late); }
.imp-datemode { display:flex; align-items:center; gap:8px; font-size:12.5px; color:var(--muted); font-weight:600; }
.imp-datemode .select { padding:7px 10px; font-size:13px; }
.imp-notice { font-size:12.5px; padding:9px 13px; border-radius:var(--radius-sm); margin-bottom:10px; background:var(--info-tint); color:var(--info); }
.imp-notice.bad  { background:var(--danger-tint); color:var(--danger); }
.imp-notice.warn { background:var(--late-tint); color:var(--late); }
.imp-notice a { cursor:pointer; text-decoration:underline; font-weight:700; }
.imp-table-wrap { border:1px solid var(--line-soft); border-radius:var(--radius); max-height:50vh; max-height:50dvh; overflow:auto; -webkit-overflow-scrolling:touch; }
.imp-table { width:100%; border-collapse:collapse; font-size:13px; min-width:860px; }
.imp-table thead th { position:sticky; top:0; z-index:1; background:var(--surface); text-align:left; font-size:11px; letter-spacing:.07em; text-transform:uppercase; color:var(--muted); padding:11px 12px; border-bottom:1px solid var(--line-soft); }
.imp-table td { padding:11px 12px; border-bottom:1px solid var(--line-soft); vertical-align:top; color:var(--ink); }
.imp-table tbody tr:nth-child(even) td { background:var(--surface-soft); }
.imp-table tr.imp-error td:first-child { box-shadow:inset 3px 0 0 var(--danger); }
.imp-name { font-weight:600; }
.imp-sub { font-size:12px; color:var(--muted); margin-top:2px; display:flex; flex-wrap:wrap; gap:6px; align-items:center; }
.imp-act { display:inline-flex; align-items:center; gap:6px; border-radius:999px; padding:4px 11px; font-size:11.5px; font-weight:700; letter-spacing:.03em; text-transform:uppercase; white-space:nowrap; background:var(--surface-soft); color:var(--muted); }
.imp-act::before { content:''; width:6px; height:6px; border-radius:50%; background:currentColor; }
.imp-act.create { background:var(--success-tint); color:var(--success); }
.imp-act.update { background:var(--info-tint); color:var(--info); }
.imp-act.error  { background:var(--danger-tint); color:var(--danger); }
.imp-chg { font-size:12.5px; margin-bottom:2px; }
.imp-chg b { font-weight:700; margin-right:4px; }
.imp-chg .arrow { color:var(--muted); margin:0 3px; }
.imp-chg .old { color:var(--muted); text-decoration:line-through; text-decoration-color:rgba(102,111,140,.5); }
.imp-line { font-size:12.5px; margin-top:3px; }
.imp-line.err  { color:var(--danger); font-weight:600; }
.imp-line.warn { color:var(--late); }
.imp-more { text-align:center; margin:12px 0 0; }
.imp-skip { display:flex; align-items:center; gap:8px; font-size:13px; font-weight:600; color:var(--ink-soft); margin-top:14px; cursor:pointer; }
@media (max-width:640px) { .imp-toolbar { align-items:stretch; } .imp-datemode { width:100%; justify-content:space-between; } }

/* Edit log pager */
.edit-log-pager { display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; margin-top:14px; padding-top:12px; border-top:1px solid var(--line-soft); font-size:12.5px; color:var(--muted); }
.edit-log-pager .pager-btns { display:flex; gap:6px; }
.edit-log-pager .btn[disabled] { opacity:.45; cursor:not-allowed; }

/* Consumption / scrap corrections */
.row-actions { display:flex; gap:8px; flex-wrap:nowrap; align-items:center; }
.reverted-pill { display:inline-flex; align-items:center; border-radius:999px; padding:2px 9px; font-size:10.5px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; background:var(--danger-tint); color:var(--danger); }
tr.is-reverted td { opacity:.62; }
tr.is-reverted td .row-actions, tr.is-reverted td:last-child { opacity:1; }
tr.is-reverted td b, tr.is-reverted td.num { text-decoration:line-through; text-decoration-color:rgba(192,70,58,.5); }
.cn-stock-hint { font-size:12.5px; color:var(--muted); margin:-4px 0 12px; }
.cn-stock-hint b { color:var(--ink); }
.re-effect-note { font-size:12.5px; color:var(--ink-soft); background:var(--surface-soft); border-radius:var(--radius-sm); padding:9px 12px; margin-bottom:14px; }

/* Records of items that have left the inventory: kept as read-only history */
tr.row-gone td, .qr-item.row-gone, .row-gone { color: var(--muted, #8a93b2); }
tr.row-gone td { opacity:.62; background-image: repeating-linear-gradient(135deg, transparent 0 9px, rgba(138,147,178,.06) 9px 10px); }
tr.row-gone td:last-child { opacity:1; }               /* keep the (disabled) action buttons readable */
tr.row-gone b, .qr-item.row-gone .qr-name { text-decoration: none; font-weight: 600; }
.qr-item.row-gone { opacity:.7; }
.badge-gone { background: transparent; color: var(--muted, #8a93b2); border: 1px dashed var(--line-soft, #3a4262); font-size: 10.5px; font-weight: 600; padding: 2px 8px; }
button[disabled].btn, .btn:disabled { opacity:.45; cursor:not-allowed; }

/* Row action buttons: one consistent look and spacing in every table (Transfers, Procurement, Repairs, Consumption,
   Scraps, Petty cash). A soft button sits on the same tint as a hovered row, so give ghost buttons a faint outline
   to keep them readable instead of looking like loose text. */
td .btn-ghost { box-shadow: inset 0 0 0 1px var(--line); }
td .btn-ghost:hover:not(:disabled) { box-shadow: inset 0 0 0 1px var(--line); }
td .flex.gap-8, td .row-actions { align-items:center; }
td .flex.gap-8 > .btn, td .row-actions > .btn { white-space:nowrap; }

/* Organization → Email (SMTP) card */
.section-head.collapsible { cursor:pointer; margin-bottom:6px; align-items:center; }
.section-head.collapsible:focus-visible { outline:2px solid var(--accent); outline-offset:4px; border-radius:8px; }
.email-head h3 { margin:0 0 3px; }
.section-head .chev { flex:0 0 auto; color:var(--muted); transition:transform .18s; }
.section-head.collapsed .chev { transform:rotate(180deg); }
#email-card-body { padding-top:14px; }
#email-card-body[hidden] { display:none; }
.email-grid { display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:0 18px; max-width:760px; margin-top:12px; }
.email-grid .field { margin-bottom:16px; }
@media (max-width: 700px) { .email-grid { grid-template-columns:minmax(0, 1fr); } }
.email-result { margin-top:14px; padding:11px 14px; border-radius:10px; font-size:13.5px; line-height:1.45; }
.email-result.ok  { background:var(--success-tint); color:var(--success); }
.email-result.err { background:var(--danger-tint);  color:var(--danger); }
/* on/off switch (pill) — drawn from a real checkbox, so it works with the keyboard and screen readers */
.sw-row { display:flex; align-items:center; gap:12px; }
.sw-label { font-weight:600; color:var(--ink); cursor:pointer; margin:0; }
.sw { position:relative; display:inline-block; flex:0 0 auto; width:46px; height:26px; margin:0; }
.sw input[type="checkbox"] { position:absolute; inset:0; width:100%; height:100%; margin:0; padding:0; opacity:0; cursor:pointer; z-index:1; }
.sw .sw-track { position:absolute; inset:0; border-radius:999px; background:var(--line); transition:background .15s; }
.sw .sw-track::after { content:''; position:absolute; top:3px; left:3px; width:20px; height:20px; border-radius:50%; background:#fff; box-shadow:0 1px 3px rgba(16,21,38,.28); transition:transform .15s; }
.sw input:checked + .sw-track { background:var(--success); }
.sw input:checked + .sw-track::after { transform:translateX(20px); }
.sw input:focus-visible + .sw-track { outline:2px solid var(--accent); outline-offset:2px; }
.sw input:disabled + .sw-track { opacity:.5; }
#em-test { box-shadow: inset 0 0 0 1.5px var(--line); }
#em-test:hover:not(:disabled) { box-shadow: inset 0 0 0 1.5px var(--accent); }

/* ═════════ v12.3.10 — smoother theme and tab/page switching ═════════ */
/* Theme: one cross-fade of the whole page (View Transitions), per-element fade as the fallback */
::view-transition-old(root), ::view-transition-new(root) { animation-duration:.38s; animation-timing-function:cubic-bezier(.4,0,.2,1); }
html.theme-vt *, html.theme-vt *::before, html.theme-vt *::after { transition:none !important; }
html.theme-fade *, html.theme-fade *::before, html.theme-fade *::after {
  transition:background-color .32s cubic-bezier(.4,0,.2,1), color .32s cubic-bezier(.4,0,.2,1), border-color .32s cubic-bezier(.4,0,.2,1),
             fill .32s cubic-bezier(.4,0,.2,1), stroke .32s cubic-bezier(.4,0,.2,1), box-shadow .32s cubic-bezier(.4,0,.2,1) !important;
}
/* Page (sidebar nav) and tab content entrances */
@keyframes viewEnter { from { opacity:.55; } to { opacity:1; } }
@keyframes tabEnter  { from { opacity:.45; transform:translateY(4px); } to { opacity:1; transform:none; } }
.view-enter { animation:viewEnter .22s cubic-bezier(.2,.7,.2,1) both; }
.tab-enter  { animation:tabEnter .22s cubic-bezier(.2,.7,.2,1) both; }
/* Tab/chip/nav colour changes ease instead of snapping */
.tab-row .tab, .section-tabs .stab, .pos-cat, .pos-seg button, .pos-methods button, .pos-tabs button, .pos-prev-tabs button, .nav-item {
  transition:background-color .2s cubic-bezier(.4,0,.2,1), color .2s cubic-bezier(.4,0,.2,1), border-color .2s cubic-bezier(.4,0,.2,1), box-shadow .2s cubic-bezier(.4,0,.2,1), transform .1s;
}
@media (prefers-reduced-motion: reduce) {
  .view-enter, .tab-enter { animation:none !important; }
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation-duration:.001s !important; }
}

/* ═════════ v12.3.12 — overview & sidebar follow the person's permissions ═════════ */
.nav-section-label.nav-section-empty { display:none !important; }
.activity-dot.sale { background:var(--success); }
.badge-corrected, .badge-reopened { background:var(--late-tint); color:var(--late); }

.perm-group-title { display:flex; align-items:center; justify-content:space-between; gap:8px; flex-wrap:wrap; }
.perm-bulk { display:inline-flex; gap:4px; }
.perm-bulk button { border:1px solid var(--line); background:var(--surface-soft); color:var(--ink-soft); border-radius:6px; padding:2px 8px; font-size:11px; font-weight:600; cursor:pointer; text-transform:none; letter-spacing:0; transition:background-color .18s, color .18s, border-color .18s; }
.perm-bulk button:hover { border-color:var(--accent); color:var(--ink); }
.perm-quick { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:12px 14px; margin-bottom:12px; border:1px dashed var(--line); border-radius:10px; background:var(--surface-soft); }
.perm-quick div { display:flex; flex-direction:column; gap:2px; font-size:13px; }
.perm-quick span { font-size:12px; color:var(--muted); }

/* ═════════ v12.3.17 — motion polish (smooth at 60 Hz and on 90/120/144 Hz screens) ═════════
   Rules followed by everything below, so it costs nothing at any refresh rate:
   • Only transform and opacity are animated for movement (the compositor runs them on the GPU at the screen's own refresh
     rate, off the main thread — which is why they stay smooth while the app is busy loading data).
   • Durations are in milliseconds, never frames, so a 120 Hz screen simply gets more in-between frames of the same motion.
   • Entrances ease OUT (fast start = feels instant), exits ease IN and are shorter than entrances.
   • No `will-change` left permanently on anything, no per-frame JavaScript, no animated blur. */
:root {
  --ease-out: cubic-bezier(.2,.8,.2,1);     /* entrances: lands softly */
  --ease-in:  cubic-bezier(.4,0,1,1);       /* exits: leaves briskly */
  --ease-std: cubic-bezier(.4,0,.2,1);      /* colour / state changes */
}

/* Touch screens: no 300 ms tap delay, no grey flash on tap — everything tappable responds on the first frame */
a, button, [role="button"], label, select, summary, .nav-item, .tab, .stab, .stat-card, .report-card, .inv-grid-card, .qr-item, .activity-item, .alert-card {
  touch-action:manipulation; -webkit-tap-highlight-color:transparent;
}
/* A flick at the end of a dialog's scroll no longer drags the page behind it */
.modal, .confirm-dialog { overscroll-behavior:contain; }

/* Pressed feedback on the first frame (transform only, so it never touches layout) */
.nav-item:active, .tab-row .tab:active, .section-tabs .stab:active, .pager-btn:active, .view-toggle-btn:active,
.modal-close-btn:active, .sidebar-collapse-btn:active, .theme-toggle-btn:active, .bs-dp-day:active { transform:scale(.96); }
.stat-card:active, .report-card:active, .inv-grid-card:active, .alert-card:active { transform:scale(.99); }
.modal-close-btn, .pager-btn, .view-toggle-btn, .theme-toggle-btn, .bs-dp-day, .bs-dp-nav, .report-card, .inv-grid-card, .alert-card { transition-property:background-color, color, border-color, box-shadow, transform; transition-duration:.15s; transition-timing-function:var(--ease-out); }

/* Toast leaves with a short fade/slide instead of a hard cut (class added by toast() in common.js) */
@keyframes toastOut { to { opacity:0; transform:translateY(8px) scale(.98); } }
.toast.out { animation:toastOut .16s var(--ease-in) forwards; pointer-events:none; }

/* Dialogs that are built on the fly (confirm / reason / restock / chart zoom) fade out; see dismissOverlay() in common.js */
@keyframes overlayOut { to { opacity:0; } }
@keyframes dialogOut  { to { opacity:0; transform:translateY(6px) scale(.985); } }
.confirm-backdrop.is-closing, .modal-backdrop.is-closing { animation:overlayOut .12s linear forwards !important; pointer-events:none; }
.confirm-backdrop.is-closing > .confirm-dialog, .modal-backdrop.is-closing > .modal { animation:dialogOut .12s var(--ease-in) forwards !important; }

/* One consistent reduced-motion guard for everything added in this version */
@media (prefers-reduced-motion: reduce) {
  .toast, .toast.out, .modal, .confirm-dialog, .modal-backdrop, .confirm-backdrop { animation-duration:.001s !important; }
  .nav-item:active, .tab-row .tab:active, .section-tabs .stab:active, .pager-btn:active, .view-toggle-btn:active, .btn:active:not(:disabled),
  .modal-close-btn:active, .sidebar-collapse-btn:active, .theme-toggle-btn:active, .bs-dp-day:active,
  .stat-card:active, .report-card:active, .inv-grid-card:active, .alert-card:active { transform:none; }
  .sidebar { transition-duration:.001s !important; transition-delay:0s !important; }
}
