/* ---- app-shell.css ----
 * Extracted from resources/views/layouts/app.blade.php so the browser can
 * actually cache this across page navigations (this is a traditional
 * multi-page app, not an SPA — every navigation was re-downloading and
 * re-parsing this whole stylesheet inline with zero caching benefit).
 * The few genuinely dynamic bits (brand-color CSS variables, which the
 * admin can change any time in Settings) stay in a small inline <style>
 * in the layout itself — everything else lives here, static. */

        @font-face { font-family: 'IBM Plex Sans'; font-weight: 400; font-style: normal; font-display: swap; src: url('/fonts/ibm-plex-sans-latin-400-normal.woff2') format('woff2'); }
        @font-face { font-family: 'IBM Plex Sans'; font-weight: 500; font-style: normal; font-display: swap; src: url('/fonts/ibm-plex-sans-latin-500-normal.woff2') format('woff2'); }
        @font-face { font-family: 'IBM Plex Sans'; font-weight: 600; font-style: normal; font-display: swap; src: url('/fonts/ibm-plex-sans-latin-600-normal.woff2') format('woff2'); }
        @font-face { font-family: 'IBM Plex Mono'; font-weight: 400; font-style: normal; font-display: swap; src: url('/fonts/ibm-plex-mono-latin-400-normal.woff2') format('woff2'); }
        @font-face { font-family: 'IBM Plex Mono'; font-weight: 500; font-style: normal; font-display: swap; src: url('/fonts/ibm-plex-mono-latin-500-normal.woff2') format('woff2'); }


        :root {
            /* Brand palette derived from the single admin-configurable brand_color setting */
            --brand-red: #ED1C24;

            --ink: #16181D;
            --page-bg: #F2F4F7;
            --sidebar-bg: #FFFFFF;
            --card: #FFFFFF;
            --border: #E7E9EE;
            --border-soft: #EFF1F5;
            --text: #1C2129;
            --muted: #767E8C;
            --muted-soft: #9CA3B0;

            --danger: #E23D3D;
            --danger-bg: #FCEAEA;
            --success: #17A76B;
            --success-bg: #E5F7EE;
            --warning: #F0A519;
            --warning-bg: #FDF1DD;
            --info: #6C5DD3;
            --info-bg: #EEEBFB;
            --teal: #17A0B0;
            --teal-bg: #E3F6F8;

            --shadow-card: 0 1px 2px rgba(16,24,40,.04), 0 1px 3px rgba(16,24,40,.06);
            --shadow-pop: 0 8px 24px rgba(16,24,40,.12), 0 2px 6px rgba(16,24,40,.06);
            /* Used only by .dd-panel (View/Delete-style row menus, Mails/
               PDF/Convert menus, etc). Noticeably stronger than
               --shadow-pop — these panels float directly over a
               near-white page (--page-bg is only a shade off #fff), so
               --shadow-pop's subtle lift wasn't enough to read as a
               popup rather than just faint, hard-to-place text. */
            --shadow-dd: 0 16px 40px rgba(16,24,40,.24), 0 4px 12px rgba(16,24,40,.14), 0 0 0 1px rgba(16,24,40,.06);
        }

        /* Dark mode — toggled via the moon/sun button in the top bar (see
           app-shell.js), applied as a data-theme attribute on <html> and
           remembered in localStorage. Since every surface in this file
           (cards, borders, text, badges) already reads from these same
           variables, overriding them here is enough to re-skin the whole
           app without touching individual rules. */
        html[data-theme="dark"] {
            --ink: #E5E7EB;
            --page-bg: #0F1115;
            --sidebar-bg: #161920;
            --card: #161920;
            --border: #262B35;
            --border-soft: #1F232B;
            --text: #E5E7EB;
            --muted: #9199A8;
            --muted-soft: #6B7280;

            --danger-bg: rgba(226,61,61,0.16);
            --success-bg: rgba(23,167,107,0.16);
            --warning-bg: rgba(240,165,25,0.16);
            --info-bg: rgba(108,93,211,0.2);
            --teal-bg: rgba(23,160,176,0.2);

            --shadow-card: 0 1px 2px rgba(0,0,0,.4), 0 1px 3px rgba(0,0,0,.3);
            --shadow-pop: 0 8px 24px rgba(0,0,0,.5), 0 2px 6px rgba(0,0,0,.3);
            --shadow-dd: 0 16px 40px rgba(0,0,0,.65), 0 4px 12px rgba(0,0,0,.45), 0 0 0 1px rgba(255,255,255,.06);
        }

        * { box-sizing: border-box; }
        /* Belt-and-suspenders for the `hidden` attribute: several elements
           here (the PWA install banner, its Install button, etc.) are
           toggled via element.hidden = true/false in JS. That only works
           if nothing else sets `display` on the same element with equal or
           higher specificity — .btn { display: inline-flex } and
           .pwa-install-banner { display: flex } do exactly that, silently
           overriding the browser's built-in "[hidden] { display: none }"
           rule (author styles always win over the browser's default
           stylesheet, regardless of specificity), so the element stayed
           visible even after being "hidden". This restores the intended
           behavior everywhere .hidden is used. */
        [hidden] { display: none !important; }
        /* The page must scroll as ONE document. Previously body had height:100%
           plus overflow-x:hidden; because html also had overflow set, body became
           its own scroll box, which (with the sidebar sticky inside it) left the
           sidebar scrolling away and a blank grey band under the page, with a
           second scrollbar. Now only <html> clips sideways overflow; body just
           grows with its content (overflow-x: clip does not create a scroll box). */
        html { height: 100%; overflow-x: hidden; }
        html, body { width: 100%; max-width: 100vw; overscroll-behavior-x: none; touch-action: pan-y; }
        body { min-height: 100%; height: auto; overflow-x: clip; }
        /* NOTE: deliberately no overflow-x on .app-shell itself — setting only
           overflow-x (without overflow-y) on an element forces the browser to
           compute overflow-y as `auto` too (that's a CSS spec requirement, not
           a bug), which turned .app-shell into its own independent scroll
           container separate from the page. That broke the sidebar's
           `position: sticky` (sticky is relative to the nearest scrolling
           ancestor — once .app-shell became one, the sidebar started
           scrolling away with the page instead of staying put). Horizontal
           overflow is already prevented at the html/body level above, so
           .app-shell doesn't need its own overflow-x rule too. */
        .app-shell { max-width: 100%; }
        body {
            margin: 0;
            font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'SF Pro Display', 'Helvetica Neue', Helvetica, Arial, sans-serif;
            background: var(--page-bg);
            color: var(--text);
            font-size: 10.5px;
            -webkit-font-smoothing: antialiased;
        }
        h1, h2, h3 { font-family: inherit; font-weight: 600; letter-spacing: -0.01em; margin: 0 0 0.75rem; color: var(--text); }
        h1 { font-size: 1.5rem; }
        h2 { font-size: 1.05rem; }
        a { color: inherit; }

        /* Global font override: Apple system font (San Francisco) everywhere — UI
           text and figures alike. Sizes are left to each component's own rem-based
           rules below instead of being pinned to one fixed size, so text scales
           sensibly (and stays legible) across desktop and mobile. */
        body, body * { font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'SF Pro Display', 'Helvetica Neue', Helvetica, Arial, sans-serif !important; }
        .stat .num, .doc-sheet .money, .money, code, pre { font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'SF Pro Display', 'Helvetica Neue', Helvetica, Arial, sans-serif !important; font-variant-numeric: tabular-nums; }

        /* ---- App shell: fixed left sidebar + sticky top bar + scrolling content ---- */
        .app-shell { display: flex; min-height: 100vh; }

        .sidebar {
            width: 210px; flex-shrink: 0; background: var(--sidebar-bg); color: var(--text);
            display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh;
            border-right: 1px solid var(--border);
        }
        .sidebar-brand {
            padding: 1rem 0.9rem 0.75rem;
        }
        .sidebar-brand .mark { display: flex; align-items: center; }
        .sidebar-brand .mark img { width: 100%; max-width: 130px; height: auto; display: block; }
        .sidebar-brand .tagline { font-size: 0.6rem; letter-spacing: 0.07em; text-transform: uppercase; color: var(--muted-soft); margin-top: 0.45rem; font-weight: 600; }

        .sidebar-cta { padding: 0 0.8rem 0.75rem; }
        .sidebar-cta .btn { width: 100%; text-align: center; background: var(--brand); }
        .sidebar-cta .btn:hover { background: var(--brand-dark); }

        .sidebar-nav { flex: 1; padding: 0.3rem 0.5rem; overflow-y: auto; }
        .sidebar-nav a {
            display: flex; align-items: center; gap: 0.55rem; padding: 0.45rem 0.55rem; margin-bottom: 0.15rem;
            border-radius: 8px; color: var(--muted); text-decoration: none; font-size: 0.8rem; font-weight: 500;
            position: relative;
        }
        .sidebar-nav a svg { flex-shrink: 0; opacity: 0.85; width: 13px; height: 13px; }
        .sidebar-nav a:hover { background: var(--brand-lighter); color: var(--brand-darker); }
        .sidebar-nav a.active { background: var(--brand-light); color: var(--brand-darker); font-weight: 600; }
        .sidebar-nav a.active svg { opacity: 1; color: var(--brand-dark); }
        .sidebar-nav .nav-section { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted-soft); font-weight: 700; padding: 0.75rem 0.55rem 0.3rem; }

        /* ---- Mobile nav toggle (hamburger) button: hidden on desktop, shown
           only once the sidebar becomes an off-canvas drawer below. ---- */
        .nav-toggle {
            display: none; align-items: center; justify-content: center; width: 36px; height: 36px;
            border-radius: 8px; border: 1px solid var(--border); background: var(--card); color: var(--text);
            cursor: pointer; flex-shrink: 0;
        }
        .nav-toggle svg { width: 18px; height: 18px; }
        .sidebar-close { display: none; }
        .sidebar-backdrop {
            display: none; position: fixed; inset: 0; background: rgba(16, 20, 28, 0.5); z-index: 39;
        }

        /* ---- Off-canvas sidebar on tablets/phones: below this width there's no
           room for a permanent 210px sidebar next to page content, so it becomes
           a full-height drawer that slides in from the left over the page,
           toggled by the hamburger button in the top bar. This keeps every nav
           icon and label fully visible (nothing squeezed or clipped) instead of
           just shrinking the sidebar in place. ---- */
        @media (max-width: 900px) {
            .nav-toggle { display: inline-flex; }
            .mobile-refresh-btn { display: inline-flex; }
            /* "Recently cleared" / "Awaiting approval" dashboard rows: the
               5-column grid (dot, badge, description, stage, time) is too
               tight for a phone screen — text was getting clipped by the
               card's overflow instead of wrapping. Switch to a wrapping
               flex layout: dot + badge + description on the first line,
               stage + time dropping to their own line underneath. */
            .activity-feed li.with-dot {
                display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 0.5rem;
            }
            .activity-feed li.with-dot .activity-desc {
                flex: 1 1 auto; min-width: 0; white-space: normal; word-break: break-word;
            }
            .activity-feed li.with-dot .activity-meta,
            .activity-feed li.with-dot .activity-time { white-space: normal; }
            .activity-feed li.with-dot .activity-meta { flex-basis: 100%; margin-left: 1.5rem; }
            .app-shell { position: relative; }
            .sidebar {
                position: fixed; top: 0; left: 0; z-index: 40; width: 260px; max-width: 82vw;
                transform: translateX(-100%); transition: transform 0.22s ease, visibility 0.22s; box-shadow: var(--shadow-pop);
                /* visibility: hidden (not just the transform) while closed — mobile
                   Safari has a known bug where a fixed+transformed element still
                   counts toward the page's scrollable width using its pre-transform
                   position, even though it's rendered off-screen. That left a large
                   patch of "phantom" horizontally-scrollable blank space roughly the
                   width of the sidebar on every page. Hiding it from layout while
                   closed removes it from that calculation entirely. */
                visibility: hidden;
            }
            .app-shell.sidebar-open .sidebar { transform: translateX(0); visibility: visible; }
            .app-shell.sidebar-open .sidebar-backdrop { display: block; }
            .sidebar-brand { display: flex; align-items: center; justify-content: space-between; padding: 0.9rem 0.9rem 0.7rem; }
            .sidebar-close {
                display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
                border-radius: 8px; border: 1px solid var(--border); background: var(--card); color: var(--muted); cursor: pointer; flex-shrink: 0;
            }
            .sidebar-close svg { width: 15px; height: 15px; }
            .sidebar-nav { padding: 0.3rem 0.55rem; }
            .sidebar-nav a { padding: 0.55rem 0.6rem; gap: 0.55rem; font-size: 0.85rem; }
            .sidebar-nav a svg { width: 17px; height: 17px; }
            .nav-group-toggle { padding: 0.55rem 0.6rem; font-size: 0.85rem; }
            .nav-group-items a { padding: 0.5rem 0.6rem 0.5rem 2.3rem; font-size: 0.82rem; }
            .main { width: 100%; }
            .topbar { padding: 0 0.9rem; gap: 0.6rem; }
            .container { padding: 1.1rem 0.35rem 2.25rem; }
            /* The account/notifications dropdown was anchored to its bell/
               avatar icon with a fixed 220px width — on a phone the icon
               sits well left of the right edge, so the panel's right-
               anchored 220px ran off the left side of the screen instead
               of being clipped by it. Anchor it to the viewport instead so
               it always sits fully on screen regardless of where its
               trigger icon happens to be. */
            .user-menu-panel {
                position: fixed !important; left: 0.75rem !important; right: 0.75rem !important; top: 72px !important;
                width: auto !important; max-width: none !important; max-height: calc(100vh - 88px) !important; overflow-y: auto;
            }
        }

        /* ---- Even smaller phones: trim further so the search box, hamburger,
           and topbar icons all stay visible on one row without overlapping. ---- */
        @media (max-width: 480px) {
            .topbar { height: 56px; }
            .topbar-right { gap: 0.5rem; }
            .user-menu .who-name, .user-menu .who-role { display: none; }
            .user-menu summary svg { display: none; }
            .container { padding: 0.9rem 0.7rem 2rem; }
            .card { padding: 1rem; }
            .user-menu-panel { top: 64px !important; max-height: calc(100vh - 80px) !important; }
        }

        /* ---- Collapsible nav groups (Zoho-style "Sales", "Administration", etc.) ---- */
        .nav-group { margin-bottom: 0.15rem; }
        .nav-group-toggle {
            display: flex; align-items: center; justify-content: space-between; width: 100%;
            gap: 0.55rem; padding: 0.45rem 0.55rem; border-radius: 8px; color: var(--muted);
            background: transparent; border: none; font-family: inherit; font-size: 0.8rem; font-weight: 500;
            cursor: pointer; text-align: left;
        }
        .nav-group-toggle:hover { background: var(--brand-lighter); color: var(--brand-darker); }
        .nav-group-toggle .label { display: flex; align-items: center; gap: 0.55rem; }
        .nav-group-toggle .label svg { flex-shrink: 0; opacity: 0.85; width: 13px; height: 13px; }
        .nav-group-toggle .chevron { flex-shrink: 0; opacity: 0.6; transition: transform 0.15s ease; width: 10px; height: 10px; }
        .nav-group.open .nav-group-toggle .chevron { transform: rotate(90deg); }
        .nav-group.has-active > .nav-group-toggle { color: var(--brand-darker); font-weight: 600; }
        .nav-group.has-active > .nav-group-toggle .label svg { opacity: 1; color: var(--brand-dark); }

        .nav-group-items { max-height: 0; overflow: hidden; transition: max-height 0.18s ease; }
        .nav-group.open .nav-group-items { max-height: 500px; }
        /* No slide animation while the page is loading (class removed by app-shell.js
           after first paint), and groups remembered as open are open from the very
           first frame via the <html> class set in the layout's <head>. */
        .nav-no-anim .nav-group-items, .nav-no-anim .nav-group-toggle .chevron { transition: none !important; }
        html.nav-open-sales .nav-group[data-group="sales"] .nav-group-items,
        html.nav-open-purchases .nav-group[data-group="purchases"] .nav-group-items,
        html.nav-open-accessories .nav-group[data-group="accessories"] .nav-group-items,
        html.nav-open-administration .nav-group[data-group="administration"] .nav-group-items { max-height: 500px; }
        html.nav-open-sales .nav-group[data-group="sales"] .nav-group-toggle .chevron,
        html.nav-open-purchases .nav-group[data-group="purchases"] .nav-group-toggle .chevron,
        html.nav-open-accessories .nav-group[data-group="accessories"] .nav-group-toggle .chevron,
        html.nav-open-administration .nav-group[data-group="administration"] .nav-group-toggle .chevron { transform: rotate(90deg); }
        .nav-group-items a, .nav-group-items .nav-item {
            display: flex; align-items: center; padding: 0.42rem 0.55rem 0.42rem 2.15rem; margin-bottom: 0.1rem;
            border-radius: 8px; color: var(--muted); text-decoration: none; font-size: 0.78rem; font-weight: 500;
        }
        .nav-group-items a:hover, .nav-group-items .nav-item:hover { background: var(--brand-lighter); color: var(--brand-darker); }
        .nav-group-items a.active, .nav-group-items .nav-item.active { background: var(--brand-light); color: var(--brand-darker); font-weight: 600; }
        .nav-badge { display: inline-block; min-width: 1.1rem; padding: 0.05rem 0.35rem; margin-left: 0.4rem; border-radius: 999px; background: var(--danger); color: #fff; font-size: 0.68rem; font-weight: 700; text-align: center; line-height: 1.3; }

        /* ---- Sidebar "+" shortcut: shown next to a nav item on hover,
           jumps straight to that item's "create new" form (Zoho's pattern).
           .nav-row wraps a nav item + its optional .nav-plus as siblings —
           can't nest an <a> inside another <a>, so they're side-by-side
           flex children instead of one link wrapping everything. ---- */
        .nav-row { display: flex; align-items: center; }
        .nav-row .nav-item, .nav-row > a:first-child { flex: 1; min-width: 0; margin-bottom: 0.1rem; }
        .nav-row .nav-plus {
            flex-shrink: 0; width: 20px; height: 20px; margin: 0 0.3rem 0.1rem 0; border-radius: 6px;
            display: flex; align-items: center; justify-content: center; color: var(--muted-soft);
            text-decoration: none; font-size: 0.95rem; font-weight: 600; line-height: 1; opacity: 0; transition: opacity 0.12s ease;
        }
        .nav-row:hover .nav-plus { opacity: 1; }
        .nav-row .nav-plus:hover { background: var(--brand-light); color: var(--brand-darker); }
        /* Always-visible on touch devices — there's no "hover" to reveal it on a phone/tablet. */
        @media (hover: none) { .nav-row .nav-plus { opacity: 0.55; } }

        .sidebar-foot { padding: 0.8rem 0.9rem 0.9rem; border-top: 1px solid var(--border-soft); }
        .sidebar-foot .who { font-size: 0.76rem; color: var(--muted); margin-bottom: 0.55rem; display: flex; align-items: center; gap: 0.5rem; }
        .sidebar-foot .who .avatar {
            width: 24px; height: 24px; border-radius: 99px; background: var(--brand); color: #fff;
            display: inline-flex; align-items: center; justify-content: center; font-weight: 700; flex-shrink: 0;
            overflow: hidden;
        }
        .logout-btn {
            display: flex; align-items: center; gap: 0.5rem; width: 100%; background: transparent; border: 1px solid var(--border);
            color: var(--muted); padding: 0.45rem 0.7rem; border-radius: 7px; font-size: 0.8rem; cursor: pointer; font-family: inherit;
        }
        .logout-btn:hover { background: var(--danger-bg); color: var(--danger); border-color: #f0cccc; }
        .user-menu-link {
            display: flex; align-items: center; gap: 0.5rem; width: 100%; background: transparent; border: 1px solid transparent;
            color: var(--text); padding: 0.45rem 0.55rem; border-radius: 7px; font-size: 0.8rem; text-decoration: none; box-sizing: border-box;
        }
        .user-menu-link:hover { background: var(--page-bg); }

        /* ---- Top bar ---- */
        .topbar {
            position: sticky; top: 0; z-index: 20; height: 64px; background: var(--card); border-bottom: 1px solid var(--border);
            display: flex; align-items: center; justify-content: space-between; padding: 0 1.75rem; gap: 1rem;
        }
        .topbar-right { display: flex; align-items: center; gap: 0.9rem; }
        .mobile-refresh-btn { display: none; }
        .mobile-refresh-btn:disabled { opacity: 0.5; }
        .icon-btn {
            width: 28px; height: 28px; border-radius: 99px; border: 1px solid var(--border); background: var(--card);
            display: inline-flex; align-items: center; justify-content: center; color: var(--muted); cursor: pointer; position: relative;
        }
        .icon-btn svg { width: 13px; height: 13px; }
        .icon-btn:hover { background: var(--page-bg); color: var(--text); }
        .icon-btn .dot {
            position: absolute; top: 8px; right: 9px; width: 8px; height: 8px; border-radius: 99px;
            background: var(--danger); border: 1.5px solid #fff;
        }
        /* Notification dot color: red when something unread needs action
           (pending approval or rejected), green when everything unread is
           just "cleared" (approved) news — see $unreadNotifications logic
           below. The dot itself is a plain solid color; it only *pulses*
           (via .dot-blink, added/removed by JS below) while there's a
           notification the person hasn't seen the bell light up for yet —
           it should not blink forever just because older items are still
           unread. */
        .icon-btn .dot.dot-attention { background: var(--danger); }
        .icon-btn .dot.dot-cleared { background: var(--success); }
        .icon-btn .dot.dot-attention.dot-blink { animation: dot-pulse-red 1.6s ease-in-out infinite; }
        .icon-btn .dot.dot-cleared.dot-blink { animation: dot-pulse-green 1.6s ease-in-out infinite; }
        @keyframes dot-pulse-red {
            0%, 100% { box-shadow: 0 0 0 0 rgba(226, 61, 61, 0.55); }
            50% { box-shadow: 0 0 0 4px rgba(226, 61, 61, 0); }
        }
        @keyframes dot-pulse-green {
            0%, 100% { box-shadow: 0 0 0 0 rgba(23, 167, 107, 0.55); }
            50% { box-shadow: 0 0 0 4px rgba(23, 167, 107, 0); }
        }
        /* Same red/green pulsing dot, reused inline in list rows (dashboard
           "Awaiting approval" / "Recently cleared" panels). */
        .approval-dot { display: inline-block; width: 8px; height: 8px; border-radius: 99px; margin-right: 0.5rem; flex-shrink: 0; }
        .approval-dot-attention { background: var(--danger); animation: dot-pulse-red 1.6s ease-in-out infinite; }
        .approval-dot-cleared { background: var(--success); animation: dot-pulse-green 1.6s ease-in-out infinite; }

        .user-menu { position: relative; }
        .user-menu summary { list-style: none; display: flex; align-items: center; gap: 0.6rem; cursor: pointer; padding: 0.25rem 0.4rem 0.25rem 0.25rem; border-radius: 99px; }
        .user-menu summary::-webkit-details-marker { display: none; }
        .user-menu summary:hover { background: var(--page-bg); }
        .user-menu .avatar {
            width: 28px; height: 28px; border-radius: 99px; background: var(--brand); color: #fff;
            display: inline-flex; align-items: center; justify-content: center; font-weight: 700; flex-shrink: 0;
            overflow: hidden;
        }
        .user-menu .avatar img, .sidebar-foot .who .avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
        .user-menu .who-name { font-size: 0.85rem; font-weight: 600; color: var(--text); }
        .user-menu .who-role { display: block; font-size: 0.7rem; color: var(--muted); font-weight: 500; }
        .user-menu[open] summary { background: var(--page-bg); }
        .user-menu-panel {
            position: absolute; right: 0; top: calc(100% + 8px); width: 220px; background: var(--card); border: 1px solid var(--border);
            border-radius: 12px; box-shadow: var(--shadow-pop); padding: 0.6rem; z-index: 30;
        }
        .user-menu-email { font-size: 0.8rem; font-weight: 600; color: var(--text); padding: 0.4rem 0.55rem 0.1rem; word-break: break-all; }
        .user-menu-role { font-size: 0.72rem; color: var(--muted); padding: 0 0.55rem 0.5rem; text-transform: capitalize; }
        .user-menu-panel hr { border: none; border-top: 1px solid var(--border-soft); margin: 0.3rem 0; }

        .main { flex: 1; min-width: 0; }
        .container { max-width: 1600px; margin: 0 auto; padding: 1.75rem 1.25rem 3rem; }

        .card {
            background: var(--card); border: 1px solid var(--border); border-radius: 14px;
            padding: 1.35rem 1.4rem; margin-bottom: 1.25rem; box-shadow: var(--shadow-card);
        }
        table { width: 100%; border-collapse: collapse; }
        th, td { text-align: left; padding: 0.65rem 0.5rem; border-bottom: 1px solid var(--border-soft); font-size: 0.87rem; }
        th { color: var(--muted); font-weight: 600; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; }
        tbody tr:hover { background: var(--page-bg); }
        td.num, th.num, .num-figure { font-family: 'IBM Plex Mono', monospace; font-variant-numeric: tabular-nums; }

        .btn {
            display: inline-flex; align-items: center; justify-content: center; padding: 0.55rem 1.1rem; border-radius: 8px; border: 1px solid transparent;
            background: var(--brand); color: #fff; text-decoration: none; font-size: 0.85rem; cursor: pointer;
            font-family: inherit; font-weight: 600;
        }
        .btn:hover { background: var(--brand-dark); }
        .btn-outline { background: var(--card); color: var(--text); border-color: var(--border); font-weight: 500; }
        .btn-outline:hover { background: var(--page-bg); }
        .btn-danger { background: var(--danger); color: #fff; }
        .btn-danger:hover { background: #c62e2e; }
        .btn-sm { padding: 0.35rem 0.8rem; font-size: 0.8rem; }
        label { display: block; font-size: 0.83rem; font-weight: 600; margin-bottom: 0.3rem; color: var(--text); }
        input, select, textarea {
            width: 100%; padding: 0.55rem 0.7rem; border: 1px solid var(--border); border-radius: 8px;
            font-size: 0.88rem; font-family: inherit; margin-bottom: 0.9rem; background: var(--card); color: var(--text);
        }
        input:focus, select:focus, textarea:focus { outline: 2px solid var(--brand-light); outline-offset: 0; border-color: var(--brand); }
        .field-error { color: var(--danger); font-size: 0.8rem; margin-top: -0.6rem; margin-bottom: 0.7rem; }

        /* Searchable <select> replacement — see initSearchableSelects() in
           app-shell.js. The real <select> stays in the DOM (hidden) so the
           form still submits its value normally; this is just the visible
           search-as-you-type UI in front of it. */
        .searchable-dropdown {
            position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 30;
            background: var(--card); border: 1px solid var(--border); border-radius: 10px;
            box-shadow: var(--shadow-dd); max-height: 260px; overflow-y: auto; padding: 0.3rem;
        }
        .searchable-item { padding: 0.5rem 0.6rem; border-radius: 7px; font-size: 0.9rem; cursor: pointer; }
        .searchable-item:hover, .searchable-item.is-active { background: var(--page-bg); }
        .searchable-empty { padding: 0.5rem 0.6rem; font-size: 0.85rem; color: var(--muted); }

        /* ---- iOS-only fix: fields spilling past their margins on focus ----
           iOS Safari auto-zooms the whole page in when a tapped text field's
           rendered font-size is under 16px (Android has no such behavior,
           which is why this only showed up on iOS). The zoomed-in viewport
           doesn't reset cleanly afterwards, so inputs/selects appear to
           cross their container's margins. Raising the font-size to the
           16px threshold on phone/tablet widths — where this form is
           actually used on a phone — stops iOS from triggering that zoom,
           without changing how anything looks on desktop. */
        @media (max-width: 900px) {
            input, select, textarea { font-size: 16px; }
        }

        /* ---- Zoho-style form helpers: shaded top section, hint text, field+search-button rows ---- */
        .form-section-shaded {
            background: var(--page-bg); margin: -0.3rem -0.3rem 1.35rem; padding: 1.1rem 1.25rem 0.1rem;
            border-radius: 10px; border: 1px solid var(--border-soft);
        }
        .form-hint { font-size: 0.78rem; color: var(--muted); margin-top: -0.65rem; margin-bottom: 0.9rem; }
        .field-with-btn { display: flex; align-items: flex-start; gap: 0.5rem; }
        .field-with-btn > select, .field-with-btn > input { flex: 1; margin-bottom: 0; }
        .field-with-btn { margin-bottom: 0.9rem; }
        .field-btn {
            flex-shrink: 0; width: 38px; height: 38px; border-radius: 8px; border: 1px solid var(--brand);
            background: var(--brand); color: #fff; display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
        }
        .field-btn:hover { background: var(--brand-dark); }
        .radio-inline { display: flex; align-items: center; gap: 1.75rem; margin-bottom: 0.9rem; }
        .radio-inline label { display: flex; align-items: center; gap: 0.4rem; font-weight: 500; margin-bottom: 0; }
        .radio-inline input[type="radio"] { width: auto; margin: 0; }
        .amount-with-prefix { display: flex; margin-bottom: 0.9rem; }
        .amount-with-prefix select { width: auto; flex-shrink: 0; border-top-right-radius: 0; border-bottom-right-radius: 0; margin-bottom: 0; border-right: none; background: var(--page-bg); }
        .amount-with-prefix input { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-bottom: 0; }
        .checkbox-inline { display: flex; align-items: center; gap: 0.5rem; font-weight: 500; margin-bottom: 0; white-space: nowrap; }
        .checkbox-inline input { width: auto; margin: 0; }
        .status-active { color: var(--success); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .status-stopped { color: var(--warning); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .tag-link { color: var(--brand); font-weight: 600; font-size: 0.85rem; text-decoration: none; display: inline-flex; align-items: center; gap: 0.35rem; }
        .totals-panel { margin-left: auto; width: 100%; max-width: 320px; }
        .totals-panel .totals-row { display: flex; justify-content: space-between; align-items: center; padding: 0.5rem 0; font-size: 0.88rem; }
        .totals-panel .totals-row input { width: 130px; margin-bottom: 0; text-align: right; }
        .totals-panel .totals-row.total { border-top: 1px solid var(--border); font-weight: 700; font-size: 1.05rem; padding-top: 0.75rem; }

        /* ---- Full-document form panel (Zoho-style "New Quote" slide-over look) ---- */
        .doc-panel { padding: 0; overflow: hidden; }
        .doc-panel-head {
            display: flex; align-items: center; justify-content: space-between; gap: 1rem;
            padding: 1rem 1.4rem; border-bottom: 1px solid var(--border);
        }
        .doc-panel-head .title { display: flex; align-items: center; gap: 0.6rem; }
        .doc-panel-head .title svg { color: var(--brand-dark); flex-shrink: 0; }
        .doc-panel-head .title h1 { margin: 0; font-size: 1.15rem; }
        .doc-panel-head .panel-close {
            width: 30px; height: 30px; border-radius: 8px; border: none; background: transparent;
            color: var(--danger); display: inline-flex; align-items: center; justify-content: center;
            cursor: pointer; text-decoration: none; flex-shrink: 0;
        }
        .doc-panel-head .panel-close:hover { background: var(--danger-bg); }
        .doc-panel-body { padding: 1.4rem; }
        .doc-panel-foot {
            display: flex; align-items: center; gap: 0.6rem; padding: 1rem 1.4rem;
            border-top: 1px solid var(--border); background: var(--page-bg); flex-wrap: wrap;
        }
        .field-group { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
        @media (max-width: 720px) { .field-group { grid-template-columns: 1fr; } }
        .section-label {
            font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
            color: var(--muted); margin: 1.35rem 0 0.6rem;
        }

        /* ---- Zoho-style tabbed form section (Vendor/Customer "Other Details,
           Address, Contact Persons..." and Expense "Record Expense, Record
           Mileage, Bulk Add Expenses" tab rows) ---- */
        .zoho-tabs { border-bottom: 1px solid var(--border); margin: 0.4rem 0 1.25rem; display: flex; gap: 1.6rem; flex-wrap: wrap; }
        .zoho-tabs button {
            background: none; border: none; border-bottom: 2px solid transparent; cursor: pointer;
            padding: 0.6rem 0.1rem; font-size: 0.85rem; font-weight: 600; color: var(--muted); font-family: inherit;
        }
        .zoho-tabs button.active { color: var(--brand-dark); border-bottom-color: var(--brand); }
        .zoho-tabs button:hover { color: var(--text); }
        .zoho-tab-panel { display: none; }
        .zoho-tab-panel.active { display: block; }
        .zoho-combo { position: relative; }
        .zoho-combo input { padding-right: 2rem; }
        .zoho-combo::after {
            content: ""; position: absolute; right: 0.8rem; top: 0.9rem; width: 0; height: 0;
            border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 5px solid var(--muted); pointer-events: none;
        }
        .phone-group { display: flex; gap: 0; margin-bottom: 0.9rem; }
        .phone-group .phone-code {
            width: 68px; flex-shrink: 0; border-top-right-radius: 0; border-bottom-right-radius: 0;
            border-right: none; margin-bottom: 0; background: var(--page-bg); text-align: center;
        }
        .phone-group input[type="text"] { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-bottom: 0; }
        .repeater-table { width: 100%; border-collapse: collapse; margin-bottom: 0.75rem; }
        .repeater-table th { font-size: 0.68rem; padding: 0.4rem; }
        .repeater-table td { padding: 0.3rem; border-bottom: none; vertical-align: top; }
        .repeater-table input, .repeater-table select { margin-bottom: 0; }
        .repeater-remove {
            background: none; border: none; color: var(--danger); cursor: pointer; font-size: 1.1rem;
            width: 28px; height: 38px; display: inline-flex; align-items: center; justify-content: center;
        }
        .bulk-rows-table { width: 100%; border-collapse: separate; border-spacing: 0 0.4rem; }
        .bulk-rows-table th { font-size: 0.65rem; padding: 0.3rem 0.4rem; white-space: nowrap; }
        .bulk-rows-table td { padding: 0.2rem 0.4rem; border-bottom: none; }
        .bulk-rows-table input, .bulk-rows-table select { margin-bottom: 0; font-size: 0.8rem; padding: 0.4rem 0.5rem; }

        /* ---- Status badges ---- */
        .badge {
            display: inline-block; padding: 0.2rem 0.65rem; border-radius: 99px; font-size: 0.68rem; font-weight: 700;
            text-transform: uppercase; letter-spacing: 0.04em;
        }
        .badge-draft, .badge-unpaid { color: var(--muted); background: var(--border-soft); }
        .badge-sent, .badge-partial { color: var(--warning); background: var(--warning-bg); }
        .badge-accepted, .badge-paid, .badge-confirmed { color: var(--success); background: var(--success-bg); }
        .badge-declined, .badge-overdue, .badge-cancelled { color: var(--danger); background: var(--danger-bg); }
        .badge-expired, .badge-invoiced { color: var(--info); background: var(--info-bg); }
        .badge-pending_approval, .badge-pending_admin_approval { color: var(--info); background: var(--info-bg); }
        .badge-rejected { color: var(--danger); background: var(--danger-bg); }
        .badge-posted { color: var(--success); background: var(--success-bg); }
        .badge-approved { color: var(--success); background: var(--success-bg); }
        .badge-pending { color: var(--warning); background: var(--warning-bg); }
        .badge-signed { color: var(--success); background: var(--success-bg); }
        .badge-yet_to_be_billed { color: var(--muted); background: var(--border-soft); }
        .badge-partially_billed { color: var(--warning); background: var(--warning-bg); }
        .badge-billed { color: var(--success); background: var(--success-bg); }
        .badge-open { color: var(--warning); background: var(--warning-bg); }

        /* ---- Requisition priority tags ---- */
        .tag-priority {
            display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.2rem 0.6rem; border-radius: 6px;
            font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
        }
        .tag-priority::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
        .tag-priority-low { color: var(--muted); background: var(--border-soft); }
        .tag-priority-medium { color: var(--teal); background: var(--teal-bg); }
        .tag-priority-high { color: var(--warning); background: var(--warning-bg); }
        .tag-priority-urgent { color: var(--danger); background: var(--danger-bg); }

        /* ---- Requisitions: deliberately different from the invoice/PO
           "doc-sheet" print layout below — this is an internal request
           ticket, not a billing document, so it gets a card + stepper
           treatment instead of a letterhead sheet. ---- */
        .req-card {
            background: var(--card); border: 1px solid var(--border); border-radius: 14px;
            box-shadow: var(--shadow-card); overflow: hidden; margin-bottom: 1.25rem;
        }
        .req-card-head {
            padding: 1.1rem 1.4rem; border-bottom: 1px solid var(--border-soft);
            background: linear-gradient(135deg, var(--teal-bg) 0%, var(--card) 65%);
            display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; flex-wrap: wrap;
        }
        .req-card-head .req-id { font-size: 1.3rem; font-weight: 700; color: var(--text); display: flex; align-items: center; gap: 0.6rem; }
        .req-card-head .req-meta { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.5rem; }
        .req-card-head .req-chip {
            display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.2rem 0.6rem; border-radius: 6px;
            font-size: 0.72rem; color: var(--muted); background: var(--border-soft); font-weight: 600;
        }
        .req-body { padding: 1.4rem; }
        .req-purpose { background: var(--brand-lighter); border-radius: 10px; padding: 0.85rem 1rem; font-size: 0.88rem; margin-bottom: 1.25rem; }
        .req-purpose .label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); font-weight: 700; margin-bottom: 0.25rem; }

        /* Horizontal approval stepper — Requested -> HR -> Admin -> Approved */
        .req-stepper { display: flex; align-items: flex-start; margin-bottom: 1.5rem; }
        .req-step { flex: 1; text-align: center; position: relative; }
        .req-step:not(:first-child)::before {
            content: ''; position: absolute; top: 13px; left: -50%; width: 100%; height: 2px; background: var(--border);
        }
        .req-step.done:not(:first-child)::before { background: var(--success); }
        .req-step .dot {
            width: 28px; height: 28px; border-radius: 50%; background: var(--border-soft); color: var(--muted-soft);
            display: flex; align-items: center; justify-content: center; margin: 0 auto 0.4rem; font-weight: 700;
            font-size: 0.75rem; position: relative; z-index: 1; border: 2px solid var(--card);
        }
        .req-step.done .dot { background: var(--success); color: #fff; }
        .req-step.current .dot { background: var(--teal); color: #fff; }
        .req-step.rejected .dot { background: var(--danger); color: #fff; }
        .req-step .step-label { font-size: 0.72rem; font-weight: 600; color: var(--text); }
        .req-step .step-sub { font-size: 0.66rem; color: var(--muted-soft); margin-top: 0.1rem; }

        .req-items-table { width: 100%; border-collapse: collapse; margin-bottom: 1rem; }
        .req-items-table th {
            text-align: left; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted);
            padding: 0.5rem 0.6rem; border-bottom: 2px solid var(--border-soft);
        }
        .req-items-table td { padding: 0.6rem; border-bottom: 1px solid var(--border-soft); font-size: 0.88rem; }
        .req-items-table tbody tr:last-child td { border-bottom: none; }

        .req-convert-banner {
            display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap;
            background: var(--success-bg); border: 1px solid #c8ecd9; border-radius: 10px; padding: 0.9rem 1.1rem; margin-bottom: 1.25rem;
        }
        .req-convert-banner .msg { font-size: 0.88rem; color: var(--success); font-weight: 600; }
        .req-convert-banner .msg span { display: block; font-size: 0.76rem; color: var(--text); font-weight: 400; margin-top: 0.15rem; }

        .flash { padding: 0.75rem 1rem; border-radius: 10px; margin-bottom: 1rem; font-size: 0.88rem; border: 1px solid transparent; }
        .flash-status { background: var(--success-bg); color: var(--success); border-color: #c8ecd9; }
        .flash-error { background: var(--danger-bg); color: var(--danger); border-color: #f5cccc; }

        /* ---- Document letterhead: logo + title on invoice/quotation/receipt pages ---- */
        .doc-letterhead {
            display: flex; align-items: center; justify-content: space-between; gap: 1rem;
            padding-bottom: 1rem; margin-bottom: 1.25rem; border-bottom: 2px solid var(--brand);
        }
        .doc-letterhead img { height: 38px; width: auto; display: block; }
        .doc-letterhead .doc-title { text-align: right; }
        .doc-letterhead .doc-title h1 { margin: 0 0 0.25rem; }

        /* ---- Key/value detail grid used across document detail panes
           (Customer, Against invoice, Amount, etc.) — auto-fit collapses to
           a single column on its own once there's no room for 180px+
           columns side by side, so no extra breakpoint is needed. ---- */
        .info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.7rem 1.5rem; }
        .info-grid dt { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); margin-bottom: 0.2rem; }
        .info-grid dd { margin: 0; font-size: 0.9rem; color: var(--text); word-break: break-word; }

        /* ---- Dashboard: stat cards with icon roundels ---- */
        .stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 0.75rem; margin-bottom: 1.5rem; }
        .stat {
            background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 0.85rem 0.95rem;
            display: flex; align-items: center; gap: 0.7rem; box-shadow: var(--shadow-card); min-width: 0;
        }
        .stat .icon-roundel {
            width: 22px; height: 22px; border-radius: 7px; display: flex; align-items: center; justify-content: center;
            flex-shrink: 0; box-shadow: inset 0 0 0 1px rgba(16,24,40,.04);
        }
        .stat .icon-roundel svg { width: 11px; height: 11px; }
        .stat > div:last-child { min-width: 0; }
        .stat .num {
            font-family: 'IBM Plex Mono', monospace; font-size: 1.05rem; font-weight: 600; font-variant-numeric: tabular-nums;
            line-height: 1.15; overflow-wrap: anywhere; word-break: break-word;
        }
        .stat .label { color: var(--muted); font-size: 0.72rem; margin-top: 0.15rem; font-weight: 500; }
        .stat-muted .icon-roundel { background: var(--border-soft); color: var(--muted); }
        .stat-info .icon-roundel { background: var(--info-bg); color: var(--info); }
        .stat-warning .icon-roundel { background: var(--warning-bg); color: var(--warning); }
        .stat-teal .icon-roundel { background: var(--teal-bg); color: var(--teal); }
        .stat-danger .icon-roundel { background: var(--danger-bg); color: var(--danger); }
        .stat-danger .num { color: var(--danger); }
        .stat-brand .icon-roundel { background: var(--brand-light); color: var(--brand-dark); }
        .stat-brand .num { color: var(--brand-darker); }
        .trend-badge {
            display: inline-block; font-family: 'IBM Plex Sans', sans-serif; font-size: 0.68rem; font-weight: 600;
            padding: 0.05rem 0.4rem; border-radius: 999px; vertical-align: middle; margin-left: 0.3rem;
        }
        .trend-badge.trend-up { background: var(--success-bg); color: var(--success); }
        .trend-badge.trend-down { background: var(--danger-bg); color: var(--danger); }

        .dash-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 1.25rem; }
        .dash-head h1 { margin: 0; }
        .dash-head .sub { color: var(--muted); font-size: 0.85rem; margin-top: 0.15rem; }
        .quick-actions .btn, .quick-actions .btn-outline { margin-left: 0.5rem; }
        .dash-grid { display: grid; grid-template-columns: 1.35fr 1fr; gap: 1.25rem; margin-bottom: 1.25rem; }
        @media (max-width: 900px) { .dash-grid { grid-template-columns: 1fr; } }
        /* Approval-activity row: sized-to-content, not stretched to match
           whichever panel happens to be taller — "Awaiting approval" is
           often empty/short and shouldn't inflate to match a long
           "Recently cleared" list (or vice versa). */
        .dash-grid-approvals { grid-template-columns: 1fr 1fr; align-items: start; }
        @media (max-width: 900px) { .dash-grid-approvals { grid-template-columns: 1fr; } }

        /* ---- Chart containers: fixed heights so canvases render at a sane, consistent
               size regardless of card width (Chart.js fills its parent). ---- */
        .chart-box { position: relative; width: 100%; height: 190px; }
        .chart-box-sm { height: 160px; }
        .chart-box-lg { height: 230px; }
        .doughnut-wrap { display: flex; align-items: center; justify-content: center; }
        .doughnut-box { position: relative; width: 100%; max-width: 170px; height: 170px; }
        .kpi-note { color: var(--muted-soft); font-size: 0.72rem; margin-top: 0.15rem; }
        .report-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 1.25rem; margin-bottom: 1.25rem; }
        @media (max-width: 900px) { .report-grid { grid-template-columns: 1fr; } }
        .legend-inline { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; margin-top: 0.75rem; font-size: 0.78rem; color: var(--muted); }
        .legend-inline span.dot { display: inline-block; width: 8px; height: 8px; border-radius: 99px; margin-right: 0.35rem; vertical-align: middle; }
        .chart-download-btn {
            width: 26px; height: 26px; border-radius: 7px; border: 1px solid var(--border); background: var(--card);
            color: var(--muted); cursor: pointer; font-size: 0.8rem; line-height: 1; display: inline-flex;
            align-items: center; justify-content: center; flex-shrink: 0;
        }
        .chart-download-btn:hover { background: var(--page-bg); color: var(--text); border-color: var(--muted-soft); }

        /* ---- Reports: time-range filter bar ---- */
        .range-bar {
            display: flex; align-items: center; flex-wrap: wrap; gap: 0.6rem 1rem; background: var(--card);
            border: 1px solid var(--border); border-radius: 12px; padding: 0.7rem 1rem; margin-bottom: 1.25rem;
            box-shadow: var(--shadow-card);
        }
        .range-bar-label { font-size: 0.83rem; font-weight: 600; color: var(--text); white-space: nowrap; }
        .range-bar-presets { display: flex; gap: 0.4rem; flex-wrap: wrap; }
        .range-pill {
            border: 1px solid var(--brand); background: var(--card); color: var(--brand-dark); border-radius: 99px;
            padding: 0.35rem 0.85rem; font-size: 0.8rem; font-weight: 600; cursor: pointer; font-family: inherit;
        }
        .range-pill:hover { background: var(--brand-lighter); }
        .range-pill.active { background: var(--brand); border-color: var(--brand); color: #fff; }
        .range-bar-custom { display: flex; align-items: center; gap: 0.5rem; }
        .range-bar-custom input[type="date"] {
            width: auto; margin-bottom: 0; padding: 0.4rem 0.6rem; font-size: 0.82rem;
        }
        .range-bar-custom span { color: var(--muted); font-size: 0.8rem; }
        .range-bar-custom .btn-outline { padding: 0.4rem 0.9rem; }
        .range-bar-summary { margin-left: auto; color: var(--muted); font-size: 0.82rem; white-space: nowrap; }
        @media (max-width: 900px) { .range-bar-summary { margin-left: 0; } }

        .callout-danger { border-color: #f3cccc; background: var(--danger-bg); }
        .callout-danger h2 { color: var(--danger); display: flex; align-items: center; gap: 0.45rem; }
        .callout-warning { border-color: #f5e2b8; background: var(--warning-bg); }
        .callout-warning h2 { color: var(--warning); display: flex; align-items: center; gap: 0.45rem; }

        .empty-note { color: var(--muted); font-size: 0.88rem; margin: 0.5rem 0 0; }
        .card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.9rem; }
        .card-head h2 { margin: 0; }
        .card-head .card-sub-link { font-size: 0.78rem; color: var(--muted); text-decoration: none; font-weight: 600; }
        .card-head .card-sub-link:hover { color: var(--brand-dark); }

        .activity-feed { list-style: none; margin: 0; padding: 0; }
        .activity-feed li {
            display: grid; grid-template-columns: auto 1fr auto auto; align-items: center; gap: 0.6rem;
            padding: 0.6rem 0; border-bottom: 1px solid var(--border-soft); font-size: 0.84rem;
        }
        .activity-feed li:last-child { border-bottom: none; }
        /* Variant used by the dashboard "Awaiting approval" / "Recently cleared"
           panels, which prefix each row with a red/green pulsing status dot.
           Extra vertical padding + a small row gap so entries read as
           distinct items rather than a cramped list. */
        .activity-feed li.with-dot { grid-template-columns: auto auto 1fr auto auto; padding: 0.95rem 0; }
        .activity-feed.feed-spaced li.with-dot + li.with-dot { margin-top: 0.15rem; }
        .activity-badge {
            font-size: 0.64rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
            padding: 0.18rem 0.55rem; border-radius: 99px; white-space: nowrap;
        }
        .activity-invoice { background: var(--info-bg); color: var(--info); }
        .activity-payment { background: var(--success-bg); color: var(--success); }
        .activity-quotation { background: var(--warning-bg); color: var(--warning); }
        .activity-sales-order { background: var(--teal-bg); color: var(--teal); }
        .activity-desc { color: var(--text); text-decoration: none; }
        .activity-desc:hover { text-decoration: underline; }
        .activity-meta { color: var(--muted); font-family: 'IBM Plex Mono', monospace; font-variant-numeric: tabular-nums; font-size: 0.8rem; }
        .activity-time { color: var(--muted-soft); font-size: 0.75rem; white-space: nowrap; }

        /* ---- Hero KPI card (brand-colored highlight) ---- */
        .hero-card {
            background: linear-gradient(135deg, var(--brand-dark), var(--brand-darker)); color: #fff; border-radius: 14px;
            padding: 1.4rem 1.4rem 1.2rem; display: flex; flex-direction: column; justify-content: space-between; min-height: 100%;
        }
        .hero-card .num { font-family: 'IBM Plex Mono', monospace; font-size: 1.5rem; font-weight: 600; overflow-wrap: anywhere; word-break: break-word; }
        .hero-card .label { font-size: 0.82rem; opacity: 0.85; margin-top: 0.15rem; }
        .hero-card svg.spark { width: 100%; height: 46px; margin-top: 0.9rem; display: block; }

        /* Row actions (Edit / PDF-Print / Convert, etc.) sit in one tight
           row rather than stacking — <details> dropdowns are block-level
           by default, which otherwise forces each onto its own line. */
        .row-actions { display: flex; align-items: center; justify-content: flex-end; gap: 0.35rem; flex-wrap: nowrap; white-space: nowrap; }
        .row-actions a, .row-actions button { margin-right: 0; flex-shrink: 0; }
        .row-actions .dd { flex-shrink: 0; }
        .locked-note { background: var(--warning-bg); border: 1px solid #f0dcae; color: #8a640d; padding: 0.6rem 0.9rem; border-radius: 8px; font-size: 0.875rem; margin-bottom: 1rem; }
        .text-right { text-align: right; }
        .lineitem-row { display: grid; grid-template-columns: 3fr 1fr 1fr 1fr auto; gap: 0.5rem; align-items: start; }

        /* Laravel's default pagination markup (unstyled Tailwind classes) — keep it tidy */
        .container nav[role="navigation"] { margin: 0.5rem 0 1.5rem; font-size: 0.85rem; color: var(--muted); }
        .container nav[role="navigation"] a, .container nav[role="navigation"] span { text-decoration: none; }

        /* ---- Zoho-style list header: title + New button + list card ---- */
        .list-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 1rem; }
        .list-head h1 { display: flex; align-items: center; gap: 0.35rem; margin: 0; }
        .list-head h1 .chev { color: var(--muted-soft); font-size: 0.75rem; }
        .list-actions { display: flex; align-items: center; gap: 0.5rem; }
        .list-card { padding: 0; overflow: hidden; }
        /* -webkit-overflow-scrolling: touch gives this real momentum
           scrolling on iOS Safari — without it, overflow-x: auto still
           technically works but the drag can feel like it isn't
           responding at all, which is what made a wide table (Customers,
           with 9 columns) look like its off-screen columns were just
           unreachable rather than a swipe away. The scroll-shadow
           gradient is the same trick as .lineitem-scroll elsewhere in
           this file: a soft edge fades in on whichever side still has
           more content, and fades out once you've scrolled all the way
           to that edge, so there's a visible hint that the table keeps
           going instead of just a hard, silent cut at the screen edge. */
        .list-card .table-scroll {
            overflow-x: auto; -webkit-overflow-scrolling: touch;
            background:
                linear-gradient(to right, var(--card-bg, #fff) 0%, rgba(255,255,255,0) 100%) left / 24px 100% no-repeat local,
                linear-gradient(to left, var(--card-bg, #fff) 0%, rgba(255,255,255,0) 100%) right / 24px 100% no-repeat local,
                linear-gradient(to right, rgba(20,25,35,0.12), rgba(20,25,35,0)) left / 10px 100% no-repeat scroll,
                linear-gradient(to left, rgba(20,25,35,0.12), rgba(20,25,35,0)) right / 10px 100% no-repeat scroll;
        }
        /* The "No records yet. Create one." row uses colspan to span every
           column, but on a table wider than the screen (common on mobile,
           where several columns force horizontal scroll) that row inherits
           the table's full scrollable width too — so the message renders
           off in the scrollable area instead of the visible screen, and can
           look clipped or oddly positioned depending on scroll position.
           Sticky-positioning it to the left edge of the scroll container
           keeps it pinned to the visible viewport regardless of the table's
           real width or current scroll offset. */
        .empty-row-cell {
            position: sticky; left: 0; width: 1px; white-space: normal;
        }
        .list-card table { width: auto; min-width: 100%; margin: 0; }
        .list-card th, .list-card td { white-space: nowrap; }
        .list-toolbar { display: flex; align-items: center; justify-content: space-between; padding: 0.75rem 1.1rem; border-bottom: 1px solid var(--border-soft); gap: 0.5rem; flex-wrap: wrap; }
        .list-toolbar .view-by { font-size: 0.8rem; color: var(--muted); display: flex; align-items: center; gap: 0.4rem; }
        .list-toolbar .view-by select { width: auto; margin: 0; padding: 0.3rem 0.55rem; font-size: 0.8rem; }

        /* Sort: a small icon button that IS the <select>, not a button next
           to one. .list-sort-icon is purely decorative (pointer-events:
           none) and sits under the real <select>, which is stretched to
           fill the same 32x32 box at opacity: 0 — so the tap target is
           always the real control. Tapping it opens the browser's normal
           native option picker, full text and all ("Date Created (Newest
           first)", etc) — nothing about the options themselves is
           shortened, only the closed button is icon-sized. */
        .list-sort { position: relative; width: 32px; height: 32px; flex: 0 0 auto; }
        .list-sort-icon {
            position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
            border: 1px solid var(--border); border-radius: 7px; background: var(--card); color: var(--muted-soft); pointer-events: none;
        }
        .list-sort select {
            position: absolute; inset: 0; width: 100%; height: 100%; border: none; margin: 0; padding: 0;
            background: none; color: var(--text); opacity: 0; cursor: pointer;
        }
        .list-sort:focus-within .list-sort-icon { border-color: var(--brand); }

        /* Search: starts as the same small icon button, and expands into a
           real text input only once tapped (JS toggles .is-open — see
           wireUpListCard() in app-shell.js) or once it holds a query, so a
           filter someone already typed stays visible/obviously active
           instead of hiding itself. Collapses back to the icon on blur
           when empty. */
        .list-search { position: relative; display: flex; align-items: center; flex: 0 0 auto; }
        .list-search-toggle {
            flex: 0 0 auto; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
            border: 1px solid var(--border); border-radius: 7px; background: var(--card); color: var(--muted-soft); cursor: pointer; padding: 0;
        }
        .list-search-toggle:hover { background: var(--page-bg); }
        .list-search-input {
            width: 0; min-width: 0; height: 32px; border: none; border-radius: 7px; margin-left: 0;
            padding: 0; font-size: 0.85rem; color: var(--text); background: var(--card); box-sizing: border-box;
            opacity: 0; transition: width 0.16s ease, opacity 0.1s ease, padding 0.16s ease, margin-left 0.16s ease, border-color 0.1s ease;
        }
        .list-search.is-open .list-search-input {
            width: 190px; max-width: 45vw; opacity: 1; padding: 0 0.6rem; margin-left: 0.4rem; border: 1px solid var(--border);
        }
        .list-search-input:focus { outline: none; border-color: var(--brand); }
        @media (max-width: 480px) {
            .list-search.is-open .list-search-input { max-width: 38vw; }
        }
        .sr-only {
            position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
            overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
        }
        .list-card th, .list-card td { padding: 0.7rem 1.1rem; }
        .list-card thead th:first-child, .list-card tbody td:first-child { width: 2.2rem; padding-right: 0; }
        .list-card tbody tr td a { color: var(--brand-dark); text-decoration: none; font-weight: 600; }
        .list-card tbody tr td a:hover { text-decoration: underline; }
        .status-paid { color: var(--success); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .status-draft { color: var(--muted); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .status-open, .status-partial { color: var(--warning); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .status-overdue { color: var(--danger); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .status-pending_approval { color: var(--info); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .status-pending_admin_approval { color: var(--info); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .status-rejected { color: var(--danger); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .status-approved, .status-confirmed, .status-accepted { color: var(--brand-dark); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .status-cancelled, .status-declined { color: var(--muted); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; }
        .status-yet_to_be_billed { color: var(--muted); font-weight: 600; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.02em; }
        .status-partially_billed { color: var(--warning); font-weight: 600; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.02em; }
        .status-billed { color: var(--success); font-weight: 600; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.02em; }
        .list-footer { display: flex; align-items: center; justify-content: space-between; padding: 0.75rem 1.1rem; font-size: 0.82rem; color: var(--muted); flex-wrap: wrap; gap: 0.5rem; }
        .list-footer nav[role="navigation"] { margin: 0; }

        /* ---- Any row.clickable-row (list tables site-wide) is a real navigation
               target: pointer cursor on hover, click-anywhere-in-the-row handled
               by the delegated listener at the bottom of this file. ---- */
        .clickable-row { cursor: pointer; }

        /* ---- Zoho-style master-detail "split view": a scrollable list of
               documents on the left, the selected one's full detail on the
               right. Used by quotations/invoices/sales orders/sales receipts/
               payments-received show+index pages. ---- */
        .split-shell { display: flex; align-items: flex-start; gap: 1.1rem; }
        .split-sidebar {
            width: 310px; flex-shrink: 0; background: var(--card); border: 1px solid var(--border);
            border-radius: 14px; box-shadow: var(--shadow-card); overflow: hidden; position: sticky; top: 1.1rem;
        }
        .split-sidebar-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.85rem 1rem; border-bottom: 1px solid var(--border-soft); }
        .split-sidebar-head h1 { margin: 0; font-size: 1rem; }
        .split-sidebar-head .btn { padding: 0.35rem 0.65rem; font-size: 0.78rem; }
        .split-list { max-height: calc(100vh - 190px); overflow-y: auto; }
        .split-list-item { display: block; padding: 0.75rem 1rem; border-bottom: 1px solid var(--border-soft); border-left: 3px solid transparent; text-decoration: none; color: inherit; cursor: pointer; }
        .split-list-item:hover { background: var(--page-bg); }
        .split-list-item.active { background: var(--brand-lighter); border-left-color: var(--brand); }
        .split-list-item .row-top { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; font-weight: 700; font-size: 0.86rem; }
        .split-list-item .row-top .party { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .split-list-item .row-top .amt { font-family: 'IBM Plex Mono', monospace; white-space: nowrap; font-weight: 600; font-size: 0.82rem; }
        .split-list-item .row-meta { color: var(--muted); font-size: 0.76rem; margin-top: 0.2rem; }
        .split-list-item .row-status { margin-top: 0.4rem; }
        .split-list-empty { padding: 2rem 1.1rem; color: var(--muted); font-size: 0.85rem; text-align: center; }
        .split-list-empty .btn { margin-top: 0.75rem; }
        .split-list-foot { padding: 0.6rem 1rem; border-top: 1px solid var(--border-soft); font-size: 0.78rem; color: var(--muted); }
        .split-list.split-list-card { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.6rem; padding: 0.75rem; }
        .split-list.split-list-card .split-list-item { border: 1px solid var(--border-soft); border-radius: 10px; }

        /* ---- Small screens: the two-pane split view (quote list + detail)
               has no room for a fixed 310px sidebar next to the detail pane,
               so below this width it stacks into one column instead — the
               list on top (its own short scroll area), the open document
               below it, full width. Without this, the flex row above just
               overflows sideways and everything (list amounts, buttons,
               PDF preview) only shows a sliver at a time. ---- */
        @media (max-width: 1080px) {
            .split-shell { flex-direction: column; }
            .split-sidebar { width: 100%; position: static; max-height: none; }
            .split-list { max-height: 340px; }
            .split-detail { width: 100%; }
            .doc-sheet { padding: 1.1rem 1.1rem; }
            .doc-sheet-head { flex-wrap: wrap; }
            .doc-sheet-head .doc-id { text-align: left; }
            .doc-sheet table.items-table { display: block; overflow-x: auto; white-space: nowrap; }
            .pdf-frame { height: 70vh; min-height: 520px; }
        }

        .split-detail { flex: 1; min-width: 0; }
        .detail-topbar { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.9rem; }
        .detail-topbar .doc-num { font-size: 1.2rem; font-weight: 700; margin: 0; }
        .detail-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
        /* WhatsApp share button, sat right after "Share" — .detail-actions above
           already wraps, so on a narrow/phone screen this naturally drops onto
           its own line directly under Share instead of needing extra layout. */
        .btn-whatsapp { display: inline-flex; align-items: center; gap: 0.35rem; background: #25D366; border-color: #25D366; color: #fff; }
        .btn-whatsapp:hover { background: #1EBE59; border-color: #1EBE59; }
        .btn-whatsapp svg { flex-shrink: 0; }
        .detail-actions .dd { position: relative; }
        .detail-actions .dd summary { list-style: none; cursor: pointer; }
        .detail-actions .dd summary::-webkit-details-marker { display: none; }
        .detail-actions .dd[open] summary { }
        .detail-actions .dd-panel {
            position: absolute; right: 0; top: calc(100% + 6px); background: var(--card); border: 1px solid var(--border);
            border-radius: 10px; box-shadow: var(--shadow-dd); padding: 0.4rem; min-width: 200px; z-index: 25;
        }
        .detail-actions .dd-panel a, .detail-actions .dd-panel button {
            display: block; width: 100%; text-align: left; padding: 0.5rem 0.6rem; border-radius: 7px; border: none;
            background: none; font-size: 0.83rem; color: var(--text); cursor: pointer; text-decoration: none; font-family: inherit;
        }
        .detail-actions .dd-panel a:hover, .detail-actions .dd-panel button:hover { background: var(--page-bg); }
        .detail-actions .dd-panel form { margin: 0; }

        /* Smaller, more compact Edit/Mails/Share/View/PDF-Print row on
           phone screens — less horizontal space per button means more of
           them fit before wrapping, and anchor points sit further from
           the screen edges to begin with. */
        @media (max-width: 640px) {
            .detail-actions .btn, .detail-actions .dd > summary.btn {
                padding: 0.32rem 0.55rem;
                font-size: 0.75rem;
                gap: 0.2rem;
            }
        }

        /* Generic <details class="dd"> dropdown — same pattern as
           .detail-actions .dd above, usable anywhere (list toolbars, etc). */
        .dd { position: relative; }
        .dd summary { list-style: none; cursor: pointer; }
        .dd summary::-webkit-details-marker { display: none; }
        .dd-panel {
            position: absolute; right: 0; top: calc(100% + 6px); background: var(--card); border: 1px solid var(--border);
            border-radius: 10px; box-shadow: var(--shadow-dd); padding: 0.4rem; min-width: 210px; z-index: 25;
        }
        .dd-panel a, .dd-panel button {
            display: flex; align-items: center; gap: 0.55rem; width: 100%; text-align: left; padding: 0.5rem 0.6rem; border-radius: 7px; border: none;
            background: none; font-size: 0.83rem; color: var(--text); cursor: pointer; text-decoration: none; font-family: inherit;
        }
        .dd-panel a:hover, .dd-panel button:hover { background: var(--page-bg); }
        .dd-panel button:disabled { color: var(--muted-soft); cursor: not-allowed; }
        .dd-panel button:disabled:hover { background: none; }
        .dd-panel form { margin: 0; }
        .dd-panel .dd-hint { padding: 0.4rem 0.6rem 0.2rem; font-size: 0.72rem; color: var(--muted); }
        .dd-icon { flex-shrink: 0; width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

        /* Inline-editable field used for a payment's Reference # in the
           Payment History table (see bills/_detail.blade.php) — looks
           like plain text until you actually touch it, so the table
           doesn't read as one big form. The checkmark save button is
           hidden until the value is actually changed (see the matching
           'input' listener in app-shell.js) so it doesn't clutter every
           row that nobody's editing. */
        .inline-edit-form { display: flex; align-items: center; gap: 0.35rem; margin: 0; }
        .inline-edit-input {
            border: 1px solid transparent; background: none; padding: 0.2rem 0.35rem; margin: 0; border-radius: 5px;
            font: inherit; color: inherit; width: 9em; max-width: 100%;
        }
        .inline-edit-input:hover { background: var(--page-bg); }
        .inline-edit-input:focus { outline: none; border-color: var(--brand); background: var(--card); }
        .inline-edit-save {
            display: none; flex-shrink: 0; width: 22px; height: 22px; border-radius: 999px; border: none;
            background: var(--brand); color: #fff; font-size: 0.7rem; cursor: pointer; align-items: center; justify-content: center;
        }
        .inline-edit-form.is-dirty .inline-edit-save { display: flex; }

        /* Permanent fix for every dropdown panel above (Mails, PDF/Print,
           Convert, row "…" actions, etc — .dd-panel and
           .detail-actions .dd-panel both match here) on phone-width
           screens: fixed position with an equal safe margin from both
           edges, instead of anchored to the button with `right: 0`. A
           fixed 12px margin on both sides can never overflow either edge
           regardless of where the triggering button sits on the page —
           app-shell.js only sets `top` (from the button's own position);
           everything else here is a hard guarantee, not a per-case nudge.
           Applies on every page that uses this <details class="dd"> +
           .dd-panel pattern. */
        @media (max-width: 640px) {
            .dd-panel, .detail-actions .dd-panel {
                position: fixed;
                left: 0.75rem;
                right: 0.75rem;
                width: auto;
                min-width: 0;
                max-width: none;
                max-height: 70vh;
                overflow-y: auto;
            }
        }

        /* Toolbar icon buttons (view toggle, hide/show stats, etc). */
        .icon-btn-group { display: flex; align-items: center; gap: 0.35rem; }
        .icon-btn {
            display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px;
            border: 1px solid var(--border); border-radius: 8px; background: var(--card); color: var(--muted); cursor: pointer;
        }
        .icon-btn:hover { background: var(--page-bg); color: var(--text); }
        .icon-btn.active { background: var(--brand-lighter); border-color: var(--brand); color: var(--brand-dark); }
        .stats-toggle-row { display: flex; justify-content: flex-end; margin-bottom: 0.4rem; }
        .stats-toggle-row button {
            background: none; border: none; color: var(--muted); font-size: 0.78rem; cursor: pointer;
            display: flex; align-items: center; gap: 0.25rem; padding: 0.2rem 0.3rem;
        }
        .stats-toggle-row button:hover { color: var(--text); }

        /* Small centered modal used for quick-upload flows. */
        .modal-backdrop {
            display: none; position: fixed; inset: 0; background: rgba(20, 24, 32, 0.45); z-index: 60;
            align-items: center; justify-content: center; padding: 1rem;
        }
        .modal-backdrop.open { display: flex; }
        .modal-box { background: var(--card); border-radius: 12px; box-shadow: var(--shadow-dd); width: 100%; max-width: 420px; padding: 1.25rem; }
        .modal-box h2 { margin: 0 0 0.9rem; font-size: 1.05rem; }
        .modal-box .modal-actions { display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1rem; }
        .modal-close { background: none; border: none; color: var(--muted); cursor: pointer; float: right; font-size: 1.1rem; line-height: 1; }

        /* Status strips and the "What's next?" box: plain, uncoloured,
           square-cornered panels (same card surface as the rest of the
           page, a thin neutral border and no tinted background). */
        .approved-strip, .pending-strip, .rejected-strip {
            display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
            background: var(--card); color: var(--text);
            border: 1px solid var(--border); border-radius: 0;
            padding: 0.65rem 0.95rem; font-size: 0.85rem; margin-bottom: 0.85rem;
        }
        .approved-strip > span:first-child, .pending-strip > span:first-child, .rejected-strip > span:first-child { color: var(--muted); }
        .approved-strip a, .pending-strip a, .rejected-strip a { color: inherit; text-decoration: underline; font-weight: 600; }

        /* "Approved by ..." statement: shown as a pop-up in the top-right
           corner that fades away on its own after a few seconds. */
        .approved-strip.approved-toast {
            position: fixed; top: 76px; right: 20px; z-index: 300; margin: 0; max-width: min(420px, calc(100vw - 32px));
            box-shadow: var(--shadow-dd); pointer-events: none;
            animation: approvedToast 5.5s ease forwards; flex-wrap: nowrap; align-items: flex-start;
        }
        @keyframes approvedToast {
            0%   { opacity: 0; transform: translateY(-8px); visibility: visible; }
            8%   { opacity: 1; transform: translateY(0); }
            82%  { opacity: 1; transform: translateY(0); }
            100% { opacity: 0; transform: translateY(-8px); visibility: hidden; }
        }
        @media (max-width: 640px) {
            .approved-strip.approved-toast { top: auto; bottom: 16px; right: 16px; left: 16px; max-width: none; }
        }

        .whats-next {
            background: var(--card); border: 1px solid var(--border); border-radius: 0;
            padding: 0.75rem 0.95rem; margin-bottom: 0.85rem; font-size: 0.85rem; color: var(--text);
            display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; justify-content: space-between;
        }
        .whats-next .msg strong { color: var(--muted); text-transform: uppercase; font-size: 0.7rem; letter-spacing: 0.06em; display: block; margin-bottom: 0.2rem; font-weight: 600; }
        .whats-next-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
        .whats-next-actions form { margin: 0; }

        .doc-tabs { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.85rem; flex-wrap: wrap; gap: 0.6rem; }
        .doc-tabs-left, .doc-tabs-right { display: flex; gap: 0.25rem; background: var(--border-soft); padding: 0.25rem; border-radius: 10px; }
        .doc-tabs-left button, .doc-tabs-right button {
            border: none; background: transparent; padding: 0.4rem 0.9rem; border-radius: 8px; font-size: 0.82rem;
            font-weight: 600; color: var(--muted); cursor: pointer; font-family: inherit;
        }
        .doc-tabs-left button.active, .doc-tabs-right button.active { background: var(--card); color: var(--text); box-shadow: var(--shadow-card); }

        .doc-sheet { position: relative; border: 1px solid var(--border); border-radius: 14px; padding: 1.75rem 2rem; background: var(--card); overflow: hidden; }
        .doc-sheet .ribbon {
            position: absolute; top: 16px; left: -46px; width: 180px; transform: rotate(-45deg); text-align: center;
            background: var(--success); color: #fff; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.06em;
            text-transform: uppercase; padding: 0.32rem 0; box-shadow: 0 2px 4px rgba(0,0,0,.15);
        }
        .doc-sheet-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; padding-bottom: 1rem; margin-bottom: 1.1rem; border-bottom: 2px solid var(--brand); }
        .doc-sheet-head .company img { height: 44px; width: auto; display: block; margin-bottom: 0.5rem; }
        .doc-sheet-head .company .addr { font-size: 0.78rem; color: var(--muted); line-height: 1.55; max-width: 320px; }
        .doc-sheet-head .doc-id { text-align: right; flex-shrink: 0; }
        .doc-sheet-head .doc-id h2 { margin: 0 0 0.15rem; font-size: 1.65rem; color: var(--brand-dark); letter-spacing: 0.03em; }
        .doc-sheet-head .doc-id .docno { color: var(--muted); font-size: 0.85rem; }
        .doc-sheet-meta { display: flex; justify-content: space-between; gap: 1.5rem; margin: 1.1rem 0; flex-wrap: wrap; }
        .doc-sheet-meta .bill-to .label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); margin-bottom: 0.25rem; }
        .doc-sheet-meta .bill-to a { color: var(--brand-dark); font-weight: 700; text-decoration: none; font-size: 0.95rem; }
        .doc-sheet-meta .bill-to a:hover { text-decoration: underline; }
        .doc-sheet-meta .meta-fields { text-align: right; font-size: 0.83rem; color: var(--text); }
        .doc-sheet-meta .meta-fields .mf-row { margin-bottom: 0.2rem; }
        .doc-sheet-meta .meta-fields .mf-row strong { color: var(--muted); font-weight: 600; margin-right: 0.3rem; }
        .mf-row { margin-bottom: 0.35rem; font-size: 0.85rem; color: var(--text); }
        .mf-row strong { color: var(--muted); font-weight: 600; margin-right: 0.3rem; }
        .doc-sheet table.items-table { width: 100%; border-collapse: collapse; margin-top: 0.5rem; }
        .doc-sheet table.items-table thead th { background: var(--brand); color: #fff; text-transform: none; font-size: 0.76rem; padding: 0.55rem 0.7rem; border: none; }
        .doc-sheet table.items-table td { padding: 0.6rem 0.7rem; font-size: 0.85rem; }
        .doc-sheet .totals-block { margin-left: auto; width: 100%; max-width: 280px; margin-top: 0.75rem; }
        .doc-sheet .totals-block .t-row { display: flex; justify-content: space-between; padding: 0.3rem 0; font-size: 0.85rem; }
        .doc-sheet .totals-block .t-row.grand { border-top: 1px solid var(--border); font-weight: 700; font-size: 1.05rem; padding-top: 0.6rem; margin-top: 0.2rem; }
        .doc-sheet .words-line { font-size: 0.78rem; color: var(--muted); margin-top: 0.5rem; text-align: right; }
        .doc-sheet .notes-block { margin-top: 1.35rem; font-size: 0.83rem; color: var(--muted); }
        /* overflow was "hidden" for the old transform-zoom toolbar (it had to
           clip the scaled iframe). It's "visible" now — nothing here scales
           anymore, real pinch-zoom happens on the PDF itself via the page's
           viewport meta, so there's nothing that needs clipping, and hidden
           would only risk cutting off content on tall renders. */
        .pdf-frame-wrap { border: 1px solid var(--border); border-radius: 14px; overflow: visible; position: relative; }
        /* touch-action: pinch-zoom keeps the browser from swallowing a
           two-finger gesture that starts on the iframe itself, so pinching
           directly on the embedded PDF works the same as pinching the page
           around it. */
        .pdf-frame { width: 100%; height: 92vh; min-height: 900px; display: block; border: none; touch-action: pinch-zoom; }
        .pdf-open-pill {
            position: sticky; top: 0.6rem; z-index: 6; display: flex; align-items: center; gap: 0.3rem;
            width: fit-content; margin: 0.6rem 0.6rem 0 auto; background: var(--card); border: 1px solid var(--border);
            border-radius: 999px; padding: 0.4rem 0.85rem; box-shadow: var(--shadow-pop);
            font-size: 0.78rem; font-weight: 600; color: var(--text); text-decoration: none; cursor: pointer;
        }
        .pdf-open-pill:hover { background: var(--page-bg); }
        .activity-mini { list-style: none; margin: 0; padding: 0; }
        .activity-mini li { display: flex; gap: 0.7rem; padding: 0.7rem 0; border-bottom: 1px solid var(--border-soft); font-size: 0.85rem; }
        .activity-mini li:last-child { border-bottom: none; }
        .activity-mini .dot { width: 8px; height: 8px; border-radius: 99px; background: var(--brand); margin-top: 0.4rem; flex-shrink: 0; }
        .activity-mini .when { color: var(--muted-soft); font-size: 0.75rem; display: block; margin-top: 0.1rem; }

        /* ---- Mobile safety net (applies site-wide) ----
           1) Item-entry tables (Quotations/Invoices/Sales Orders/Bills/
              Purchase Orders/Credit Notes "Item Table") use a fixed
              multi-column CSS grid per row that has no room to breathe on a
              phone — rather than squeezing every field down to a sliver,
              wrap the header row + #line-items in a horizontally scrolling
              strip (JS below) so each field keeps a sane minimum width and
              the row scrolls instead of collapsing.
           2) Any other plain <table> inside a .card (dashboard summaries,
              permissions matrix, bulk-add rows, contact-person repeater,
              approval/send-history logs, etc.) gets the same horizontal-
              scroll treatment instead of overflowing the page sideways.
              Tables that already manage their own scrolling (.list-card's
              .table-scroll wrapper, the printable .doc-sheet items-table)
              are explicitly excluded so they keep their existing behavior. */
        .lineitem-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
        .lineitem-scroll [class*="lineitem-row"] { min-width: 640px; }
        @media (max-width: 700px) {
            .card table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
            .list-card table { display: table; }
            .doc-sheet table.items-table { display: block; }
            .perm-table, .bulk-rows-table, .repeater-table { white-space: nowrap; }
        }

        .pwa-install-banner {
            position: fixed; left: 1rem; right: 1rem; bottom: 1rem; z-index: 500; max-width: 480px; margin: 0 auto;
            background: var(--card); border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow-card);
            padding: 0.9rem 1rem; display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap;
        }
        .pwa-install-text { display: flex; flex-direction: column; font-size: 0.85rem; }
        .pwa-install-text strong { font-size: 0.92rem; }
        .pwa-install-text span { color: var(--muted); margin-top: 0.15rem; }
        .pwa-install-actions { display: flex; gap: 0.5rem; flex-shrink: 0; }

/* Pagination — replaces Laravel's default Tailwind-based ->links() markup,
   which rendered completely unstyled since this app doesn't load Tailwind.
   Horizontally scrollable so a page with many numbered links never spills
   off a phone screen; see resources/views/vendor/pagination/custom*.blade.php. */
.pagination-nav { margin-top: 1rem; }
.pagination-scroll {
    display: flex;
    gap: 4px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 2px;
}
.pagination-scroll .page-link {
    flex: 0 0 auto;
    min-width: 36px;
    text-align: center;
    padding: 6px 10px;
    border: 1px solid var(--border, #ddd);
    border-radius: 6px;
    font-size: 0.85rem;
    color: inherit;
    text-decoration: none;
    background: var(--card);
}
.pagination-scroll .page-link.active {
    background: var(--brand, #4AAE33);
    color: #fff;
    border-color: var(--brand, #4AAE33);
}
.pagination-scroll .page-link.disabled {
    opacity: 0.4;
    pointer-events: none;
}
.pagination-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem 1rem;
    justify-content: space-between;
}
.pagination-nav .pagination-scroll { flex: 1 1 auto; min-width: 0; }
.pagination-goto, .pagination-per-page {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.82rem;
    color: var(--muted, #767e8c);
    white-space: nowrap;
}
.pagination-goto input[type="number"] {
    width: 4.2em;
    padding: 4px 6px;
    border: 1px solid var(--border, #ddd);
    border-radius: 6px;
    font-size: 0.85rem;
    text-align: center;
}
.pagination-per-page select {
    padding: 4px 6px;
    border: 1px solid var(--border, #ddd);
    border-radius: 6px;
    font-size: 0.85rem;
    background: var(--card);
}

/* Every "record a payment/expense/refund" style action form across the
   app (Bills, Invoices, Quotations, Sales/Purchase Orders, Receipts,
   Expenses...) uses an inline `display: grid; grid-template-columns:
   1fr 1fr ... auto` layout with no mobile fallback, which is what made
   the Record-Expense row and similar forms overflow/clip on a phone.
   Rather than patch each of the ~11 places this pattern is copy-pasted,
   one rule collapses all of them to a single stacked column below
   640px. This deliberately does NOT touch .lineitem-row (item-table
   rows use their own horizontal-scroll treatment instead, since
   stacking one field per line wouldn't make sense for those). */
@media (max-width: 640px) {
    [style*="display: grid"] {
        grid-template-columns: 1fr !important;
    }
    /* These buttons had margin-top:1.6rem to align with input baselines
       in the desktop grid row — once stacked to one column above, that
       margin just leaves an odd gap above the button instead. */
    button[style*="margin-top: 1.6rem"] {
        margin-top: 0.5rem !important;
    }
}

/* Client form's "Other Details / Address / Contact Persons / Custom
   Fields / Reporting Tags / Remarks" tab row — was a plain unwrapped
   flex row with no CSS at all, so on a phone the later tabs (Reporting
   Tags, Remarks) got clipped off the right edge instead of being
   reachable. Same horizontal-scroll-strip treatment as the pagination
   and line-item fixes: it scrolls within its own bounds now instead of
   pushing the whole page wider. Shows up wherever this client form is
   used, including the quick-add-customer flow inside quotation/invoice
   creation, not just the main Clients page. */
.client-tabs-scroll {
    display: flex;
    gap: 1.5rem;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    white-space: nowrap;
}
.client-tabs-scroll .tab-link {
    flex: 0 0 auto;
}

/* ---- Approval status button + pop-up (components/approval-popup) ---- */
.approval-btn { display: inline-flex; align-items: center; gap: 0.35rem; }
.approval-state {
    font-size: 0.7rem; font-weight: 600; color: var(--muted);
    border-left: 1px solid var(--border); padding-left: 0.4rem; margin-left: 0.1rem;
}
.approval-btn.needs-attention { border-color: var(--text); }
.approval-btn.needs-attention .approval-state { color: var(--text); }
.approval-btn.needs-attention .approval-state::before {
    content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
    background: var(--brand-red); margin-right: 0.3rem; vertical-align: 1px;
}
.approval-pop {
    position: fixed; inset: 0; z-index: 400; background: rgba(16, 24, 40, 0.35);
    display: flex; align-items: flex-start; justify-content: center; padding: 10vh 1rem 1rem;
}
.approval-pop[hidden] { display: none; }
.approval-pop-box {
    background: var(--card); color: var(--text); border: 1px solid var(--border); border-radius: 0;
    box-shadow: var(--shadow-dd); width: 100%; max-width: 480px; max-height: 80vh; overflow: auto;
}
.approval-pop-head {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    padding: 0.75rem 1rem; border-bottom: 1px solid var(--border); font-size: 0.92rem;
    position: sticky; top: 0; background: var(--card);
}
.approval-pop-close { background: none; border: none; font-size: 1.35rem; line-height: 1; color: var(--muted); cursor: pointer; padding: 0 0.2rem; }
.approval-pop-close:hover { color: var(--text); }
.approval-pop-body { padding: 0.9rem 1rem 1rem; font-size: 0.85rem; }
.approval-pop-summary { margin: 0 0 0.6rem; color: var(--muted); }
.approval-pop-table { width: 100%; margin: 0; }
.approval-pop-table td { padding: 0.45rem 0.2rem; font-size: 0.84rem; }
.approval-pop-h { font-size: 0.82rem; margin: 1.1rem 0 0.5rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); font-weight: 600; }
.approval-pop-body textarea { min-height: 60px; }
.approval-pop-body select { width: 100%; }
html.approval-pop-open { overflow: hidden; }
@media (max-width: 640px) {
    .approval-pop { padding: 0; align-items: flex-end; }
    .approval-pop-box { max-width: none; max-height: 85vh; }
}

/* ---- Document top bar: title, then ONE tidy row of equal-height buttons ---- */
.detail-topbar { align-items: center; row-gap: 0.6rem; }
.detail-topbar .doc-num { white-space: nowrap; }
.detail-actions { flex-wrap: nowrap; gap: 0.45rem; margin-left: auto; }
.detail-actions > *, .detail-actions > form { flex-shrink: 0; margin: 0; }
.detail-actions .btn, .detail-actions .dd > summary.btn, .detail-actions .approval-btn {
    box-sizing: border-box; height: 34px; display: inline-flex; align-items: center; justify-content: center;
    gap: 0.3rem; padding: 0 0.8rem; line-height: 1; white-space: nowrap; vertical-align: middle;
}
/* Narrow desktop panes (sidebar + list + detail side by side): let the row
   wrap rather than spill out of the pane. */
@media (min-width: 641px) and (max-width: 1180px) {
    .detail-actions { flex-wrap: wrap; }
}
/* Phones: title on its own line, then every button on ONE line that always
   fits the screen width: compact buttons that share the space, and only if
   a phone is very narrow does a long label shorten with "…" (never spills
   off the edge, never scrolls sideways). */
@media (max-width: 640px) {
    .detail-topbar { flex-direction: column; align-items: stretch; }
    .detail-actions { margin-left: 0; width: 100%; flex-wrap: nowrap; gap: 0.3rem; overflow: visible; }
    .detail-actions > *, .detail-actions > form { flex: 1 1 auto; min-width: 0; }
    .detail-actions > form > .btn, .detail-actions > .dd > summary.btn { width: 100%; }
    .detail-actions .btn, .detail-actions .dd > summary.btn, .detail-actions .approval-btn {
        height: 32px; padding: 0 0.45rem; font-size: 0.72rem; gap: 0.2rem; min-width: 0;
        overflow: hidden; text-overflow: ellipsis;
    }
    /* Buttons that are themselves the row items size from their label... */
    .detail-actions > .btn, .detail-actions > .approval-btn { width: auto; }
    /* ...while buttons wrapped in a <form> or drop-down fill that wrapper. */
    .detail-actions > form > .btn, .detail-actions > .dd > summary.btn { width: 100%; }
    .detail-actions > .dd { display: flex; }
    .detail-actions .approval-btn svg { display: none; }
    .detail-actions .approval-btn .approval-state { display: none; }
    .detail-actions .approval-btn.needs-attention::after {
        content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--brand-red); flex-shrink: 0;
    }
}
