
        :root {
            --bg: #0f1117;
            --surface: #1a1d27;
            --surface2: #242836;
            --border: #2e3346;
            /* Brightened a step: #e4e6f0 → #eef0f8 (regular) and
               #8b90a5 → #a3a8bd (dim) so paragraphs and labels read
               more clearly against the dark backdrop without going
               full pure-white. */
            --text: #eef0f8;
            --text-dim: #a3a8bd;
            --accent: #4f8cff;
            --accent-dim: #2a4a8a;
            --green: #34d399;
            --yellow: #fbbf24;
            --red: #f87171;
            --orange: #fb923c;
            --purple: #a78bfa;
            --cell-bg: #1e2130;
            --cell-border: #3a4058;
            --row-alt: #1b1f32;
            --row-hover: #252a3e;
            --grid-header-bg: #2d3348;
            --grid-header-text: #c4c9db;
            --grid-border: #4a5568;
            --scrollbar-thumb: #3a3f50;
            --context-bg: #242836;
            --input-bg: #0f1117;
            /* --card-bg sits one step deeper than --surface so nested
               panels and tables read as elevated cards. Hard-coded in
               27+ inline styles as the var(--card-bg, #0f0f1e) fallback;
               defining it here lets light mode override that fallback. */
            --card-bg: #0f0f1e;
            --bg-dark: #0a0c12;
            --shadow: rgba(0,0,0,0.3);
            --overlay-light: rgba(255,255,255,0.06);
        }

        body.light-mode {
            --bg: #f0f2f5;
            --surface: #ffffff;
            --surface2: #e8eaef;
            --border: #d1d5db;
            /* Darkened a step for better contrast against the light bg.
               --text: #111827 → #0a0e15 (almost-black) so body copy
               carries more weight; --text-dim: #4b5563 → #374151 so
               muted labels stay readable instead of fading out. */
            --text: #0a0e15;
            --text-dim: #374151;
            --accent: #2563eb;
            --accent-dim: #93b4f5;
            --green: #059669;
            --yellow: #d97706;
            --red: #dc2626;
            --orange: #ea580c;
            --purple: #7c3aed;
            --cell-bg: #ffffff;
            --cell-border: #d1d5db;
            --row-alt: #f9fafb;
            --row-hover: #f3f4f6;
            --grid-header-bg: #e5e7eb;
            --grid-header-text: #1f2937;
            --grid-border: #d1d5db;
            --scrollbar-thumb: #9ca3af;
            --context-bg: #ffffff;
            --input-bg: #ffffff;
            /* Light-mode --card-bg is white so nested cards / tables /
               inputs that hardcoded var(--card-bg, #0f0f1e) become
               readable instead of falling back to the dark literal. */
            --card-bg: #ffffff;
            --bg-dark: #e5e7eb;
            --shadow: rgba(0,0,0,0.1);
            --overlay-light: rgba(0,0,0,0.04);
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
            background: var(--bg);
            color: var(--text);
            line-height: 1.6;
        }

        /* ── Global dark-mode scrollbars ─────────────────────────
           Match the styled scrollbars used in the workspace/Excel
           grid, applied to every scrollable region. Light mode
           keeps the OS-default chrome. */
        body:not(.light-mode) {
            scrollbar-width: thin;
            scrollbar-color: var(--scrollbar-thumb) var(--surface);
        }
        body:not(.light-mode) ::-webkit-scrollbar {
            width: 10px;
            height: 10px;
        }
        body:not(.light-mode) ::-webkit-scrollbar-track {
            background: var(--surface);
        }
        body:not(.light-mode) ::-webkit-scrollbar-thumb {
            background: var(--scrollbar-thumb);
            border-radius: 5px;
            border: 2px solid var(--surface);
        }
        body:not(.light-mode) ::-webkit-scrollbar-thumb:hover {
            background: #4a5168;
        }
        body:not(.light-mode) ::-webkit-scrollbar-corner {
            background: var(--surface);
        }

        /* ── Light-mode AI panel readability ────────────────────
           The WIP Assistant uses rgba(255,255,255, 0.02–0.08) inline
           styles to draw subtle card chips on its dark surface. In
           light mode those backgrounds become invisible on the white
           panel. Override the inline styles via higher-specificity
           rules so chips, presets, and the input pill stay legible.
           Inline-style precedence is matched by id-targeted rules
           with !important. */
        body.light-mode #agx-ai-panel #ai-input-pill {
            background: var(--surface2, #f1f5f9) !important;
            border-color: var(--border, #d1d5db) !important;
        }
        body.light-mode #agx-ai-panel #ai-input-pill:focus-within {
            background: #fff !important;
            border-color: var(--accent, #2563eb) !important;
        }
        body.light-mode #agx-ai-panel #ai-presets {
            background: var(--surface2, #f1f5f9) !important;
        }
        body.light-mode #agx-ai-panel #ai-clear {
            background: var(--surface2, #f1f5f9) !important;
            border-color: var(--border, #d1d5db) !important;
            color: var(--text-dim, #4b5563) !important;
        }
        /* Chips inside the panel: tool-call cards, attached files,
           applied-edit cards, citation pills. They share the
           rgba(255,255,255,0.04) hardcoded backdrop. Match by
           styled inline pattern via attribute starts-with. */
        body.light-mode #agx-ai-panel [style*="background:rgba(255,255,255,0.04)"],
        body.light-mode #agx-ai-panel [style*="background: rgba(255,255,255,0.04)"],
        body.light-mode #agx-ai-panel [style*="background:rgba(255,255,255,0.06)"],
        body.light-mode #agx-ai-panel [style*="background:rgba(255,255,255,0.08)"] {
            background: var(--surface2, #f1f5f9) !important;
            color: var(--text, #111827) !important;
        }
        /* Modal sharing-line and admin job-share rows use the same
           white-with-alpha trick. Same fix. */
        body.light-mode .modal-content [style*="background:rgba(255,255,255,0.04)"],
        body.light-mode .modal-content [style*="background: rgba(255,255,255,0.04)"],
        body.light-mode .modal-content [style*="background:rgba(255,255,255,0.08)"] {
            background: var(--surface2, #f1f5f9) !important;
            color: var(--text, #111827) !important;
        }
        /* Estimate editor sticky header — light-mode cleanup. The dark-
           mode shadow/border treatment reads as a heavy boxed strip on
           a light background. Strip the drop shadow, soften the bottom
           edge to a hairline, and lighten the totals chips so they
           don't feel chunky against the cream backdrop. */
        body.light-mode #ee-header {
            box-shadow: 0 1px 0 rgba(0,0,0,0.04) !important;
            border-bottom-color: rgba(0,0,0,0.06) !important;
        }
        /* Totals chips inside the header — find them via their inline
           rgba(255,255,255,0.03) bg signature. Replace with a flat
           soft surface and a feather-weight border. */
        body.light-mode #ee-totals > div[style*="background:rgba(255,255,255,0.03)"],
        body.light-mode #ee-totals > div[style*="background: rgba(255,255,255,0.03)"] {
            background: rgba(0,0,0,0.02) !important;
            border-color: rgba(0,0,0,0.05) !important;
        }

        .container {
            display: flex;
            flex-direction: column;
            height: 100vh;
            overflow: hidden;
        }

        /* THEME TOGGLE */
        .theme-toggle {
            background: rgba(255,255,255,0.12);
            border: 1px solid rgba(255,255,255,0.2);
            color: #fff;
            border-radius: 50%;
            width: 22px;
            height: 22px;
            font-size: 12px;
            cursor: pointer;
            transition: background 0.15s;
            line-height: 1;
            padding: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
        }
        .theme-toggle:hover {
            background: rgba(255,255,255,0.25);
        }

        /* HEADER */
        /* Sleek single-row header. Down from ~130px (two rows + 72px
           logo) to a hard 46px so the workspace below gets more
           vertical room. Gradient + 1px green hairline preserved
           because the user wanted that fade kept. */
        header {
            background: linear-gradient(135deg, #0d1f12 0%, #14351d 40%, #1B8541 100%);
            border-bottom: 1px solid #3B8542;
            padding: 0 24px;
            position: sticky;
            top: 0;
            z-index: 100;
            height: 46px;
        }

        .header-content {
            max-width: 1600px;
            margin: 0 auto;
            display: flex;
            align-items: center;
            gap: 24px;
            height: 100%;
        }

        /* Logo lockup. 26px is small enough to share the row with
           tabs without dominating, large enough to read clearly. */
        .header-brand {
            display: flex;
            align-items: center;
            text-decoration: none;
            flex: 0 0 auto;
        }
        .header-logo {
            height: 26px;
            width: auto;
            display: block;
        }

        /* Right cluster — pushes to the far right via flex auto-margin. */
        .header-user-menu {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-left: auto;
            flex: 0 0 auto;
        }
        .header-user-menu #user-name {
            font-size: 11px;
            color: rgba(255, 255, 255, 0.75);
            font-weight: 500;
            white-space: nowrap;
        }
        .header-user-menu #user-role-badge {
            font-size: 9px;
            padding: 2px 7px;
            border-radius: 10px;
            background: rgba(255, 255, 255, 0.10);
            color: rgba(255, 255, 255, 0.7);
            text-transform: uppercase;
            letter-spacing: 0.4px;
            font-weight: 600;
        }
        .header-user-menu #account-btn,
        .header-user-menu #logout-btn {
            font-size: 11px;
            padding: 4px 10px;
            border-radius: 6px;
            background: rgba(255, 255, 255, 0.08);
            border: 1px solid rgba(255, 255, 255, 0.12);
            color: rgba(255, 255, 255, 0.85);
            cursor: pointer;
            transition: background 0.12s, border-color 0.12s;
            white-space: nowrap;
        }
        .header-user-menu #account-btn:hover,
        .header-user-menu #logout-btn:hover {
            background: rgba(255, 255, 255, 0.16);
            border-color: rgba(255, 255, 255, 0.25);
        }

        /* NAVIGATION — inline with logo, height-filling so the active
           underline sits flush with the header's bottom edge for that
           "tab is part of the chrome" feel. */
        nav.tabs {
            display: flex;
            gap: 0;
            height: 100%;
            border-bottom: none;
            margin: 0;
            flex: 0 0 auto;
        }

        nav.tabs button {
            background: transparent;
            border: none;
            color: rgba(255, 255, 255, 0.55);
            padding: 0 16px;
            height: 100%;
            cursor: pointer;
            font-size: 13px;
            font-weight: 500;
            position: relative;
            transition: color 0.15s;
            white-space: nowrap;
        }

        nav.tabs button:hover {
            color: rgba(255, 255, 255, 0.95);
        }

        /* Active state — text color only. The visual indicator is a
           single .agx-tab-slider bar wired by tab-slider.js that
           floats across the whole bar to track the active tab. */
        nav.tabs button.active {
            color: #5ddb7e;
            font-weight: 600;
        }


        /* MAIN CONTENT */
        main {
            flex: 1;
            overflow-y: auto;
            /* Padding lives on .main-inner instead of main itself so
               position:sticky descendants (the estimate editor and lead
               detail headers) can pin flush to the top of the scroll
               viewport. With padding here, sticky:top:0 anchors at the
               inside edge of the padding, leaving a strip where scroll
               content would bleed through above the sticky element. */
        }

        .main-inner {
            max-width: 1600px;
            margin: 0 auto;
            width: 100%;
            padding: 30px;
        }

        .tab-content {
            display: none;
        }

        .tab-content.active {
            display: block;
        }

        /* Read-only mode for job detail when the current PM doesn't own the job. */

        /* Form controls always disabled (typing is meaningless if save is blocked). */
        .read-only-mode input:not([type=button]):not([type=hidden]),
        .read-only-mode select,
        .read-only-mode textarea {
            pointer-events: none !important;
            background-color: rgba(255,255,255,0.04) !important;
            opacity: 0.6;
        }

        /* The workspace (left-side spreadsheet/cell editor) becomes entirely
           non-interactive but stays at full visual fidelity — the user can
           still read formulas and cell content, just can't edit them. */
        .read-only-mode .ws-col-left {
            pointer-events: none !important;
        }

        /* Disable every button in the detail view by default... */
        .read-only-mode button {
            pointer-events: none !important;
            opacity: 0.4 !important;
            cursor: not-allowed !important;
        }
        /* ...except the navigation whitelist: Back to WIP, sub-tab switcher
           (both legacy .sub-tab-btn-job and workspace-layout .ws-right-tab),
           card collapse arrows (rendered as plain divs/spans, not buttons,
           so they're never blocked), and any escape-hatch element with
           [data-readonly-allowed]. Modal buttons stay enabled so any modal
           that does open can still be closed. */
        .read-only-mode .job-detail-header button,
        .read-only-mode .sub-tab-btn-job,
        .read-only-mode .ws-right-tab,
        .read-only-mode .card-toggle,
        .read-only-mode button[data-readonly-allowed],
        .read-only-mode .modal button {
            pointer-events: auto !important;
            opacity: 1 !important;
            cursor: pointer !important;
        }
        /* Native [disabled] applied via the JS hardening below — this just
           keeps it visually consistent with the CSS-disabled state. */
        .read-only-mode button[disabled] {
            pointer-events: none !important;
            opacity: 0.4 !important;
            cursor: not-allowed !important;
        }

        /* CARDS */
        .card {
            background: var(--surface);
            border: 1px solid var(--border);
            border-radius: 8px;
            padding: 12px 14px;
            margin-bottom: 12px;
        }

        /* BUTTONS */
        /* Button system — default = subtle neutral. Variants: .primary
           (green accent for the main action), .secondary (muted, used for
           Cancel/Refresh), .danger (red, for destructive actions),
           .ghost (transparent, for tertiary), .small (compact size). */
        button {
            background: rgba(255, 255, 255, 0.04);
            color: var(--text);
            border: 1px solid var(--border);
            padding: 5px 10px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 12px;
            font-weight: 500;
            transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 6px;
            line-height: 1.3;
            font-family: inherit;
            white-space: nowrap;
        }
        button:hover {
            background: rgba(255, 255, 255, 0.06);
            border-color: rgba(255, 255, 255, 0.18);
        }
        button:active:not(:disabled) { transform: translateY(1px); }
        button:focus-visible {
            outline: none;
            box-shadow: 0 0 0 2px rgba(93, 219, 126, 0.45);
        }
        button:disabled {
            opacity: 0.45;
            cursor: not-allowed;
            transform: none !important;
        }

        button.primary {
            background: rgba(79, 140, 255, 0.18);
            border-color: rgba(79, 140, 255, 0.45);
            color: #4f8cff;
        }
        button.primary:hover {
            background: rgba(79, 140, 255, 0.28);
        }

        button.success {
            background: rgba(52, 211, 153, 0.18);
            border-color: rgba(52, 211, 153, 0.4);
            color: #34d399;
        }
        button.success:hover {
            background: rgba(52, 211, 153, 0.28);
        }

        button.secondary {
            background: transparent;
            color: var(--text-dim);
            border: 1px solid var(--border);
        }
        button.secondary:hover {
            background: rgba(255, 255, 255, 0.04);
            color: var(--text);
            border-color: rgba(255, 255, 255, 0.2);
        }

        button.danger {
            background: rgba(248, 113, 113, 0.08);
            border-color: rgba(248, 113, 113, 0.35);
            color: #f87171;
        }
        button.danger:hover {
            background: #f87171;
            border-color: #f87171;
            color: #1a0608;
        }

        button.ghost {
            background: transparent;
            border-color: transparent;
            color: var(--text-dim);
        }
        button.ghost:hover {
            background: rgba(255,255,255,0.05);
            color: var(--text);
        }

        button.small {
            padding: 5px 12px;
            font-size: 12px;
            border-radius: 5px;
        }

        /* SUMMARY CARDS */
        .summary-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            margin-bottom: 30px;
        }

        .summary-card {
            background: var(--surface);
            border: 1px solid var(--border);
            border-radius: 10px;
            padding: 20px;
            text-align: center;
        }

        .summary-card-label {
            font-size: 12px;
            color: var(--text-dim);
            text-transform: uppercase;
            letter-spacing: 0.5px;
            margin-bottom: 8px;
        }

        .summary-card-value {
            font-size: 28px;
            font-weight: 700;
            color: var(--accent);
            font-variant-numeric: tabular-nums;
        }

        /* MODAL */
        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.7);
            z-index: 1000;
            align-items: center;
            justify-content: center;
        }

        .modal.active {
            display: flex;
        }

        .modal-content {
            background: var(--surface);
            border: 1px solid var(--border);
            border-radius: 10px;
            padding: 14px 18px;
            /* Widened from 960 → 1280 so dense forms (lead editor,
               estimate editor, job edit) breathe instead of crushing
               their two- and three-column rows. The 96vw cap keeps
               margin from the viewport edge so the modal still
               visually reads as a dialog, not a page takeover. */
            max-width: 1280px;
            width: 96%;
            max-height: 86vh;
            overflow-y: auto;
            box-shadow: 0 12px 40px rgba(0,0,0,0.35);
            font-size: 13px;
        }

        .modal-header {
            font-size: 15px;
            font-weight: 700;
            margin-bottom: 10px;
            color: var(--text);
            padding-bottom: 8px;
            border-bottom: 1px solid var(--border);
            cursor: move; /* signals the header is a drag handle */
            user-select: none;
        }
        .modal-header:active { cursor: grabbing; }

        .modal-footer {
            display: flex;
            gap: 8px;
            justify-content: flex-end;
            margin-top: 12px;
            padding-top: 10px;
            border-top: 1px solid var(--border);
        }

        /* Hide native number-input spinner buttons in the estimate
           editor's line-item rows. The spinners take up cell width and
           occasionally intercept clicks meant for the input itself.
           Scoped to the editor so other places (e.g. modals) keep
           native spinners if they're useful there. */
        #ee-lines-container input[type=number]::-webkit-inner-spin-button,
        #ee-lines-container input[type=number]::-webkit-outer-spin-button,
        [data-section-id] input[type=number]::-webkit-inner-spin-button,
        [data-section-id] input[type=number]::-webkit-outer-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }
        #ee-lines-container input[type=number],
        [data-section-id] input[type=number] {
            -moz-appearance: textfield;
            appearance: textfield;
        }

        /* FORMS */
        .form-group {
            margin-bottom: 8px;
        }

        label {
            display: block;
            margin-bottom: 3px;
            font-size: 10px;
            font-weight: 600;
            color: var(--text-dim);
            text-transform: uppercase;
            letter-spacing: 0.4px;
        }

        /* Brand accent for native form controls so checkboxes/radios pick
           up the green theme instead of the OS default (which renders red
           on Windows for many users). */
        input[type="checkbox"],
        input[type="radio"] {
            accent-color: #5ddb7e;
        }

        /* Reusable checkbox-with-label row.
           Use whenever you have a single <input type="checkbox"> sitting
           next to descriptive text. The global label{} rule
           (display:block + uppercase + 10px + bold + letter-spacing) and
           the global input{width:100%} rule wreck native checkbox layout
           — this class undoes both within its scope. */
        label.agx-check-row {
            display: flex;
            align-items: flex-start;
            gap: 6px;
            font-size: 11px;
            font-weight: 500;
            line-height: 1.35;
            text-transform: none;
            letter-spacing: normal;
            color: var(--text, #fff);
            cursor: pointer;
            margin: 0;
        }
        label.agx-check-row input[type="checkbox"],
        label.agx-check-row input[type="radio"] {
            width: auto;
            flex: 0 0 auto;
            margin: 1px 0 0 0;
            padding: 0;
            background: transparent;
            border: none;
        }
        label.agx-check-row .agx-check-hint {
            color: var(--text-dim, #888);
            font-weight: normal;
        }

        /* Capability row in the Role editor. Beats the global label rule
           above for these specific rows so the cap text doesn't render as
           tiny uppercase dimmed metadata. */
        .cap-group-title {
            font-size: 10px;
            font-weight: 700;
            color: var(--text-dim);
            text-transform: uppercase;
            letter-spacing: 0.5px;
            padding: 0 4px;
            margin: 8px 0 4px 0;
        }
        .cap-group-title:first-child { margin-top: 0; }
        label.cap-row {
            display: flex !important;
            align-items: center !important;
            gap: 10px !important;
            padding: 7px 10px !important;
            border-radius: 5px !important;
            font-size: 13px !important;
            font-weight: normal !important;
            color: var(--text) !important;
            text-transform: none !important;
            letter-spacing: 0 !important;
            margin: 0 !important;
            cursor: pointer;
            transition: background 0.12s;
        }
        label.cap-row:hover { background: rgba(255,255,255,0.04); }
        label.cap-row input[type="checkbox"] {
            width: auto !important;
            margin: 0 !important;
            flex: 0 0 auto;
            transform: scale(1.05);
        }
        label.cap-row .cap-text { flex: 1 1 auto; line-height: 1.3; min-width: 0; }
        label.cap-row .cap-key {
            font-family: 'SF Mono', 'Fira Code', 'Courier New', monospace;
            font-size: 10px;
            color: var(--text-dim);
            margin-left: 8px;
            font-weight: normal;
            opacity: 0.7;
        }

        input, select, textarea {
            width: 100%;
            background: var(--bg);
            border: 1px solid var(--border);
            color: var(--text);
            /* Vertical padding tightened 6px → 4px so the input height
               sits flush with the 13px font + line-height instead of
               adding ~6px of dead space on top + bottom. Forms render
               significantly tighter, modals show more rows above the
               fold. Override per-control with explicit padding when
               a tall click target is genuinely wanted. */
            padding: 4px 10px;
            border-radius: 5px;
            font-size: 13px;
            line-height: 1.35;
            font-family: inherit;
            transition: border-color 0.15s, box-shadow 0.15s;
        }
        /* Date inputs need a bit more room — the spinner / picker icon
           clips at 4px vertical padding in some browsers. */
        input[type="date"], input[type="datetime-local"], input[type="time"] {
            padding: 5px 10px;
        }
        /* Textareas keep the slightly taller padding so multi-line
           content doesn't feel cramped against the border. */
        textarea {
            padding: 6px 10px;
            line-height: 1.45;
        }

        input:focus, select:focus, textarea:focus {
            outline: none;
            border-color: var(--accent);
            box-shadow: 0 0 0 3px rgba(79,140,255,0.15);
        }

        textarea {
            resize: vertical;
            min-height: 52px;
        }

        .form-row {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 10px;
        }

        .modal-content h3,
        .modal-content h4 {
            font-size: 12px;
            font-weight: 600;
            color: var(--text-dim);
            text-transform: uppercase;
            letter-spacing: 0.4px;
            margin: 10px 0 6px;
        }

        .modal-content hr {
            border: none;
            border-top: 1px solid var(--border);
            margin: 10px 0;
        }

        /* TABLES */
        .table-container {
            overflow-x: auto;
            margin-bottom: 10px;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            font-size: 12px;
        }

        th {
            background: var(--surface2);
            color: var(--text-dim);
            padding: 6px 8px;
            text-align: left;
            font-weight: 600;
            font-size: 11px;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            border-bottom: 1px solid var(--border);
            position: sticky;
            top: 0;
            z-index: 10;
        }

        th.sortable {
            cursor: pointer;
            user-select: none;
            transition: color 0.2s;
        }

        th.sortable:hover {
            color: var(--accent);
        }

        th.sortable::after {
            content: ' ⇅';
            opacity: 0.3;
            font-size: 11px;
        }

        th.sortable.sort-asc::after {
            content: ' ▲';
            opacity: 0.8;
            color: var(--accent);
        }

        th.sortable.sort-desc::after {
            content: ' ▼';
            opacity: 0.8;
            color: var(--accent);
        }

        /* Slim header buttons — used in the estimate editor sticky header
           where the action row holds 5+ buttons and the standard .small
           padding ate too much horizontal space. Tighter padding + smaller
           font, with the same color variants (.success, .danger, etc.)
           inheriting from the global button rules. .ee-icon-btn is the
           further-shrunk square variant for icon-only buttons (e.g. the
           Delete trash can). */
        .ee-btn {
            padding: 5px 10px;
            font-size: 12px;
            font-weight: 500;
            border: 1px solid var(--border, #333);
            background: rgba(255, 255, 255, 0.04);
            color: var(--text, #fff);
            border-radius: 6px;
            cursor: pointer;
            transition: background 0.12s, border-color 0.12s;
            line-height: 1;
            font-family: inherit;
            white-space: nowrap;
        }
        .ee-btn:hover {
            background: rgba(255, 255, 255, 0.08);
            border-color: rgba(255, 255, 255, 0.18);
        }
        .ee-btn.secondary {
            background: rgba(255, 255, 255, 0.06);
        }
        .ee-btn.primary {
            background: rgba(79, 140, 255, 0.18);
            border-color: rgba(79, 140, 255, 0.45);
            color: #4f8cff;
        }
        .ee-btn.primary:hover {
            background: rgba(79, 140, 255, 0.28);
        }
        .ee-btn.ghost {
            background: transparent;
            border-color: rgba(255, 255, 255, 0.12);
            color: var(--text-dim, #aaa);
        }
        .ee-btn.ghost:hover {
            background: rgba(255, 255, 255, 0.06);
            color: var(--text, #fff);
        }
        .ee-btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }
        .ee-btn.success {
            background: rgba(52, 211, 153, 0.18);
            border-color: rgba(52, 211, 153, 0.4);
            color: #34d399;
        }
        .ee-btn.success:hover {
            background: rgba(52, 211, 153, 0.28);
        }
        .ee-btn.danger {
            background: rgba(248, 113, 113, 0.12);
            border-color: rgba(248, 113, 113, 0.35);
            color: #f87171;
        }
        .ee-btn.danger:hover {
            background: rgba(248, 113, 113, 0.22);
        }
        .ee-icon-btn {
            padding: 5px 9px;
            font-size: 13px;
            min-width: 30px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
        }

        /* Dense BT-style table — used by Leads, Estimates, and any future
           dense list view in the Estimates sub-tab area. Both class names
           apply the same styles so .leads-table existing call sites keep
           working while the canonical name is .dense-table. */
        .leads-table,
        .dense-table {
            width: 100%;
            border-collapse: collapse;
        }
        .leads-table th,
        .dense-table th {
            padding: 10px 12px;
            background: rgba(255,255,255,0.025);
            border-bottom: 1px solid var(--border, #333);
            position: static; /* override the global sticky default */
        }
        .leads-table td,
        .dense-table td {
            padding: 10px 12px;
            border-bottom: 1px solid var(--border, #2a2a3a);
            vertical-align: middle;
        }
        .leads-table tbody tr,
        .dense-table tbody tr {
            cursor: pointer;
            transition: background 0.12s;
        }
        .leads-table tbody tr:hover,
        .dense-table tbody tr:hover {
            background: rgba(79, 140, 255, 0.06);
        }
        .leads-table tbody tr:last-child td,
        .dense-table tbody tr:last-child td {
            border-bottom: none;
        }
        .leads-table th.num,
        .leads-table td.num,
        .dense-table th.num,
        .dense-table td.num {
            text-align: right;
        }
        .leads-table .lead-title-cell {
            max-width: 320px;
        }

        td {
            padding: 6px 8px;
            border-bottom: 1px solid var(--border);
            font-variant-numeric: tabular-nums;
        }

        tr:last-child td {
            border-bottom: none;
        }

        tr:hover {
            background: rgba(79, 140, 255, 0.05);
        }

        table.totals-row td {
            background: var(--surface2);
            font-weight: 600;
            border-top: 2px solid var(--border);
        }

        /* STATUS BADGES */
        .badge {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 12px;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.3px;
        }

        .badge.on-track {
            background: rgba(52, 211, 153, 0.2);
            color: var(--green);
        }

        .badge.at-risk {
            background: rgba(251, 191, 36, 0.2);
            color: var(--yellow);
        }

        .badge.not-started {
            background: var(--surface2);
            color: var(--text-dim);
        }

        .badge.over-budget {
            background: rgba(248, 113, 113, 0.2);
            color: var(--red);
        }

        /* PROGRESS BARS */
        .progress-bar {
            width: 100%;
            height: 8px;
            background: var(--surface2);
            border-radius: 4px;
            overflow: hidden;
        }

        .progress-fill {
            height: 100%;
            background: linear-gradient(90deg, var(--accent), var(--purple));
            transition: width 0.3s ease;
        }

        /* SUB-TABS */
        .sub-tabs {
            display: flex;
            gap: 0;
            border-bottom: 1px solid var(--border);
            margin-bottom: 20px;
        }

        .sub-tabs button {
            background: transparent;
            border: none;
            color: var(--text-dim);
            padding: 10px 16px;
            cursor: pointer;
            font-size: 14px;
            transition: color 0.15s;
            position: relative;
        }
        .sub-tabs button:hover {
            color: var(--text);
        }
        .sub-tabs button.active {
            color: #5ddb7e;
            font-weight: 600;
        }

        /* Sub-edit modal tab bar — same plain text-color rule. The
           sliding indicator is shared via .agx-tab-slider. */
        .sub-modal-tab {
            padding: 10px 14px;
            background: transparent;
            border: none;
            color: var(--text-dim, #aaa);
            font-size: 13px;
            font-weight: 600;
            cursor: pointer;
            position: relative;
            transition: color 0.15s;
        }
        .sub-modal-tab:hover {
            color: var(--text, #fff);
        }
        .sub-modal-tab.active {
            color: #5ddb7e;
        }

        /* ─── Tab buttons: suppress global button chrome ─────────────
           The global `button { background, border, border-radius:6px }`
           + `button:focus-visible { box-shadow: green ring }` rules
           leak into tab buttons and draw a rounded box around the
           active / focused tab — collides with the sliding indicator.
           Strip those for any element styled as a tab (text-color +
           the slider are the only tab visual). */
        .tab-btn,
        .ws-right-tab,
        .sub-tab-btn-job,
        .sub-tabs button,
        .sub-modal-tab {
            background: transparent;
            border-radius: 0;
        }
        .tab-btn:hover,
        .ws-right-tab:hover,
        .sub-tab-btn-job:hover,
        .sub-tabs button:hover,
        .sub-modal-tab:hover {
            background: transparent;
            border-color: transparent;
        }
        .tab-btn:focus,
        .ws-right-tab:focus,
        .sub-tab-btn-job:focus,
        .sub-tabs button:focus,
        .sub-modal-tab:focus,
        .tab-btn:focus-visible,
        .ws-right-tab:focus-visible,
        .sub-tab-btn-job:focus-visible,
        .sub-tabs button:focus-visible,
        .sub-modal-tab:focus-visible {
            outline: none;
            box-shadow: none;
        }

        /* ─── Sliding tab indicator ──────────────────────────────────
           A single 2px lime bar appended to each tab bar by
           js/tab-slider.js. Width + transform get set inline to match
           the active tab's offsetLeft / offsetWidth, with the
           transition driving a smooth slide whenever the active tab
           changes. Fades away if no active tab is found. */
        .agx-tab-slider {
            position: absolute;
            bottom: -1px;
            left: 0;
            width: 0;
            height: 2px;
            background: #5ddb7e;
            border-radius: 2px;
            box-shadow:
                0 0 8px  rgba(93, 219, 126, 0.6),
                0 0 14px rgba(93, 219, 126, 0.3);
            pointer-events: none;
            opacity: 0;
            transition:
                transform 0.28s cubic-bezier(0.4, 0.0, 0.2, 1),
                width     0.28s cubic-bezier(0.4, 0.0, 0.2, 1),
                opacity   0.15s;
            will-change: transform, width;
            z-index: 5;
        }

        .sub-tab-content, .sub-tab-content-job {
            display: none;
        }

        .sub-tab-content.active, .sub-tab-content-job.active {
            display: block;
        }

        /* ESTIMATE SPECIFIC */
        .estimate-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
            margin-bottom: 30px;
        }

        .estimate-grid.full {
            grid-template-columns: 1fr;
        }

        .line-items-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
        }

        /* PROPOSAL VIEW */
        .proposal {
            background: white;
            color: #333;
            padding: 40px;
            border-radius: 0;
            font-family: 'Times New Roman', serif;
        }

        .proposal-header {
            text-align: center;
            margin-bottom: 30px;
            border-bottom: 2px solid #333;
            padding-bottom: 20px;
        }

        .proposal-company {
            font-size: 24px;
            font-weight: bold;
            color: #1a2a4a;
            margin-bottom: 5px;
        }

        .proposal-tagline {
            font-size: 12px;
            color: #666;
            letter-spacing: 1px;
        }

        .proposal-title {
            font-size: 20px;
            font-weight: bold;
            margin: 20px 0;
            color: #333;
        }

        .proposal-info-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
            margin: 20px 0;
        }

        .proposal-info-box {
            border: 1px solid #ddd;
            padding: 15px;
            background: #f9f9f9;
        }

        .proposal-info-label {
            font-size: 11px;
            font-weight: bold;
            text-transform: uppercase;
            color: #666;
            margin-bottom: 5px;
        }

        .proposal-info-value {
            font-size: 14px;
            color: #333;
        }

        .proposal-section {
            margin: 30px 0;
        }

        .proposal-section-title {
            font-size: 14px;
            font-weight: bold;
            text-transform: uppercase;
            border-bottom: 1px solid #ddd;
            padding-bottom: 10px;
            margin-bottom: 15px;
            color: #1a2a4a;
        }

        .proposal-price-display {
            font-size: 32px;
            font-weight: bold;
            color: #1a2a4a;
            margin: 20px 0;
            text-align: center;
        }

        .proposal-signature-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 40px;
            margin-top: 60px;
        }

        .proposal-signature-block {
            border-top: 1px solid #333;
            padding-top: 10px;
        }

        .proposal-signature-label {
            font-size: 12px;
            font-weight: bold;
            margin-top: 30px;
        }

        .proposal-no-print {
            background: var(--surface);
            border: 1px solid var(--border);
            margin-top: 30px;
            padding: 20px;
        }

        /* ACTION BUTTONS */
        .action-buttons {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }

        /* WIP Action Tabs (tab-styled buttons) */
        .wip-action-tabs {
            display: flex;
            gap: 0;
            margin-bottom: 16px;
            border-bottom: 2px solid var(--border);
        }
        .wip-action-tab {
            background: none;
            border: none;
            padding: 8px 16px;
            font-size: 13px;
            color: var(--text-dim);
            cursor: pointer;
            position: relative;
            font-family: inherit;
            font-weight: 500;
            transition: color 0.15s;
        }
        .wip-action-tab:hover {
            color: var(--text);
        }
        .wip-action-tab::after {
            content: '';
            position: absolute;
            left: 8px;
            right: 8px;
            bottom: -2px;
            height: 2px;
            background: transparent;
            border-radius: 1px;
            transition: background 0.15s;
        }
        .wip-action-tab:hover::after {
            background: var(--accent);
        }
        .wip-action-tab.active {
            color: var(--text);
        }
        .wip-action-tab.active::after {
            background: var(--green);
        }

        /* JOB CARDS */
        .job-cards-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
            gap: 20px;
            margin-bottom: 20px;
        }

        .job-card {
            background: var(--surface);
            border: 1px solid var(--border);
            border-radius: 10px;
            padding: 20px;
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .job-card:hover {
            border-color: var(--accent);
            box-shadow: 0 0 20px rgba(79, 140, 255, 0.1);
        }

        .job-card-title {
            font-size: 16px;
            font-weight: 600;
            margin-bottom: 8px;
            color: var(--accent);
        }

        .job-card-subtitle {
            font-size: 12px;
            color: var(--text-dim);
            margin-bottom: 12px;
        }

        .job-card-stat {
            display: flex;
            justify-content: space-between;
            margin-bottom: 8px;
            font-size: 13px;
        }

        .job-card-stat-label {
            color: var(--text-dim);
        }

        .job-card-stat-value {
            font-weight: 600;
            color: var(--text);
        }

        /* JOB DETAIL VIEW */
        .job-detail-header {
            display: flex;
            align-items: center;
            gap: 20px;
            margin-bottom: 30px;
        }

        .job-detail-header button {
            padding: 8px 16px;
            font-size: 13px;
        }

        .job-detail-info {
            flex: 1;
        }

        .job-detail-title {
            font-size: 28px;
            font-weight: 700;
            margin-bottom: 8px;
        }

        .job-detail-meta {
            display: flex;
            gap: 20px;
            font-size: 13px;
            color: var(--text-dim);
        }

        /* RESPONSIVE */
        @media (max-width: 768px) {
            .main-inner {
                padding: 15px;
            }

            .estimate-grid,
            .line-items-grid {
                grid-template-columns: 1fr;
            }

            .form-row {
                grid-template-columns: 1fr;
            }

            .summary-grid {
                grid-template-columns: 1fr;
            }

            /* Mobile fallback — stack header content into two rows.
               Bumps the height to ~84px on phones, but the trade-off
               is each control gets a tappable target. The new
               single-row layout would crush at <600px otherwise. */
            header {
                padding: 8px 16px;
                height: auto;
            }
            .header-content {
                flex-wrap: wrap;
                gap: 8px 14px;
            }
            .header-user-menu {
                margin-left: 0;
                flex: 1 1 100%;
                justify-content: flex-end;
            }
            nav.tabs {
                flex: 1 1 100%;
                height: 36px;
                overflow-x: auto;
            }
            nav.tabs button {
                padding: 0 12px;
            }

            table {
                font-size: 12px;
            }

            th, td {
                padding: 8px;
            }

            .proposal {
                padding: 20px;
            }

            .job-detail-header {
                flex-direction: column;
                align-items: flex-start;
            }
        }

        /* PRINT STYLES */
        @media print {
            body {
                background: white;
                color: #333;
            }

            header, nav, .action-buttons, button, .modal {
                display: none !important;
            }

            main, .main-inner {
                padding: 0;
            }

            .tab-content {
                display: block !important;
            }

            .proposal-no-print {
                display: none !important;
            }

            .proposal {
                background: white;
                color: #333;
                box-shadow: none;
                border: none;
            }

            table {
                color: #333;
            }

            th {
                background: #e5e5e5;
                color: #333;
            }

            tr:hover {
                background: transparent;
            }
        }
    
    /* Estimate Editor */
    #editEstimate_lineItems tbody tr { border-bottom: 1px solid var(--bg-dark, var(--border)); }
    #editEstimate_lineItems tbody tr:hover { background: rgba(255,255,255,0.02); }
    #editEstimate_lineItems tbody tr.section-header { background: rgba(255,255,255,0.08); font-weight: bold; border-top: 2px solid var(--text-dim); }
    #editEstimate_lineItems input, #editEstimate_lineItems select { background: var(--surface2); border: 1px solid var(--border); color: var(--text); padding: 6px 8px; border-radius: 3px; font-size: 13px; width: 100%; }
    #editEstimate_lineItems input:focus, #editEstimate_lineItems select:focus { outline: none; border-color: var(--accent); }
    .estimate-line-delete { background: var(--red); color: white; border: none; padding: 4px 8px; border-radius: 3px; cursor: pointer; font-size: 12px; }
    .estimate-line-delete:hover { opacity: 0.8; }
    @media print { .modal-header, .modal-footer { display: none !important; } }

    /* ── Attachment thumbnail broken-image placeholder ────────────
       The img's onerror handler adds .att-thumb-broken to the tile
       when the thumbnail fails to load (file missing on server, R2
       URL not yet propagating, etc.). CSS swaps the dead img for a
       labeled placeholder so the user can identify which attachment
       is broken and clean it up via the × button. */
    .att-thumb-tile.att-thumb-broken img {
      display: none;
    }
    .att-thumb-tile.att-thumb-broken {
      background: var(--surface2, #1a1d27);
    }
    .att-thumb-tile.att-thumb-broken::after {
      content: '🖼❌  missing on server';
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 8px;
      text-align: center;
      font-size: 10px;
      color: var(--text-dim, #888);
      pointer-events: none;
    }
    