
        :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. Project 86 palette — charcoal base fading
           into a deep blue accent edge. The original AGX greens
           (#0d1f12 / #14351d / #1B8541 / #3B8542) are archived in
           archive/branding/agx/snapshot/styles.css for restore. */
        header {
            background: linear-gradient(135deg, #0f172a 0%, #1e293b 40%, #2563eb 100%);
            border-bottom: 1px solid #3b82f6;
            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;
            gap: 10px;
            text-decoration: none;
            flex: 0 0 auto;
        }
        .header-logo {
            height: 34px;
            width: auto;
            display: block;
        }
        /* Wordmark next to the hex icon. Matches the lockup's
           Inter ultra-light + tracked-out caps so the header reads
           as the same brand surface as the login page. */
        .header-wordmark {
            font-family: Inter, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
            font-weight: 200;
            font-size: 16px;
            letter-spacing: 2.5px;
            color: #F8FAFC;
            white-space: nowrap;
            user-select: none;
        }

        /* 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);
        }

        /* Right-cluster icon buttons (bell, theme toggle) — circular,
           transparent at rest, subtle fill on hover. Sized to match
           the avatar so all three sit on the same baseline. */
        .header-icon-btn {
            position: relative;
            width: 32px;
            height: 32px;
            border-radius: 50%;
            background: transparent;
            border: 1px solid transparent;
            color: rgba(255, 255, 255, 0.85);
            font-size: 16px;
            line-height: 1;
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            padding: 0;
            transition: background 0.12s, border-color 0.12s;
        }
        .header-icon-btn:hover {
            background: rgba(255, 255, 255, 0.12);
            border-color: rgba(255, 255, 255, 0.18);
        }
        /* Icon decorator slot inside the header buttons — overrides
           the default tab-btn 1.4em sizing (which applies via the
           global rule even though we don't have .tab-btn here, but
           keeping the override defensive). 18px reads cleanly inside
           a 32px circular button without crowding. */
        .header-icon-btn .agx-icon-slot {
            margin-right: 0;
            display: inline-flex;
        }
        .header-icon-btn .agx-icon {
            width: 18px;
            height: 18px;
        }
        /* Red dot on the bell — only visible when count > 0. JS sets
           data-count and toggles the .has-notifs flag on the parent
           button. CSS shows the dot accordingly. */
        .header-notif-dot {
            position: absolute;
            top: 4px;
            right: 4px;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: #ef4444;
            box-shadow: 0 0 0 2px var(--header-bg, #1a1a2e);
            display: none;
        }
        .header-icon-btn.has-notifs .header-notif-dot { display: block; }

        /* Initials avatar — outline-only "badge" surface. Default state
           is transparent fill with a cyan ring; hover bumps the ring +
           gentle scale + soft glow rather than dropping a color fill,
           so the badge always reads as the same shape and never
           competes with the rest of the chrome. Click toggles
           #user-avatar-menu. */
        .header-avatar {
            width: 32px;
            height: 32px;
            border-radius: 50%;
            border: 1.5px solid rgba(34, 211, 238, 0.55);
            background: transparent;
            color: #F8FAFC;
            font-size: 12px;
            font-weight: 600;
            letter-spacing: 0.3px;
            cursor: pointer;
            text-transform: uppercase;
            line-height: 1;
            padding: 0;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1),
                        border-color 0.18s,
                        box-shadow 0.18s;
        }
        .header-avatar:hover {
            transform: scale(1.08);
            border-color: #22D3EE;
            box-shadow: 0 0 0 3px rgba(34, 211, 238, 0.18),
                        0 0 14px rgba(34, 211, 238, 0.35);
        }
        .header-avatar:active { transform: scale(0.96); }

        /* Popovers — used for both the avatar menu and the
           notifications panel. Anchored bottom-right to the header
           cluster via fixed offsets (the cluster itself is flex so
           we can't use position:absolute on the panel relative to
           a specific button without DOM gymnastics; fixed-to-viewport
           with right/top measured from the header gives a consistent
           anchor). */
        .header-popover {
            position: absolute;
            top: calc(100% + 6px);
            right: 12px;
            min-width: 220px;
            max-width: 320px;
            background: #1d1d28;
            border: 1px solid #353545;
            border-radius: 8px;
            box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
            z-index: 9000;
            color: #ddd;
            overflow: hidden;
            font-size: 12px;
        }
        .header-popover-wide { min-width: 300px; max-width: 380px; }
        .header-popover-section {
            padding: 10px 12px;
            border-bottom: 1px solid #2c2c38;
        }
        .header-popover-title {
            font-size: 11px;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            color: #aaa;
        }
        .header-popover-name {
            font-size: 13px;
            font-weight: 700;
            color: #fff;
            margin-bottom: 2px;
        }
        .header-popover-role {
            font-size: 10px;
            color: #9aa;
            text-transform: uppercase;
            letter-spacing: 0.6px;
            font-weight: 600;
        }
        .header-popover-item {
            display: block;
            width: 100%;
            text-align: left;
            background: transparent;
            border: 0;
            color: #ddd;
            font-size: 12px;
            padding: 9px 12px;
            cursor: pointer;
            font-weight: 500;
        }
        .header-popover-item:hover {
            background: rgba(255, 255, 255, 0.06);
            color: #fff;
        }
        .header-popover-body { max-height: 360px; overflow-y: auto; }
        .header-popover-empty {
            padding: 20px 12px;
            text-align: center;
            color: #888;
            font-size: 12px;
            font-style: italic;
        }

        /* Directory popover — Buildertrend-style menu anchored to
           the directory icon button in the right cluster. Items are
           SVG icon + label rows with generous padding and a soft
           accent hover. Reuses .header-popover positioning so the
           panel hangs off the cluster like Notifications and the
           avatar menu. */
        .header-directory-menu {
            min-width: 220px;
            padding: 6px 0;
            background: #fff;
            color: #1a1a2e;
            border-color: #d6d6dd;
        }
        .header-directory-menu button {
            display: flex !important;
            align-items: center;
            justify-content: flex-start;
            gap: 12px;
            width: 100%;
            text-align: left;
            background: transparent;
            border: 0;
            color: #1a1a2e;
            font-size: 14px;
            padding: 10px 16px;
            cursor: pointer;
            font-weight: 500;
            white-space: nowrap;
            height: auto;
        }
        .header-directory-menu button:hover {
            background: rgba(79, 140, 255, 0.08);
            color: #1a1a2e;
        }
        .header-directory-menu button .agx-icon-slot { margin-right: 0; }
        .header-directory-menu button .agx-icon {
            width: 22px;
            height: 22px;
            flex: 0 0 auto;
            color: #4b4b5a;
        }
        .header-directory-menu button:hover .agx-icon { color: #2c2c40; }

        /* 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;
        }

        /* Inactive tabs render at near-logo brightness (0.85 white) so
           they read as "lit, just not the chosen one." Hover boosts
           to full #fff for clear cursor feedback. The active tab
           also sits at full white plus the bold weight + the white
           .agx-tab-slider underline + glow. */
        nav.tabs button {
            background: transparent;
            border: none;
            color: rgba(255, 255, 255, 0.85);
            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: #ffffff;
        }
        /* Header tab icons render larger than the text — same "icon-led"
           treatment as the node-library sidebar but slightly tighter
           since the header is height-constrained at 46px. 1.6em on the
           13px row = ~21px icon, with the .agx-icon vertical-align
           overridden so the larger icon sits optically centered against
           the smaller label. */
        nav.tabs button .agx-icon {
            width: 1.6em;
            height: 1.6em;
            vertical-align: -0.4em;
            margin-right: 4px;
        }

        /* 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: #ffffff;
            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);
        }

        /* Outline-only success/danger to match the Save-button pill
           style. The .primary blue stays filled so AI / primary CTAs
           still have their pop; .success and .danger are
           secondary actions (Export, Import, Delete) and read better
           as outlined. Subtle hover fill gives cursor feedback
           without dominating the surface. */
        button.success {
            background: transparent;
            border-color: rgba(52, 211, 153, 0.45);
            color: #34d399;
        }
        button.success:hover {
            background: rgba(52, 211, 153, 0.10);
            border-color: rgba(52, 211, 153, 0.65);
        }

        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: transparent;
            border-color: rgba(248, 113, 113, 0.45);
            color: #f87171;
        }
        button.danger:hover {
            background: rgba(248, 113, 113, 0.10);
            border-color: rgba(248, 113, 113, 0.7);
            color: #f87171;
        }

        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;
            /* Flex column so .modal-footer can use `order` to render
               above the body content. The body fields are unwrapped
               direct children at the default order: 0 — header (-2)
               and footer (-1) sit above them in visual order. */
            display: flex;
            flex-direction: column;
        }

        .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;
            order: -2;
        }
        .modal-header:active { cursor: grabbing; }

        .modal-footer {
            display: flex;
            gap: 8px;
            justify-content: flex-end;
            order: -1;
            margin-top: 0;
            margin-bottom: 12px;
            padding-top: 0;
            padding-bottom: 10px;
            border-top: none;
            border-bottom: 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;
        }
        /* See note on button.success/danger above — same outline-only
           treatment so the Save-button pill style is consistent across
           legacy <button class="success"> and the modern .ee-btn
           variants. .ee-btn.primary (blue, AI/primary CTAs) stays
           filled. */
        .ee-btn.success {
            background: transparent;
            border-color: rgba(52, 211, 153, 0.45);
            color: #34d399;
        }
        .ee-btn.success:hover {
            background: rgba(52, 211, 153, 0.10);
            border-color: rgba(52, 211, 153, 0.65);
        }
        .ee-btn.danger {
            background: transparent;
            border-color: rgba(248, 113, 113, 0.45);
            color: #f87171;
        }
        .ee-btn.danger:hover {
            background: rgba(248, 113, 113, 0.10);
            border-color: rgba(248, 113, 113, 0.7);
        }
        .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: 2px 8px;
            border-radius: 10px;
            font-size: 10px;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.4px;
            line-height: 1.4;
        }

        .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: #ffffff;
            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: #ffffff;
        }

        /* ─── 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 white 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: #ffffff;
            border-radius: 2px;
            box-shadow:
                0 0 8px  rgba(255, 255, 255, 0.65),
                0 0 14px rgba(255, 255, 255, 0.35);
            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;
    }

    /* ── Copy-to-clipboard button (js/copy-button.js) ──
       Wraps emails / addresses / any [data-agx-copy] field with a
       small clipboard emoji at the right edge. Subtle by default,
       full opacity on hover, briefly flips to a green check on copy. */
    .agx-copy-wrap {
      position: relative;
      display: block;
      width: 100%;
    }
    .agx-copy-wrap > input,
    .agx-copy-wrap > textarea {
      width: 100%;
      box-sizing: border-box;
      padding-right: 30px;
    }
    .agx-copy-btn {
      background: transparent;
      border: none;
      cursor: pointer;
      padding: 0;
      font-size: 13px;
      line-height: 1;
      opacity: 0.45;
      transition: opacity 0.12s, color 0.12s, transform 0.12s;
      color: var(--text-dim, #888);
      user-select: none;
    }
    .agx-copy-btn:hover { opacity: 1; transform: scale(1.1); }
    .agx-copy-btn:focus { outline: none; opacity: 1; }
    .agx-copy-wrap > .agx-copy-btn {
      position: absolute;
      right: 4px;
      top: 50%;
      transform: translateY(-50%);
      width: 24px;
      height: 24px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
    }
    .agx-copy-wrap > .agx-copy-btn:hover {
      transform: translateY(-50%) scale(1.1);
    }
    .agx-copy-btn-inline {
      margin-left: 4px;
      vertical-align: middle;
    }
    .agx-copy-btn.agx-copy-flashed {
      opacity: 1;
      color: #34d399;
    }

    /* ── AGX inline icons (js/agx-icons.js) ──
       SVGs use stroke="currentColor" so they pick up the parent's
       text color. Default size = 1em × 1em, vertical-aligned to the
       baseline so they sit cleanly inside text and buttons. */
    .agx-icon {
      display: inline-block;
      width: 1em;
      height: 1em;
      vertical-align: -0.15em;
      flex-shrink: 0;
    }
    /* Auto-decoration slot: when [data-agx-icon] is set, the helper
       prepends <span class="agx-icon-slot"><svg .../></span> at the
       start of the element. Margin-right gives a small gap to the
       text label. Inline-flex centering keeps the SVG aligned. */
    .agx-icon-slot {
      display: inline-flex;
      align-items: center;
      margin-right: 6px;
    }
    /* When the icon-slot sits inside a top-level tab-btn, give the
       icon a touch more visual presence than the surrounding text.
       Bumped from 1.05em → 1.4em so the icons read clearly on the
       sticky header without needing to squint. */
    .tab-btn .agx-icon-slot { margin-right: 8px; }
    .tab-btn .agx-icon-slot .agx-icon {
      width: 1.4em; height: 1.4em; vertical-align: -0.32em;
    }
