:root {
    --bg: #0d1117;
    --surface: #161b22;
    --surface-hover: #1c2129;
    --border: #30363d;
    --border-light: #21262d;
    --text: #c9d1d9;
    --text-muted: #8b949e;
    --text-bright: #f0f6fc;
    --accent: #58a6ff;
    --accent-muted: #1f6feb;
    --green: #3fb950;
    --green-muted: #238636;
    --yellow: #d29922;
    --red: #f85149;
    --orange: #db6d28;
    --purple: #bc8cff;
    --red-muted: #2a1414;
    --radius: 8px;
    --radius-sm: 6px;
    --shadow: 0 1px 3px rgba(0,0,0,0.3), 0 1px 2px rgba(0,0,0,0.2);
    --shadow-lg: 0 10px 30px rgba(0,0,0,0.5);

    /* DEVOPS-134: semantic surface/code vars. Many rules below were written
       with hardcoded fallbacks in var(--x, #hex) form; promoting them to
       first-class vars (with the same dark values) lets the light palette
       override them in one place instead of per-rule. */
    --bg-secondary: #141418;
    --bg-hover: #1e1e24;
    --bg-primary: #0d0d11;
    --bg-elevated: #1c1c22;
    --bg-input: #1e1e24;
    --code-bg: #0d0d11;
    --chat-user-bg: #15234a;
    --chat-user-border: #1e3a8a;
    --accent-bg: #0f3460;
    --accent-text: #6ea8fe;
    --text-base: #c9d1d9;
    --muted: #888;
    --badge-pending-bg: #1f2937;
    --badge-inprogress-bg: #0c2d6b;
    --badge-completed-bg: #0d2818;
    --badge-warning-bg: #3b2607;
    --badge-error-bg: #3b0b0b;
    --badge-critical-bg: #5c0b0b;
    --badge-critical-fg: #ff7b72;
    --badge-private-bg: #2b1a3d;
    --status-review-bg: #1a3a2a;
    --status-blocked-bg: #3b2607;
    --status-manual-bg: #1f2937;
    --status-manual-text: #6b7280;
}

/* ── DEVOPS-134: light theme ───────────────────────────
   A tested light palette for every var, keyed off [data-theme="light"]
   (set by the FOUC pre-render script in base.html before first paint).
   Contrast pairs are GitHub-light derived: --bg #ffffff, --text #24292f
   (4.6:1), --text-muted #57606a (5.1:1 on white), --accent #0969da
   (5.2:1 on white). */
html[data-theme="light"] {
    --bg: #ffffff;
    --surface: #f6f8fa;
    --surface-hover: #eaeef2;
    --border: #d0d7de;
    --border-light: #eaeef2;
    --text: #24292f;
    --text-muted: #57606a;
    --text-bright: #1f2328;
    --accent: #0969da;
    --accent-muted: #1f6feb;
    --green: #1a7f37;
    --green-muted: #1a7f37;
    --yellow: #9a6700;
    --red: #cf222e;
    --orange: #bc4c00;
    --purple: #8250df;
    --red-muted: #ffebe9;
    --shadow: 0 1px 3px rgba(31,35,40,0.12), 0 1px 2px rgba(31,35,40,0.06);
    --shadow-lg: 0 10px 30px rgba(31,35,40,0.15);

    --bg-secondary: #f6f8fa;
    --bg-hover: #eaeef2;
    --bg-primary: #f6f8fa;
    --bg-elevated: #ffffff;
    --bg-input: #ffffff;
    --code-bg: #f6f8fa;
    --chat-user-bg: #ddf4ff;
    --chat-user-border: #b6e3ff;
    --accent-bg: #ddf4ff;
    --accent-text: #0969da;
    --text-base: #24292f;
    --muted: #57606a;
    --badge-pending-bg: #eaeef2;
    --badge-inprogress-bg: #ddf4ff;
    --badge-completed-bg: #dafbe1;
    --badge-warning-bg: #fff8c5;
    --badge-error-bg: #ffebe9;
    --badge-critical-bg: #ffd7d5;
    --badge-critical-fg: #cf222e;
    --badge-private-bg: #f5f0ff;
    --status-review-bg: #dafbe1;
    --status-blocked-bg: #fff8c5;
    --status-manual-bg: #eaeef2;
    --status-manual-text: #57606a;
}

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

/* ── Themed scrollbars ─────────────────────────────────────
   Match the GitHub-dark palette so scrollbars don't look like
   the default OS chrome dropped into the page. Firefox uses
   the standard property; WebKit/Blink pseudo-elements cover
   Chrome/Edge/Safari. */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track {
    background: transparent;
}
*::-webkit-scrollbar-thumb {
    background-color: var(--border);
    border-radius: 5px;
    border: 2px solid var(--bg);  /* faux-padding so the thumb feels inset */
}
*::-webkit-scrollbar-thumb:hover {
    background-color: var(--text-muted);
}
*::-webkit-scrollbar-corner { background: transparent; }

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
    background: var(--bg);
    color: var(--text);
    line-height: 1.6;
    min-height: 100vh;
}

/* ── Navbar ──────────────────────────────────────────── */
.navbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 2rem;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 100;
    backdrop-filter: blur(8px);
}

.nav-left { display: flex; align-items: center; gap: 0.75rem; }
.nav-right { display: flex; align-items: center; gap: 1rem; }

.nav-separator {
    width: 1px;
    height: 1.25rem;
    background: var(--border);
}

.nav-brand {
    font-size: 1.125rem;
    font-weight: 700;
    color: var(--accent);
    text-decoration: none;
    letter-spacing: 1.5px;
}

.nav-tabs {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}
.nav-tabs::-webkit-scrollbar { height: 3px; }
.nav-tabs::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
/* JS toggles tabs-no-overflow when the strip fits (no fade needed). */
.nav-tabs.tabs-no-overflow {
    -webkit-mask-image: none;
    mask-image: none;
}

.nav-tab {
    color: var(--text-muted);
    font-size: 0.8125rem;
    font-weight: 500;
    text-decoration: none;
    padding: 0.375rem 0.875rem;
    border-radius: var(--radius-sm);
    transition: color 0.15s, background 0.15s;
}

.nav-tab:hover {
    color: var(--text-bright);
    background: var(--border);
}

.nav-tab.active {
    color: var(--text-bright);
    background: var(--accent-muted);
}

/* ── JARVIS-140: primary-nav slide-out drawer ─────────────
   Operator feedback after first phone use of the app: a horizontal tab
   strip across the top is a *website* pattern. On phones the primary nav
   collapses to a hamburger that opens a side drawer — the app convention.
   This supersedes the JARVIS-134 scrollable-strip decision below.

   Same idiom as the JARVIS-141 pop-out selectors: one DOM node, fixed
   pane, translateX(-100%) → .open, shared .popout-scrim to dismiss. Only
   the presentation changes, so the {% block nav_active_* %} markers keep
   working and there is no second copy of the nav links.

   Selectors are `.navbar`-qualified for the same reason JARVIS-141
   qualified `.chat-shell .chat-threads`: the ≤768px blocks further down
   set overflow/mask on bare `.nav-tabs`, and the drawer has to win
   regardless of source order. */
.nav-drawer-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0.375rem 0.5rem;
    background: none;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-bright);
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
}
.nav-drawer-toggle:hover { background: var(--border); }

/* Drawer chrome — only rendered inside the drawer, never on desktop. */
.nav-drawer-header { display: none; }
.nav-drawer-title {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--text-muted);
}
.nav-drawer-close {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    margin-right: -0.5rem;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
}
.nav-drawer-close:hover { color: var(--text-bright); }

/* Scroll lock while the drawer is open — without it the page behind the
   scrim scrolls under the user's thumb. The class goes on BOTH <html> and
   <body>: the global `html, body { overflow-x: hidden }` rule further down
   makes <html> the scrolling element, so body-only overflow does nothing
   (verified in Chromium — the page still scrolled). */
html.drawer-open,
body.drawer-open { overflow: hidden; }

@media (max-width: 800px) {
    /* backdrop-filter makes .navbar a containing block for fixed-position
       descendants, which would trap the drawer inside the bar (and let
       .nav-left's overflow:hidden clip it). The bar's background is opaque
       (--surface), so the blur was a no-op anyway. */
    .navbar { backdrop-filter: none; }
    .navbar .nav-drawer-toggle { display: inline-flex; }
    /* The separator divided the brand from the tab strip. With the tabs in
       the drawer it dangles off the brand with nothing after it. */
    .navbar .nav-separator { display: none; }
    .navbar .nav-tabs {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        width: min(86vw, 320px);
        flex-direction: column;
        align-items: stretch;
        gap: 0.125rem;
        padding: 0.75rem 0.75rem 1.5rem;
        background: var(--surface);
        border-right: 1px solid var(--border);
        border-radius: 0;
        overflow-x: hidden;
        overflow-y: auto;
        -webkit-mask-image: none;
        mask-image: none;
        transform: translateX(-100%);
        transition: transform 0.22s ease;
        z-index: 150;
    }
    .navbar .nav-tabs.open { transform: translateX(0); }
    .navbar .nav-drawer-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 0.875rem 0.5rem;
        margin-bottom: 0.375rem;
        border-bottom: 1px solid var(--border);
    }
    /* Phone tap targets: the 44px minimum, same as the JARVIS-134 pass. */
    .navbar .nav-tab {
        display: flex;
        align-items: center;
        min-height: 44px;
        padding: 0.625rem 0.875rem;
        font-size: 0.9375rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .navbar .nav-tabs { transition: none; }
}

.nav-team-indicator {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.8125rem;
    color: var(--text-muted);
    background: var(--bg);
    padding: 0.375rem 0.75rem;
    border-radius: 20px;
    border: 1px solid var(--border);
}

.nav-team-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--green);
}

/* ── DEVOPS-134: light/dark toggle in the navbar ────── */
.nav-theme-toggle {
    font-size: 1rem;
    line-height: 1;
    padding: 0.375rem;
}
.nav-theme-toggle:hover { color: var(--accent); }

/* ── Layout ──────────────────────────────────────────── */
.container { max-width: 1200px; margin: 0 auto; padding: 2rem; }

.page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1.5rem;
}

h1 { font-size: 1.5rem; color: var(--text-bright); font-weight: 600; }
h2 { font-size: 1.125rem; color: var(--text-bright); font-weight: 600; }

/* ── Dashboard Grid ──────────────────────────────────── */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1rem;
}

.card {
    display: block;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1.25rem;
    text-decoration: none;
    color: var(--text);
    transition: border-color 0.2s, transform 0.15s, box-shadow 0.2s;
}

.card:hover {
    border-color: var(--accent);
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.5rem;
}

.card-header h2 { margin: 0; font-size: 1.0625rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The team card's header has three children (drag handle, name, badges), and
   `justify-content: space-between` spread them — which read as a deliberately
   CENTRED team name with a stray grip to its left. Letting the name take the
   free space puts it flush left where a title belongs, and still pins the
   badges right. Most obvious on a phone, wrong at every width. */
.team-card .card-header h2 { flex: 1 1 auto; }

.team-badge {
    font-size: 0.6875rem;
    color: var(--text-muted);
    background: var(--bg);
    padding: 0.125rem 0.5rem;
    border-radius: 12px;
    border: 1px solid var(--border);
    font-family: monospace;
}

.description { color: var(--text-muted); font-size: 0.8125rem; margin-bottom: 0.75rem; }

/* JARVIS-48: long team descriptions must not blow up the listing cards —
   clamp the *render* to 2 lines; the full text stays in the data (title
   attribute on hover + the team detail page show it in full). */
.team-card .description {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

.stats { display: flex; gap: 0.5rem; margin-top: 0.75rem; flex-wrap: wrap; }
.stat { text-align: center; flex: 1; min-width: 48px; }
.stat-value { display: block; font-size: 1.375rem; font-weight: 700; color: var(--text-muted); }
.stat-value.stat-active { color: var(--accent); }
.stat-value.stat-highlight { color: var(--green); }
.stat-value.stat-warn { color: var(--yellow); }
.stat-value.stat-review { color: var(--orange); }
.stat-label { font-size: 0.6875rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }

.repo-path { margin-top: 0.75rem; font-size: 0.6875rem; color: var(--text-muted); font-family: monospace; padding-top: 0.75rem; border-top: 1px solid var(--border-light); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Team goal/lifecycle (formerly the "initiative" surface, merged 2026-05) */
.team-target-date { margin-top: 0.5rem; font-size: 0.75rem; color: var(--text-muted); }
.team-goal { margin-top: 0.5rem; padding: 0.625rem 0.75rem; font-size: 0.8125rem; line-height: 1.5; background: var(--bg-subtle, rgba(127,127,127,0.06)); border-left: 3px solid var(--border-light); border-radius: 4px; }
.team-goal > :first-child { margin-top: 0; }
.team-goal > :last-child { margin-bottom: 0; }
.todo-completed { opacity: 0.55; }
.todo-completed .todo-title { text-decoration: line-through; }

.card { overflow: hidden; }

/* ── Archived Teams ─────────────────────────────────── */
.team-archived { opacity: 0.5; }
.team-archived:hover { opacity: 0.75; }

.card-header-badges { display: flex; align-items: center; gap: 0.5rem; }

.badge-archived { background: var(--badge-pending-bg); color: var(--text-muted); border: 1px solid var(--border); }

.archived-banner {
    padding: 0.625rem 1rem;
    background: rgba(139, 148, 158, 0.1);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font-size: 0.8125rem;
    margin-bottom: 1.25rem;
}

/* ── Breadcrumb ──────────────────────────────────────── */
.breadcrumb { margin-bottom: 1.25rem; font-size: 0.8125rem; color: var(--text-muted); display: flex; align-items: center; gap: 0.5rem; }
.breadcrumb a { color: var(--accent); text-decoration: none; }
.breadcrumb a:hover { text-decoration: underline; }
.breadcrumb-sep { color: var(--border); }

/* ── Team Header ─────────────────────────────────────── */
.team-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 1.5rem;
}

.team-header-info h1 { margin-bottom: 0.25rem; }
.team-header-actions { display: flex; gap: 0.5rem; align-items: flex-start; }

/* ── Tabs ────────────────────────────────────────────── */
.tabs {
    display: flex;
    gap: 0;
    border-bottom: 1px solid var(--border);
    margin-bottom: 1.5rem;
    overflow-x: auto;
    /* iOS: ensure horizontal-only swipe is captured by this strip and
       not eaten by the page-level horizontal-overflow:hidden. */
    touch-action: pan-x;
    -webkit-overflow-scrolling: touch;
    /* Scroll-position-aware edge fades. The team page carries 11 tabs (980px
       against a 366px strip on a phone), and a phone shows no scrollbar until
       you touch it, so the fade IS the affordance. It used to be a fixed
       right-edge gradient: it kept promising more content after you had
       reached the end, and never hinted that anything lay to the left — so a
       member who scrolled to "Members" got no cue that Tasks was behind them.
       app.js's initTabsAffordance() sets these classes from scrollLeft.
       Browsers without mask support simply get no fade and still scroll. */
    -webkit-mask-image: none;
    mask-image: none;
}
.tabs.tabs-more-after {
    -webkit-mask-image: linear-gradient(to right, black calc(100% - 24px), transparent);
    mask-image: linear-gradient(to right, black calc(100% - 24px), transparent);
}
.tabs.tabs-more-before {
    -webkit-mask-image: linear-gradient(to right, transparent, black 24px);
    mask-image: linear-gradient(to right, transparent, black 24px);
}
.tabs.tabs-more-before.tabs-more-after {
    -webkit-mask-image: linear-gradient(to right, transparent, black 24px, black calc(100% - 24px), transparent);
    mask-image: linear-gradient(to right, transparent, black 24px, black calc(100% - 24px), transparent);
}
.tabs::-webkit-scrollbar { height: 3px; }
.tabs::-webkit-scrollbar-thumb { background: var(--text-muted); border-radius: 3px; }
.tabs:not(:hover)::-webkit-scrollbar-thumb { background: var(--border); }

.tab {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 0.875rem;
    font-weight: 500;
    padding: 0.75rem 1.25rem;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    transition: color 0.2s, border-color 0.2s;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    white-space: nowrap;
    font-family: inherit;
}

.tab:hover { color: var(--text); }
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }

.tab-count {
    font-size: 0.6875rem;
    background: var(--bg);
    color: var(--text-muted);
    padding: 0.0625rem 0.4375rem;
    border-radius: 10px;
    border: 1px solid var(--border);
    min-width: 1.25rem;
    text-align: center;
}

.tab.active .tab-count { background: var(--accent-muted); color: var(--text-bright); border-color: var(--accent-muted); }

.tab-panel { display: none; }
.tab-panel.active { display: block; }

/* ── Section Header ──────────────────────────────────── */
.section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1rem;
}

/* ── Section Header Right ────────────────────────────── */
.section-header-right { display: flex; align-items: center; gap: 0.75rem; }

/* ── Read Toggle ─────────────────────────────────────── */
.read-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem 0.625rem;
    font-size: 0.75rem;
    font-weight: 500;
    font-family: inherit;
    color: var(--text-muted);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.read-toggle:hover { color: var(--text); border-color: var(--text-muted); }

.read-toggle.active { color: var(--accent); border-color: var(--accent-muted); background: rgba(88,166,255,0.08); }

.read-toggle-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--text-muted);
    transition: background 0.15s;
}

.read-toggle.active .read-toggle-dot { background: var(--accent); }

/* ── Buttons ─────────────────────────────────────────── */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.5rem 1rem;
    font-size: 0.8125rem;
    font-weight: 500;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
    font-family: inherit;
}

.btn:hover { background: var(--surface-hover); border-color: var(--text-muted); }

.btn-primary {
    background: var(--accent-muted);
    border-color: var(--accent-muted);
    color: #fff;
}

.btn-primary:hover { background: var(--accent); border-color: var(--accent); }

.btn-success { border-color: var(--green-muted); color: var(--green); }
.btn-success:hover { background: var(--green-muted); color: #fff; }
.btn-danger { color: var(--red); }
.btn-danger:hover { background: rgba(248,81,73,0.1); border-color: var(--red); color: var(--red); }

.btn-sm { padding: 0.25rem 0.625rem; font-size: 0.75rem; }

.btn-icon {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 0.375rem;
    border-radius: 4px;
    transition: color 0.15s, background 0.15s;
    display: flex;
    align-items: center;
    justify-content: center;
}

.btn-icon:hover { color: var(--accent); background: rgba(88,166,255,0.1); }
.btn-icon.btn-danger { color: var(--red); }
.btn-icon.btn-danger:hover { color: var(--red); background: rgba(248,81,73,0.1); }

/* ── Task Cards ──────────────────────────────────────── */
.task-list { display: flex; flex-direction: column; gap: 0.5rem; }

.task-card {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    padding: 0.875rem 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    transition: border-color 0.15s;
    gap: 1rem;
}

.task-card:hover { border-color: var(--text-muted); }

.task-card-left { display: flex; align-items: flex-start; gap: 0.75rem; flex: 1; min-width: 0; }
.task-card-right { display: flex; align-items: center; gap: 0.75rem; flex-shrink: 0; }

.task-card-content { flex: 1; min-width: 0; }
.task-title { font-size: 0.875rem; font-weight: 500; color: var(--text-bright); display: flex; align-items: center; gap: 0.5rem; }
.task-key { font-family: var(--font-mono, 'SF Mono', 'Fira Code', monospace); font-size: 0.7rem; font-weight: 600; color: var(--accent); background: rgba(99, 102, 241, 0.1); padding: 0.1rem 0.4rem; border-radius: 3px; white-space: nowrap; letter-spacing: 0.02em; }
.task-category { font-size: 0.6rem; font-weight: 600; padding: 0.1rem 0.35rem; border-radius: 3px; text-transform: uppercase; letter-spacing: 0.03em; }
.task-category-feature { background: rgba(56, 139, 253, 0.15); color: var(--accent); }
.task-category-bugfix { background: rgba(248, 81, 73, 0.15); color: var(--red); }
.task-category-chore { background: rgba(139, 148, 158, 0.15); color: var(--text-muted); }
.task-category-docs { background: rgba(63, 185, 80, 0.15); color: var(--green); }
.task-category-hotfix { background: rgba(210, 153, 34, 0.15); color: var(--orange); }
.task-category-surface { background: rgba(147, 101, 255, 0.15); color: var(--purple); text-transform: none; }
.task-category-session { background: rgba(56, 139, 253, 0.22); color: var(--accent); text-transform: none; }
.task-category-operator { background: rgba(248, 81, 73, 0.22); color: var(--red); text-transform: none; }
.task-effort { font-size: 0.6rem; color: var(--text-muted); font-weight: 500; }
.task-pr-link { font-size: 0.75rem; color: var(--accent); text-decoration: none; font-weight: 500; }
.task-pr-link:hover { text-decoration: underline; }
.task-description { font-size: 0.75rem; color: var(--text-muted); margin-top: 0.25rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.task-meta { display: flex; gap: 1rem; margin-top: 0.375rem; }
.task-due { color: var(--yellow); font-size: 0.75rem; }
.task-cost { font-size: 0.75rem; color: var(--text-muted); font-family: monospace; }

.task-actions { display: flex; gap: 0.25rem; opacity: 0; transition: opacity 0.15s; }
.task-card:hover .task-actions { opacity: 1; }

.task-completed { opacity: 0.55; }
.task-completed:hover { opacity: 0.8; }
.task-completed .task-title { text-decoration: line-through; text-decoration-color: var(--text-muted); }

.completed-section { margin-top: 1.5rem; border-top: 1px solid var(--border); padding-top: 0.75rem; }
.completed-toggle {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 0.8rem;
    font-weight: 500;
    cursor: pointer;
    padding: 0.25rem 0;
    margin-bottom: 0.5rem;
}
.completed-toggle:hover { color: var(--text-bright); }
.completed-chevron { transition: transform 0.2s; }
.completed-section.collapsed .completed-chevron { transform: rotate(-90deg); }
.completed-section.collapsed .completed-list { display: none; }

.priority-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    margin-top: 0.375rem;
    flex-shrink: 0;
}

.priority-dot.priority-1 { background: var(--red); box-shadow: 0 0 6px rgba(248,81,73,0.4); }
.priority-dot.priority-2 { background: var(--orange); }
.priority-dot.priority-3 { background: var(--yellow); }
.priority-dot.priority-4 { background: var(--text-muted); }
.priority-dot.priority-5 { background: var(--border); }

/* ── Badges ──────────────────────────────────────────── */
.badge {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    border-radius: 12px;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: capitalize;
    white-space: nowrap;
}

.badge-pending { background: var(--badge-pending-bg); color: var(--text-muted); }
.badge-in_progress, .badge-in-progress { background: var(--badge-inprogress-bg); color: var(--accent); }
.badge-completed { background: var(--badge-completed-bg); color: var(--green); }
.badge-info { background: var(--badge-inprogress-bg); color: var(--accent); }
.badge-warning { background: var(--badge-warning-bg); color: var(--yellow); }
.badge-error { background: var(--badge-error-bg); color: var(--red); }
.badge-critical { background: var(--badge-critical-bg); color: var(--badge-critical-fg); }
/* JARVIS-23: visibility badge — private teams visible only to members */
.badge-private { background: var(--badge-private-bg); color: var(--purple); border: 1px solid rgba(188,140,255,0.25); }

/* ── Status Select ──────────────────────────────────── */
.status-select {
    appearance: none;
    -webkit-appearance: none;
    border: none;
    padding: 0.125rem 1.25rem 0.125rem 0.5rem;
    border-radius: 12px;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: capitalize;
    white-space: nowrap;
    cursor: pointer;
    outline: none;
    background-repeat: no-repeat;
    background-position: right 0.35rem center;
    background-size: 10px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%238b949e' stroke-width='2.5'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    transition: opacity 0.15s;
}
.status-select:hover { opacity: 0.85; }
.status-select:focus { box-shadow: 0 0 0 1px var(--accent); }
.status-select.status-pending { background-color: var(--badge-pending-bg); color: var(--text-muted); }
.status-select.status-in_progress { background-color: var(--badge-inprogress-bg); color: var(--accent); }
.status-select.status-review { background-color: var(--status-review-bg); color: var(--green); }
.status-select.status-blocked { background-color: var(--status-blocked-bg); color: var(--orange); }
.status-select.status-manual { background-color: var(--status-manual-bg); color: var(--status-manual-text); }
.status-select.status-completed { background-color: var(--badge-completed-bg); color: var(--green); }
.status-select option { background: var(--surface); color: var(--text-base); }

/* ── Admin Page ──────────────────────────────────────── */
.admin-status-bar {
    display: flex;
    gap: 1rem;
    padding: 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    margin-bottom: 1.5rem;
    align-items: center;
    flex-wrap: wrap;
}
.admin-status-item { display: flex; flex-direction: column; gap: 0.25rem; flex: 1; min-width: 100px; }
.admin-status-label { font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); }
.admin-status-value { font-size: 1rem; font-weight: 600; color: var(--text-bright); }
.admin-status-value.status-running { color: var(--green); }
.admin-status-value.status-paused { color: var(--red); }
.admin-status-value.status-warn { color: var(--orange); }
.admin-bulk-actions { display: flex; gap: 0.5rem; margin-bottom: 1rem; flex-wrap: wrap; }
.admin-section { margin-bottom: 1.5rem; }
.admin-section h2 { font-size: 1rem; margin-bottom: 0.75rem; }
.btn-danger-fill { background: var(--red); color: #fff; border: none; padding: 0.375rem 1rem; border-radius: var(--radius-sm); cursor: pointer; font-weight: 600; font-size: 0.8rem; }
.btn-danger-fill:hover { opacity: 0.85; }
.btn-success { background: var(--green); color: #fff; border: none; padding: 0.375rem 1rem; border-radius: var(--radius-sm); cursor: pointer; font-weight: 600; font-size: 0.8rem; }
.task-agent { font-size: 0.75rem; color: var(--accent); }
.checkbox-label { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8125rem; color: var(--text-muted); cursor: pointer; }
.checkbox-label input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); }

/* ── Messages ────────────────────────────────────────── */
.message-list, .notif-list { display: flex; flex-direction: column; gap: 0.5rem; }

.message, .notif {
    padding: 0.875rem 1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    background: var(--surface);
    transition: border-color 0.15s;
}

.message:hover, .notif:hover { border-color: var(--text-muted); }

.unread { border-left: 3px solid var(--accent); }
.message-list.hide-read .message-read { display: none; }
.notif-list.hide-read .notif-read { display: none; }

.message-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.25rem; gap: 0.5rem; }
.message-header strong { color: var(--text-bright); }
.message-header-right { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; }
.message-from { font-size: 0.75rem; color: var(--text-muted); margin-bottom: 0.375rem; }
.message-body {
    color: var(--text-muted);
    font-size: 0.8125rem;
    line-height: 1.5;
    /* List view: clamp to 3 lines with ellipsis. Full body opens in a
       modal via openMessageDetail() — see app.js. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}
.message-clickable { cursor: pointer; }
.message-clickable:hover { background: rgba(255, 255, 255, 0.02); }

/* Detail modal layout — see openMessageDetail() in app.js. */
.message-detail-meta {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: 0.8125rem;
    color: var(--text-muted);
    margin-bottom: 1rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--border);
    flex-wrap: wrap;
}
.message-detail-body {
    color: var(--text);
    font-size: 0.9375rem;
    line-height: 1.55;
}
.message-detail-body > :first-child { margin-top: 0; }
.message-detail-body > :last-child { margin-bottom: 0; }
.message-detail-body p { margin: 0 0 0.75rem; }
.message-detail-body pre {
    background: var(--code-bg);
    padding: 0.75rem 1rem;
    border-radius: 6px;
}
.message-detail-body code {
    background: rgba(255, 255, 255, 0.06);
    padding: 0.1rem 0.35rem;
    border-radius: 3px;
    font-size: 0.875em;
}
.message-detail-body pre code {
    background: transparent;
    padding: 0;
}

/* ── Notifications ───────────────────────────────────── */
.notif-header { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
.notif-header-left { display: flex; align-items: center; gap: 0.5rem; }
.notif-header-left strong { color: var(--text-bright); }
.notif-header-right { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; }
.notif-body { margin-top: 0.375rem; color: var(--text-muted); font-size: 0.8125rem; }

.severity-info { border-left: 3px solid var(--accent); }
.severity-warning { border-left: 3px solid var(--yellow); }
.severity-error { border-left: 3px solid var(--red); }
.severity-critical { border-left: 3px solid #ff7b72; background: rgba(248,81,73,0.05); }

/* ── Reminders ───────────────────────────────────────── */
.reminder-list-cards { display: flex; flex-direction: column; gap: 0.5rem; }

.reminder-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    gap: 1rem;
}

.reminder-card-left { display: flex; align-items: center; gap: 1rem; flex: 1; min-width: 0; }
.reminder-time { color: var(--accent); font-family: monospace; font-size: 0.8125rem; white-space: nowrap; }
.reminder-message { font-size: 0.875rem; color: var(--text); overflow-wrap: anywhere; min-width: 0; }

/* Narrow viewports: stack time / message / button vertically so the
   button doesn't steal horizontal space from a long message and the
   Complete label doesn't get overrun. 640px catches phones AND
   narrow tablet windows without disturbing desktop. */
@media (max-width: 640px) {
    .reminder-card {
        flex-direction: column;
        align-items: stretch;
        gap: 0.5rem;
    }
    .reminder-card-left {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.25rem;
    }
    .reminder-card .btn {
        align-self: flex-start;
    }
}

/* ── Date ────────────────────────────────────────────── */
.date { color: var(--text-muted); font-size: 0.75rem; white-space: nowrap; }

.empty { color: var(--text-muted); font-size: 0.875rem; font-style: italic; padding: 2rem 0; text-align: center; }

.text-muted { color: var(--text-muted); }

/* ── Modal ───────────────────────────────────────────── */
.modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.6);
    backdrop-filter: blur(4px);
    z-index: 200;
    align-items: center;
    justify-content: center;
}

.modal-overlay.open { display: flex; }

.modal {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    width: 90%;
    max-width: 720px;
    max-height: 90vh;
    overflow-y: auto;
    box-shadow: var(--shadow-lg);
}

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem 1.25rem;
    border-bottom: 1px solid var(--border);
}

.modal-header h3 { font-size: 1rem; color: var(--text-bright); font-weight: 600; }

.modal-close {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 1.5rem;
    cursor: pointer;
    line-height: 1;
    padding: 0 0.25rem;
}

.modal-close:hover { color: var(--text); }

.modal-body { padding: 1.25rem; }

/* ── Form ────────────────────────────────────────────── */
.form-group { margin-bottom: 1rem; }
.form-group label {
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 0.375rem;
}

.form-group input,
.form-group select,
.form-group textarea {
    width: 100%;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text);
    font-family: inherit;
    transition: border-color 0.15s;
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(88,166,255,0.15);
}

.form-group textarea { min-height: 80px; resize: vertical; }

.form-group select { cursor: pointer; }

.form-row { display: flex; gap: 1rem; }
.form-row .form-group { flex: 1; }

.form-actions { display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1.25rem; padding-top: 1rem; border-top: 1px solid var(--border); }

/* ── Toast ───────────────────────────────────────────── */
#toast-container {
    position: fixed;
    bottom: 1.5rem;
    right: 1.5rem;
    z-index: 300;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.toast {
    padding: 0.75rem 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: 0.8125rem;
    color: var(--text);
    box-shadow: var(--shadow-lg);
    animation: toast-in 0.3s ease;
    max-width: 360px;
}

.toast.toast-success { border-left: 3px solid var(--green); }
.toast.toast-error { border-left: 3px solid var(--red); }

@keyframes toast-in {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ── Assistant Page ──────────────────────────────────── */
.assistant-briefing {
    display: flex;
    gap: 1.5rem;
    margin-bottom: 2rem;
    align-items: stretch;
}

.assistant-briefing-main {
    flex: 1;
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 1.25rem;
    height: 600px;
    display: flex;
    flex-direction: column;
}

.assistant-briefing-main h2 { margin: 0 0 0.5rem; font-size: 1.0625rem; }

.assistant-briefing-meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.assistant-briefing-main .docs-rendered {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
}

.assistant-briefing-sidebar {
    width: 280px;
    min-width: 280px;
    height: 600px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* Mobile: stack briefing above sidebar. Without this, the flex row's
   min-content width (main + 280px sidebar) exceeds the container, the
   sidebar gets clipped past the right viewport edge, and the main panel
   *looks* like it bleeds to the window edge because the flex container
   itself widened past .container's padding. */
@media (max-width: 768px) {
    .assistant-briefing {
        flex-direction: column;
        gap: 1rem;
    }
    .assistant-briefing-main {
        height: auto;
        max-height: 65vh;
        min-width: 0;
    }
    .assistant-briefing-sidebar {
        width: 100%;
        min-width: 0;
        height: auto;
        max-height: none;
    }

    /* JARVIS-150: stacked sidebar blocks get a capped height with internal scroll
       so the page keeps its shape and the next block stays reachable without
       scrolling through an entire list. Desktop layout unchanged. */
    .assistant-briefing-sidebar .assistant-sidebar-section {
        max-height: 40vh;
        overflow-y: auto;
    }
}

/* Reminders view — borrows .assistant-task-item / .todo-due chrome.
   .reminder-overdue paints the chip red so overdue items stand out. */
/* No onclick on reminder rows — only the dismiss button is actionable.
   Selectors include .assistant-task-item to win on specificity over the
   parent rule, which appears later in the file with cursor: pointer and
   a brighter hover background. */
.assistant-task-item.reminder-item { position: relative; cursor: default; }
.assistant-task-item.reminder-item:hover {
    background: var(--bg-secondary, #141418);
    border-color: var(--border, #2a2a30);
}
.reminder-overdue {
    color: var(--red, #f85149);
    font-weight: 600;
}
.reminder-dismiss {
    appearance: none;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-muted);
    width: 28px;
    height: 28px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    align-self: center;
    flex-shrink: 0;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.reminder-dismiss:hover {
    background: var(--green-muted, #238636);
    color: var(--text-bright, #f0f6fc);
    border-color: var(--green-muted, #238636);
}
.reminder-dismiss:disabled { cursor: default; opacity: 0.5; }
.reminder-dismissing { opacity: 0.4; pointer-events: none; }

.assistant-sidebar-section {
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 1rem;
}

.assistant-sidebar-section h3 { margin: 0 0 0.75rem; font-size: 0.9375rem; }

.assistant-task-list { display: flex; flex-direction: column; gap: 0.5rem; }

.assistant-task-item {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    font-size: 0.8125rem;
    padding: 0.5rem 0.625rem;
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border, #2a2a30);
    border-radius: 4px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}

.assistant-task-item:hover {
    background: var(--bg-hover, #1e1e24);
    border-color: var(--border-light, #3a3a42);
}

.assistant-task-title { color: var(--text); }

.assistant-inbox-counts { display: flex; flex-direction: column; gap: 0.5rem; }

.assistant-inbox-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.assistant-inbox-item.has-unread { color: var(--text); font-weight: 600; }

.assistant-inbox-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 999px;
    background: var(--bg-secondary);
    font-size: 0.75rem;
}

.has-unread .assistant-inbox-count { background: var(--accent); color: #fff; }

/* ── Task Detail Modal ───────────────────────────────── */
.task-card-clickable { cursor: pointer; transition: background 0.15s; }
.task-card-clickable:hover { background: var(--bg-hover, #1e1e24); }

.task-detail { font-size: 0.875rem; }

.task-detail-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.task-detail-badge {
    font-size: 0.75rem;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    background: var(--bg-secondary, #141418);
    color: var(--text-muted);
}

.task-detail-badge.status-pending { background: var(--badge-pending-bg); color: #9ca3af; }
.task-detail-badge.status-in_progress { background: #1e3a8a; color: #93c5fd; }
.task-detail-badge.status-review { background: #3a2a1a; color: #fbbf24; }
.task-detail-badge.status-blocked { background: #3a1a1a; color: #fca5a5; }
.task-detail-badge.status-completed { background: var(--badge-completed-bg); color: #6ee7b7; }

.task-detail-badge.priority-1 { background: #3a1a1a; color: #fca5a5; }
.task-detail-badge.priority-2 { background: #3a2a1a; color: #fbbf24; }

.task-detail-dates {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-bottom: 0.5rem;
}

.task-detail-links {
    font-size: 0.8125rem;
    margin-bottom: 1rem;
}
.task-detail-links a { color: var(--accent-text, #6ea8fe); }

.task-detail-section {
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
}
.task-detail-section h4 {
    margin: 0 0 0.625rem;
    font-size: 0.6875rem;
    color: var(--text-muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.task-detail-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
}
.task-detail-section-header h4 { margin: 0; }

/* ─── Sub-tickets (parent rows on team page) ─── */
.task-card-group { display: flex; flex-direction: column; gap: 0.25rem; }
.subtask-toggle {
    align-self: flex-start;
    margin-left: 1.5rem;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 0.8125rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.125rem 0.375rem;
    border-radius: 3px;
}
.subtask-toggle:hover { color: var(--text); background: var(--bg-hover, #1e1e24); }
.subtask-chevron { transition: transform 0.15s; }
.subtask-toggle[aria-expanded="true"] .subtask-chevron { transform: rotate(90deg); }
.subtask-list {
    margin-left: 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    border-left: 2px solid var(--border, #2a2a30);
    padding-left: 0.75rem;
}
.subtask-list .task-card { padding: 0.5rem 0.75rem; font-size: 0.8125rem; }

/* ─── Sub-ticket rows inside detail modal ─── */
.task-subtask-list { display: flex; flex-direction: column; gap: 0.25rem; margin: 0.5rem 0; }
.task-subtask-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.375rem 0.625rem;
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border, #2a2a30);
    border-radius: 4px;
    font-size: 0.8125rem;
}
.task-subtask-title { flex: 1; min-width: 0; color: var(--text); overflow: hidden; text-overflow: ellipsis; }
.task-subtask-title.task-subtask-completed { text-decoration: line-through; color: var(--text-muted); }

.task-detail-description {
    line-height: 1.6;
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 0.875rem 1rem;
    color: var(--text);
}
.task-detail-description > :first-child { margin-top: 0; }
.task-detail-description > :last-child { margin-bottom: 0; }
.task-detail-description p { margin: 0.5rem 0; }
.task-detail-description pre {
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 0.5rem;
    overflow-x: auto;
    font-size: 0.8125rem;
}

.task-comments {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin-bottom: 1rem;
    max-height: 400px;
    overflow-y: auto;
}

.task-comment {
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 0.625rem 0.75rem;
    background: var(--bg-secondary, #141418);
}

.task-comment-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-bottom: 0.375rem;
}

.task-comment-author { font-weight: 600; color: var(--text); }
.task-comment-date { flex: 1; }

.task-comment-delete {
    opacity: 0;
    font-size: 1rem;
    padding: 0 0.25rem;
    transition: opacity 0.15s;
}
.task-comment:hover .task-comment-delete { opacity: 1; }

.task-comment-body {
    font-size: 0.8125rem;
    line-height: 1.5;
}
.task-comment-body p { margin: 0.25rem 0; }

.task-comment-form textarea {
    width: 100%;
    min-height: 80px;
    padding: 0.5rem;
    background: var(--bg-input, #1e1e24);
    border: 1px solid var(--border);
    border-radius: 4px;
    color: var(--text);
    font-family: inherit;
    font-size: 0.8125rem;
    resize: vertical;
    box-sizing: border-box;
}

/* Sidebar Toggle */
.sidebar-toggle {
    margin-bottom: 0.75rem;
}

.sidebar-toggle-select {
    width: 100%;
    padding: 0.375rem 1.75rem 0.375rem 0.625rem;
    font-size: 0.8125rem;
    font-weight: 600;
    font-family: inherit;
    color: var(--text, #e6e6e6);
    background-color: var(--bg-secondary, #141418);
    border: 1px solid var(--border);
    border-radius: 6px;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    /* Chevron drawn as an inline SVG so it themes with --text-muted and
       needs no extra markup. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238b949e' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.625rem center;
    transition: border-color 0.15s;
}

.sidebar-toggle-select:hover {
    border-color: var(--border-light, #3a3a42);
}

.sidebar-toggle-select:focus {
    outline: none;
    border-color: var(--accent, #e94560);
}

.form-hint {
    font-size: 0.6875rem;
    color: var(--text-muted);
    font-weight: normal;
    margin-left: 0.25rem;
}

/* Personal To-Do List */
.todo-list { display: flex; flex-direction: column; gap: 0.5rem; }

.todo-item {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    font-size: 0.8125rem;
    padding: 0.5rem 0.625rem;
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border, #2a2a30);
    border-radius: 4px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}

.todo-item:hover {
    background: var(--bg-hover, #1e1e24);
    border-color: var(--border-light, #3a3a42);
}

.todo-item-content {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    flex: 1;
    min-width: 0;
}

.todo-item-header {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    flex-wrap: wrap;
}

.todo-item-header .initiative-chip { margin-left: 0; }
.todo-item-header .initiative-chip-none { background: transparent; border: 1px dashed var(--border); color: var(--text-muted); }

.todo-title {
    color: var(--text-muted);
    font-weight: 500;
    line-height: 1.3;
    word-break: break-word;
}

.todo-meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    font-size: 0.6875rem;
}

.todo-recurrence {
    color: var(--accent-text, #6ea8fe);
    flex-shrink: 0;
    font-size: 0.7rem;
    font-weight: 500;
}

/* Inline mark-done control on a to-do card (parity with the Tasks status-select,
   but a to-do is binary done/not-done). A subtle pill button rather than a bare
   checkbox so it reads as actionable and fits the dark palette. */
.todo-done-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.3125rem;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--text-muted);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 0.25rem 0.5rem;
    cursor: pointer;
    white-space: nowrap;
    user-select: none;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.todo-done-toggle:hover {
    color: var(--green);
    border-color: var(--green);
    background: rgba(63,185,80,0.1);
}
.todo-done-toggle:disabled { opacity: 0.6; cursor: default; }

.todo-due {
    color: var(--text-muted);
    background: var(--bg, #0d0d11);
    padding: 0.125rem 0.375rem;
    border-radius: 3px;
    flex-shrink: 0;
}

.status-badge.status-overdue { background: #3a1a1a; color: #fca5a5; }
.status-badge.status-today { background: #3a2a1a; color: #fbbf24; }
.status-badge.status-scheduled { background: #1e3a8a; color: #93c5fd; }
.status-badge.status-open { background: var(--badge-pending-bg); color: #9ca3af; }

/* ── Todo detail modal ─────────────────────────────── */
.todo-card { cursor: pointer; }

.todo-detail-status { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.75rem; }

.badge-priority-1 { background: var(--red); color: #fff; }
.badge-priority-2 { background: var(--orange); color: #fff; }
.badge-priority-3 { background: var(--yellow); color: var(--bg); }
.badge-priority-4 { background: var(--border); color: var(--text); }
.badge-priority-5 { background: var(--border-light); color: var(--text-muted); }

.todo-detail-dates {
    display: flex; gap: 1.5rem; flex-wrap: wrap;
    font-size: 0.75rem; color: var(--text-muted);
    padding-bottom: 0.75rem; margin-bottom: 0.75rem;
    border-bottom: 1px solid var(--border);
}

.todo-detail-section { margin-bottom: 1rem; }
.todo-detail-section h4 { font-size: 0.8125rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 0.5rem; }

.todo-comments { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 0.75rem; }
.todo-comment { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.5rem 0.75rem; }
.todo-comment-meta { display: flex; justify-content: space-between; font-size: 0.75rem; color: var(--text-muted); margin-bottom: 0.25rem; }
.todo-comment-body { font-size: 0.8125rem; color: var(--text); }
.todo-comment-body p { margin: 0; }

.todo-has-desc { font-size: 0.6875rem; flex-shrink: 0; }

/* Report Library — reuses .docs-layout, .docs-sidebar, .docs-tree, .docs-content, .docs-viewer */
.assistant-library { margin-bottom: 2rem; }
.assistant-library h2 { margin-bottom: 1rem; }

.status-badge {
    font-size: 0.6875rem;
    padding: 0.125rem 0.375rem;
    border-radius: 3px;
    background: var(--bg-secondary);
    color: var(--text-muted);
}

/* Badge variants */
.badge-type { background: var(--accent-bg, #0f3460); color: var(--accent-text, #6ea8fe); }
.badge-n8n { background: var(--badge-completed-bg); color: #6ee7b7; }
.badge-claude { background: var(--badge-private-bg); color: #c4b5fd; }
.badge-manual { background: var(--badge-pending-bg); color: var(--text-muted); }
.badge-pinned { background: var(--badge-warning-bg); color: #fbbf24; }
.badge-healthy { background: var(--badge-completed-bg); color: #6ee7b7; }
.badge-never { background: var(--badge-pending-bg); color: var(--text-muted); }

/* Workflow Schedule Table */
.assistant-workflows { margin-bottom: 2rem; }

.assistant-schedule-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.assistant-schedule-table th {
    text-align: left;
    padding: 0.5rem 0.75rem;
    border-bottom: 2px solid var(--border);
    color: var(--text-muted);
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.assistant-schedule-table td {
    padding: 0.625rem 0.75rem;
    border-bottom: 1px solid var(--border);
}

/* ── Team Prioritization (UI-8) ──────────────────────── */
.assistant-prioritization { margin-bottom: 2rem; }
.assistant-prioritization h2 { margin-bottom: 1rem; }

/* FAQ-style accordion (2026-07-20): the per-lead editor slots directly UNDER the clicked
   row and expands, like an FAQ item. openLeadModal() moves #lead-modal in the DOM to sit
   after the row and toggles .open; the grid-template-rows 0fr->1fr trick animates to the
   content's natural height with no JS measurement and no clipping. Collapsed = 0 height =
   invisible; on close the drawer is parked back outside the flex list so it leaves no gap. */
.lead-accordion {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .28s ease;
}
.lead-accordion.open { grid-template-rows: 1fr; }
.lead-accordion-inner {
    overflow: hidden;   /* clips the panel while the grid row collapses to 0 */
    min-height: 0;
    opacity: 0;
    transition: opacity .2s ease .04s;
}
.lead-accordion.open .lead-accordion-inner { opacity: 1; }
/* the editor card itself (was a centered modal panel): full width, no viewport caps,
   an accent rail tying it to the row above; border/padding/inputs inherit from
   .lead-modal-panel unchanged. */
.lead-accordion-inner > .lead-modal-panel {
    max-width: none;
    width: 100%;
    max-height: none;
    margin: .4rem 0 .3rem;
    border-left: 3px solid var(--accent);
}
/* the row whose drawer is open */
.prio-row.selected {
    border-color: var(--accent);
    background: var(--accent-muted);
}

.prioritization-list {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}

.prioritization-slot {
    display: flex;
    align-items: flex-start;
    gap: 0.875rem;
    padding: 0.875rem 1rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    transition: border-color 0.15s;
}

.prioritization-slot:hover { border-color: var(--text-muted); }

.prioritization-rank {
    flex-shrink: 0;
    width: 1.875rem;
    height: 1.875rem;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--text-bright);
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 50%;
}

.prioritization-fields {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.prioritization-lead-select,
.prioritization-notes {
    width: 100%;
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text);
    font-family: inherit;
    transition: border-color 0.15s;
}

.prioritization-lead-select { cursor: pointer; }

.prioritization-notes { min-height: 48px; resize: vertical; line-height: 1.45; }

.prioritization-lead-select:focus,
.prioritization-notes:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(88,166,255,0.15);
}

.prioritization-reorder {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.prioritization-reorder .btn-icon:disabled {
    opacity: 0.3;
    cursor: default;
}

.prioritization-reorder .btn-icon:disabled:hover {
    color: var(--text-muted);
    background: none;
}

/* ── Lead Prioritization rows (2026-07-04) ──────────── */
.prio-row { display:flex; gap:.75rem; align-items:center; padding:.5rem .75rem;
    border:1px solid var(--border); border-radius:var(--radius-sm);
    background:var(--surface); margin-bottom:.4rem; cursor:pointer; }
.prio-row:hover { border-color:var(--accent); }
.prio-rank { width:1.5rem; text-align:center; font-weight:600; }
.prio-tier { font-size:.7rem; color:var(--text-muted); }
.prio-name { flex:0 0 8rem; font-weight:600; }
.prio-focus { flex:1; color:var(--text-muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Lead-level activity rollup (JARVIS-129): last event across ALL the teams the
   lead owns + a 7-day count. Muted — it is a liveness hint, not a metric. */
.prio-activity { flex-shrink:0; font-size:.75rem; color:var(--text-muted); white-space:nowrap; }
.prio-reqs { font-size:.75rem; color:var(--accent); }
.prio-status-btn { flex-shrink:0; margin-left:.25rem; font-size:.8rem; line-height:1; }

/* JARVIS-173: red-resource health indicator on the lead Prioritization rows.
   A small red dot + count, right-aligned, rendered ONLY when the lead's team
   has at least one red Infrastructure/GitHub resource (0 red = no dot, so no
   layout shift when absent). Clicking navigates to the red team-page section. */
.prio-health { flex-shrink:0; display:inline-flex; align-items:center; gap:.3rem;
    margin-left:.5rem; font-size:.75rem; font-weight:600; color:var(--red);
    text-decoration:none; }
.prio-health:hover { text-decoration:underline; }
.prio-health-dot { width:.5rem; height:.5rem; border-radius:50%; background:var(--red);
    box-shadow:0 0 6px rgba(248,81,73,0.4); }
.prio-health-count { font-variant-numeric: tabular-nums; }

/* Open / review ticket chips (JARVIS-153): the lead's backlog and the
   operator's merge queue, summed across the lead's teams. Plain .badge so they
   match every other count pill in the app. */
.prio-chips { flex-shrink:0; display:flex; gap:.3rem; align-items:center; }

/* Drop indicator (JARVIS-154). The drop target is the list container, so the
   gap between two rows is live; this line says which boundary a release will
   land on. Drawn with box-shadow rather than a border so it costs no layout
   and cannot nudge the rows around mid-drag. */
.prio-row.prio-drop-before { box-shadow: 0 -3px 0 0 var(--accent); }
.prio-row.prio-drop-after  { box-shadow: 0 3px 0 0 var(--accent); }
.prio-row.prio-dragging    { opacity:.45; }

/* ── Inactive leads zone (lead deactivation, 2026-07-10) ── */
.prio-inactive-section { margin-top: 1rem; margin-bottom: 0; }
.prio-inactive-section .lead-subhead {
    margin: 0 0 .5rem;
    font-size: .8rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: .05em;
}
.prio-inactive-section .lead-section-body { padding-top: .1rem; }
.prio-row-inactive { opacity: .65; }
.prio-row-inactive:hover { opacity: 1; }
.prio-row-inactive .prio-name { color: var(--text-muted); }

/* Narrow screens: the row is a single nowrap flex line, and the ticket chips
   (JARVIS-153) are one cell too many for it. Let it wrap and give the free-text
   context snippet its own line; below 480px drop the snippet altogether — the
   counts and the activity hint are what the row is scanned for, and the note is
   one tap away in the drawer. */
/* The row is one nowrap flex line, and the ticket chips (JARVIS-153) are one
   cell too many for a phone. Wrap it into fixed lines rather than letting each
   row find its own wrap point — identical structure per row is what makes a
   stack of them scannable. Line 1: rank · tier · name, counts pinned right.
   Line 2: activity hint · request count · the pause/resume control. Line 3: the
   free-text context snippet, which drops out entirely below 480px — the counts
   are what the row is scanned for and the note is one tap away in the drawer.
   The ::after is a zero-height full-width flex item: the standard way to force
   a line break at a chosen point in a wrapping flex container. */
@media (max-width: 768px) {
    .prio-row { flex-wrap: wrap; gap: .35rem .6rem; }
    .prio-rank { order: 1; }
    .prio-tier { order: 2; }
    .prio-name { order: 3; flex: 0 1 auto; }
    .prio-chips { order: 4; margin-left: auto; }
    .prio-row::after { content: ""; order: 5; flex: 1 0 100%; height: 0; }
    .prio-activity { order: 6; }
    .prio-reqs { order: 7; }
    .prio-health { order: 8; }
    .prio-status-btn { order: 8; margin-left: auto; }
    .prio-focus { order: 9; flex: 1 1 100%; }
}
@media (max-width: 480px) {
    .prio-focus { display: none; }
    .prio-activity { font-size: .7rem; }
}

/* ── Per-lead modal (Task 7 / 2026-07-04) ──────────────────────────────── */
.lead-modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
}
.lead-modal-panel {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 1.5rem;
    max-width: 640px;
    width: 90%;
    max-height: 85vh;
    overflow: auto;
    position: relative;
}
.lead-modal-panel h2 { margin-top: 0; margin-bottom: 1rem; }
.lead-modal-panel h3 { font-size: 0.875rem; color: var(--text-muted); text-transform: uppercase;
    letter-spacing: .04em; margin: 1.25rem 0 .5rem; }
.lead-modal-panel section { margin-bottom: 1rem; }
.lead-modal-close {
    position: absolute;
    top: .75rem;
    right: .75rem;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 1.25rem;
    cursor: pointer;
    line-height: 1;
    padding: .25rem .5rem;
}
.lead-modal-close:hover { color: var(--text); }
.lead-modal-actions { display: flex; justify-content: flex-end; margin-top: 1rem; }
/* Modal form controls — match the app surface instead of browser-default white. */
.lead-modal-panel input,
.lead-modal-panel textarea {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text);
    padding: .375rem .5rem;
    font: inherit;
    font-size: .8125rem;
}
.lead-modal-panel input:focus,
.lead-modal-panel textarea:focus { outline: none; border-color: var(--accent); }
.lm-req .btn { margin-right: .375rem; margin-top: .375rem; }
#lm-note { width: 100%; box-sizing: border-box; min-height: 120px; }
.lm-saved-flash {
    font-size: .75rem;
    font-weight: 500;
    color: var(--green, #22c55e);
    margin-left: .5rem;
    vertical-align: middle;
}
.lm-req {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: .625rem .75rem;
    margin-bottom: .5rem;
    background: var(--surface);
}
.lm-req p { margin: .25rem 0 .5rem; font-size: .875rem; color: var(--text-muted); }
.lm-req-type {
    font-size: .7rem;
    background: var(--bg-elevated, #1c1c22);
    border: 1px solid var(--border);
    border-radius: 3px;
    padding: .1rem .35rem;
    margin-left: .35rem;
    color: var(--text-muted);
}
/* Inline note form inside modal requests */
.lm-req-note-form {
    margin-top: .5rem;
    padding: .5rem .6rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}
.lm-req-note-form label { display: block; font-size: .75rem; color: var(--text-muted); margin-bottom: .3rem; }
.lm-req-note-form textarea {
    width: 100%; box-sizing: border-box;
    padding: .35rem .5rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text);
    font-size: .85rem;
    resize: vertical;
}
.lm-req-note-form .lm-req-note-btns { display: flex; gap: .4rem; justify-content: flex-end; margin-top: .4rem; }

/* ── Lead dropdown: drop the panel from the top instead of centering it ───── */
.lead-modal-backdrop { align-items: flex-start; }
.lead-modal-panel {
    margin-top: 4.5rem;
    max-height: calc(100vh - 6rem);
    box-shadow: var(--shadow-lg);
    animation: lm-drop .16s ease;
}
@keyframes lm-drop { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .lead-modal-panel { animation: none; } }
/* Priorities editor — a roomier 8–10 line box (rows=9 in markup). */
#lm-note { min-height: 11.5rem; line-height: 1.55; }

/* ── Collapsible request rows: title-only until opened ────────────────────── */
.lm-req { padding: 0; overflow: hidden; }         /* header/body own their padding */
.lm-req-title {
    display: flex; align-items: center; gap: .5rem;
    padding: .45rem .6rem; cursor: pointer; user-select: none;
}
.lm-req-title:hover { background: var(--surface-hover); }
.lm-req-title:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.lm-req-caret { flex: none; font-size: .6rem; color: var(--text-muted); transition: transform .15s; }
.lm-req.open .lm-req-caret { transform: rotate(90deg); }
.lm-req-t {
    font-size: .8125rem; font-weight: 500; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;   /* collapsed = one line */
}
.lm-req.open .lm-req-t { white-space: normal; }
.lm-req-type { flex: none; margin-left: auto; }
.lm-req-body { display: none; padding: 0 .6rem .55rem 1.75rem; }
.lm-req.open .lm-req-body { display: block; }
.lm-req-body p { margin: .1rem 0 .5rem; font-size: .8125rem; color: var(--text-muted); }
/* JARVIS-155: approve-with-action notice — what approving will execute, in an
   amber callout so the state change is impossible to miss in the lead modal. */
.lm-req-body .lm-req-action {
    margin: .25rem 0 .5rem;
    padding: .375rem .5rem;
    font-size: .8125rem;
    color: var(--text-bright);
    background: rgba(255, 193, 7, 0.12);
    border: 1px solid rgba(255, 193, 7, 0.4);
    border-radius: var(--radius-sm);
}
/* Per-type chip tint (semantic, not the accent) */
.lm-req-type-merge { color: var(--accent); }
.lm-req-type-decision { color: var(--purple); }
.lm-req-type-prioritize { color: var(--yellow); }
/* Resolve = go, Ignore = stop — semantic colors, distinct from the accent. */
.btn.lm-resolve { color: var(--green); border-color: color-mix(in srgb, var(--green) 45%, var(--border)); }
.btn.lm-ignore  { color: var(--red);   border-color: color-mix(in srgb, var(--red) 40%, var(--border)); }

/* Collapsible sections — used in lead modal + team Lead tab */
.lead-section { margin-bottom: .75rem; }
.lead-collapse-header { cursor: pointer; user-select: none; display: flex; align-items: center; gap: .4rem; }
.lead-caret { display: inline-block; font-size: .7rem; transition: transform .15s; color: var(--text-muted); }
.lead-section.collapsed .lead-caret { transform: rotate(-90deg); }
.lead-section.collapsed .lead-section-body { display: none; }
/* Hint line in the focus editor */
.lead-hint { font-size: .75rem; color: var(--text-muted); margin-bottom: .4rem; }
/* Team-page lead panel form controls — match the modal input styling. */
.lead-section input,
.lead-section textarea {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--text);
    padding: .375rem .5rem;
    font: inherit;
    font-size: .8125rem;
}
.lead-section input:focus,
.lead-section textarea:focus { outline: none; border-color: var(--accent); }
#lead-note { width: 100%; box-sizing: border-box; min-height: 120px; }
.ls-saved-flash {
    font-size: .75rem;
    font-weight: 500;
    color: var(--green, #22c55e);
    margin-left: .5rem;
    vertical-align: middle;
}

/* ── Team Folder Hierarchy ───────────────────────────── */
.grid-tree {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    margin-bottom: 1.5rem;
}

.folder-group {
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
}

.folder-group .folder-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.875rem 1.25rem;
    cursor: pointer;
    background: var(--bg-secondary, #141418);
    user-select: none;
    transition: background 0.15s;
}

.folder-group .folder-header:hover {
    background: var(--bg-hover, #1e1e24);
}

.folder-group .folder-header h2 {
    margin: 0;
    font-size: 1.0625rem;
}

.folder-group .folder-icon {
    font-size: 0.75rem;
    color: var(--text-muted);
    transition: transform 0.2s;
    display: inline-block;
    width: 1rem;
    text-align: center;
}

.folder-group.collapsed .folder-icon {
    transform: rotate(-90deg);
}

.folder-group .folder-description {
    color: var(--text-muted);
    font-size: 0.8125rem;
    flex: 1;
    /* JARVIS-48: the folder header is a single flex row — ellipsize long
       descriptions to one line so the header never wraps; full text on
       hover via the title attribute. min-width:0 lets the flex item shrink. */
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.folder-group .folder-count {
    font-size: 0.75rem;
    color: var(--text-muted);
    background: var(--bg-primary, #0d0d11);
    padding: 0.125rem 0.5rem;
    border-radius: 999px;
    margin-left: auto;
}

/* UI-5: folder delete trash icon. Pinned to the right edge of the header
   (margin-left:auto is a no-op when a flex:1 description already fills the
   row). Hidden until the header is hovered to keep the row uncluttered. */
.folder-group .folder-header .js-delete-folder {
    margin-left: auto;
    flex: 0 0 auto;
    opacity: 0;
    transition: opacity 0.15s, color 0.15s, background 0.15s;
}

.folder-group .folder-header:hover .js-delete-folder,
.folder-group .folder-header .js-delete-folder:focus-visible {
    opacity: 1;
}

.folder-group .folder-header .js-delete-folder:hover {
    color: var(--red);
    background: rgba(248,81,73,0.1);
}

.folder-group .folder-children {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 1rem;
    padding: 1rem 1.25rem;
}

.folder-group.collapsed .folder-children {
    display: none;
}

/* Nested folders */
.folder-group .folder-group {
    grid-column: 1 / -1;
}

/* ── JARVIS-42: drag-and-drop re-parenting ───────────────
   NOTE: functional styling only — not a designer-tuned pass.
   Drop-target highlight, drag handle, and root dropzone are
   placeholders pending a human visual review. */
.team-card .drag-handle {
    cursor: grab;
    color: var(--text-muted);
    font-size: 0.75rem;
    letter-spacing: -2px;
    /* A little more room now that the team name sits flush left beside it
       rather than floating in the middle of the header. */
    margin-right: 0.5rem;
    user-select: none;
    opacity: 0.5;
    transition: opacity 0.15s;
}

.team-card:hover .drag-handle {
    opacity: 1;
}

.team-card.dragging {
    opacity: 0.5;
}

/* Wrapper lets the Move button sit OUTSIDE the <a> (valid HTML) while still
   appearing over the card's corner. */
.team-card-wrapper {
    position: relative;
    display: flex;
}
.team-card-wrapper > .team-card {
    flex: 1;
}

.btn-move {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    z-index: 2;
    font-size: 0.7rem;
    padding: 0.125rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--bg-primary, #0d0d11);
    color: var(--text-muted);
    cursor: pointer;
    opacity: 0;
    transition: background 0.15s, color 0.15s, opacity 0.15s;
}

.team-card-wrapper:hover .btn-move,
.btn-move:focus-visible {
    opacity: 1;
}

.btn-move:hover {
    background: var(--bg-hover, #1e1e24);
    color: var(--text, #e6e6e6);
}

/* Drop-target highlight while dragging */
.js-drop-folder.drop-hover {
    outline: 2px dashed var(--accent, #6366f1);
    outline-offset: -2px;
}

.root-dropzone {
    border: 1px dashed var(--border);
    border-radius: 8px;
    padding: 0.625rem 1rem;
    margin-bottom: 1rem;
    color: var(--text-muted);
    font-size: 0.8125rem;
    text-align: center;
    transition: border-color 0.15s, background 0.15s;
}

.root-dropzone.drop-hover {
    border-color: var(--accent, #6366f1);
    background: var(--bg-hover, #1e1e24);
    color: var(--text, #e6e6e6);
}

/* ── Responsive ──────────────────────────────────────── */
@media (max-width: 768px) {
    .navbar { padding: 0.75rem 1rem; }
    .container { padding: 1rem; }
    .grid { grid-template-columns: 1fr; }
    .stats { flex-wrap: wrap; }
    .form-row { flex-direction: column; gap: 0; }
    .task-card { flex-direction: column; gap: 0.75rem; }
    .task-card-right { width: 100%; justify-content: space-between; }
    .task-actions { opacity: 1; }
    .tab { padding: 0.625rem 0.875rem; font-size: 0.8125rem; }
    .message-header { flex-direction: column; align-items: flex-start; gap: 0.375rem; }
    .notif-header { flex-direction: column; align-items: flex-start; gap: 0.375rem; }
    /* Page header: stack the action buttons below the title on narrow
       viewports so they don't fight the h1 for horizontal space. This
       applies to all pages that use .page-header (teams dashboard, etc.)
       — the flex-wrap keeps multiple buttons from overflowing. */
    .page-header { flex-direction: column; align-items: flex-start; gap: 0.75rem; }
    .page-header > div { width: 100%; display: flex; flex-wrap: wrap; gap: 0.5rem; }

    /* Team detail header: the same treatment .page-header already gets.
       Edit + Archive sat beside the title in a `space-between` row, which
       squeezed the info column to ~215px of the 366px available — so the
       description, target date and goal all wrapped inside a narrow gutter
       while 40% of the card sat empty. Stack them and the prose gets the
       full width. */
    .team-header { flex-direction: column; align-items: stretch; gap: 0.75rem; }
    .team-header-actions { flex-wrap: wrap; }

    /* Section headers (Messages, Notifications, Tasks, …) carry 2-3 controls
       next to the h2. In a `space-between` row those controls were squeezed
       until their LABELS broke mid-phrase — "Show / read", "Mark all / read",
       "+ New / Message" each on two lines. Stack the row and keep every label
       on one line; if they still don't fit they wrap as whole buttons. */
    .section-header { flex-direction: column; align-items: flex-start; gap: 0.75rem; }
    /* flex-start above keeps a lone direct-child button at its natural size
       (stretch turned "Refresh" into a full-width slab); the group below still
       gets the whole row to wrap its controls across. */
    .section-header-right { width: 100%; flex-wrap: wrap; }
    .section-header .btn,
    .section-header .read-toggle { white-space: nowrap; }
}

@media (max-width: 480px) {
    .nav-subtitle { display: none; }
    .nav-separator { display: none; }
}

/* ── Install hint (JARVIS-134) ────────────────────────────
   In-app "Add to Home Screen" banner. Some Android OEM browsers hide the
   native install prompt, so this offers it explicitly. Hidden until the
   page is standalone-capable but not yet installed; dismissible. */
#install-hint {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0.5rem 0.75rem;
    background: var(--surface);
    border: 1px solid var(--accent-muted);
    border-radius: var(--radius-sm);
    color: var(--text);
    font-size: 0.8125rem;
}
#install-hint[hidden] { display: none; }
#install-hint span { flex: 1; }

/* ── Mobile nav (JARVIS-134 → superseded by JARVIS-140) ──
   JARVIS-134 made the tab strip horizontally scrollable ("no hamburger,
   no hiding links"). Operator feedback after using it on a phone reversed
   that call: the strip reads as a website nav bar. The tabs are now a
   slide-out drawer (see the .navbar .nav-tabs block up top), so the strip
   never has to fit — the navbar stays a single row of brand + hamburger. */
@media (max-width: 768px) {
    .nav-tab {
        flex-shrink: 0;
        white-space: nowrap;
    }
}

/* ─── Docs Tab ─── */
.docs-layout {
    display: flex;
    height: calc(100vh - 200px);
    min-height: 400px;
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
}
.docs-sidebar {
    width: 240px;
    min-width: 240px;
    border-right: 1px solid var(--border);
    padding: 12px;
    overflow-y: auto;
    background: var(--bg-secondary, #141418);
}
.docs-search {
    width: 100%;
    padding: 6px 8px;
    margin-bottom: 10px;
    background: var(--bg-input, #1e1e24);
    border: 1px solid var(--border);
    border-radius: 4px;
    color: var(--text);
    font-size: 13px;
    box-sizing: border-box;
}
/* UI-7: Report Library "retros + briefings only" toggle. */
.docs-filter-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 10px;
    font-size: 12px;
    color: var(--text-muted);
    cursor: pointer;
    user-select: none;
}
.docs-filter-toggle input[type="checkbox"] {
    margin: 0;
    cursor: pointer;
    accent-color: var(--accent, #6366f1);
}
.docs-filter-toggle:hover { color: var(--text); }
.docs-tree { font-size: 13px; }
.docs-tree .folder {
    margin-bottom: 4px;
}
.docs-tree .folder-header {
    display: flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
    padding: 3px 4px;
    border-radius: 3px;
    color: var(--text-muted);
    font-weight: 600;
    font-size: 12px;
}
.docs-tree .folder-header:hover { background: var(--bg-hover, #1e1e24); }
/* Collapse affordance: a caret that points down when expanded and rotates
   to point right when the folder carries the `collapsed` class. Generated in
   CSS so both the team doc tree and the assistant report tree (which share
   these `.docs-tree` class names) get the chevron with no markup change. */
.docs-tree .folder-header::before {
    content: "";
    flex: 0 0 auto;
    width: 0;
    height: 0;
    margin-right: 2px;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid currentColor;
    transition: transform 0.15s ease;
}
.docs-tree .folder.collapsed > .folder-header::before {
    transform: rotate(-90deg);
}
.docs-tree .folder-header .folder-count {
    font-size: 10px;
    color: var(--text-muted);
    margin-left: auto;
}
.docs-tree .folder-files { padding-left: 16px; }
.docs-tree .folder.collapsed > .folder-files { display: none; }
.docs-tree .file-item {
    display: block;
    padding: 3px 6px;
    border-radius: 3px;
    cursor: pointer;
    color: var(--text);
    text-decoration: none;
    font-size: 12px;
    /* Wrap long titles to multiple lines rather than clipping with
       ellipsis. The sidebar is narrow (240px desktop, 100% mobile) and
       hidden context is worse than added height — users need the full
       title to identify the doc/report. */
    white-space: normal;
    overflow-wrap: anywhere;
    line-height: 1.35;
}
.docs-tree .file-item:hover { background: var(--bg-hover, #1e1e24); }
.docs-tree .file-item.active {
    background: var(--accent, #e94560);
    color: #fff;
}
.docs-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.docs-viewer {
    display: flex;
    flex-direction: column;
    flex: 1;
    overflow: hidden;
    min-height: 0;
}
.docs-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: var(--text-muted);
}
.docs-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 16px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.docs-title { font-weight: 600; font-size: 15px; }
.docs-path {
    font-size: 12px;
    color: var(--text-muted);
    margin-left: 8px;
}
.docs-actions { display: flex; gap: 6px; align-items: center; }
.docs-version-badge {
    font-size: 11px;
    color: var(--text-muted);
    margin-right: 4px;
}
.docs-tags {
    display: flex;
    gap: 6px;
    padding: 6px 16px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
    flex-wrap: wrap;
}
.docs-tag {
    padding: 2px 8px;
    background: var(--accent-bg, #0f3460);
    color: var(--accent-text, #6ea8fe);
    border-radius: 3px;
    font-size: 11px;
}
.docs-version-panel {
    border-bottom: 1px solid var(--border);
    padding: 10px 16px;
    max-height: 200px;
    overflow-y: auto;
    flex-shrink: 0;
    background: var(--bg-secondary, #141418);
}
.docs-version-panel-header {
    font-weight: 600;
    font-size: 13px;
    margin-bottom: 8px;
}
.docs-version-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 8px;
    border-radius: 4px;
    font-size: 12px;
}
.docs-version-item:hover { background: var(--bg-hover, #1e1e24); }
.docs-version-item.current { font-weight: 600; }
.docs-version-item .version-link {
    color: var(--accent-text, #6ea8fe);
    cursor: pointer;
    font-size: 11px;
}
.docs-rendered {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
    padding: 20px 24px;
    line-height: 1.7;
    font-size: 14px;
}
/* Markdown content styles */
.docs-rendered h1 { font-size: 22px; margin: 0 0 16px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.docs-rendered h2 { font-size: 18px; margin: 24px 0 8px; }
.docs-rendered h3 { font-size: 15px; margin: 20px 0 6px; }
.docs-rendered pre {
    background: var(--code-bg);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 12px;
    overflow-x: auto;
    font-size: 13px;
}
.docs-rendered code {
    background: var(--code-bg);
    padding: 1px 4px;
    border-radius: 3px;
    font-size: 13px;
}
.docs-rendered pre code { background: transparent; padding: 0; }
.docs-rendered table {
    border-collapse: collapse;
    width: 100%;
    margin: 12px 0;
}
.docs-rendered th, .docs-rendered td {
    border: 1px solid var(--border);
    padding: 6px 10px;
    text-align: left;
    font-size: 13px;
}
.docs-rendered th { background: var(--bg-secondary, #141418); }
.docs-rendered a { color: var(--accent-text, #6ea8fe); }
.docs-rendered blockquote {
    border-left: 3px solid var(--accent, #e94560);
    padding-left: 12px;
    margin: 12px 0;
    color: var(--text-muted);
}
.docs-rendered ul, .docs-rendered ol { padding-left: 24px; }
.docs-rendered img { max-width: 100%; border-radius: 4px; }
/* Wrapper around rendered <table> so wide tables scroll horizontally
   instead of overflowing the viewport. Injected by renderDocContent. */
.docs-table-wrap {
    overflow-x: auto;
    margin: 12px 0;
    -webkit-overflow-scrolling: touch;
}
.docs-table-wrap > table { margin: 0; }

/* ── In-pane raw-markdown editor (JARVIS-62) ────────────────────────────
   Replaces the create/edit pop-up modals. The editor fills the same area
   as #docs-rendered; the header action buttons swap between view/edit sets.
   The content area can optionally be split into textarea + preview column. */
.docs-editor {
    display: flex;
    flex-direction: column;
    flex: 1;
    overflow: hidden;
    min-height: 0;
}
/* One metadata row (label + input), e.g. Title, Tags, Category. */
.docs-editor-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 16px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.docs-editor-label {
    font-size: 10px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    white-space: nowrap;
    min-width: 52px;
}
.docs-editor-input {
    flex: 1;
    background: transparent;
    border: none;
    color: var(--text-bright);
    font-size: 13px;
    padding: 2px 4px;
    outline: none;
    border-radius: 3px;
    min-width: 0;
}
.docs-editor-input:focus { background: var(--surface-hover, #1c2129); }
.docs-editor-select {
    flex: 1;
    background: var(--surface, #161b22);
    border: 1px solid var(--border);
    color: var(--text);
    font-size: 12px;
    padding: 3px 6px;
    border-radius: 3px;
}
/* Wrapper for the textarea + optional preview column. */
.docs-editor-content-area {
    display: flex;
    flex: 1;
    min-height: 0;
    overflow: hidden;
}
.docs-editor-textarea {
    flex: 1;
    resize: none;
    border: none;
    border-right: 1px solid transparent;
    background: transparent;
    color: var(--text);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 13px;
    line-height: 1.6;
    padding: 16px;
    outline: none;
    overflow-y: auto;
    tab-size: 2;
    caret-color: var(--accent, #58a6ff);
}
/* When preview is visible, constrain textarea to 50% and show a divider. */
.docs-editor-content-area.with-preview .docs-editor-textarea {
    flex: 0 0 50%;
    border-right-color: var(--border);
}
.docs-editor-preview {
    display: none;
    flex: 1;
    overflow-y: auto;
    padding: 16px 20px;
    font-size: 14px;
    line-height: 1.7;
}
.docs-editor-content-area.with-preview .docs-editor-preview { display: block; }
/* Footer bar: preview toggle (and future actions). */
.docs-editor-footer {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 16px;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
    background: var(--surface, #161b22);
}
/* "editing" label shown in the header when in edit mode. */
.docs-edit-hint {
    font-size: 10px;
    color: var(--accent, #58a6ff);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    margin-right: 4px;
}

/* Unsaved edits — documents don't autosave (a PATCH mints a GCS version),
   so this is the only standing signal that work is not yet persisted. */
.docs-edit-hint.dirty {
    color: var(--yellow);
}
/* Mobile: stack textarea above preview instead of side-by-side. */
@media (max-width: 768px) {
    .docs-editor-content-area.with-preview {
        flex-direction: column;
    }
    .docs-editor-content-area.with-preview .docs-editor-textarea {
        flex: 0 0 45%;
        border-right: none;
        border-bottom: 1px solid var(--border);
    }
    .docs-editor-content-area.with-preview .docs-editor-preview {
        flex: 1;
    }
}

/* Sidebar collapse toggle — shown in the doc viewer header so the user
   can reclaim sidebar width while reading. Glyph is the button's text
   content (« expanded / » collapsed) so the control stays visible even
   if this stylesheet fails to load; JS swaps the character on toggle. */
.docs-collapse-btn {
    appearance: none;
    background: transparent;
    border: 1px solid transparent;
    color: var(--text-muted);
    font-size: 16px;
    font-weight: 600;
    line-height: 1;
    padding: 4px 8px;
    margin-right: 8px;
    border-radius: 4px;
    cursor: pointer;
}
.docs-collapse-btn:hover { background: var(--bg-hover, #1e1e24); color: var(--text); }
.docs-collapse-btn[aria-pressed="true"] {
    background: var(--bg-secondary, #141418);
    color: var(--accent-text, #6ea8fe);
    border-color: var(--border);
}
.docs-header-left { display: flex; align-items: center; gap: 4px; min-width: 0; }
.docs-header-left .docs-title,
.docs-header-left .docs-path {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.docs-layout.sidebar-collapsed > .docs-sidebar { display: none; }

/* ── Mobile / narrow viewport (DEVOPS-90) ────────────────────────────
   Stack the sidebar above the content; tighten heading rhythm; bump
   tap targets in the doc tree to the Material 48-px minimum. */
@media (max-width: 768px) {
    .docs-layout {
        flex-direction: column;
        height: auto;
        max-height: none;
    }
    .docs-sidebar {
        width: 100%;
        min-width: 0;
        max-height: 220px;
        border-right: none;
        border-bottom: 1px solid var(--border);
    }
    /* 44px min-height = Apple HIG tap target. Without min-height, padding
       + line-box collapses to ~36px on a 14-15px font and fails the bar. */
    .docs-tree .file-item {
        padding: 10px 8px;
        font-size: 14px;
        min-height: 44px;
        display: flex;
        align-items: center;
    }
    .docs-tree .folder-header {
        padding: 10px 6px;
        font-size: 13px;
        min-height: 44px;
    }
    .docs-rendered { padding: 12px 14px; font-size: 15px; line-height: 1.6; }
    .docs-rendered h1 { font-size: 20px; line-height: 1.25; margin: 0 0 12px; }
    .docs-rendered h2 { font-size: 17px; line-height: 1.3; margin: 18px 0 6px; }
    .docs-rendered h3 { font-size: 15px; line-height: 1.3; margin: 14px 0 4px; }
    .docs-header { flex-wrap: wrap; gap: 6px; }
    /* Hide gcs path on narrow screens — it eats horizontal space and
       isn't actionable on mobile. Selector intentionally broad: the
       same .docs-path class is reused by the initiatives and reports
       library headers (no .docs-header-left wrapper there). */
    .docs-path { display: none; }
}

/* --- Initiatives --- */
.initiatives-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1rem; margin-top: 1rem; }
.initiative-card { display: block; padding: 1rem; text-decoration: none; color: inherit; }
.initiative-card.initiative-status-paused { opacity: 0.75; }
.initiative-card.initiative-status-closed { opacity: 0.55; filter: grayscale(0.3); }
.initiative-goal-excerpt { font-size: 0.9rem; color: var(--muted, #888); margin: 0.5rem 0; }
.initiative-countdown { font-weight: 600; font-size: 0.85rem; margin-top: 0.25rem; }
.initiative-countdown.urgent { color: #d33; }
.initiative-countdown.soon { color: #e80; }
.initiative-countdown.overdue { color: #a00; }
.initiative-closed-at { font-size: 0.8rem; color: #888; margin-top: 0.5rem; }
.badge-status-active { background: #2a7f3b; color: #fff; }
.badge-status-paused { background: #aa8800; color: #fff; }
.badge-status-closed { background: #555; color: #fff; }
.status-filter-pills { display: flex; gap: 0.5rem; }
.filter-pill { padding: 0.25rem 0.75rem; border-radius: 999px; background: #eee; text-decoration: none; color: #333; font-size: 0.85rem; }
.filter-pill.active { background: #333; color: #fff; }
.initiative-chip { display: inline-block; padding: 0.1rem 0.5rem; border-radius: 999px; background: #e0e8ff; color: #234; font-size: 0.75rem; text-decoration: none; margin-left: 0.5rem; }
.initiative-chip:hover { background: #c8d5ff; }
/* Remove (×) button inside a removable chip (AG-3 team editor). Inherits the
   chip's text color; brightens to the danger hue on hover. */
.chip-remove {
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    cursor: pointer;
    color: inherit;
    opacity: 0.65;
    font-size: 0.95em;
    line-height: 1;
}
.chip-remove:hover { opacity: 1; color: var(--red); }
.initiative-header { display: flex; justify-content: space-between; align-items: flex-start; }
.initiative-actions { display: flex; gap: 0.5rem; }
.initiative-overview-stats { display: flex; gap: 1rem; margin-bottom: 1.5rem; }
.stat-card {
    padding: 1.25rem 1.5rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    min-width: 120px;
    text-align: center;
}
.stat-big { display: block; font-size: 1.5rem; font-weight: 600; color: var(--text-bright); }

.markdown-body { color: var(--text); line-height: 1.7; }
.markdown-body h1, .markdown-body h2, .markdown-body h3 { color: var(--text-bright); margin-top: 1rem; margin-bottom: 0.5rem; }
.markdown-body code { background: var(--surface); padding: 0.15em 0.4em; border-radius: var(--radius-sm); font-size: 0.875em; }
.markdown-body pre { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.75rem 1rem; overflow-x: auto; }
.markdown-body a { color: var(--accent); }
.markdown-body ul, .markdown-body ol { padding-left: 1.5rem; }
.markdown-body blockquote { border-left: 3px solid var(--border); padding-left: 1rem; color: var(--text-muted); }

.workflow-list { list-style: none; padding: 0; }
.workflow-item {
    padding: 0.625rem 0.75rem;
    border-left: 3px solid var(--border);
    margin-bottom: 0.375rem;
    background: var(--surface);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.workflow-name { color: var(--text-bright); font-weight: 500; }
.workflow-details { color: var(--text-muted); font-size: 0.8125rem; }
.workflow-item.status-healthy { border-left-color: var(--green); }
.workflow-item.status-degraded { border-left-color: var(--yellow); }
.workflow-item.status-error { border-left-color: var(--red); }
.breadcrumb { color: #888; text-decoration: none; font-size: 0.85rem; }

/* ─── Chat ─── */
.chat-shell {
    display: grid;
    /* minmax(0, 1fr) lets the chat panel shrink below its min-content
       size. Without this the header row (title + agent/model pickers
       + Delete) refused to shrink and pushed the whole shell past
       the viewport on iPad (~187px overflow at 768px). */
    grid-template-columns: 240px minmax(0, 1fr);
    gap: 0.75rem;
    height: calc(100vh - 130px);
    min-height: 480px;
}

/* Full-height chat without a magic offset.
   `height: calc(100vh - 130px)` assumed a fixed amount of chrome above the
   shell. The install hint (JARVIS-134) adds ~62px on a phone and the navbar
   grows when it wraps, so on a 390px viewport the composer — the one control
   the page exists for — sat 28px below the fold behind a page scroll, inside
   a page that also has an inner scroller. Measuring nothing is more robust
   than measuring wrongly: make body → main → shell one flex column and let
   the shell take whatever is left. dvh (not vh) so a phone's collapsing URL
   bar doesn't clip the composer either. */
body.chat-page {
    /* A DEFINITE height, not min-height: the inner `overflow-y: auto` scroller
       only bounds itself when every ancestor has a resolved height, otherwise
       the message list grows the page and takes the composer with it. */
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
body.chat-page > main.container {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
/* The hint's `margin: 0 auto` suppresses the cross-axis stretch it got as a
   block child, which would otherwise shrink it to its text on this page only. */
body.chat-page > #install-hint { width: 100%; }
body.chat-page .chat-shell {
    flex: 1 1 auto;
    height: auto;
    min-height: 0;
}
body.chat-page .chat-messages { min-height: 0; }
.chat-panel,
.chat-threads {
    /* Belt + suspenders: grid items inherit min-content sizing too. */
    min-width: 0;
}
.chat-header {
    /* Allow header controls to wrap when the panel is narrow rather
       than blowing out the row width. */
    flex-wrap: wrap;
    min-width: 0;
}
.chat-title-input {
    /* Don't let the title input refuse to shrink. */
    min-width: 0;
}

/* iPad and smaller: narrower sidebar so the chat panel keeps a
   readable width. 768px is the iPad-portrait breakpoint already
   used elsewhere in the file. */
@media (max-width: 900px) {
    .chat-shell {
        grid-template-columns: 200px minmax(0, 1fr);
        gap: 0.5rem;
    }
}

/* JARVIS-141: the thread list becomes a pop-out drawer instead of a strip
   stacked above the chat panel, so the whole viewport stays with the
   conversation. A "Threads" toggle in the chat header slides it in from the
   left; the scrim closes it. Breakpoint aligned to the other selector drawers
   (JARVIS-152): notes/requests/reports and the JARVIS-140 nav drawer all
   collapse at 800px, so one breakpoint governs all drawer UI. */
@media (max-width: 800px) {
    .chat-shell {
        grid-template-columns: 1fr;
    }
    .chat-shell .chat-threads {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        /* 82vw (was 86) leaves a wider strip of the conversation showing, so
           the drawer reads as an overlay you can dismiss rather than a new
           page you navigated to. */
        width: min(82vw, 320px);
        max-height: none;
        border-radius: 0;
        transform: translateX(-100%);
        transition: transform 0.22s ease;
        z-index: 150;
    }
    .chat-shell .chat-threads.open {
        transform: translateX(0);
    }
    .chat-shell .chat-threads-toggle {
        display: inline-block;
    }
    .chat-thread-list {
        /* Looser per-item padding helps the tap targets in the drawer. */
        padding: 0.25rem;
    }
    .chat-thread-item {
        padding: 0.625rem 0.625rem;
    }
    /* Explicit close — the scrim left to tap is only ~70px on a 390px phone.
       (The header/composer overrides for this breakpoint live at the end of
       the chat section: the base .chat-header / .chat-composer rules are
       declared BELOW this block, and a media query adds no specificity, so
       overrides placed here would lose the cascade to them.) */
    .chat-shell .chat-drawer-close { display: block; }
    .chat-shell .chat-threads-header { position: relative; padding-right: 2.75rem; }
}
@media (prefers-reduced-motion: reduce) {
    .chat-threads {
        transition: none;
    }
}
.chat-threads {
    display: flex;
    flex-direction: column;
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border, #2a2a30);
    border-radius: 6px;
    min-height: 0;
}
.chat-threads-header {
    padding: 0.5rem;
    border-bottom: 1px solid var(--border, #2a2a30);
    display: flex;
    flex-direction: column;
    gap: 0;
}
/* All three nav items get the same treatment — none is the "primary"
   action visually (prior + New chat was btn-primary, overweighted vs
   Settings and Admin). Per-item border-top + first-child override
   gives separators between items without a double-line at the top. */
.chat-header-link {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: 0;
    border-top: 1px solid var(--border, #2a2a30);
    color: var(--text);
    font-size: 0.8125rem;
    text-decoration: none;
    padding: 0.5rem 0.625rem;
    cursor: pointer;
    font-family: inherit;
}
.chat-header-link:first-child { border-top: 0; }
.chat-header-link:hover {
    color: var(--accent, #58a6ff);
    background: var(--bg-hover, #1e1e24);
}
.chat-thread-list { flex: 1; overflow-y: auto; padding: 0.375rem; }
.chat-thread-item {
    padding: 0.5rem 0.625rem;
    border-radius: 4px;
    cursor: pointer;
    transition: background 0.15s;
    margin-bottom: 0.25rem;
}
.chat-thread-item:hover { background: var(--bg-hover, #1e1e24); }
.chat-thread-item.active { background: var(--bg-hover, #1e1e24); border: 1px solid var(--border-light, #3a3a42); }
.chat-thread-title {
    color: var(--text);
    font-size: 0.875rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.chat-thread-meta { color: var(--text-muted); font-size: 0.75rem; margin-top: 0.125rem; }
.chat-usage {
    padding: 0.5rem 0.75rem;
    border-top: 1px solid var(--border, #2a2a30);
    font-size: 0.75rem;
    color: var(--text-muted);
    text-align: center;
}
.chat-usage.usage-high { color: var(--yellow, #fbbf24); }
.chat-usage.usage-over { color: var(--red, #f87171); font-weight: 600; }

/* JARVIS-141: pop-out selector drawers. On phones the per-page selector
   list (chat threads, notes list, requests list) slides in over the main
   panel instead of crowding the viewport. The toggle is desktop-hidden and
   only surfaces inside each page's mobile media query. */
.chat-threads-toggle { display: none; }
.popout-scrim {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 120;
}
.popout-scrim.open { display: block; }

.chat-panel {
    display: flex;
    flex-direction: column;
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border, #2a2a30);
    border-radius: 6px;
    min-height: 0;
}
.chat-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.75rem;
    border-bottom: 1px solid var(--border, #2a2a30);
}
.chat-title-input {
    flex: 1;
    background: transparent;
    border: 1px solid transparent;
    color: var(--text);
    font-size: 0.9375rem;
    padding: 0.25rem 0.5rem;
    border-radius: 3px;
}
.chat-title-input:hover:not(:disabled), .chat-title-input:focus { border-color: var(--border, #2a2a30); outline: none; }
.chat-title-input:disabled { color: var(--text-muted); }
.chat-model-picker {
    background: var(--bg, #0d0d11);
    border: 1px solid var(--border, #2a2a30);
    color: var(--text);
    font-size: 0.8125rem;
    padding: 0.25rem 0.5rem;
    border-radius: 3px;
    /* A <select> sizes itself to its widest OPTION, so every model added to
       the picker (six landed in #144) widened this control and squeezed the
       title input next to it. Cap it and let the native ellipsis do the rest;
       the full name is still visible while the dropdown is open. */
    max-width: 100%;
    min-width: 0;
}

/* Drawer close (mobile only — the desktop thread list is always on screen). */
.chat-drawer-close {
    display: none;
    position: absolute;
    top: 0.25rem;
    right: 0.25rem;
    width: 2.25rem;
    height: 2.25rem;
    background: none;
    border: 0;
    color: var(--text-muted);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
}
.chat-drawer-close:hover { color: var(--text); }

/* Empty-state shortcut into the thread drawer (mobile only). */
.chat-empty-threads {
    display: none;
    margin-top: 0.875rem;
}

.chat-messages {
    flex: 1;
    overflow-y: auto;
    padding: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
}
.chat-empty {
    margin: auto;
    color: var(--text-muted);
    text-align: center;
}
.chat-msg {
    /* min(800px, 100%) caps the bubble at 800 but still lets it
       shrink below that on narrow viewports — the prior pair
       (max-width:800px + width:100%) ignored container width when the
       container itself was constrained, so long tokens (tool names
       with underscores) blew the bubble past the viewport edge. */
    max-width: min(800px, 100%);
    min-width: 0;
    align-self: flex-start;
    background: var(--bg, #0d0d11);
    border: 1px solid var(--border, #2a2a30);
    border-radius: 6px;
    padding: 0.625rem 0.875rem;
}
.chat-msg-user {
    align-self: flex-end;
    background: var(--chat-user-bg);
    border-color: var(--chat-user-border);
}
.chat-msg-header {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-bottom: 0.25rem;
    font-weight: 600;
    text-transform: lowercase;
}
.chat-msg-body {
    line-height: 1.55;
    /* `overflow-wrap: anywhere` breaks long unbreakable tokens
       (jarvis_list_tasks, repo URLs, base64 blobs) at any character
       when no soft-break opportunity exists. word-wrap:break-word
       alone won't break before the first space. */
    overflow-wrap: anywhere;
    min-width: 0;
}
.chat-msg-body p { margin: 0.375rem 0; }
.chat-msg-body > :first-child { margin-top: 0; }
.chat-msg-body > :last-child { margin-bottom: 0; }
.chat-msg-body ul, .chat-msg-body ol { padding-left: 1.25rem; margin: 0.375rem 0; }
.chat-msg-body li { margin: 0.125rem 0; }

/* ── Typing indicator ──────────────────────────────────────
   Shown inside an empty assistant bubble while we wait for the
   first streamed token. The bubble has no text content, so :empty
   matches; once the first chunk lands the indicator disappears.
   Three dots pulse in sync — single pseudo-element with two
   box-shadow copies is simpler than three offsets and looks fine
   at this size. */
.chat-msg-body:empty::after {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--text-muted, #8b94a3);
    margin: 0.5rem 0;
    box-shadow:
        12px 0 0 var(--text-muted, #8b94a3),
        24px 0 0 var(--text-muted, #8b94a3);
    animation: chat-typing-pulse 1.2s infinite ease-in-out;
}
@keyframes chat-typing-pulse {
    0%, 100% { opacity: 0.3; }
    50%      { opacity: 1; }
}

/* Accessibility: users with prefers-reduced-motion get a static
   indicator at mid-opacity instead of the pulsing animation. Still
   tells them the assistant is thinking; doesn't trigger motion
   sensitivity. */
@media (prefers-reduced-motion: reduce) {
    .chat-msg-body:empty::after {
        animation: none;
        opacity: 0.6;
    }
}
.chat-msg-body pre {
    background: var(--code-bg);
    border: 1px solid var(--border, #2a2a30);
    padding: 0.625rem;
    border-radius: 4px;
    overflow-x: auto;
}
.chat-msg-body code { font-family: ui-monospace, monospace; font-size: 0.85em; }
.chat-msg-body :not(pre) > code { background: var(--bg-input); padding: 0.1rem 0.3rem; border-radius: 3px; }
.chat-msg-body table { border-collapse: collapse; margin: 0.5rem 0; }
.chat-msg-body th, .chat-msg-body td { border: 1px solid var(--border, #2a2a30); padding: 0.25rem 0.5rem; }

.chat-tool-call {
    margin: 0.375rem 0;
    border: 1px solid var(--border, #2a2a30);
    border-radius: 4px;
    background: var(--bg-elevated);
    font-size: 0.8125rem;
}
.chat-tool-call > summary {
    padding: 0.375rem 0.625rem;
    cursor: pointer;
    color: var(--text-muted, #9ca3af);
    font-family: ui-monospace, monospace;
    list-style: none;
}
.chat-tool-call > summary::-webkit-details-marker { display: none; }
.chat-tool-call[open] > summary { border-bottom: 1px solid var(--border, #2a2a30); color: var(--text, #e6e6ea); }
.chat-tool-call-err { border-color: #5a2222; background: #160d0d; }
.chat-tool-call-err > summary { color: #f08080; }
.chat-tool-section-label {
    padding: 0.375rem 0.625rem 0.125rem;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted, #9ca3af);
}
.chat-tool-call pre {
    margin: 0;
    padding: 0.375rem 0.625rem;
    background: var(--bg-primary);
    border: none;
    border-radius: 0;
    font-size: 0.75rem;
    overflow-x: auto;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ── Pending-confirmation card (JARVIS-29) ───────────── */
.chat-tool-call-pending {
    border-color: #b97a1f;
    background: #1a1308;
}
.chat-tool-call-pending > summary { color: #f0c878; }
.chat-tool-call-pending[open] > summary {
    border-bottom-color: #5a3f10;
    color: #f5d894;
}

.chat-tool-call-confirmed {
    border-color: #2a5a3a;
    background: #0e1810;
}
.chat-tool-call-confirmed > summary { color: #80f0a0; }
.chat-tool-call-confirmed[open] > summary { border-bottom-color: #1f3f2a; }

.chat-tool-call-cancelled {
    border-color: var(--border, #2a2a30);
    background: var(--bg-elevated);
    opacity: 0.65;
}
.chat-tool-call-cancelled > summary { color: var(--text-muted, #9ca3af); }

.chat-tool-call-preview {
    padding: 0.5rem 0.625rem;
    border-bottom: 1px solid var(--border, #2a2a30);
    font-size: 0.8125rem;
    color: var(--text, #e6e6ea);
}
.chat-tool-call-pending .chat-tool-call-preview {
    border-bottom-color: #5a3f10;
    background: #1f1809;
}
.chat-tool-call-preview dl {
    margin: 0;
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.125rem 0.75rem;
}
.chat-tool-call-preview dt {
    color: var(--text-muted, #9ca3af);
    font-family: ui-monospace, monospace;
    font-size: 0.75rem;
    align-self: start;
}
.chat-tool-call-preview dd {
    margin: 0;
    word-break: break-word;
    font-family: ui-monospace, monospace;
    font-size: 0.75rem;
}
.chat-tool-call-preview-empty {
    color: var(--text-muted, #9ca3af);
    font-style: italic;
}

.chat-tool-call-actions {
    display: flex;
    gap: 0.5rem;
    padding: 0.5rem 0.625rem;
    border-top: 1px solid var(--border, #2a2a30);
    justify-content: flex-end;
}
.chat-tool-call-pending .chat-tool-call-actions {
    border-top-color: #5a3f10;
    background: #18120a;
}
.chat-tool-call-actions button {
    padding: 0.3125rem 0.875rem;
    font-size: 0.8125rem;
    font-family: inherit;
    border-radius: 4px;
    border: 1px solid var(--border, #2a2a30);
    background: var(--bg, #0d0d11);
    color: var(--text, #e6e6ea);
    cursor: pointer;
    transition: background 0.1s ease, border-color 0.1s ease;
}
.chat-tool-call-actions button:hover:not(:disabled) {
    background: #1a1a22;
    border-color: #3a3a44;
}
.chat-tool-call-actions button.btn-confirm {
    background: #2a5a3a;
    border-color: #357845;
    color: #e6f6e8;
    font-weight: 500;
}
.chat-tool-call-actions button.btn-confirm:hover:not(:disabled) {
    background: #357845;
    border-color: #4a9358;
}
.chat-tool-call-actions button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.chat-tool-call-error {
    padding: 0.4375rem 0.625rem;
    background: #160d0d;
    color: #f08080;
    font-size: 0.75rem;
    border-top: 1px solid #5a2222;
}

/* DEVOPS-160 Phase 3: sandboxed cross-origin design-artifact preview. */
.design-preview-frame {
    width: 100%;
    height: 60vh;
    margin-top: 0.5rem;
    border: 1px solid var(--border, #ccc);
    border-radius: 8px;
}

/* Loading placeholder — shown while the re-mint fetch is in flight.
   Matches the frame's margin/border/radius so the layout doesn't jump
   when the iframe arrives. A CSS animation gives a subtle pulse. */
.design-preview-loading {
    width: 100%;
    height: 4rem;
    margin-top: 0.5rem;
    border: 1px solid var(--border, #30363d);
    border-radius: 8px;
    background: var(--surface, #161b22);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    color: var(--text-muted, #8b949e);
    font-size: 0.8125rem;
    animation: design-preview-pulse 1.4s ease-in-out infinite;
}

/* Spinner ring before the label text. Pure CSS — no extra markup. */
.design-preview-loading::before {
    content: '';
    width: 14px;
    height: 14px;
    border: 2px solid var(--border, #30363d);
    border-top-color: var(--text-muted, #8b949e);
    border-radius: 50%;
    animation: design-preview-spin 0.75s linear infinite;
    flex-shrink: 0;
}

/* Label text alongside the spinner. The scaffolder left textContent
   empty; this ::after injects the visible copy so no JS change is
   needed in chat.html. */
.design-preview-loading::after {
    content: 'Loading preview\2026';   /* … */
}

@keyframes design-preview-pulse {
    0%, 100% { opacity: 1; }
    50%       { opacity: 0.55; }
}

@keyframes design-preview-spin {
    to { transform: rotate(360deg); }
}

/* Failed placeholder — shown when the re-mint fetch fails (non-2xx or
   network error). Matches the frame footprint. The error detail from
   data-error is surfaced on hover via a CSS tooltip pattern so the
   default view is clean but the context is accessible. */
.design-preview-failed {
    width: 100%;
    margin-top: 0.5rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--border, #30363d);
    border-radius: 8px;
    background: var(--surface, #161b22);
    color: var(--text-muted, #8b949e);
    font-size: 0.75rem;
    font-style: italic;
    display: flex;
    align-items: center;
    gap: 0.375rem;
    /* position:relative allows the ::after tooltip to anchor here. */
    position: relative;
    cursor: default;
}

/* Warning icon prefix. */
.design-preview-failed::before {
    content: '\26A0\FE0F';  /* ⚠️ */
    font-style: normal;
    flex-shrink: 0;
    font-size: 0.875rem;
}

/* Visible label text. */
.design-preview-failed::after {
    content: 'Preview unavailable';
}

/* Reveal data-error detail as a tooltip on hover. CSS attr() reads the
   data attribute without JS. Uses a sibling overlay approach: the
   :hover state on the element shows the pseudo-element tooltip above it.
   Only applied when the attribute is present and non-empty. */
.design-preview-failed[data-error]:not([data-error=""]):hover::after {
    content: attr(data-error);
    position: absolute;
    bottom: calc(100% + 4px);
    left: 0;
    background: var(--surface, #161b22);
    border: 1px solid var(--border, #30363d);
    border-radius: 4px;
    padding: 0.25rem 0.5rem;
    font-size: 0.6875rem;
    font-style: normal;
    color: var(--text, #c9d1d9);
    white-space: pre-wrap;
    max-width: 320px;
    z-index: 10;
    box-shadow: var(--shadow, 0 1px 3px rgba(0,0,0,0.3));
    /* Prevent the tooltip from triggering its own hover (would flicker). */
    pointer-events: none;
}

.chat-composer {
    display: flex;
    /* Anchor the Send button to the bottom of the textarea instead of
       stretching it to match the textarea's height. With stretch (the
       default), pasting a long prompt or auto-growing the textarea
       gave a giant square button. Flex-end keeps the button a
       comfortable single-tap-target size while the textarea grows. */
    align-items: flex-end;
    gap: 0.5rem;
    padding: 0.625rem 0.75rem;
    border-top: 1px solid var(--border, #2a2a30);
}
.chat-composer textarea {
    flex: 1;
    min-width: 0;
    background: var(--bg, #0d0d11);
    border: 1px solid var(--border, #2a2a30);
    color: var(--text);
    border-radius: 6px;
    padding: 0.5rem 0.75rem;
    font-family: inherit;
    font-size: 0.875rem;
    line-height: 1.4;
    /* Auto-grow via JS sets explicit `height`; manual drag-resize
       still works as an escape hatch for users who want a fixed size. */
    resize: vertical;
    min-height: 44px;
    max-height: 240px;
    /* Smooth the transition when the JS height-set lands so the box
       doesn't flicker as the user types past line breaks. */
    transition: height 0.08s ease;
}
.chat-composer textarea:disabled { opacity: 0.5; }
.chat-composer .btn {
    /* Comfortable tap target; matches the textarea's resting height
       (44px) instead of inheriting whatever stretched height the
       flex container would compute. */
    min-height: 44px;
    align-self: flex-end;
}

/* ── JARVIS-135 audio-loop composer buttons ─────────────────────────── */
.chat-composer .chat-mic-btn,
.chat-composer .chat-speak-btn {
    font-size: 1.125rem;
    line-height: 1;
    min-height: 44px;
    min-width: 44px;
    align-self: flex-end;
    padding: 0 0.5rem;
}
.chat-composer .chat-mic-btn.recording {
    color: #fff;
    background: var(--danger, #b3261e);
    border-color: var(--danger, #b3261e);
    animation: chat-mic-pulse 1.2s ease-in-out infinite;
}
.chat-composer .chat-mic-btn.disabled {
    opacity: 0.45;
    cursor: not-allowed;
}
.chat-composer .chat-speak-btn.off {
    opacity: 0.45;
}
@keyframes chat-mic-pulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.08); }
}

.chat-agent-model {
    font-size: 0.6875rem;
    color: var(--text-muted);
    font-family: ui-monospace, monospace;
    padding: 0 0.375rem;
}

/* ── Chat on phones: header + composer ────────────────────
   Placed after the base .chat-header / .chat-composer declarations on
   purpose — a media query carries no extra specificity, so these have to
   come later in the file to win. Breakpoint matches the drawer (800px). */
@media (max-width: 800px) {
    /* Two deliberate rows instead of three ragged ones. The flat flex row
       left the title input 33px of the 354px available — unreadable, and it
       is an editable field — because a <select> sizes itself to its widest
       option and wins the negotiation. Wrapping can't be trusted to fix it
       (flex picks line breaks from base sizes, which came out lopsided), so
       state the rows: identity and deletion on top, the two pickers sharing
       the width below. */
    .chat-header {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr) auto;
        column-gap: 0.5rem;
        row-gap: 0.5rem;
        align-items: center;
        padding: 0.5rem 0.625rem;
    }
    .chat-header .chat-threads-toggle { grid-area: 1 / 1; }
    .chat-header .chat-title-input { grid-area: 1 / 2 / 2 / 4; font-size: 0.875rem; }
    .chat-header #chat-delete-btn { grid-area: 1 / 4; }
    .chat-header #chat-agent { grid-area: 2 / 1 / 3 / 3; }
    .chat-header #chat-model { grid-area: 2 / 3 / 3 / 5; }

    /* Composer: full-width input, controls beneath it. On one row the
       textarea got 127px of a 390px phone — Mic, Speak and Send together
       claimed more width than the thing being typed into, and Send was
       clipped past the right edge. */
    .chat-composer {
        flex-wrap: wrap;
        row-gap: 0.5rem;
        padding: 0.5rem 0.625rem;
    }
    .chat-composer textarea {
        order: 1;
        flex: 1 1 100%;
    }
    .chat-composer .chat-mic-btn { order: 2; }
    .chat-composer .chat-speak-btn { order: 3; }
    /* Send anchored to the trailing edge — thumb-side and unambiguous. */
    .chat-composer #chat-send-btn { order: 4; margin-left: auto; }

    /* Drawer shortcut in the empty state exists only below this breakpoint. */
    .chat-empty-threads { display: inline-block; }
}

/* ── Pagination (messages, notifications) ────────────── */
.pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--border-light);
}
.pagination .pagination-info {
    font-size: 0.8125rem;
    color: var(--text-muted);
}
.pagination .pagination-disabled {
    opacity: 0.4;
    pointer-events: none;
    cursor: default;
}

/* ── Chat settings (DEVOPS-103) ──────────────────────────
   Shell with vertical tabs + a main pane. Memory tab is
   active; Files / Skills / Dreaming are stubs whose copy
   names the ticket implementing each. Future tabs slot in
   beside the existing ones with one entry in the tab list
   plus one .chat-settings-tab-panel. */
.chat-settings-shell {
    display: grid;
    grid-template-columns: 180px 1fr;
    gap: 0.75rem;
    min-height: calc(100vh - 130px);
}
.chat-settings-tabs {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border, #2a2a30);
    border-radius: 6px;
    padding: 0.5rem;
    height: fit-content;
}
.chat-settings-tab {
    text-align: left;
    background: transparent;
    border: 1px solid transparent;
    color: var(--text);
    font-size: 0.875rem;
    padding: 0.5rem 0.75rem;
    border-radius: 4px;
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s, border-color 0.15s;
}
.chat-settings-tab:hover:not(.disabled) {
    background: var(--bg-hover, #1e1e24);
    border-color: var(--border-light, #3a3a42);
}
.chat-settings-tab.active {
    background: var(--bg-hover, #1e1e24);
    border-color: var(--accent, #58a6ff);
    color: var(--text-bright, #f0f6fc);
}
.chat-settings-tab.pending {
    color: var(--text-muted);
    opacity: 0.75;
}
.chat-settings-tab.pending:hover { opacity: 1; }

.chat-settings-pane {
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border, #2a2a30);
    border-radius: 6px;
    padding: 1rem 1.25rem;
    min-height: 0;
}

.chat-settings-skills-actions {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 0.625rem;
}

/* Mobile chat-settings: tab list moves to the top (was a left sidebar
   that was either invisible or cramped on phones). The tabs become a
   horizontal scroll strip — same affordance pattern as the team-page
   tab strip. */
@media (max-width: 768px) {
    .chat-settings-shell {
        grid-template-columns: 1fr;
        gap: 0.5rem;
    }
    .chat-settings-tabs {
        flex-direction: row;
        overflow-x: auto;
        flex-wrap: nowrap;
        touch-action: pan-x;
        -webkit-overflow-scrolling: touch;
        gap: 0.25rem;
        padding: 0.375rem;
    }
    .chat-settings-tab {
        flex-shrink: 0;
        white-space: nowrap;
    }
    .chat-settings-pane {
        padding: 0.75rem 0.875rem;
    }
}

/* Admin table: enable horizontal scroll inside the wrapper on small
   viewports so wide columns don't push the page past the viewport
   edge. Existing .admin-table-wrap doesn't have overflow-x. */
@media (max-width: 768px) {
    .admin-table-wrap {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    .admin-table {
        min-width: 600px; /* keep columns legible inside the scroll */
    }
}
.chat-settings-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--border, #2a2a30);
    margin-bottom: 1rem;
}
.chat-settings-title {
    font-size: 1.125rem;
    color: var(--text-bright, #f0f6fc);
    margin: 0;
}
.chat-settings-back {
    font-size: 0.8125rem;
    color: var(--text-muted);
    text-decoration: none;
}
.chat-settings-back:hover { color: var(--accent, #58a6ff); }

.chat-settings-intro {
    color: var(--text-muted);
    font-size: 0.8125rem;
    margin-bottom: 1rem;
    line-height: 1.5;
}

.chat-settings-memory-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}
@media (max-width: 900px) {
    .chat-settings-memory-grid { grid-template-columns: 1fr; }
}

.chat-settings-memory-card {
    background: var(--bg, #0d0d11);
    border: 1px solid var(--border, #2a2a30);
    border-radius: 6px;
    padding: 0.875rem;
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}
.chat-settings-memory-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.chat-settings-memory-card-header h3 {
    font-size: 0.9375rem;
    color: var(--text-bright, #f0f6fc);
    margin: 0;
}
.chat-settings-memory-scope-tag {
    font-size: 0.6875rem;
    color: var(--text-muted);
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border-light, #3a3a42);
    border-radius: 999px;
    padding: 0.125rem 0.5rem;
}
.chat-settings-agent-picker {
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border, #2a2a30);
    color: var(--text);
    font-size: 0.8125rem;
    padding: 0.25rem 0.5rem;
    border-radius: 3px;
}

.chat-settings-memory-textarea {
    width: 100%;
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border, #2a2a30);
    color: var(--text);
    border-radius: 4px;
    padding: 0.625rem 0.75rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
    line-height: 1.5;
    white-space: pre-wrap;
    resize: vertical;
    min-height: 320px;
}
.chat-settings-memory-textarea:focus {
    outline: none;
    border-color: var(--accent, #58a6ff);
}

.chat-settings-memory-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.chat-settings-memory-meta {
    font-size: 0.75rem;
    color: var(--text-muted);
}
.chat-settings-memory-actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}
.chat-settings-saved-indicator {
    font-size: 0.75rem;
    color: var(--green, #3fb950);
    background: rgba(63, 185, 80, 0.12);
    border: 1px solid var(--green-muted, #238636);
    border-radius: 999px;
    padding: 0.125rem 0.5rem;
    transition: opacity 0.3s;
}
.chat-settings-error-banner {
    background: rgba(248, 81, 73, 0.08);
    border: 1px solid var(--red, #f85149);
    color: #f08080;
    font-size: 0.75rem;
    padding: 0.5rem 0.625rem;
    border-radius: 4px;
}

.chat-settings-stub {
    color: var(--text-muted);
    padding: 2rem 1rem;
    text-align: center;
    border: 1px dashed var(--border, #2a2a30);
    border-radius: 6px;
}
.chat-settings-stub h3 {
    color: var(--text);
    margin-bottom: 0.5rem;
    font-size: 1rem;
}
.chat-settings-stub p { font-size: 0.875rem; }

/* Sidebar link from /chat to settings — small affordance,
   doesn't compete with the "+ New chat" primary action. */
.chat-settings-link {
    display: inline-block;
    margin-left: 0.5rem;
    color: var(--text-muted);
    font-size: 0.8125rem;
    text-decoration: none;
    padding: 0.25rem 0.375rem;
    border-radius: 3px;
}
.chat-settings-link:hover {
    color: var(--accent, #58a6ff);
    background: var(--bg-hover, #1e1e24);
}
/* Mirror of .chat-settings-link for the workspace-level admin surface.
   Same muted register so it sits beside Settings without competing. */
.chat-admin-link {
    display: inline-block;
    margin-left: 0.25rem;
    color: var(--text-muted);
    font-size: 0.8125rem;
    text-decoration: none;
    padding: 0.25rem 0.375rem;
    border-radius: 3px;
}
.chat-admin-link:hover {
    color: var(--accent, #58a6ff);
    background: var(--bg-hover, #1e1e24);
}

/* ── Chat-agent admin (DEVOPS-107) ───────────────────────
   List page + per-agent edit page. Shares palette with
   .chat-settings-* so the two admin/personalisation
   surfaces feel like one product. */
.admin-page-shell {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0.5rem 0 2rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}
.admin-page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--border);
}
/* Same stacking .page-header gets: at 390px the action button was squeezed
   until "+ New agent" broke across two lines. */
@media (max-width: 768px) {
    .admin-page-header { flex-direction: column; align-items: stretch; }
    .admin-page-header > .btn { align-self: flex-start; white-space: nowrap; }
}
.admin-page-title {
    font-size: 1.25rem;
    color: var(--text-bright);
    margin: 0 0 0.375rem 0;
    font-weight: 600;
}
.admin-edit-slug {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    color: var(--text-muted);
    font-size: 0.9375rem;
    font-weight: 500;
    margin-left: 0.25rem;
}
.admin-edit-suffix {
    color: var(--text-muted);
    font-weight: 500;
    margin-left: 0.25rem;
}
.admin-page-intro {
    color: var(--text-muted);
    font-size: 0.8125rem;
    line-height: 1.5;
    max-width: 70ch;
    margin: 0;
}
.admin-page-intro code {
    background: var(--bg);
    border: 1px solid var(--border-light);
    border-radius: 3px;
    padding: 0 0.25rem;
    font-size: 0.75rem;
}
.admin-back-link {
    font-size: 0.8125rem;
    color: var(--text-muted);
    text-decoration: none;
    white-space: nowrap;
    padding-top: 0.25rem;
}
.admin-back-link:hover { color: var(--accent); }
.admin-loading {
    color: var(--text-muted);
    font-size: 0.875rem;
    padding: 1rem 0;
}
.admin-error-banner {
    background: rgba(248, 81, 73, 0.08);
    border: 1px solid var(--red);
    color: #f08080;
    font-size: 0.8125rem;
    padding: 0.625rem 0.75rem;
    border-radius: 4px;
}

/* ── List table ── */
.admin-table-wrap {
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
}
.admin-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}
.admin-table thead th {
    text-align: left;
    background: var(--bg);
    color: var(--text-muted);
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 0.625rem 0.875rem;
    border-bottom: 1px solid var(--border);
}
.admin-table tbody tr {
    border-bottom: 1px solid var(--border-light);
}
.admin-table tbody tr:last-child { border-bottom: none; }
.admin-table tbody tr:hover { background: var(--bg-hover, #1e1e24); }
.admin-table td {
    padding: 0.625rem 0.875rem;
    vertical-align: top;
    color: var(--text);
}
.admin-cell-monospace {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
    color: var(--text);
}
.admin-cell-muted {
    color: var(--text-muted);
    font-size: 0.8125rem;
}
.admin-col-numeric {
    text-align: right;
    font-variant-numeric: tabular-nums;
    width: 4rem;
}
.admin-col-actions {
    width: 4.5rem;
    text-align: right;
}
.admin-agent-name {
    color: var(--text-bright);
    font-weight: 500;
}
.admin-agent-slug {
    color: var(--text-muted);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75rem;
    margin-top: 0.125rem;
}
/* Make the agent name cell a link to its detail page (AG-3) without the
   default anchor blue/underline — the row hover already signals it's
   interactive; the name brightens to the accent on hover. */
.admin-agent-link {
    display: block;
    text-decoration: none;
    color: inherit;
}
.admin-agent-link:hover .admin-agent-name { color: var(--accent); }
.admin-overrides-none {
    color: var(--text-muted);
    font-size: 0.75rem;
    font-style: italic;
}
.admin-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}
.admin-chip {
    display: inline-flex;
    align-items: center;
    background: rgba(219, 109, 40, 0.12);
    border: 1px solid var(--orange);
    color: #f0a060;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.6875rem;
    border-radius: 999px;
    padding: 0.0625rem 0.5rem;
    white-space: nowrap;
}

/* ── Edit cards ── */
.admin-edit-cards {
    display: flex;
    flex-direction: column;
    gap: 0.875rem;
}
.admin-edit-card {
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 0.875rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    border-left: 3px solid var(--border-light);
}
.admin-edit-card.managed {
    /* Amber accent stripe — same hue as the chip — signals that this
       field is currently overriding the code default. */
    border-left-color: var(--orange);
}
.admin-edit-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.admin-edit-card-label {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.admin-edit-card-title {
    color: var(--text-bright);
    font-weight: 600;
    font-size: 0.9375rem;
}
.admin-edit-card-field {
    color: var(--text-muted);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75rem;
    background: var(--bg);
    border: 1px solid var(--border-light);
    border-radius: 3px;
    padding: 0 0.25rem;
    /* Hidden by default — the friendly label conveys what the field
       is; the code chip just duplicates that for power-users who
       know the DB column. Fades in on hover/focus of the card so the
       hint is still reachable. Opacity (not display:none) keeps the
       chip's slot in layout so the header doesn't jump. */
    opacity: 0;
    transition: opacity 0.15s ease;
}
.admin-edit-card:hover .admin-edit-card-field,
.admin-edit-card:focus-within .admin-edit-card-field {
    opacity: 1;
}
.admin-edit-card-help {
    color: var(--text-muted);
    font-size: 0.75rem;
    line-height: 1.5;
    margin: 0;
}
.admin-status-badge {
    font-size: 0.6875rem;
    border-radius: 999px;
    padding: 0.125rem 0.5rem;
    white-space: nowrap;
}
.admin-status-managed {
    background: rgba(219, 109, 40, 0.12);
    border: 1px solid var(--orange);
    color: #f0a060;
}
.admin-status-tracking {
    background: var(--bg);
    border: 1px solid var(--border-light);
    color: var(--text-muted);
}
.admin-edit-card-input {
    width: 100%;
    background: var(--bg);
    border: 1px solid var(--border);
    color: var(--text);
    border-radius: 4px;
    padding: 0.5rem 0.625rem;
    font-family: inherit;
    font-size: 0.875rem;
    box-sizing: border-box;
}
.admin-edit-card-input:focus {
    outline: none;
    border-color: var(--accent);
}
select.admin-edit-card-input {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
}
.admin-edit-card-textarea {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
    line-height: 1.5;
    resize: vertical;
    min-height: 360px;
    white-space: pre-wrap;
}
.admin-edit-card-meta {
    display: flex;
    justify-content: flex-end;
}
.admin-edit-card-counter {
    color: var(--text-muted);
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
}
.admin-edit-card-counter-over {
    color: var(--red);
    font-weight: 600;
}
.admin-edit-card-default-disclosure {
    background: var(--bg);
    border: 1px solid var(--border-light);
    border-radius: 4px;
    padding: 0.375rem 0.625rem;
}
.admin-edit-card-default-disclosure summary {
    cursor: pointer;
    font-size: 0.75rem;
    color: var(--text-muted);
    user-select: none;
}
.admin-edit-card-default-disclosure summary:hover { color: var(--accent); }
.admin-edit-card-default-pre {
    margin: 0.5rem 0 0 0;
    padding: 0.5rem 0.625rem;
    background: var(--bg-secondary, #141418);
    border: 1px solid var(--border-light);
    border-radius: 3px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75rem;
    color: var(--text-muted);
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 260px;
    overflow: auto;
}
.admin-edit-card-error {
    background: rgba(248, 81, 73, 0.08);
    border: 1px solid var(--red);
    color: #f08080;
    font-size: 0.75rem;
    padding: 0.5rem 0.625rem;
    border-radius: 4px;
}
.admin-edit-card-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
}
.admin-saved-indicator {
    font-size: 0.75rem;
    color: var(--green);
    background: rgba(63, 185, 80, 0.12);
    border: 1px solid var(--green-muted);
    border-radius: 999px;
    padding: 0.125rem 0.5rem;
    transition: opacity 0.3s;
}

/* Identity card (DEVOPS-136) — the three small related fields
   (display_name, description, default_model) share one card and one
   Save button; each field row keeps its own status badge + reset. */
.admin-identity-field {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    border-left: 3px solid transparent;
    padding-left: 0.625rem;
}
.admin-identity-field + .admin-identity-field {
    border-top: 1px solid var(--border-light);
    padding-top: 0.625rem;
}
.admin-identity-field.managed {
    border-left-color: var(--orange);
}
.admin-identity-field-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.admin-identity-field-label {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-muted);
}
.admin-identity-row-actions {
    display: flex;
    justify-content: flex-end;
}
.admin-identity-row-actions [data-reset][hidden] {
    display: none !important;
}

/* Transient autosave indicator (AG-5) — shown while a field PUT is in flight,
   replaced by the "Saved ✓" indicator on success or the error row on failure. */
.admin-field-saving {
    font-size: 0.75rem;
    color: var(--text-muted);
    padding: 0.125rem 0.5rem;
}

/* Danger zone (AG-5) — delete-agent control at the bottom of the detail page. */
.admin-danger-zone {
    margin-top: 1.5rem;
    border: 1px solid var(--red);
    border-radius: var(--radius-sm);
    background: rgba(248, 81, 73, 0.06);
    padding: 0.875rem 1rem;
}
.admin-danger-zone-body {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}
.admin-danger-zone-title {
    font-weight: 600;
    color: var(--red);
}
.admin-danger-zone .admin-edit-card-error {
    margin-top: 0.75rem;
}

/* Tool checkbox list — 2-3 columns depending on viewport. Each row
   is a label so clicking the name toggles the box. */
.admin-tool-checkbox-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 0.25rem 0.75rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 0.625rem 0.75rem;
    max-height: 320px;
    overflow-y: auto;
}
.admin-tool-checkbox {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
    color: var(--text);
    cursor: pointer;
    padding: 0.125rem 0;
}
.admin-tool-checkbox input { cursor: pointer; }
.admin-tool-checkbox-orphan {
    color: var(--orange);
}

/* ── Chat-skill admin (DEVOPS-110) ───────────────────────
   Shares almost all chrome with .admin-* above; the only
   skill-specific extras are the source badge (bundled vs
   user) and the body byte-counter tier colors. */
/* Defensive: .btn sets display: inline-flex, which beats the UA
   default [hidden] { display: none } at specificity 0,1,0 vs 0,0,1.
   Without this, a `hidden` Reset/Clear button still paints. Applies
   to all admin cards (agents + skills) so the bug is fixed once. */
.admin-edit-card [data-reset][hidden],
.admin-edit-card [data-clear][hidden],
.admin-edit-card [data-saved][hidden] {
    display: none !important;
}
.admin-skill-source-badge {
    display: inline-flex;
    align-items: center;
    font-size: 0.6875rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    border-radius: 999px;
    padding: 0.125rem 0.5rem;
    white-space: nowrap;
    text-transform: lowercase;
    letter-spacing: 0.25px;
}
.admin-skill-source-badge--bundled {
    background: var(--bg);
    border: 1px solid var(--border-light);
    color: var(--text-muted);
}
.admin-skill-source-badge--user {
    /* Accent blue ties to --accent so user-authored rows read as
       "promoted by an admin", distinct from the neutral bundled chip. */
    background: rgba(56, 139, 253, 0.12);
    border: 1px solid var(--accent, #388bfd);
    color: var(--accent, #79b8ff);
}
/* Meta strip on the edit page: source badge + last-edit line + chips. */
.admin-skill-meta-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-top: 0.5rem;
    color: var(--text-muted);
    font-size: 0.8125rem;
}
.admin-skill-meta-last-edit {
    color: var(--text-muted);
}
.admin-skill-meta-managed {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    flex-wrap: wrap;
}
.admin-skill-meta-label {
    color: var(--text-muted);
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
/* Byte counter tiers — 75% amber, 95% red — mirrors the chat-files
   quota meter so the two surfaces feel consistent. */
.admin-edit-card-counter-amber {
    color: var(--yellow, #d0a85c);
}
.admin-edit-card-counter-red {
    color: var(--red);
    font-weight: 600;
}

/* ── Chat-settings: Skills tab (DEVOPS-105) ──────────────
   Skill row = info on the left, iOS-style toggle on the
   right. Hidden checkbox + visible track gives us a proper
   touch/keyboard target with no JS state mirroring. */
.chat-settings-skill-card {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--border, #2a2a30);
    border-radius: 6px;
    background: var(--bg, #0d0d11);
    margin-bottom: 0.5rem;
}
.chat-settings-skill-info {
    flex: 1;
    min-width: 0;
}
.chat-settings-skill-name code {
    font-size: 0.875rem;
    background: transparent;
    padding: 0;
    color: var(--text);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.chat-settings-skill-desc {
    margin: 0.25rem 0 0 0;
    color: var(--text-muted, #9ca3af);
    font-size: 0.8125rem;
    line-height: 1.4;
}

/* Toggle switch: hidden checkbox + visible track */
.chat-settings-skill-toggle {
    flex-shrink: 0;
    position: relative;
    display: inline-block;
    width: 38px;
    height: 22px;
    cursor: pointer;
    margin-top: 0.125rem;
}
.chat-settings-skill-toggle input[type="checkbox"] {
    opacity: 0;
    width: 0;
    height: 0;
    position: absolute;
}
.chat-settings-toggle-track {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background: var(--border, #2a2a30);
    border-radius: 11px;
    transition: background 0.15s ease;
}
.chat-settings-toggle-track::before {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    background: var(--text, #f0f6fc);
    border-radius: 50%;
    transition: transform 0.15s ease;
}
.chat-settings-skill-toggle input:checked + .chat-settings-toggle-track {
    background: var(--green, #238636);
}
.chat-settings-skill-toggle input:checked + .chat-settings-toggle-track::before {
    transform: translateX(16px);
}
.chat-settings-skill-toggle input:focus-visible + .chat-settings-toggle-track {
    outline: 2px solid var(--accent, #58a6ff);
    outline-offset: 2px;
}
.chat-settings-skill-toggle input:disabled + .chat-settings-toggle-track {
    opacity: 0.5;
    cursor: not-allowed;
}

.chat-settings-skills-empty {
    color: var(--text-muted, #9ca3af);
    font-style: italic;
    text-align: center;
    padding: 2rem;
}
.chat-settings-skills-loading {
    color: var(--text-muted, #9ca3af);
    font-size: 0.8125rem;
    padding: 0.5rem 0;
}

/* ── Chat-settings: Files tab (DEVOPS-104) ───────────────
   Quota meter + dropzone + file list table. Shares palette
   with the Skills + Memory tabs so the three feel like one
   surface. Toasts stack at the bottom of the dropzone. */
.chat-settings-empty {
    color: var(--text-muted);
    font-style: italic;
    text-align: center;
    padding: 1.5rem;
}

.chat-files-loading {
    color: var(--text-muted);
    font-size: 0.8125rem;
    padding: 0.5rem 0;
}

.chat-files-quota {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin: 0.75rem 0 1rem 0;
}
.chat-files-quota-label {
    color: var(--text-muted);
    font-size: 0.8125rem;
}
.chat-files-quota-track {
    height: 6px;
    background: var(--border);
    border-radius: 3px;
    overflow: hidden;
}
.chat-files-quota-fill {
    height: 100%;
    width: 0%;
    transition: width 0.2s ease, background-color 0.2s ease;
    border-radius: 3px;
}
.chat-files-quota-green { background: var(--green); }
.chat-files-quota-amber { background: var(--yellow); }
.chat-files-quota-red   { background: var(--red); }

.chat-files-dropzone {
    position: relative;
    border: 1px dashed var(--border);
    border-radius: 6px;
    padding: 1.5rem 1rem;
    text-align: center;
    color: var(--text-muted);
    background: var(--surface);
    margin-bottom: 1rem;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.chat-files-dropzone:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.chat-files-dropzone-active {
    border-color: var(--accent);
    background: var(--surface-hover);
    color: var(--text);
}
.chat-files-dropzone-label {
    margin-bottom: 0.625rem;
    font-size: 0.875rem;
}
.chat-files-dropzone code {
    background: transparent;
    padding: 0;
    color: var(--text);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
}

.chat-files-toasts {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    margin-top: 0.875rem;
    text-align: left;
}
.chat-files-toast {
    background: var(--surface-hover);
    border: 1px solid var(--border);
    color: var(--text);
    padding: 0.5rem 0.625rem;
    border-radius: 4px;
    font-size: 0.8125rem;
    word-break: break-word;
}
.chat-files-toast-error {
    background: rgba(248, 81, 73, 0.08);
    border-color: var(--red);
    color: #f08080;
}

.chat-files-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}
.chat-files-table thead th {
    text-align: left;
    color: var(--text-muted);
    font-weight: 500;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 0.5rem 0.625rem;
    border-bottom: 1px solid var(--border);
}
.chat-files-table tbody td {
    padding: 0.5rem 0.625rem;
    border-bottom: 1px solid var(--border-light);
    color: var(--text);
    vertical-align: middle;
}
.chat-files-table tbody tr:last-child td {
    border-bottom: none;
}
.chat-files-name-cell code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
    background: transparent;
    padding: 0;
    color: var(--text);
    word-break: break-all;
}
.chat-files-size-cell,
.chat-files-when-cell {
    color: var(--text-muted);
    white-space: nowrap;
}
.chat-files-action-cell {
    text-align: right;
    width: 2.5rem;
}
.chat-files-delete-btn {
    background: transparent;
    border: 1px solid transparent;
    color: var(--text-muted);
    font-size: 1.125rem;
    line-height: 1;
    padding: 0.125rem 0.5rem;
    border-radius: 4px;
    cursor: pointer;
    transition: color 0.15s ease, border-color 0.15s ease, background-color 0.15s ease;
}
.chat-files-delete-btn:hover {
    color: var(--red);
    border-color: var(--red);
    background: rgba(248, 81, 73, 0.08);
}
.chat-files-delete-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* ─── DEVOPS-124: mobile fixes + team-card density (was style_b.css, promoted 2026-05-20) ─── */

/* === Team card stats: hide zero-value entries === */
/* Cards with all zeros end up with a blank stats row — intentional;
   the team is "quiet" and there's nothing to surface. */
.team-card .stat.stat-zero {
  display: none;
}
/* Left-align the remaining stats instead of stretching them across
   the card. flex:1 in the baseline makes 1-2 stats look awkward —
   flex:0 0 auto sizes each to its content. Gap controls spacing. */
.team-card .stats .stat {
  flex: 0 0 auto;
  min-width: 0;
  text-align: center;
  padding: 0 0.75rem 0 0;
}
.team-card .stats .stat-label {
  white-space: nowrap;
}

/* ─── Teams dashboard on touch + small viewports ───────────────────────
   Declared here, after the DEVOPS-124 team-card block, because these
   override rules from it and a media query carries no extra specificity. */

/* Desktop drives re-parenting by drag-and-drop, so the "Organize" toggle has
   nothing to offer there; the touch media query below turns it on. */
.js-organize-toggle { display: none; }
.js-organize-toggle[aria-pressed="true"] {
  color: var(--accent);
  border-color: var(--accent);
}

/* JARVIS-42's re-parenting is HTML5 drag-and-drop, which does not fire on
   touch. On a phone that left the drag grip and the "Drop here to move a team
   to the top level" zone as decorations that cannot be operated — and the
   "Move…" fallback, the one control that DOES work there, was `opacity: 0`
   until hover, so it never appeared at all. Re-parenting was effectively
   impossible from a phone. `hover: none` is the condition that actually
   matters (a touch tablet at any width); the width clause covers phone-sized
   windows too, where nothing is lost — the card itself carries
   `draggable="true"`, so the grip is decoration and dragging still works. */
@media (hover: none), (max-width: 800px) {
  .team-card .drag-handle,
  .root-dropzone {
    display: none;
  }
  /* The touch route is the "Organize" toggle in the page header, which sets
     .teams-organizing. Showing a Move button on every card unconditionally
     would tax every reader — most of them members who will never re-parent
     anything — with a row of eleven identical buttons to serve a rare
     operator action. Off by default, one tap away.
     Out of the card's corner too: always-visible there, it would sit on top
     of the private/archived badges. */
  .teams-organizing .team-card-wrapper {
    flex-direction: column;
    align-items: stretch;
  }
  .teams-organizing .btn-move {
    position: static;
    opacity: 1;
    align-self: flex-end;
    margin-top: 0.375rem;
    /* Sized as a thumb target, not as the 0.7rem/2px-padding corner label it
       is on desktop, where it only has to survive a mouse. */
    min-height: 40px;
    padding: 0.5rem 0.875rem;
    font-size: 0.8125rem;
  }
  .js-organize-toggle { display: inline-block; }
}

@media (max-width: 600px) {
  /* The folder header ellipsized its description down to a three-word
     fragment ("— Everything that touches a liv…"), which carries no
     information and crowds the folder name. Drop it; the name is the part
     doing the work, and the description is on the team pages. */
  .folder-group .folder-description {
    display: none;
  }
  /* The header is the collapse control, so give it a full-height tap target
     and stop the chevron from being a 12px pinpoint. */
  .folder-group .folder-header {
    padding: 0.75rem 0.875rem;
    min-height: 44px;
  }
  .folder-group .folder-icon {
    width: 1.5rem;
    font-size: 0.875rem;
  }
  /* Folder delete is hover-revealed and unreachable on touch; the folder can
     still be deleted from a desktop. Hiding it beats a 0-opacity ghost that
     steals a tap near the header's right edge. */
  .folder-group .folder-header .js-delete-folder {
    display: none;
  }
}

@media (max-width: 480px) {
  /* Five stats at 0.75rem of trailing padding each measure ~367px against a
     316px card, so the row wrapped and left "Reminders" hanging alone under
     the first column — an accidental-looking orphan. A three-column grid
     wraps predictably (3 + 2) and lines the columns up. Left-aligned: the
     values then share a left edge with the name and description above them
     instead of floating mid-column. */
  .team-card .stats {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    row-gap: 0.625rem;
    column-gap: 0.5rem;
  }
  .team-card .stats .stat {
    padding: 0;
    text-align: left;
  }
  .team-card .stats .stat-value {
    font-size: 1.25rem;
    line-height: 1.1;
  }
}

/* === Stop the navbar from pushing horizontal scroll on mobile ===
   The bug behind "text spilling" reports: on a 380px viewport, the
   navbar (brand + 4 tabs + team indicator) measures ~487px wide and
   forces a body horizontal scroll. Cards then *look* like they're
   bleeding off the right edge because the viewport scrolls left of
   the card boundary. Fix is to contain the navbar within viewport
   width, not the cards. */
html,
body {
  overflow-x: hidden;  /* belt + suspenders against any other stray overflow */
}

@media (max-width: 768px) {
  .navbar {
    padding: 0.625rem 0.75rem;
    gap: 0.5rem;
  }
  .nav-left {
    min-width: 0;
    flex: 1 1 auto;
    overflow: hidden;
  }
  /* JARVIS-140: the tabs no longer live in the bar on phones (they're a
     slide-out drawer), so nothing here can push the navbar wide. The
     brand + hamburger are fixed-width; only the team indicator can grow. */
  .nav-tab {
    white-space: nowrap;
    flex-shrink: 0;
  }
  /* Team indicator gets squeezed first — drop the label, keep the
     colored dot as an anchor so the user still knows which team. */
  .nav-team-indicator {
    flex-shrink: 0;
    max-width: 8rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

@media (max-width: 480px) {
  .nav-brand { font-size: 0.875rem; }
  /* Hide the team-indicator's text label on very narrow phones —
     they're already on the team page so the redundancy isn't worth
     the 80px. The colored dot stays visible. */
  .nav-team-indicator {
    max-width: 1rem;
    padding: 0;
  }
  .nav-team-indicator > :not(.nav-team-dot) {
    display: none;
  }
}

/* === Mobile: stop horizontal overflow on the teams page === */
/* The baseline media query at 768px overrides .grid → 1fr but
    misses .folder-group .folder-children, which still demands a
    280px minimum column. On a 375px iPhone the 280px column +
    container/folder padding can exceed viewport width and cards get
    clipped at the right edge. */
@media (max-width: 768px) {
  .folder-group .folder-children {
    grid-template-columns: 1fr;
    padding: 0.75rem 0.875rem;
  }
  /* Cards/folders themselves: small radius cut so the border doesn't
     hide the right-edge content when the viewport is tight. */
  .team-card,
  .folder-group {
    /* min-width:0 lets grid items shrink below their content size
       (default is min-content, which is what was forcing overflow). */
    min-width: 0;
  }
}

@media (max-width: 480px) {
  /* Slightly tighter outer container padding so cards actually use
     the available width on small phones. */
  .container {
    padding: 0.75rem;
  }
  .folder-group .folder-children {
    padding: 0.625rem 0.75rem;
  }
}

/* === Task list / cards: stop content from spilling past the edge ===
   The whole flex chain (.task-card-group → .task-card → .task-card-
   left → .task-card-content → .task-title) needs min-width:0 at every
   step or a long task title / description widens the card past its
   parent. Also add overflow:hidden on .task-card as a safety clip so
   any rogue inline content (long URLs, code spans) gets cut at the
   card boundary instead of bleeding into the next column / off-screen. */
.task-card-group {
  min-width: 0;
}
.task-card {
  min-width: 0;
  overflow: hidden;
}
.task-card-left,
.task-card-content {
  min-width: 0;
}
/* `.task-title` is itself a flex container; let badges + text wrap to
   multiple lines instead of forcing the row width. Long unbreakable
   words (URLs, paths) break with overflow-wrap. */
.task-title {
  flex-wrap: wrap;
  min-width: 0;
  overflow-wrap: anywhere;
  line-height: 1.35;
}
/* Description: the baseline uses nowrap + ellipsis but the flex parent
   wasn't constraining it. With the chain fixed above, ellipsis truly
   kicks in. Keep nowrap on desktop; let it wrap to 2 lines on phones
   where dropping context is more annoying than added height. */
.task-description {
  max-width: 100%;
}
.task-meta {
  flex-wrap: wrap;
  min-width: 0;
}
@media (max-width: 480px) {
  .task-description {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* === Modal: breathing room + mobile === */
/* Baseline modal-body is 1.25rem all-around with no overflow rules
   for long URLs / code blocks / dense descriptions. */
.modal {
  /* Tighter on phones, more generous on desktop. */
  width: calc(100% - 1.5rem);
}

.modal-body {
  padding: 1.5rem 1.75rem;
  /* Long URLs, code lines, and pasted shell commands frequently land
     in task descriptions — let them wrap rather than blow out the
     modal width. */
  overflow-wrap: anywhere;
}

.modal-body pre,
.modal-body code {
  /* Code blocks should scroll horizontally inside the modal, not
     extend past it. */
  max-width: 100%;
  overflow-x: auto;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.modal-body img,
.modal-body table {
  max-width: 100%;
  height: auto;
}

.modal-body p,
.modal-body li {
  /* Avoid edge-to-edge lines that look slabby; readable line length. */
  max-width: 64ch;
}

@media (max-width: 768px) {
  .modal {
    width: calc(100% - 1rem);
    max-height: 92vh;
    border-radius: 12px;
  }
  .modal-header {
    padding: 0.875rem 1rem;
  }
  .modal-body {
    padding: 1rem 1rem 1.25rem;
  }
}

@media (max-width: 480px) {
  /* Full-bleed takeover on small phones — square corners at the top
     so the modal feels intentional rather than a clipped card. */
  .modal-overlay {
    padding: 0;
    align-items: flex-end;  /* slide-up sheet feel */
  }
  .modal {
    width: 100%;
    max-height: 100vh;
    border-radius: 16px 16px 0 0;
    border-bottom: none;
  }
}

/* ── Designs Tab ──────────────────────────────────────── */

/* Responsive card grid — three columns on desktop, two on tablet,
   one on phones. Matches the widget-grid breakpoints. */
.designs-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
}

@media (max-width: 900px) {
    .designs-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 480px) {
    .designs-grid { grid-template-columns: 1fr; }
}

.design-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.design-card:hover {
    border-color: var(--text-muted);
    box-shadow: var(--shadow);
}

.design-card-header {
    padding: 0.75rem 1rem 0;
    flex-shrink: 0;
}

.design-card-title {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-bright);
    /* Two-line clamp — most titles are short but some agent-generated
       ones can be a sentence. Clamp keeps the grid uniform. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    line-height: 1.35;
}

.design-card-meta {
    padding: 0.375rem 1rem 0;
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    flex: 1;
    min-height: 2.5rem;
}

.design-card-author {
    font-size: 0.6875rem;
    color: var(--text-muted);
    /* Truncate long email addresses. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.design-card-date {
    font-size: 0.6875rem;
    color: var(--text-muted);
}

.design-card-actions {
    padding: 0.625rem 1rem;
    display: flex;
    gap: 0.5rem;
    border-top: 1px solid var(--border-light);
    margin-top: 0.625rem;
    flex-shrink: 0;
}

.design-preview-btn {
    flex: 1;
    justify-content: center;
}

/* ── Design Preview Modal ─────────────────────────────── */

/* Full-viewport overlay — darker than the standard modal overlay so
   the preview content has the visual focus. */
.design-preview-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.85);
    backdrop-filter: blur(4px);
    z-index: 250;         /* above the standard modal (z-index 200) */
    align-items: center;
    justify-content: center;
    padding: 1rem;
}

.design-preview-overlay.open {
    display: flex;
}

.design-preview-modal {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    width: 100%;
    max-width: 1024px;
    height: 90vh;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    box-shadow: var(--shadow-lg);
}

.design-preview-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1.25rem;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}

.design-preview-modal-title {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-bright);
}

.design-preview-close {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 1.5rem;
    cursor: pointer;
    line-height: 1;
    padding: 0 0.25rem;
    transition: color 0.15s;
}

.design-preview-close:hover {
    color: var(--text-bright);
}

.design-preview-modal-body {
    flex: 1;
    min-height: 0;
    position: relative;
    /* Loading and error states center their content. */
    display: flex;
    flex-direction: column;
}

/* The iframe fills the modal body when a preview is loaded. */
.design-preview-iframe {
    width: 100%;
    height: 100%;
    flex: 1;
    border: none;
    background: #fff;   /* designs may assume a white page background */
}

/* While the signed-URL round-trip is in flight, dim the body to hint
   that content is coming. The .loading class is removed once the URL
   resolves and the iframe src is set. */
.design-preview-overlay.loading .design-preview-modal-body {
    opacity: 0.5;
}

@media (max-width: 768px) {
    .design-preview-modal {
        height: 100vh;
        max-height: 100vh;
        max-width: 100%;
        border-radius: var(--radius) var(--radius) 0 0;
    }

    .design-preview-overlay {
        align-items: flex-end;
        padding: 0;
    }
}

/* ── Members Tab (JARVIS-23) ─────────────────────────── */
.members-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.members-table th {
    text-align: left;
    padding: 0.5rem 0.75rem;
    border-bottom: 2px solid var(--border);
    color: var(--text-muted);
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.members-table td {
    padding: 0.625rem 0.75rem;
    border-bottom: 1px solid var(--border-light);
    vertical-align: middle;
}

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

.members-table tr:hover td { background: rgba(255,255,255,0.02); }

.member-email {
    font-family: var(--font-mono, 'SF Mono', 'Fira Code', monospace);
    font-size: 0.8125rem;
    color: var(--text);
}

.member-role {
    font-size: 0.75rem;
    padding: 0.125rem 0.5rem;
    border-radius: 12px;
    font-weight: 600;
    white-space: nowrap;
}

.member-role-owner { background: var(--badge-private-bg); color: var(--purple); }
.member-role-member { background: var(--badge-pending-bg); color: var(--text-muted); }
.member-role-viewer { background: var(--bg); color: var(--text-muted); border: 1px solid var(--border); }

.members-add-form {
    display: flex;
    gap: 0.75rem;
    align-items: flex-end;
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border);
    flex-wrap: wrap;
}

.members-add-form .form-group { margin-bottom: 0; flex: 1; min-width: 180px; }

.members-loading { color: var(--text-muted); font-size: 0.875rem; font-style: italic; padding: 1rem 0; }

/* Visibility toggle in New Team / Edit Team modals */
.visibility-toggle {
    display: flex;
    gap: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    overflow: hidden;
}

.visibility-toggle input[type="radio"] { display: none; }

.visibility-toggle label {
    flex: 1;
    text-align: center;
    padding: 0.375rem 0.75rem;
    font-size: 0.8125rem;
    font-weight: 500;
    cursor: pointer;
    color: var(--text-muted);
    background: var(--bg);
    border: none;
    transition: background 0.15s, color 0.15s;
    text-transform: none;
    letter-spacing: normal;
}

.visibility-toggle label:not(:last-child) { border-right: 1px solid var(--border); }

.visibility-toggle input[type="radio"]:checked + label {
    background: var(--accent-muted);
    color: #fff;
}

.visibility-toggle input[type="radio"]#vis-private:checked + label {
    background: #2b1a3d;
    color: var(--purple);
}

/* AG-6: inline error inside a modal form (e.g. dup slug / unknown team /
   admin-required on agent create) — surfaced in-place so the operator can
   correct and resubmit without losing the form. */
.form-error {
    margin-bottom: 1rem;
    padding: 0.5rem 0.625rem;
    font-size: 0.8125rem;
    color: var(--red, #f87171);
    background: var(--red-muted, #2a1414);
    border: 1px solid var(--red, #f87171);
    border-radius: var(--radius-sm);
}

/* ── Admin Users view (JARVIS-25) ──────────────────────────────────────── */
.admin-users-edge-auth-note {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    background: var(--bg-elevated);
    border: 1px solid rgba(96, 165, 250, 0.25);
    border-radius: var(--radius-sm, 6px);
    padding: 0.625rem 0.875rem;
    font-size: 0.8125rem;
    color: var(--accent-text);
    margin-bottom: 1.25rem;
}

.admin-users-add-form {
    margin-top: 1.25rem;
}

.admin-users-role-select {
    background: var(--bg-elevated, #1c1c22);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 4px);
    color: var(--text);
    font-size: 0.8125rem;
    padding: 0.25rem 0.5rem;
    cursor: pointer;
}

.admin-users-role-select:focus {
    outline: none;
    border-color: var(--accent);
}

.admin-users-status-btn {
    font-size: 0.75rem;
    padding: 0.125rem 0.625rem;
    border-radius: 12px;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    border: none;
}

.admin-users-status-active {
    background: rgba(34, 197, 94, 0.15);
    color: var(--green, #22c55e);
}

.admin-users-status-disabled {
    background: rgba(239, 68, 68, 0.12);
    color: var(--red, #ef4444);
}

/* ── AG-11b: MCP-server section ─────────────────────────────────────────── */
/* The command shown inline in the list table — monospace + truncated so a long
   "npx -y @modelcontextprotocol/server-foo" doesn't blow out the column. The
   full value is in the cell's title attribute. */
.admin-mcp-command {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8rem;
    color: var(--text-muted);
    display: inline-block;
    max-width: 22rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}

/* Inline enabled toggle (list rows + the editor header use the same markup). */
.admin-mcp-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
}
.admin-mcp-toggle input[disabled] {
    cursor: not-allowed;
}
.admin-mcp-toggle-state {
    font-size: 0.8rem;
    color: var(--text-muted);
}

/* Monospace variant for the command input + args/env textareas on the MCP
   editor — these hold shell-ish values where alignment + a code feel help. */
.admin-edit-card-mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.85rem;
}

/* JARVIS-144: PWA responsive pass — ensure small buttons meet 44px touch target on phones */
@media (max-width: 768px) {
  .btn-sm {
    min-height: 44px;
    min-width: 44px;
    padding: 0.5rem 0.75rem;
  }
  .btn-icon {
    min-width: 44px;
    min-height: 44px;
    padding: 0.5rem;
  }
  .modal-close,
  .lead-modal-close {
    min-width: 44px;
    min-height: 44px;
    padding: 0.5rem;
  }
}
