:root {
    --bg: #f7f8fa;
    --surface: #ffffff;
    --border: #e4e7ec;
    --border-strong: #d0d5dd;
    --text-primary: #101828;
    --text-secondary: #667085;
    --text-muted: #98a2b3;
    /* Paarsel purple, sampled from the brand artwork. Every accent in the app
       resolves to these four, so the rebrand is one edit rather than a hunt. */
    --accent: #623089;
    --accent-hover: #4d2570;
    --accent-bg: #f0eaf6;
    --accent-text: #4d2570;
    /* Brand orange. Deliberately NOT wired into anything generic: it is used on
       exactly one control, Start my day, and that scarcity is what makes it read
       as "this is the thing you press". Do not reach for it for buttons. */
    --brand-orange: #e89440;
    --brand-orange-hover: #c9762a;
    --danger-bg: #fef2f2;
    --danger-text: #b91c1c;
    --warning-bg: #fffbeb;
    --warning-text: #b45309;
    --success-bg: #f0fdf4;
    --success-text: #15803d;
    --neutral-bg: #f2f4f7;
    --neutral-text: #475467;
    --radius: 8px;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
* { box-sizing: border-box; }
body { margin: 0; background: var(--bg); color: var(--text-primary); -webkit-tap-highlight-color: transparent; }
.hidden { display: none !important; }
svg { flex-shrink: 0; }

/* ---------- Login ---------- */
#loginScreen { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; }
.login-card { background: var(--surface); border-radius: 14px; padding: 28px 24px; width: 100%; max-width: 360px; border: 1px solid var(--border); }
.login-card h1 { color: var(--text-primary); font-size: 20px; font-weight: 600; margin: 0 0 4px; }
.login-card p.sub { color: var(--text-secondary); font-size: 13px; margin: 0 0 20px; }
.field { margin-bottom: 14px; position: relative; }
/* ---------- Client name autocomplete (custom-rendered: native <datalist>
   dropdowns don't reliably show on mobile Safari, so this is the real UI) --- */
.client-suggest { position: absolute; left: 0; right: 0; top: 100%; z-index: 30; margin-top: 2px;
                   background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius);
                   max-height: 190px; overflow-y: auto; box-shadow: 0 4px 14px rgba(0,0,0,.12); }
.client-suggest.hidden { display: none; }
.client-suggest-item { padding: 9px 12px; font-size: 13px; cursor: pointer; border-bottom: 1px solid var(--border); }
.client-suggest-item:last-child { border-bottom: none; }
.client-suggest-item:hover, .client-suggest-item.active { background: var(--neutral-bg); }
.client-suggest-item .cell-sub { font-size: 11.5px; color: var(--text-muted); margin-top: 1px; }
.field label { display: block; font-size: 12px; font-weight: 600; color: var(--text-secondary); margin-bottom: 4px; }
.field input, .field select, .field textarea {
    width: 100%; padding: 9px 12px; border: 1px solid var(--border-strong); border-radius: var(--radius); font-size: 14px;
    background: var(--surface); color: var(--text-primary); font-family: inherit;
}
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-bg); }
.field-hint { font-size: 11px; color: var(--text-muted); margin-top: 4px; }

/* ---------- Buttons ---------- */
.btn-primary, .btn-secondary {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    padding: 8px 14px; border-radius: var(--radius); font-size: 13px; font-weight: 600;
    cursor: pointer; border: 1px solid transparent; white-space: nowrap;
}
.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-hover); }
.btn-secondary { background: var(--surface); color: var(--text-primary); border-color: var(--border-strong); }
.btn-secondary:hover { background: var(--neutral-bg); }
.btn-secondary.danger { background: var(--danger-bg); color: var(--danger-text); border-color: transparent; }
.btn-secondary.danger:hover { background: var(--danger-bg); opacity: .85; }
.btn-primary:disabled, .btn-secondary:disabled { opacity: .45; cursor: not-allowed; }
.btn-primary:disabled:hover { background: var(--accent); }
.btn-secondary:disabled:hover { background: var(--surface); }
.btn-block { width: 100%; padding: 10px; font-size: 14px; }
/* Small variant, used for the delete/confirm buttons on compact pipeline
   and daily-entry cards (feature 2) — same visual language as .btn-secondary,
   just tighter so a row of them doesn't overwhelm a one-line card. */
.btn-xs { padding: 4px 9px; font-size: 11.5px; }
.icon-btn { width: 30px; height: 30px; padding: 0; display: flex; align-items: center; justify-content: center; border-radius: var(--radius); border: none; background: transparent; color: var(--text-secondary); cursor: pointer; }
.icon-btn:hover { background: var(--neutral-bg); }
.err { color: var(--danger-text); font-size: 13px; margin-top: 10px; min-height: 16px; }

/* ---------- App shell ---------- */
#appShell { min-height: 100vh; display: none; }
.sidebar { position: fixed; top: 0; left: 0; bottom: 0; width: 220px; background: var(--surface);
            border-right: 1px solid var(--border); display: flex; flex-direction: column; padding: 16px 12px; z-index: 20; }
.sidebar-top { display: flex; align-items: center; justify-content: space-between; padding: 4px 4px 20px 6px; position: relative; }
.sidebar-logo { font-size: 15px; font-weight: 600; }
.bell-btn { position: relative; background: none; border: none; padding: 6px; border-radius: 50%; cursor: pointer; color: var(--text-secondary); display: flex; }
.bell-btn:hover { background: var(--neutral-bg); }
.notif-badge { position: absolute; top: 1px; right: 1px; background: var(--danger-text); color: #fff; font-size: 10px; font-weight: 700;
                min-width: 15px; height: 15px; border-radius: 8px; display: flex; align-items: center; justify-content: center; padding: 0 3px; }
.notif-dropdown { position: absolute; top: 100%; z-index: 30; width: 300px; max-width: calc(100vw - 24px); background: var(--surface); border: 1px solid var(--border);
                    border-radius: var(--radius); box-shadow: 0 8px 24px rgba(0,0,0,.12); max-height: 360px; overflow-y: auto; }
/* Sidebar (desktop) is only 220px wide — a 300px dropdown anchored to its
   right edge would overflow off the left side of the whole page. Anchor
   from the left instead, so it extends rightward into the main content
   area where there's actual room. The mobile top bar spans the full page
   width, so right:0 there sits safely inside the viewport. */
#notifDropdownDesktop { left: 0; }
#notifDropdownMobile { right: 0; }
.notif-dropdown-header { padding: 10px 14px; border-bottom: 1px solid var(--border); font-weight: 600; font-size: 13px; }
.notif-item { padding: 12px 14px; border-bottom: 1px solid var(--border); cursor: pointer; }
.notif-item:hover { background: var(--neutral-bg); }
.notif-item:last-child { border-bottom: none; }
.notif-item-title { display: flex; justify-content: space-between; align-items: flex-start; font-size: 13px; font-weight: 600; gap: 8px; }
.notif-item-title .date { font-size: 11px; color: var(--text-muted); font-weight: 400; white-space: nowrap; }
.notif-item-body { font-size: 12.5px; color: var(--text-secondary); margin-top: 3px; }
.notif-item-sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.notif-empty { padding: 20px 14px; text-align: center; font-size: 13px; color: var(--text-muted); }
.sidebar-nav { display: flex; flex-direction: column; gap: 2px; }
.sidebar-nav button, .mobile-tabs button {
    display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: var(--radius);
    border: none; background: transparent; color: var(--text-secondary); font-size: 13.5px; font-weight: 500;
    cursor: pointer; text-align: left; width: 100%;
}
.sidebar-nav button.active { background: var(--accent-bg); color: var(--accent-text); }
.sidebar-nav button:hover:not(.active) { background: var(--neutral-bg); }

.sidebar-footer { margin-top: auto; display: flex; align-items: center; gap: 10px; padding: 12px 10px 8px; border-top: 1px solid var(--border); }
.avatar { width: 30px; height: 30px; border-radius: 50%; background: var(--accent-bg); color: var(--accent-text);
           display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; flex-shrink: 0; }
.who-info { min-width: 0; overflow: hidden; }
.who-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.who-role { font-size: 11.5px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.logout-btn { margin: 6px 10px 0; padding: 7px 10px; font-size: 12.5px; font-weight: 600; color: var(--text-secondary);
               background: var(--neutral-bg); border: none; border-radius: var(--radius); cursor: pointer; }
.logout-btn.btn-block { margin: 0; font-size: 14px; }
.logout-btn:hover { background: var(--border); }

.main { margin-left: 220px; padding: 24px 28px 60px; max-width: 1040px; }

.page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.page-header h1 { font-size: 19px; font-weight: 600; margin: 0; }

.mobile-tabs { display: none; }
.mobile-topbar { display: none; }

section.tab { display: none; }
section.tab.active { display: block; }

/* ---------- KPI cards ---------- */
.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin-bottom: 22px; }
.kpi { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 14px 16px; }
.kpi .n { font-size: 24px; font-weight: 600; }
.kpi .l { font-size: 12px; color: var(--text-secondary); margin-top: 4px; }
.kpi.red { background: var(--danger-bg); border-color: transparent; } .kpi.red .n { color: var(--danger-text); } .kpi.red .l { color: var(--danger-text); }
.kpi.amber { background: var(--warning-bg); border-color: transparent; } .kpi.amber .n { color: var(--warning-text); } .kpi.amber .l { color: var(--warning-text); }
.kpi.green { background: var(--success-bg); border-color: transparent; } .kpi.green .n { color: var(--success-text); } .kpi.green .l { color: var(--success-text); }

.section-label { font-size: 13px; font-weight: 600; color: var(--text-secondary); margin: 22px 0 10px; }
.section-label:first-child { margin-top: 0; }

/* ---------- Pipeline funnel: stage-bar chart (redesign #2) ----------
   Replaces the tile-grid from the previous redesign. Tiles solved the old
   proportional-bar's clipping bug but read more like a second KPI row than a
   funnel. Here, volume is encoded by a track-fill's length instead of the
   label's own box width, so a long stage name (e.g. "Service Agreement
   Sent") never has to fight its count for space — the label always gets a
   full-width row above the bar. Lost/On Hold are kept out of the bar
   entirely (see funnel-exit-row) since they're outcomes, not stages a deal
   advances through in sequence. */
.panel-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 2px; }
.funnel-total { font-size: 12.5px; color: var(--text-secondary); }
.funnel-bar-list { max-width: 620px; margin-bottom: 6px; }
.stage-row { padding: 10px 0; cursor: pointer; }
.stage-top { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 6px; }
.stage-name { font-size: 13px; font-weight: 500; display: flex; align-items: center; gap: 7px; }
.stage-name .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; display: inline-block; }
.stage-name b { color: var(--text-secondary); font-weight: 600; }
.stage-value { font-size: 12.5px; color: var(--text-secondary); }
.stage-track { height: 9px; border-radius: 5px; background: var(--neutral-bg); overflow: hidden; }
.stage-fill { height: 100%; border-radius: 5px; }
.funnel-exit-row { display: flex; gap: 8px; margin: 10px 0 22px; flex-wrap: wrap; }
.funnel-exit-chip { font-size: 11.5px; font-weight: 600; padding: 5px 11px; border-radius: 999px; }
.funnel-exit-chip.danger { background: var(--danger-bg); color: var(--danger-text); }
.funnel-exit-chip.warn { background: var(--warning-bg); color: var(--warning-text); }

/* ---------- Activity trend chart (new) ---------- */
.trend-head { display: flex; justify-content: space-between; align-items: baseline; margin: 4px 0 10px; }
.trend-total { font-size: 12.5px; color: var(--text-secondary); }
.trend-chart { display: flex; align-items: flex-end; gap: 8px; height: 86px; max-width: 620px; margin-bottom: 22px; }
.tbar-wrap { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; height: 100%; justify-content: flex-end; }
.tbar { width: 100%; border-radius: 5px 5px 3px 3px; background: var(--accent-bg); }
.tbar.today { background: var(--accent); }
.tbar-wrap .tl { font-size: 10.5px; color: var(--text-muted); }

/* ---------- Team leaderboard (new, manager dashboard only) ---------- */
.lb-list { max-width: 420px; margin-bottom: 22px; }
.lb-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; }
.lb-rank { width: 18px; font-size: 12px; font-weight: 600; color: var(--text-muted); text-align: center; flex: 0 0 18px; }
.lb-rank.gold { color: var(--warning-text); }
.lb-avatar { width: 26px; height: 26px; border-radius: 50%; background: var(--neutral-bg); border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center; font-size: 10.5px; font-weight: 600; flex: 0 0 26px; }
.lb-body { flex: 1; min-width: 0; }
/* gap + ellipsis, because without them a long name ("Test Account (app
   testing)") runs straight into its own activity count with no space at all --
   which is exactly how it looked on the live site: "Nazim12", "Badruddin11". */
.lb-name { font-size: 13px; font-weight: 500; display: flex; justify-content: space-between;
  align-items: baseline; gap: 10px; }
.lb-name span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-name b { font-weight: 600; flex: 0 0 auto; font-variant-numeric: tabular-nums; }
.lb-bar { height: 5px; border-radius: 4px; background: var(--neutral-bg); margin-top: 4px; overflow: hidden; }
.lb-bar i { display: block; height: 100%; background: var(--accent); border-radius: 4px; }

/* ---------- Manager dashboard: funnel / trend chart / leaderboard panels ----------
   auto-fit + minmax(300px,1fr): fits as many of the 3 panels side by side as
   the available width allows -- 3 on a wide desktop, wrapping down to 2 then
   1 as the viewport narrows, with no separate mobile-breakpoint override
   needed. 300px is tuned against .main's own max-width:1040px (see .main
   below) -- that caps this grid's real container at ~984px, so anything
   above ~300px per column (3*N + 2*20 gap > 984) would always fall back to
   2 columns even on an ultrawide monitor. 300px keeps .funnel-bar-list
   (longest stage name "Service Agreement Sent" + its value) and .trend-chart
   readable on one line. Each panel is wrapped in a bordered card so a
   shorter panel (trend chart, leaderboard) doesn't look like a stray
   fragment next to the taller funnel -- grid's default stretch matches
   every card in a row to its tallest sibling, and the flex column +
   justify-content:center vertically centers a shorter panel's content
   within that matched height. */
.dash-panels-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; }
.dash-panels-grid > div { border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
  padding: 16px 18px; display: flex; flex-direction: column; justify-content: center; }

/* ---------- Data table ---------- */
/* overflow-x:auto (not hidden) so columns that can't fit on narrow screens
   (e.g. nowrap status/stage badges) scroll into view instead of getting
   silently clipped with no way to see the rest. overflow-y stays hidden so
   the wrapper's rounded corners still clip the header row cleanly. */
.data-table-wrap { border: 1px solid var(--border); border-radius: 10px; overflow-x: auto; overflow-y: hidden; background: var(--surface); -webkit-overflow-scrolling: touch; }
table.data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
table.data-table th { text-align: left; padding: 10px 14px; color: var(--text-secondary); font-weight: 600; font-size: 12px; background: var(--neutral-bg); border-bottom: 1px solid var(--border); }
table.data-table td { padding: 10px 14px; border-bottom: 1px solid var(--border); vertical-align: middle; }
table.data-table tr:last-child td { border-bottom: none; }
/* ANYTHING MARKED CLICKABLE LOOKS CLICKABLE.
   Every .clickable rule below is scoped to a parent -- a table row, a quick row,
   a KPI -- so a plain <div class="clickable"> got no pointer and no hover at
   all. The calendar rows on Today and the client rows on Sales are exactly
   that: the name opens the account, and the cursor stayed an I-beam over it.
   Lamrath spotted it in a screen recording. One base rule, so a new clickable
   cannot be born without it. */
.clickable { cursor: pointer; }
table.data-table tr.clickable { cursor: pointer; }
table.data-table tr.clickable:hover td { background: var(--neutral-bg); }
/* Generic name/sub pairing — used in the data table AND the compact
   quick-list rows (Pipeline/Daily entry). Previously scoped only to
   table.data-table, so it silently didn't apply to the quick-list rows;
   this is the fix for that. */
.cell-name { font-weight: 600; }
.cell-sub { color: var(--text-muted); font-size: 12px; margin-top: 2px; }
/* A quiet line that has to read as a problem: a client gone silent, an invoice
   past due. Uses the same token as every other danger colour so it follows the
   theme, rather than a literal that only works on one ground. */
.cell-sub.danger-text { color: var(--danger-text); }
/* "44 of 77" -- the total is context for the figure, not a second figure, so it
   sits at the size of a label rather than competing with the number. */
.kpi-of { font-size: 14px; font-weight: 600; color: var(--text-muted); }
/* WHAT IS ON MY BOOK: three figures on Today, each a way into the page holding
   them. Deliberately not KPI tiles -- these are navigation, and looking like a
   statistic is what made the old grid read as a report nobody acted on. */
.book-strip { display: flex; gap: 10px; flex-wrap: wrap; margin: 10px 0 4px; }
.book-fig { display: flex; align-items: baseline; gap: 6px; background: var(--surface);
    border: 1px solid var(--border); border-radius: var(--radius); padding: 9px 14px;
    cursor: pointer; font: inherit; }
.book-fig:hover { border-color: var(--accent-text); }
.book-fig .n { font-size: 19px; font-weight: 700; color: var(--text-primary); }
.book-fig .l { font-size: 12px; color: var(--text-muted); }
/* The single date control on the activity list. Sized like the other controls
   in that row rather than like a form field, so the row reads as one strip. */
.date-pick { height: 34px; border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--surface); color: var(--text-primary); font-size: 13px; padding: 0 8px; }
table.data-table .cell-name { font-weight: 600; }
table.data-table .cell-sub { color: var(--text-muted); font-size: 12px; margin-top: 2px; }
/* A LINE THAT HAS TO READ AS A PROBLEM STAYS RED INSIDE A TABLE.
   The rule above is more specific than `.cell-sub.danger-text`, so every warning
   in a data table -- "4 invoices past due", "last shipped 289 days ago" -- has
   been rendering in the ordinary muted grey and reading as neutral detail.
   Found by measuring the computed colour rather than looking at the page, which
   is exactly the kind of thing a screenshot alone does not settle. */
table.data-table .cell-sub.danger-text { color: var(--danger-text); }
table.data-table td.actions-cell { text-align: right; white-space: nowrap; }

/* ---------- Badges ---------- */
.badge { display: inline-flex; align-items: center; font-size: 11px; font-weight: 600; padding: 3px 9px; border-radius: 20px; background: var(--neutral-bg); color: var(--neutral-text); white-space: nowrap; }
.badge.danger { background: var(--danger-bg); color: var(--danger-text); }
.badge.warn { background: var(--warning-bg); color: var(--warning-text); }
.badge.success { background: var(--success-bg); color: var(--success-text); }
.badge.accent { background: var(--accent-bg); color: var(--accent-text); }
.rep-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 20px; background: #f0e9fe; color: #7e3af2; margin-top: 4px; }
.rep-chip-dot { width: 6px; height: 6px; border-radius: 50%; background: #7e3af2; flex: none; }

.empty { text-align: center; color: var(--text-muted); font-size: 13px; padding: 40px 10px; }

/* ---------- Modal ---------- */
.modal-backdrop { position: fixed; inset: 0; background: rgba(16,24,40,.45); z-index: 30; display: none; }
.modal-backdrop.active { display: block; }
.modal {
    position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(.98); width: 92%; max-width: 480px;
    background: var(--surface); border-radius: 14px; max-height: 86vh; overflow-y: auto; padding: 18px 20px 22px;
    z-index: 31; display: none; opacity: 0; transition: opacity .15s ease, transform .15s ease;
}
.modal.active { display: block; opacity: 1; transform: translate(-50%, -50%) scale(1); }
.modal-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 4px; }
.modal-header-right { display: flex; align-items: center; gap: 8px; }
.modal-title { font-size: 16px; font-weight: 600; }
.modal-subtitle { font-size: 13px; color: var(--text-secondary); margin-top: 2px; }
.modal-meta { display: flex; flex-wrap: wrap; gap: 14px; font-size: 13px; color: var(--text-secondary); margin: 10px 0 14px; }
.modal-meta .item { display: flex; align-items: center; gap: 5px; }
.modal-actions { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
.modal-actions button { flex: 1; min-width: 100px; }
.modal-section { border-top: 1px solid var(--border); padding-top: 14px; }
.modal-section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; font-size: 13px; font-weight: 600; color: var(--text-secondary); }
.modal-section-toggle { width: 100%; background: none; border: none; padding: 0; cursor: pointer; }
.modal-section-toggle svg { transition: transform .15s ease; }
.modal-section-toggle.open svg { transform: rotate(180deg); }
.modal-notes { font-size: 13px; color: var(--text-secondary); background: var(--neutral-bg); border-radius: var(--radius); padding: 10px 12px; margin-bottom: 14px; }

/* ---------- Lead detail sub-tabs (feature 1): Overview / Timeline / Contacts.
   Same pill-toggle visual language as .preset-group / .badge elsewhere in
   the app — active = accent bg/text, inactive = plain secondary button. ---------- */
.modal-tabs { display: flex; gap: 6px; margin: 12px 0 4px; flex-wrap: wrap; }
.modal-tabs button {
    padding: 6px 12px; border-radius: 20px; font-size: 12.5px; font-weight: 600; cursor: pointer;
    border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-secondary);
}
.modal-tabs button.active { background: var(--accent-bg); color: var(--accent-text); border-color: transparent; }
.ld-tab-panel { display: none; }
.ld-tab-panel.active { display: block; }

/* ---------- Inline confirm bar (lead-detail delete — feature 2) ---------- */
.inline-confirm-bar { background: var(--danger-bg); border-radius: var(--radius); padding: 10px 12px; margin: 8px 0 14px; }

/* ---------- "Not a fit" panel (feature 5) and "Report an issue" panel —
   both now tab-independent: they live in the shared expand zone directly
   below the page action bar (see .ld-expand-zone), opened by their matching
   action-bar button rather than by an accordion inside a tab. ---------- */
.not-a-fit-panel { padding-top: 4px; margin-bottom: 4px; }
.ld-report-panel { padding-top: 4px; margin-bottom: 4px; }
.ld-expand-zone {
    border-top: 1px solid var(--border); margin-top: 14px; padding-top: 14px;
}

/* ---------- Generic pill list (status filters, stage filters, "not a fit"
   reason picker, quick-popup stage list — features 5/6/8) ---------- */
.pill-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.pill-row.vertical { flex-direction: column; }
.pill {
    padding: 6px 12px; border-radius: 20px; font-size: 12px; font-weight: 600; cursor: pointer;
    border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-secondary); text-align: left;
}
.pill:hover { background: var(--neutral-bg); }
.pill.active { background: var(--accent-bg); color: var(--accent-text); border-color: transparent; }
.pill:disabled { opacity: .5; cursor: default; }
.pill .btn-spinner { width: 10px; height: 10px; border-width: 1.5px; vertical-align: -1px; margin-right: 4px;
    border-color: rgba(16,24,40,.15); border-top-color: var(--text-secondary); }

/* My Leads status filter (feature: pills + "more", no dropdown) — on narrow
   screens only the first few pills show plus a toggle to reveal the rest;
   on wide screens every pill is always visible and the toggle disappears. */
.leads-status-row { margin-bottom: 14px; }
.entry-status-row { margin: -8px 0 14px; }
.leads-status-row .pill-extra { display: none; }
.leads-status-row .pill-row.expanded .pill-extra { display: inline-flex; }
.pill-more-toggle { border-style: dashed; color: var(--text-muted); }
@media (min-width: 700px) {
    .leads-status-row .pill-extra { display: inline-flex !important; }
    .leads-status-row .pill-more-toggle { display: none !important; }
}

/* ---------- Photos (feature 3): small thumbnail row + "Add photo" label
   wrapping a hidden file input, styled as a .btn-secondary. ---------- */
.photo-upload-label { cursor: pointer; }
.photo-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.photo-thumb {
    width: 56px; height: 56px; border-radius: var(--radius); overflow: hidden; display: block;
    border: 1px solid var(--border); flex-shrink: 0;
    /* Now a <button>, not an <a> — reset native button chrome so it still
       looks like a plain image tile. */
  background: none; padding: 0; margin: 0; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.photo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-thumb.pending { opacity: .6; }
.photo-thumb-wrap { position: relative; flex-shrink: 0; }
.photo-delete-btn {
    position: absolute; top: -6px; right: -6px; width: 18px; height: 18px; border-radius: 50%;
    background: rgba(15, 18, 25, .75); color: #fff; border: 1px solid rgba(255, 255, 255, .5);
    display: flex; align-items: center; justify-content: center; font-size: 13px; line-height: 1;
    padding: 0; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.photo-delete-btn.confirm { background: var(--danger-text); border-color: var(--danger-text); }
.photo-delete-btn:disabled { opacity: .6; cursor: default; }

/* Full-size photo viewer — replaces navigating to a data: URL in a new tab,
   which mobile Safari silently refuses to do. */
.photo-lightbox {
    display: none; position: fixed; inset: 0; z-index: 999; background: rgba(15, 18, 25, .92);
    align-items: center; justify-content: center; padding: 24px;
}
.photo-lightbox.active { display: flex; }
.photo-lightbox img { max-width: 100%; max-height: 100%; border-radius: 8px; object-fit: contain; }
.photo-lightbox-close {
    position: absolute; top: 16px; right: 16px; width: 40px; height: 40px; border-radius: 50%;
    border: none; background: rgba(255, 255, 255, .12); color: #fff; font-size: 24px; line-height: 1;
    cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.photo-lightbox-close:hover { background: rgba(255, 255, 255, .22); }

/* ---------- Compact "quick list" rows (minimal Pipeline / Daily entry lists —
   features 6/7) — replaces the old dense data-table for these two tabs.
   Each row lives inside .quick-row-wrap, which owns the card chrome
   (border/radius/background) so an expanded accordion panel can sit flush
   underneath the row as one continuous card, instead of the old separate
   quickModal popup. ---------- */
.quick-list { display: flex; flex-direction: column; gap: 8px; }
.quick-row-wrap { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.quick-row {
    display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 14px;
}
.quick-row.clickable { cursor: pointer; }
.quick-row.clickable:hover { background: var(--neutral-bg); }
.quick-row-main { min-width: 0; flex: 1; }
.quick-row-side { display: flex; align-items: center; gap: 8px; flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }
.quick-row-icon {
    width: 32px; height: 32px; border-radius: 50%; background: var(--accent-bg); color: var(--accent-text);
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.quick-row-title-line { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.quick-row-title-line .cell-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.quick-row-time { font-size: 11.5px; color: var(--text-muted); white-space: nowrap; flex-shrink: 0; }
.quick-row-chevron { display: flex; color: var(--text-muted); transition: transform .15s ease; }
.quick-row-chevron.open { transform: rotate(180deg); }
.quick-accordion { border-top: 1px solid var(--border); background: var(--neutral-bg); padding: 12px 14px; }

/* ---------- Activity timeline ---------- */
.timeline-item { display: flex; gap: 12px; }
.timeline-dot { display: flex; flex-direction: column; align-items: center; width: 22px; flex-shrink: 0; }
.timeline-icon { width: 22px; height: 22px; border-radius: 50%; background: var(--accent-bg); color: var(--accent-text);
                  display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.timeline-line { width: 1px; flex: 1; background: var(--border); margin-top: 2px; }
.timeline-body { padding-bottom: 18px; min-width: 0; flex: 1; }
.timeline-title { font-size: 13px; margin-bottom: 2px; }
.timeline-title .date { color: var(--text-muted); font-weight: 400; }
.timeline-notes { font-size: 13px; color: var(--text-secondary); margin-bottom: 6px; }

.autofilled-box { background: var(--accent-bg); border-radius: var(--radius); padding: 8px 10px; font-size: 12.5px; margin-bottom: 12px; color: var(--accent-text); }
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* ---------- Lead detail: extra info blocks (service / why-fit) ---------- */
/* A LEAD'S FACTS ARE A TABLE, NOT A STACK OF CARDS.
   Each of these holds two or three words -- a rep's name, a date, a source. As
   full-width tinted cards stacked one per row they took half the page to say
   almost nothing, and pushed the shipping record, which is what the page is
   actually for, off to the side. Two columns, no tint, a hairline between rows:
   the same facts in roughly a third of the height. */
/* Across the top, wrapping. Each value is two or three words, so laying them
   out in rows fits eight facts in two lines instead of eight. */
.modal-info-blocks { display: flex; flex-wrap: wrap; gap: 4px 30px; margin-bottom: 2px; }
.info-block { padding: 5px 0; min-width: 0; }
/* Prose takes its own line -- "why they fit" is a sentence, not a value.
   Clamped to three lines, because on a phone a long research note pushed the
   tabs 400px down the page. Tapping it opens the rest: the text is the reason
   to ring them, so it must never become unreachable. */
.info-block.wide { flex-basis: 100%; }
.info-block.wide .info-block-text { display: -webkit-box; -webkit-box-orient: vertical;
    -webkit-line-clamp: 3; overflow: hidden; cursor: pointer; }
.info-block.wide.open .info-block-text { -webkit-line-clamp: unset; overflow: visible; }
/* A shipping code is an identifier people read back to each other over the
   phone, so it is set in a monospace face where 0 and O cannot be confused. */
.mono-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px;
    font-weight: 600; letter-spacing: .02em; }
/* The shipping system's own name for the company, beside its code. Quieter than
   the code and allowed to truncate: the code is what gets read out loud, the
   name is there to confirm it is the right company. */
/* The shipping system's own name for the company, beside its code. It WRAPS
   rather than truncating: it was cut at 260px to "TECHNICAL PRINCIPLES COMPANY
   FOR M…", and a legal name half-shown is worse than useless -- the whole point
   of putting it here is to confirm the link is the right company. */
.cms-name { color: var(--text-muted); font-size: 12px; margin-left: 7px; }
.cms-name:empty { display: none; }
/* Long enough to hold a Saudi legal name on one or two lines without pushing
   every other fact off the row. */
.info-block.has-cms-name { flex-basis: 100%; max-width: 520px; }

/* MONTH BY MONTH, AS A MIX. The bar's length is the month's revenue against the
   best month on screen; its segments are the products. The mix is the story --
   a client converting pallets to FTL is what a total alone cannot show. */
.mix-legend { display: flex; flex-wrap: wrap; gap: 10px; margin: 6px 0 8px; }
.mix-list { display: flex; flex-direction: column; gap: 2px; }
.mix-row { display: grid; grid-template-columns: 96px 1fr auto; align-items: center;
    gap: 10px; padding: 6px 0; }
.mix-row:hover { background: var(--accent-bg); border-radius: 6px; }
.mix-label { font-size: 12.5px; color: var(--text-secondary); }
.mix-bar { display: flex; height: 12px; border-radius: 6px; overflow: hidden;
    background: var(--border); min-width: 8px; }
.mix-seg { height: 100%; }
.mix-figs { font-size: 12.5px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mix-detail { display: flex; flex-wrap: wrap; gap: 10px; padding: 2px 0 8px 106px; }
.mix-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
    color: var(--text-muted); }
.mix-dot { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }
@media (max-width: 560px) {
    .mix-row { grid-template-columns: 78px 1fr auto; gap: 7px; }
    .mix-detail { padding-left: 0; }
}
.info-block-label { font-size: 10.5px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
    color: var(--text-muted); margin-bottom: 1px; }
.info-block-text { font-size: 13px; color: var(--text-primary); overflow-wrap: anywhere; }
@media (max-width: 560px) { .modal-info-blocks { gap: 4px 20px; } }

/* ---------- Inline stage dropdown (kept for any remaining dropdown use) ---------- */
.stage-select { padding: 4px 8px; border: 1px solid var(--border-strong); border-radius: var(--radius); font-size: 12px;
                 background: var(--surface); color: var(--text-primary); font-family: inherit; cursor: pointer; width: auto; max-width: 160px; }
.stage-select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-bg); }

/* ---------- "Show all" link under a truncated table ---------- */
.show-more-link { display: inline-block; margin-top: 8px; font-size: 12.5px; color: var(--accent-text); cursor: pointer; background: none; border: none; padding: 0; font-family: inherit; }
.show-more-link:hover { text-decoration: underline; }

/* ---------- Page header toolbar: search / date filter / presets / buttons ---------- */
.page-header-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.search-box { position: relative; display: flex; align-items: center; }
.search-box svg { position: absolute; left: 9px; color: var(--text-muted); pointer-events: none; }
.search-box input { padding: 7px 10px 7px 30px; border: 1px solid var(--border-strong); border-radius: var(--radius); font-size: 13px; width: 190px; background: var(--surface); color: var(--text-primary); font-family: inherit; }
.search-box input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-bg); }
.date-filter { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-secondary); }
.date-filter input { padding: 6px 8px; border: 1px solid var(--border-strong); border-radius: var(--radius); font-size: 12.5px; background: var(--surface); color: var(--text-primary); font-family: inherit; }
.preset-group { display: flex; gap: 4px; }
.preset-group .btn-secondary { padding: 6px 10px; font-size: 12px; }
.preset-group .btn-secondary.active { background: var(--accent-bg); color: var(--accent-text); border-color: transparent; }
.revenue-filter { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-secondary); }
.revenue-filter input { width: 80px; padding: 6px 8px; border: 1px solid var(--border-strong); border-radius: var(--radius); font-size: 12.5px; background: var(--surface); color: var(--text-primary); font-family: inherit; }
.leads-filter-row { flex-wrap: wrap; row-gap: 8px; margin-top: -4px; margin-bottom: 14px; }

/* ---------- Static (non-editable) field value, e.g. auto-set date ---------- */
.static-value { padding: 9px 12px; font-size: 14px; color: var(--text-secondary); background: var(--neutral-bg); border-radius: var(--radius); }
.field-hint-inline { font-size: 11px; font-weight: 400; color: var(--text-muted); }

/* Log activity: escalate-to-manager checkbox + computed status preview
   (replaces the old manual Status dropdown — status is now derived, not
   picked, so a rep can't forget to close something or mis-pick a value). */
.escalate-check { display: flex; align-items: flex-start; gap: 8px; font-size: 13.5px; color: var(--text-primary); margin: 2px 0 14px; cursor: pointer; }
.escalate-check input { margin-top: 3px; width: auto; }
.status-preview { background: var(--neutral-bg); border-radius: var(--radius); padding: 10px 12px; }
.status-preview .badge { font-size: 12.5px; padding: 5px 11px; }

/* Manager logging on a rep's behalf (feature: manager-logged activities) —
   a plain-language heads-up in the Log Activity form, and a matching badge
   wherever these entries show up in a Timeline. */
.manager-log-banner { background: var(--accent-bg); color: var(--accent-text); border-radius: var(--radius); padding: 10px 12px; margin-bottom: 14px; }
.badge.manager-logged { background: var(--accent-bg); color: var(--accent-text); }

/* ---------- Full escalation flow ---------- */
.escalation-note { background: var(--warning-bg); border-radius: var(--radius); padding: 8px 10px; margin-top: 6px; }
.escalation-note.resolved { background: var(--neutral-bg); }
.escalation-note .cell-sub { margin-top: 4px; }
.escalation-row { border-top: 1px solid var(--border); padding: 10px 0; }
.escalation-row:first-child { border-top: none; padding-top: 0; }
.escalation-row.clickable { cursor: pointer; }
.escalation-row.clickable:hover { background: var(--neutral-bg); }
.escalation-resolve-form { margin-top: 8px; background: var(--neutral-bg); border-radius: var(--radius); padding: 10px; }
.escalation-resolve-form textarea { margin-bottom: 8px; }

/* Escalation cards (manager's open queue + rep's resolved feed): a
   responsive grid — auto-fit keeps this from being hard-coded to any
   column count, same technique as .kpi-grid. Naturally 1 column on mobile,
   more as the container widens. */
.esc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; }
.esc-card { background: var(--surface); border: 1px solid var(--border); border-left: 3px solid; border-radius: 12px; padding: 12px 14px; }
.esc-card.open { border-left-color: var(--warning-text); }
.esc-card.resolved { border-left-color: var(--success-text); }
.esc-card-top { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.esc-status-icon { display: flex; width: 18px; height: 18px; border-radius: 50%; align-items: center; justify-content: center; flex-shrink: 0; }
.esc-status-icon.open { background: var(--warning-bg); color: var(--warning-text); }
.esc-status-icon.resolved { background: var(--success-bg); color: var(--success-text); }
.esc-status-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .02em; }
.esc-status-label.open { color: var(--warning-text); }
.esc-status-label.resolved { color: var(--success-text); }
.esc-date { font-size: 11px; color: var(--text-muted); margin-left: auto; white-space: nowrap; }
.esc-card-title { font-weight: 600; font-size: 14.5px; margin-bottom: 2px; }
.esc-card-title.clickable { cursor: pointer; }
.esc-card-title.clickable:hover { text-decoration: underline; }
.esc-card-rep { font-size: 11.5px; color: var(--text-muted); margin-bottom: 8px; }
.esc-bubble { display: flex; gap: 8px; margin-top: 8px; }
.esc-avatar { width: 22px; height: 22px; border-radius: 50%; font-size: 10.5px; font-weight: 700; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.esc-avatar.rep { background: var(--accent-bg); color: var(--accent-text); }
.esc-avatar.manager { background: var(--success-bg); color: var(--success-text); }
.esc-bubble-text { background: var(--neutral-bg); border-radius: 10px; border-top-left-radius: 2px; padding: 7px 10px; font-size: 13px; color: var(--text-primary); flex: 1; }
.esc-bubble.manager .esc-bubble-text { background: var(--success-bg); }
.esc-card-actions { display: flex; gap: 6px; margin-top: 10px; }
.btn-primary.btn-sm, .btn-secondary.btn-sm { padding: 5px 12px; font-size: 12.5px; }

/* ---------- Warning banner (e.g. lead's unverified estimate before confirming) ---------- */
.warning-box { background: var(--warning-bg); color: var(--warning-text); border-radius: var(--radius); padding: 8px 10px; font-size: 12.5px; margin-bottom: 12px; }

/* ---------- Clickable KPI cards + their expand panel ---------- */
.kpi.clickable { cursor: pointer; }
.kpi.clickable:hover { box-shadow: 0 0 0 2px var(--border-strong) inset; }
.kpi-expand-panel { margin: -6px 0 22px; }

/* ---------- Sidebar footer as a profile-open button ---------- */
.sidebar-footer.clickable { cursor: pointer; border-radius: var(--radius); }
.sidebar-footer.clickable:hover { background: var(--neutral-bg); }

/* ---------- Loading / buffering state for Save + Login/Logout buttons ---------- */
.btn-spinner {
    width: 13px; height: 13px; border-radius: 50%; display: inline-block;
    border: 2px solid rgba(255,255,255,.4); border-top-color: #fff; animation: btn-spin .6s linear infinite;
}
.btn-secondary .btn-spinner, .logout-btn .btn-spinner { border-color: rgba(16,24,40,.15); border-top-color: var(--text-secondary); }
@keyframes btn-spin { to { transform: rotate(360deg); } }
.btn-primary.is-loading, .btn-secondary.is-loading, .logout-btn.is-loading { cursor: default; opacity: .85; }
.btn-primary.is-saved { background: var(--success-text); }
.btn-secondary.is-saved, .logout-btn.is-saved { background: var(--success-bg); color: var(--success-text); border-color: transparent; }
.btn-check { display: inline-flex; }
form.form-loading .field, form.form-loading .two-col { opacity: .5; pointer-events: none; transition: opacity .15s ease; }

/* ---------- Location block (lead detail: no-location / unverified / verified / prompt states) ---------- */
.location-block { margin-bottom: 14px; }
.location-state { background: var(--neutral-bg); border-radius: var(--radius); padding: 10px 12px; }
.location-state.unverified { background: var(--warning-bg); }
.location-state.verified { background: var(--success-bg); }
.location-state.prompt { background: var(--accent-bg); }
.location-state-label { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; margin-bottom: 8px; }
.location-state-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.location-state-actions a.btn-secondary { text-decoration: none; }

/* ---------- Manual location search (Places Autocomplete + draggable pin) ---------- */
.location-state.search { background: var(--surface); border: 1px solid var(--border-strong); }
.location-search-map { height: 220px; border-radius: var(--radius); overflow: hidden; border: 1px solid var(--border); }

/* ---------- Non-blocking toast (replaces native alert/confirm) ---------- */
.app-toast {
    position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 12px);
    background: var(--danger-bg); color: var(--danger-text);
    border-radius: var(--radius); padding: 10px 16px; font-size: 13px; font-weight: 600;
    box-shadow: 0 4px 16px rgba(16,24,40,.15); max-width: 90vw; text-align: center;
    opacity: 0; pointer-events: none; transition: opacity .2s ease, transform .2s ease; z-index: 9999;
}
.app-toast.visible { opacity: 1; transform: translate(-50%, 0); }
.app-toast.success { background: var(--success-bg); color: var(--success-text); }
/* A caution rather than a failure — "it worked here, but not everywhere yet".
   Without this the type fell through to the base danger red, which overstates
   a message that isn't reporting anything broken. */
.app-toast.warn { background: var(--warning-bg); color: var(--warning-text); }
/* The lead-detail page has a sticky action bar pinned to the bottom of the
   viewport, so a toast at bottom:24px lands on top of its buttons and is hard
   to read (seen during the QA audit after a stage change). Lift the toast clear
   of it, but only while that page is the one on screen. */
body:has(#tab-lead-detail.active) .app-toast,
body:has(#tab-lead-detail.active) .interested-prompt,
body:has(#tab-lead-detail.active) #escalateReasonPrompt { bottom: 92px; }

/* ---------- "Add to pipeline?" nudge (non-blocking, same rationale as the toast above) ---------- */
.interested-prompt {
    position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 12px);
    background: var(--surface); border: 1px solid var(--border-strong);
    border-radius: var(--radius); padding: 14px 16px; box-shadow: 0 4px 16px rgba(16,24,40,.15);
    max-width: 90vw; width: 360px; opacity: 0; pointer-events: none;
    transition: opacity .2s ease, transform .2s ease; z-index: 9999;
}
.interested-prompt.visible { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.interested-prompt-text { font-size: 13.5px; color: var(--text-primary); margin-bottom: 10px; }
.interested-prompt-actions { display: flex; justify-content: flex-end; gap: 8px; }

/* ---------- "Update available" banner (new app version deployed while open) ----------
   Sits higher than the toast/prompt stack: it never auto-dismisses, so if a
   toast appeared while it was up the two rendered on top of each other at
   bottom:24px and neither was readable (seen during the QA audit). */
.update-banner {
    position: fixed; left: 50%; bottom: 84px; transform: translate(-50%, 12px);
    background: var(--surface); border: 1px solid var(--border-strong);
    border-radius: var(--radius); padding: 10px 12px 10px 14px; box-shadow: 0 4px 16px rgba(16,24,40,.15);
    max-width: 90vw; display: flex; align-items: center; gap: 12px;
    opacity: 0; pointer-events: none; transition: opacity .2s ease, transform .2s ease; z-index: 9999;
}
.update-banner.visible { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.update-banner-text { font-size: 13px; color: var(--text-primary); }
.update-banner-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); flex: none; animation: update-banner-pulse 1.6s ease-in-out infinite; }
@keyframes update-banner-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
.update-banner button { background: var(--accent); color: #fff; border: none; padding: 7px 12px; border-radius: 6px; font-size: 12.5px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.update-banner button:hover { background: var(--accent-hover); }

/* ---------- Other contacts list (lead detail) ---------- */
.contact-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.contact-row:last-child { border-bottom: none; }
.contact-row-name { font-size: 13.5px; font-weight: 600; }
.contact-row-title { font-weight: 400; color: var(--text-secondary); }
.contact-row-meta { display: flex; flex-wrap: wrap; gap: 10px; font-size: 12.5px; color: var(--text-secondary); margin-top: 3px; }
.contact-row-meta .item { display: flex; align-items: center; gap: 4px; }

/* ---------- Lead detail: Changes tab ---------- */
.change-row { padding: 10px 0; border-bottom: 1px solid var(--border); }
.change-row:last-child { border-bottom: none; }
.change-row-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; }
.change-field { font-size: 13px; font-weight: 600; }
.change-row-diff { font-size: 13px; color: var(--text-primary); }
.change-row-date { font-size: 12px; color: var(--text-muted); margin-top: 2px; }

/* ---------- Leads page: nearby button, filter chip ---------- */
#leadsNearbyBtn.active { background: var(--accent-bg); color: var(--accent-text); border-color: transparent; }
.filter-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--accent-bg); color: var(--accent-text); font-size: 12.5px; font-weight: 600; padding: 5px 6px 5px 12px; border-radius: 20px; margin-bottom: 14px; }
.filter-chip button { border: none; background: none; color: inherit; font-size: 15px; line-height: 1; cursor: pointer; padding: 2px 6px; border-radius: 50%; }
.filter-chip button:hover { background: rgba(29,78,216,.12); }

/* ---------- Map tab ---------- */
.map-legend { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 12px; font-size: 12.5px; color: var(--text-secondary); }
.legend-item { display: flex; align-items: center; gap: 6px; }
.legend-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.map-container { height: 65vh; min-height: 360px; border-radius: 10px; overflow: hidden; border: 1px solid var(--border); background: var(--neutral-bg); }

@media (max-width: 860px) {
    /* The header is nowrap on desktop, so on a phone the title and a full-width
       actions block fought for one line and pushed the last control off the
       right edge -- on Daily Entry the "to" date ran past 375px and could not
       be tapped. Let the title take its own line instead. */
    .page-header { flex-wrap: wrap; gap: 10px; }
    .page-header-actions { width: 100%; }
    .search-box input { width: 100%; }
    .map-container { height: 55vh; }
}

/* ---------- Responsive: collapse sidebar into bottom nav on narrow screens ---------- */
@media (max-width: 860px) {
    .sidebar { display: none; }
    .main { margin-left: 0; padding: 16px 14px 90px; }
    .mobile-topbar { display: flex; align-items: center; justify-content: space-between;
                        position: sticky; top: 0; background: var(--surface); border-bottom: 1px solid var(--border);
                        padding: 10px 14px; margin: 0 0 12px; z-index: 21; }
    .mobile-topbar-logo { font-size: 15px; font-weight: 600; }
    .topbar-actions { position: relative; display: flex; align-items: center; gap: 14px; }
    .mobile-topbar-profile { background: none; border: none; padding: 0; cursor: pointer; }
    .mobile-tabs { display: flex; position: fixed; bottom: 0; left: 0; right: 0; background: var(--surface);
                      border-top: 1px solid var(--border); z-index: 20; padding: 4px 0; }
    .mobile-tabs button { flex-direction: column; gap: 3px; font-size: 11px; padding: 6px 2px; border-radius: 0; }
    .mobile-tabs button.active { color: var(--accent-text); background: none; }
    .modal { width: calc(100% - 24px); }
    .kpi-grid { grid-template-columns: repeat(2, 1fr); }
    table.data-table { font-size: 12.5px; }
  /* Hiding the third column used to apply to EVERY table in the app, which
     also removed "Next action" from the manager's needs-attention list,
     "Activity" from Field checks, "Field" from Recent field corrections and
     "Due today" from the All-reps table -- with nothing to say a column was
     missing. Scoped to My Leads (where the third column is Priority, also
     shown as a badge on the row itself). Every other table scrolls
     sideways instead, which .data-table-wrap already supports. */
  #leadsContent table.data-table th:nth-child(3),
  #leadsContent table.data-table td:nth-child(3) { display: none; }

  /* Lead-detail sub-tabs (feature 1): let the pill row wrap and shrink its
       padding a touch so three tabs never force horizontal scroll at ~360-400px. */
  .modal-tabs { gap: 4px; }
  .modal-tabs button { padding: 6px 10px; font-size: 12px; }

  /* Quick-action popups (features 6/7) + pill rows (features 5/6/8): stack
     full-width so nothing overflows a narrowed modal, and action buttons
     (Open lead / Add to pipeline / Confirm / Cancel) stay easy to tap. */
  .quick-row { flex-wrap: wrap; }
  .quick-row-side { width: 100%; justify-content: flex-start; }
  .pill-row:not(.vertical) { gap: 5px; }
  .pill { padding: 6px 10px; font-size: 11.5px; }
  .modal-actions button { min-width: 0; flex-basis: 100%; }

  /* Inline accordion rows (Pipeline/Daily entry redesign): let the name +
     timestamp line wrap instead of squeezing the timestamp off narrow
     phones, and give the accordion panel the same tighter padding as the
     row above it. */
  .quick-row-title-line { flex-wrap: wrap; }
  .quick-accordion { padding: 10px 12px; }

  /* Photo thumbnails (feature 3): slightly smaller so 4+ fit per row without
     forcing the modal to scroll horizontally. */
  .photo-thumb { width: 48px; height: 48px; }

  /* Manager password-reset panel (feature 4) — table action buttons already
     wrap via actions-cell's white-space, but the two buttons together are
     wide; let them stack under each other in the narrow rep table. */
  table.data-table td.actions-cell { white-space: normal; }
  table.data-table td.actions-cell .btn-secondary { margin: 2px 0; }

  /* Not-a-fit / inline-confirm panels: full-width action buttons, consistent
     with the rest of the narrow-screen modal treatment above. */
  .not-a-fit-panel .modal-actions button,
  .inline-confirm-bar > div button { flex: 1 1 0; min-width: 0; }

  /* Lead detail full page: stack the rail above the tabbed content, and
     keep the sticky action bar clear of the fixed bottom tab bar. */
  .ld-page-body { display: block; }
  .ld-page-actionbar { bottom: 54px; }

  /* Toasts, the "Add to pipeline?" nudge, the escalation-reason prompt and the
     "Update available" banner all sit at bottom:24px, which on a phone puts
     them ON TOP of the fixed bottom tab bar (measured on a 375x812 screen: the
     bar occupies 757-812, the overlays reached 788-800). Text was unreadable
     and, worse, their buttons -- Refresh, Add to pipeline, Escalate -- sat over
     nav tabs, so a tap could hit the wrong thing. Lift all four clear of it. */
  .app-toast, .interested-prompt, #escalateReasonPrompt { bottom: 70px; }
  .update-banner { bottom: 130px; }
}

/* ---------- Lead detail: full page (replaces the old centered popup —
   left info rail + right tabbed content + a bottom action bar that stays
   reachable without scrolling back up). ---------- */
.ld-page-header { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 4px; }
.ld-page-title { flex: 1; min-width: 0; }
/* One column now: facts across the top, the tabbed work full width beneath. */
.ld-page-body { display: block; margin-top: 14px; }
/* The facts strip. A hairline under it separates "what this company is" from
   "what we do about it" without drawing a box round either. */
.ld-facts { padding-bottom: 12px; border-bottom: 1px solid var(--border); margin-bottom: 16px; }
.ld-main { min-width: 0; }
.ld-page-actionbar {
    display: flex; gap: 8px; flex-wrap: wrap; margin-top: 24px; padding: 14px 0 4px;
    border-top: 1px solid var(--border); position: sticky; bottom: 0; background: var(--bg);
}
.ld-page-actionbar button { flex: 1; min-width: 120px; }

/* "More" overflow (mobile only): Log activity + Add to pipeline stay put;
   Edit lead / Report an issue / Not a fit collapse behind a More toggle so
   the bar never crowds/overlaps the fixed bottom mobile tab bar. Desktop
   always shows every button inline and hides the More button entirely. */
.ld-more-btn { display: none; }
@media (min-width: 700px) {
    .ld-more-btn { display: none !important; }
}
@media (max-width: 699px) {
    .ld-page-actionbar .ld-action-extra { display: none; }
    .ld-page-actionbar .ld-more-btn { display: flex; flex: 1 1 100%; }
    .ld-page-actionbar.expanded .ld-action-extra { display: flex; }
}

/* ---------- Daily-entry accordion: full activity detail (status, outcome,
   next action, follow-up) for the tapped row, shown as a compact 2-col
   field grid above the trimmed "other activities" history. ---------- */
.entry-detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; margin-bottom: 12px; }
.entry-detail-label { font-size: 11px; color: var(--text-muted); margin-bottom: 2px; }
.entry-detail-value { font-size: 13px; color: var(--text-primary); font-weight: 600; }
.entry-detail-note { margin-bottom: 14px; }
.entry-detail-note .entry-detail-value { font-weight: 400; line-height: 1.5; }

/* ---------- Day tracking (manager-only): map + timeline of one rep's day ----
   A stop row is clickable and pairs with a numbered pin on the map above it.
   A leg between stops states only the straight-line distance between two
   recorded positions — never a claim about the route. A stretch with no
   readings gets its own dashed row rather than being folded into a stop. */
.dt-stop { display: flex; gap: 10px; padding: 8px 6px; margin-left: -6px; border-radius: var(--radius); cursor: pointer; }
.dt-stop:hover { background: var(--neutral-bg); }
.dt-stop.selected { background: var(--accent-bg); }
.dt-time { font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.dt-stop-time { width: 96px; flex: none; padding-top: 3px; }
.dt-marker { width: 20px; height: 20px; border-radius: 50%; color: #fff; font-size: 11px; font-weight: 600;
             display: flex; align-items: center; justify-content: center; flex: none; margin-top: 1px; }
.dt-stop-body { flex: 1; min-width: 0; }
.dt-stop-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dt-maplink { font-size: 12px; color: var(--accent-text); }
.dt-act { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 5px; font-size: 13px; color: var(--text-secondary); }
.dt-leg { font-size: 12px; color: var(--text-muted); margin: 2px 0 2px 112px; }
.dt-gap { font-size: 12.5px; color: var(--text-muted); margin: 6px 0 6px 6px; padding: 8px 10px;
          border: 1px dashed var(--border-strong); border-radius: var(--radius); }
@media (max-width: 860px) {
  .dt-stop-time { width: 78px; }
  .dt-leg { margin-left: 88px; }
}

/* ---------- Rep activity: the two oversight views share one page ---------- */
.ra-panel { display: none; }
.ra-panel.active { display: block; }

/* ---------- Settings (manager-only, behind the gear) ----------
   Read-only until Edit is pressed. Rows are deliberately plain: this is not a
   page anyone should enjoy spending time on. */
.set-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 0 0 4px; }
.set-title { font-size: 15px; font-weight: 600; }
.set-list-head { display: flex; align-items: center; gap: 10px; padding: 0 4px 6px;
                 font-size: 11.5px; font-weight: 600; color: var(--text-muted); text-transform: none; }
.set-row-wrap { border-top: 1px solid var(--border); }
.set-row { display: flex; align-items: center; gap: 10px; padding: 10px 4px; }
.set-row-wrap:first-of-type { border-top: 1px solid var(--border); }
.set-row-main { flex: 1; min-width: 0; }
.set-row-region { flex: 0 0 128px; font-size: 13px; }
.set-row-region select { width: 100%; padding: 5px 8px; font-size: 12.5px; border: 1px solid var(--border-strong);
                         border-radius: var(--radius); background: var(--surface); color: var(--text-primary); font-family: inherit; }
.set-row-active { flex: 0 0 132px; font-size: 12px; color: var(--text-secondary); text-align: right; }
/* Which build the rep is running, and any phone setting that stops a day
   recording. Wide enough for a version plus one fault chip without wrapping. */
.set-row-app { flex: 0 0 190px; font-size: 12px; color: var(--text-secondary); text-align: right; }
.set-row-actions { background: var(--neutral-bg); border-radius: var(--radius); padding: 12px; margin: 0 4px 10px; }
.set-row input[type="number"] { padding: 5px 8px; font-size: 12.5px; border: 1px solid var(--border-strong);
                                border-radius: var(--radius); background: var(--surface); color: var(--text-primary); font-family: inherit; }
/* Sits alongside the Offices & tracking rows, which have no fixed columns. */
.set-row + .section-label { margin-top: 22px; }

/* Team-this-week rows on the manager dashboard: overdue/due-today chips, and
   the whole row opens that rep's tracked day. */
.lb-row.clickable { cursor: pointer; border-radius: var(--radius); padding-left: 4px; padding-right: 4px; margin-left: -4px; }
.lb-row.clickable:hover { background: var(--neutral-bg); }
.lb-flags { display: flex; gap: 5px; flex-wrap: wrap; justify-content: flex-end; flex: 0 0 auto; }

@media (max-width: 860px) {
  .set-list-head { display: none; }
  .set-row { flex-wrap: wrap; }
  .set-row-region, .set-row-active, .set-row-app { flex: 1 1 auto; text-align: left; }
  /* The flags were given full width without the row being allowed to wrap, so
     instead of dropping to their own line they took all the space and crushed
     the name and count together. The row has to wrap for this to mean anything. */
  .lb-row { flex-wrap: wrap; }
  .lb-body { flex: 1 1 100%; order: 1; }
  .lb-flags { width: 100%; justify-content: flex-start; order: 2; padding-left: 38px; }
}

/* Show/hide control inside a password field. */
.pw-wrap { position: relative; display: block; }
.pw-wrap input { width: 100%; padding-right: 62px; }
.pw-reveal {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  background: none; border: 0; padding: 4px 8px; cursor: pointer;
  font-size: 12px; font-weight: 600; color: var(--accent);
}
.pw-reveal:hover { text-decoration: underline; }

/* A confirmed revenue figure, so it reads as the real number next to an estimate. */
.rev-confirmed { color: var(--success-text); font-weight: 600; }

/* ---------- Brand logo ----------
   Full lockup including the orange box everywhere the name appears — Lamrath's
   instruction, no frameless wordmark. 34px is the floor: below that the
   "Logistics simplified." line stops being words. The sidebar only exists on
   desktop and the top bar only on mobile, so they never both show at once. */
.brand-logo { display: block; height: auto; width: auto; }
.brand-logo-login { max-width: 240px; margin-bottom: 6px; }
.brand-logo-side { height: 36px; }
.brand-logo-bar { height: 32px; }
@media (max-width: 480px) { .brand-logo-login { max-width: 200px; } }

/* ---------- Day check (manager dashboard) ----------
   Who has clocked in. A left border rather than a filled card: it sits directly
   above the KPI tiles and a solid block there competes with them for the eye,
   when its job is to be glanced at and usually dismissed. Red only when there is
   a genuine gap on a working day. */
.day-check { border: 1px solid var(--border); border-left-width: 3px; border-radius: 8px;
             padding: 10px 12px; margin-bottom: 14px; background: #fff; }
.day-check.gap { border-left-color: #dc2626; }
.day-check.ok { border-left-color: #16a34a; }
.day-check.quiet { border-left-color: var(--border); }
.day-check-head { display: flex; justify-content: space-between; align-items: baseline;
                  gap: 10px; font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.day-check-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.day-check-sub { margin-top: 8px; font-size: 12px; color: var(--text-muted);
                 display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }

/* The day in one sentence, above the tiles. Quiet on purpose — it summarises
   what is already on screen, so it should not compete with it. */
.dt-summary { font-size: 13px; color: var(--text-secondary); line-height: 1.5;
              margin: 0 0 12px; padding: 10px 12px; border-radius: 8px;
              background: var(--accent-bg); }

/* Sales table: six columns do not fit a phone, and a clipped header reads as a
   broken screen rather than as something to scroll. Tenure and per-client are
   the two a manager can do without on a small screen — revenue, clients and
   activity are the comparison itself. */
@media (max-width: 700px) {
  .sales-optional { display: none; }
}

/* Global search overlay. Deliberately a panel near the top rather than a
   full-screen takeover: the results are a short list, and a rep mid-call wants
   to glance and dismiss, not navigate away from what they were doing. */
.search-overlay {
  position: fixed; inset: 0; z-index: 120;
  background: rgba(16, 24, 40, .38);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 8vh 16px 16px;
}
.search-overlay.hidden { display: none; }
.search-panel {
  width: 100%; max-width: 620px; background: var(--surface);
  border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 12px 40px rgba(16, 24, 40, .18); overflow: hidden;
}
.search-input-row {
  display: flex; align-items: center; gap: 9px;
  padding: 12px 14px; border-bottom: 1px solid var(--border); color: var(--text-muted);
}
.search-input-row input {
  flex: 1; border: none; outline: none; font-size: 15px;
  background: transparent; color: var(--text-primary);
}
#searchResults { max-height: 58vh; overflow-y: auto; }
.search-group-label {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-muted); font-weight: 700; padding: 10px 14px 4px;
}
.search-more {
  padding: 4px 14px 10px;
  font-size: 12px;
  color: var(--text-muted);
}
.search-hit {
  display: block; width: 100%; text-align: left; background: none; border: none;
  padding: 9px 14px; cursor: pointer; border-bottom: 1px solid var(--border);
  font: inherit; color: var(--text-primary);
}
.search-hit:hover, .search-hit:focus-visible { background: var(--accent-bg); outline: none; }
.search-hit .t { font-weight: 600; font-size: 14px; }
.search-hit .d { font-size: 12px; color: var(--text-secondary); }
.search-hit .m { font-size: 11.5px; color: var(--text-muted); }
.search-empty { padding: 18px 14px; color: var(--text-secondary); font-size: 13.5px; }

/* The × inside a saved-view pill. Small and quiet: deleting a view is rare, and
   a prominent control here would invite mis-taps on the pill's real purpose. */
.view-remove {
  margin-left: 6px; opacity: .45; font-weight: 700; padding: 0 2px; border-radius: 4px;
}
.view-remove:hover { opacity: 1; background: var(--danger-bg); color: var(--danger-text); }
/* A photo marker on an activity row. Deliberately quiet — it is a fact about
   the row, not a status, so it must not compete with the status badges. */
.photo-count-badge {
    display: inline-flex; align-items: center; gap: 3px; flex-shrink: 0;
    font-size: 11px; font-weight: 600; line-height: 1;
    padding: 2px 6px; border-radius: 999px;
    color: var(--neutral-text); background: var(--neutral-bg);
    border: 1px solid var(--border);
}
.entry-photo-slot .photo-row { margin-bottom: 0; }

/* ---- Sales page ---- */

/* The dashboard's one line of revenue. A card rather than a KPI tile because it
   is a doorway, not a number to read and move on from — the whole thing is the
   click target, and it says where it goes. */
.revenue-strip {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    background: var(--success-bg); border-radius: var(--radius);
    padding: 13px 15px; margin-bottom: 14px; cursor: pointer;
    border: 1px solid transparent;
}
.revenue-strip:hover, .revenue-strip:focus-visible { border-color: var(--success-text); outline: none; }
.revenue-strip-n { font-size: 22px; font-weight: 700; color: var(--success-text); font-variant-numeric: tabular-nums; }
.revenue-strip-l { font-size: 12.5px; color: var(--neutral-text); margin-top: 1px; }
.revenue-strip-go { font-size: 13px; font-weight: 600; color: var(--success-text); white-space: nowrap; }
/* The second line of the attention warning: what the list above had to leave
   out. Quieter than the count it qualifies, because it is context, not the
   headline -- but present, because a silent exclusion is what hid it before. */
.revenue-strip-sub { font-size: 12px; opacity: .85; margin-top: 2px; font-weight: 500; }

/* The team block on the manager's Today: one line per rep, the bar showing how
   much of the month was new business. A rep with nothing logged gets no bar at
   all rather than an empty one -- an empty bar reads as "measured, and zero",
   which is a different claim from "has not logged anything". */
/* THE MANAGER'S TODAY, as three blocks rather than a run of headings.
   Every heading on that page was the same 13px grey as every sub-heading, so
   "Money at risk" and "Needs attention (1)" carried identical weight and
   nothing grouped: it read as one long list. A block is a titled card; what is
   inside it can then be quiet, because the card already says where it starts. */
.dash-block { background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 16px 18px 18px; margin-bottom: 16px; }
.dash-block > .dash-head { margin-bottom: 12px; }
.dash-block .dash-title { font-size: 16px; font-weight: 650; color: var(--text-primary); letter-spacing: -.01em; }
.dash-block .dash-sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
/* Inside a block, a sub-heading is deliberately smaller and quieter than the
   block's own title -- that difference is the hierarchy. */
.dash-block .section-label { font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-muted); margin: 18px 0 8px; }
.dash-block .section-label:first-child { margin-top: 0; }
.dash-block .kpi { background: var(--bg, #f7f8fa); }
.dash-block .data-table-wrap { border-radius: 10px; }

/* WAITING ON YOU — four tiles, the shape approved in the mockup. Amber when
   something is waiting, grey when nothing is: the zeros stay on screen because
   "nothing waiting" is an answer worth seeing, and a row that only appears when
   something is wrong is one nobody learns to read. A dash means we could not
   find out, which is neither. */
.queue-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr)); gap: 10px; margin: 10px 0 16px; }
.queue-tile { text-align: left; padding: 13px 14px; border-radius: 11px; border: 1px solid var(--border);
  background: var(--surface, #fff); cursor: pointer; font: inherit; display: block; }
.queue-tile .n { display: block; font-size: 26px; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.queue-tile .l { display: block; font-size: 12.5px; color: var(--neutral-text); margin-top: 2px; }
.queue-tile.live { border-color: var(--warning-text); background: var(--warning-bg); }
.queue-tile.live .n, .queue-tile.live .l { color: var(--warning-text); }
.queue-tile.done .n { color: var(--text-muted, #98a2b3); font-weight: 600; }
.queue-tile.unknown .n { color: var(--text-muted, #98a2b3); }
.queue-tile:hover { border-color: var(--border-strong); }

.team-line { width: 100%; text-align: left; font: inherit; background: none; cursor: pointer; border: 0; display: flex; align-items: center; gap: 12px; padding: 9px 2px; border-bottom: 1px solid var(--border); }
.team-line:last-child { border-bottom: 0; }
.team-who { font-weight: 600; min-width: 116px; }
.team-bar { flex: 1; min-width: 60px; height: 7px; border-radius: 4px; background: var(--border); overflow: hidden; display: flex; }
.team-bar-a { background: var(--accent); }
.team-bar-b { background: var(--border-strong); }
/* A rep who has logged nothing TODAY. Red because it is the one line on the
   team block a manager may need to act on this morning; the month figure beside
   it stays neutral, so a quiet day on a strong month still reads as one day. */
.team-idle { color: var(--danger-text, #b91c1c); }
.team-n { font-size: 12.5px; color: var(--neutral-text); white-space: nowrap; font-variant-numeric: tabular-nums; }
/* "Nothing logged this month" is an ORDINARY state on the 2nd, not an alarm --
   four reps in red made the whole block read as a failure. Quiet means quiet:
   muted text, no border, no colour. Red is kept for the one thing that has
   genuinely gone wrong, which is an overdue promise. */
.team-line.quiet .team-who { color: var(--text-secondary); font-weight: 500; }
.team-line.quiet .team-n { color: var(--text-muted); }
/* No empty track either: a bar with nothing in it reads as "measured, and
   zero", which is a different claim from "has not logged anything". */
.team-line.quiet .team-bar { background: none; }

/* What a rep actually sells. Three SKUs that behave nothing alike — FTL is
   ~SAR 2,600 a shipment against BOX at ~SAR 50 — so the mix is what shows that
   one revenue target cannot fit everyone. */
.product-bar {
    display: flex; border-radius: 999px; overflow: hidden;
    background: var(--neutral-bg); min-width: 96px;
}
.product-bar i { display: block; height: 100%; }
.product-legend {
    display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 8px;
    font-size: 12.5px; color: var(--text-secondary);
}
.product-legend span { display: inline-flex; align-items: center; gap: 6px; }
.product-dot { width: 9px; height: 9px; border-radius: 2px; display: inline-block; flex-shrink: 0; }

/* Two standings, never one. A rep in his first month ranked on revenue alone
   comes last for having no book, which is the unfairness this exists to remove.
   Only first and last are tinted, so a colour here always means something. */
.standing-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.standing-box {
    background: var(--neutral-bg); border-radius: var(--radius);
    padding: 14px; text-align: center;
}
.standing-box.good { background: var(--success-bg); }
.standing-box.warn { background: var(--warning-bg); }
.standing-pos { font-size: 26px; font-weight: 700; letter-spacing: -.02em; }
.standing-box.good .standing-pos { color: var(--success-text); }
.standing-box.warn .standing-pos { color: var(--warning-text); }
.standing-of { font-size: 13px; font-weight: 600; color: var(--text-secondary); }
.standing-box.good .standing-of { color: var(--success-text); }
.standing-box.warn .standing-of { color: var(--warning-text); }
.standing-cap { font-size: 12.5px; color: var(--text-secondary); margin-top: 3px; }

/* Progress against a target. Only drawn when a target actually exists — null
   means "not set", and a zero bar would read as a target of nothing. */
.target-row { margin-top: 10px; }
.target-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 4px; }
.target-label { font-size: 13px; font-weight: 600; }
.target-figure { font-size: 12.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.target-figure.near { color: var(--warning-text); }
.target-figure.good { color: var(--success-text); font-weight: 600; }
.target-of { color: var(--text-muted); }
.target-track { height: 8px; border-radius: 999px; background: var(--neutral-bg); overflow: hidden; }
.target-track i { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.target-track i.near { background: var(--warning-text); }
.target-track i.good { background: var(--success-text); }
.target-input {
    width: 92px; text-align: right; font: inherit; font-size: 13px;
    padding: 5px 8px; border: 1px solid var(--border-strong); border-radius: 6px;
    background: var(--surface); color: var(--text-primary);
}

/* ---- My Leads filter bar ----
   Twenty-five controls in five wrapping rows became five pills and three
   controls. Rep, source and date are dropdowns because eight rep pills wrapped
   onto their own line on a laptop and were unusable on a phone. */
.leads-control-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 8px; }
.leads-select {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 13px; color: var(--text-secondary);
    border: 1px solid var(--border-strong); border-radius: 8px;
    padding: 3px 4px 3px 10px; background: var(--surface);
}
.leads-select select {
    font: inherit; font-size: 13px; font-weight: 600; color: var(--text-primary);
    border: none; background: transparent; padding: 3px 4px; max-width: 190px;
}
.leads-select select:focus { outline: none; }
.leads-more-panel {
    border: 1px solid var(--border); border-radius: var(--radius);
    padding: 12px; margin-bottom: 8px; background: var(--surface);
}
.leads-more-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px; }

/* A filter you cannot see is one you forget you set — and then the list looks
   broken rather than filtered. Every active filter shows here and comes off in
   one click, with the honest count beside it. */
.leads-chip-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 10px; }
.filter-chip {
    font: inherit; font-size: 12.5px; cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px; border-radius: 999px;
    background: var(--accent-bg); color: var(--accent-text);
    border: 1px solid transparent;
}
.filter-chip:hover { border-color: var(--accent); }
.filter-chip span { opacity: .6; font-weight: 700; }
.filter-chip.clear-all { background: none; color: var(--text-secondary); border-color: var(--border-strong); }
.filter-count { font-size: 12.5px; color: var(--text-secondary); margin-left: 4px; }
.filter-count b { color: var(--text-primary); }

/* Leads or clients: which list you are looking at, not a filter narrowing one.
   Styled as tabs rather than pills so it does not read as another filter row. */
.view-tabs { display: flex; gap: 2px; margin-bottom: 12px; border-bottom: 1px solid var(--border); }
.view-tab {
    font: inherit; font-size: 14px; cursor: pointer; background: none;
    border: none; border-bottom: 2px solid transparent; margin-bottom: -1px;
    padding: 8px 14px; color: var(--text-secondary);
}
.view-tab span { font-size: 12px; color: var(--text-muted); margin-left: 3px; font-variant-numeric: tabular-nums; }
.view-tab:hover { color: var(--text-primary); }
.view-tab.active { color: var(--accent-text); border-bottom-color: var(--accent); font-weight: 600; }
.view-tab.active span { color: var(--accent-text); }

/* The shipping account code, set by the rep once finance creates the client.
   Kept on one line so it reads as a small fact about the account, not a form. */
.cms-code-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.cms-code-label { font-size: 12.5px; color: var(--text-secondary); }
.cms-code-row input {
    width: 120px; font: inherit; font-size: 13px; letter-spacing: .04em;
    padding: 5px 9px; border: 1px solid var(--border-strong); border-radius: 6px;
    background: var(--surface); color: var(--text-primary); text-transform: uppercase;
}

/* The operations queue. Reuses the escalation card the sales manager already
   has, so a rep sees the same shape of answer whichever queue it came from. */
.nav-count {
    display: inline-block; margin-left: auto; min-width: 20px; text-align: center;
    font-size: 11px; font-weight: 700; padding: 1px 6px; border-radius: 999px;
    background: var(--danger-bg); color: var(--danger-text);
}
.ops-note-box { margin-top: 10px; }
.ops-note-box textarea {
    width: 100%; font: inherit; font-size: 14px; padding: 9px 12px;
    border: 1px solid var(--border-strong); border-radius: var(--radius);
    background: var(--surface); color: var(--text-primary); resize: vertical;
}

/* A client name that opens the client, inside a table that is otherwise text. */
.link-like { color: var(--accent-text); font-weight: 600; cursor: pointer; }
.link-like:hover { text-decoration: underline; }

/* ---------- My calendar ----------
   Sunday to Thursday is the working week; Friday is off and Saturday is
   available but not part of it. A past day cell is deliberately quiet. */
.cal-wrap { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.cal-head, .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal-head div { padding: 8px 4px; font-size: 10.5px; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; color: var(--text-secondary); text-align: center;
    border-bottom: 1px solid var(--border); background: var(--neutral-bg); }
.cal-cell { min-height: 74px; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
    padding: 5px 6px 7px; background: var(--surface); text-align: left; font-family: inherit;
    color: inherit; cursor: pointer; display: flex; flex-direction: column; gap: 3px; }
.cal-cell:nth-child(7n) { border-right: none; }
.cal-cell:hover { background: var(--neutral-bg); }
.cal-cell.dim { background: var(--bg); cursor: default; }
.cal-cell.off { background: var(--bg); }
.cal-cell.sat { background: var(--bg); }
.cal-cell.sel { background: var(--accent-bg); box-shadow: inset 0 0 0 2px var(--accent); }
.cal-num { font-size: 12.5px; font-weight: 600; }
.cal-num.today { background: var(--accent); color: #fff; border-radius: 999px; width: 20px; height: 20px;
    display: inline-flex; align-items: center; justify-content: center; font-size: 11px; }
.cal-past { font-size: 10.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.cal-past b { color: var(--success-text); }
.clock-strip { background: var(--neutral-bg); border-radius: var(--radius); padding: 8px 11px;
    font-size: 12.5px; margin-bottom: 8px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.area-head { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
    margin: 16px 0 4px; padding-bottom: 5px; border-bottom: 2px solid var(--accent-bg); }
.area-head b { font-size: 14px; }
@media (max-width: 640px) { .cal-cell { min-height: 58px; padding: 4px; } .cal-past { font-size: 9.5px; } }
.attn-line { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; padding: 10px 12px;
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    font-size: 13px; margin-bottom: 12px; }
.attn-line:hover { border-color: var(--accent); }

/* Plan my week — pick a day, then pick leads. The first version put six day
   buttons on every one of 65 rows; areas are collapsed now and one button adds. */
.day-strip { display: flex; gap: 8px; flex-wrap: wrap; }
.day-tile { flex: 1 1 92px; min-width: 92px; padding: 9px 8px; border-radius: var(--radius);
    border: 1px solid var(--border-strong); background: var(--surface); cursor: pointer;
    font-family: inherit; color: inherit; text-align: left; }
.day-tile:hover:not(:disabled) { border-color: var(--accent); }
.day-tile.on { background: var(--accent-bg); border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.day-tile:disabled, .day-tile.past { opacity: .45; cursor: default; }
.day-tile .n { display: block; font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.day-tile .n.full { color: var(--success-text); }
.day-tile .n .of { font-size: 12px; color: var(--text-muted); font-weight: 600; }
.day-tile .l { display: block; font-size: 11px; color: var(--text-secondary); margin-top: 1px; }

/* An onboarding the rep has asked for and the manager has not answered yet.
   Amber rather than the active purple: it is a request, not a state. */
.pill.pending { background: var(--warning-bg); color: var(--warning-text);
    border-color: var(--warning-text); font-weight: 600; }

/* The district's name under its circle on the planning map. A white halo rather
   than a box: a box would cover the map it is meant to help him read. */
.cal-map-name { text-shadow: 0 0 3px #fff, 0 0 3px #fff, 0 0 4px #fff, 0 1px 2px #fff;
    white-space: nowrap; letter-spacing: .1px; }

/* A duplicated company, its records grouped so the choice between them is one
   decision rather than two rows in a long table. */
.dupe-card { border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
    padding: 12px 14px; margin-bottom: 10px; }
.dupe-card.across-reps { border-color: var(--danger-text); }

.area-card { border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 8px;
    background: var(--surface); overflow: hidden; }
.area-card.open { border-color: var(--accent); }
.area-bar { display: flex; align-items: center; gap: 10px; width: 100%; padding: 11px 13px;
    background: none; border: none; cursor: pointer; font-family: inherit; color: inherit; text-align: left; }
.area-bar:hover { background: var(--neutral-bg); }
.area-name { font-weight: 600; font-size: 14px; }
.area-counts { flex: 1; font-size: 11.5px; color: var(--text-muted); }
.area-chev { color: var(--text-muted); font-size: 12px; }
.area-actions { padding: 0 13px 11px; }
.area-leads { border-top: 1px solid var(--border); padding: 4px 13px 10px; }
.lead-line { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--border); }
.lead-line:last-child { border-bottom: none; }
.lead-line .grow { flex: 1; min-width: 0; }
.lead-line .who { font-weight: 600; font-size: 13.5px; }
.lead-line .cell-sub { display: block; }
.lead-add { width: 28px; height: 28px; flex-shrink: 0; border-radius: 7px; border: 1px solid var(--accent);
    background: var(--accent-bg); color: var(--accent-text); font-size: 17px; font-weight: 600;
    line-height: 1; cursor: pointer; font-family: inherit; }
.lead-add:hover { background: var(--accent); color: #fff; }
.bundle { display: flex; gap: 10px; align-items: center; padding: 11px 13px; margin-bottom: 8px;
    background: var(--surface); border: 1px solid var(--accent); border-radius: var(--radius); }
.bundle .grow { flex: 1; min-width: 0; }
.bundle .who { font-weight: 600; font-size: 14px; }
.lead-drop { width: 28px; height: 28px; flex-shrink: 0; border-radius: 7px;
    border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-secondary);
    font-size: 17px; line-height: 1; cursor: pointer; font-family: inherit; }
.lead-drop:hover { border-color: var(--danger-text); color: var(--danger-text); background: var(--danger-bg); }

/* One line per area. A district holding a single lead does not need a card. */
.area-line { display: flex; align-items: center; gap: 0; flex-wrap: wrap;
    border-bottom: 1px solid var(--border); }
.area-line.open { background: var(--neutral-bg); border-radius: var(--radius); }
.area-main { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px;
    padding: 9px 4px; background: none; border: none; cursor: pointer;
    font-family: inherit; color: inherit; text-align: left; }
.area-main:hover .area-name { color: var(--accent-text); }
.area-line .area-chev { color: var(--text-muted); font-size: 11px; width: 10px; flex-shrink: 0; }
.area-line .area-name { font-weight: 600; font-size: 13.5px; }
.area-line .area-counts { font-size: 12px; color: var(--text-secondary);
    font-variant-numeric: tabular-nums; margin-left: auto; padding-right: 8px; }
.area-line .area-counts .dim { color: var(--text-muted); }
.area-add { flex-shrink: 0; min-width: 40px; padding: 4px 9px; border-radius: 7px;
    border: 1px solid var(--accent); background: var(--accent-bg); color: var(--accent-text);
    font-size: 12.5px; font-weight: 700; cursor: pointer; font-family: inherit; }
.area-add:hover { background: var(--accent); color: #fff; }
.area-line .area-leads { flex-basis: 100%; padding: 0 10px 8px 22px; }

/* Lead picking inside an area, opened from the map. Replaces the old list. */
.area-sheet { margin-top: 10px; background: var(--surface); border: 1px solid var(--accent);
    border-radius: var(--radius); padding: 11px 13px; }
.area-sheet-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
    padding-bottom: 8px; border-bottom: 1px solid var(--border); margin-bottom: 4px; }
.area-sheet-head b { font-size: 14px; }
.area-sheet-head .cell-sub { flex: 1; }
.area-sheet .lead-line input[type="checkbox"] { width: 17px; height: 17px; flex-shrink: 0; accent-color: var(--accent); }
/* Over the aim, not over a limit — amber says "unusual", never "wrong". */
.day-tile.over { border-color: var(--warning-text); }
.day-tile .n.over { color: var(--warning-text); }
.area-add.over { border-color: var(--border-strong); background: var(--surface); color: var(--text-secondary); }
.area-add.over:hover { border-color: var(--accent); color: var(--accent-text); background: var(--accent-bg); }

/* SIX MONTHS OF FREIGHT, DRAWN SMALL. A shortfall alone hides a long fall:
   Zamil read "short by SAR 4,353" while sliding from SAR 15,808 in March to
   SAR 1,003 in August. The bars say that before a word is read. */
.spark { display: flex; align-items: flex-end; gap: 3px; height: 24px; margin: 6px 0 2px; }
.spark i { display: block; width: 9px; background: var(--accent); border-radius: 2px 2px 0 0; opacity: .75; }
.spark i:last-child { opacity: 1; }
/* The explanation sits under its own row rather than squeezing into a cell. */
.chase-detail td { padding-top: 0; border-top: 0; }
.badges-row { display: flex; gap: 5px; flex-wrap: wrap; }

/* One line where two lists were, pointing at the page that holds them now. */
.strip-line { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; background: var(--accent-bg); border-radius: 10px; padding: 11px 13px; font-size: 13.5px; }

/* A CLIENT SLIPPING AWAY, on the Sales page.
   The rows had no clear boundary: five lines all starting at the same edge, the
   gap inside a client the same as the gap between two, and the figure that ranks
   the list buried mid-sentence. Lamrath, from a screen recording: "clients
   doesnt show any clear differentiation between each client, lines are not
   clear." The money column is what separates them now. */
.chase-row { display: flex; gap: 16px; align-items: flex-start;
  padding: 15px 10px; margin: 0 -10px; border-radius: 10px;
  border-bottom: 1px solid var(--border); transition: background .12s; }
.chase-row:last-child { border-bottom: 0; }
.chase-row.clickable:hover { background: var(--accent-bg); }
.chase-main { flex: 1; min-width: 0; }
.chase-name { font-weight: 650; font-size: 15px; letter-spacing: -.01em; }
.chase-badges { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
/* Tighter inside a client than the gap between two, so four lines read as one
   block rather than as a continuous column of text. */
.chase-line { font-size: 12.5px; color: var(--text-secondary); margin-top: 6px; }
.chase-foot { display: flex; gap: 10px; align-items: flex-end; margin-top: 7px; }
.chase-trend { font-size: 11.5px; color: var(--text-muted); }
.chase-money { text-align: right; flex-shrink: 0; min-width: 118px; }
.chase-money .n { font-size: 17px; font-weight: 700; color: var(--danger-text);
  font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.chase-money .l { font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-muted); margin-top: 1px; }
/* Inline, so the sparkline and its caption sit side by side rather than stacked. */
.spark { display: inline-flex; align-items: flex-end; gap: 3px; height: 20px; flex-shrink: 0; }
.spark i { display: block; width: 7px; background: var(--accent); border-radius: 2px 2px 0 0; opacity: .7; }
.spark i:last-child { opacity: 1; }

/* ---------------------------------------------------------------------------
   "Worth your time" — the four lists, each behind its own count.
   Lamrath: "show only count along with client name when clicked u can show
   details so sales page looks summariesed." Deliberately NO information mark
   for the explaining text — he turned that down ("its not worth forget"), so
   the reasoning is one line inside the open list, paid for only by whoever
   opened it. Mirrors the phone's Sales page exactly.
--------------------------------------------------------------------------- */
.wyt-card {
    border: 1px solid var(--border);
    border-radius: 14px;
    overflow: hidden;
    background: var(--surface);
}
.wyt-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 12px;
    background: var(--neutral-bg);
    border-bottom: 1px solid var(--border);
    font-size: 13.5px;
}
.wyt-scope {
    font-size: 9.5px;
    letter-spacing: .07em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--text-muted);
}
.wyt-total { font-size: 11.5px; color: var(--text-muted); white-space: nowrap; }

.wyt-row {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    padding: 11px 12px;
    background: none;
    border: 0;
    border-top: 1px solid var(--border);
    color: inherit;
    font: inherit;
    cursor: pointer;
}
.wyt-card > .wyt-row:first-of-type { border-top: 0; }
.wyt-row:hover:not(:disabled) { background: var(--neutral-bg); }
/* A row with nothing behind it is not pressable, and its chevron goes with it:
   an arrow that does nothing is worse than no arrow. */
.wyt-row:disabled { cursor: default; }
.wyt-row:disabled .wyt-chev { visibility: hidden; }

.wyt-n {
    flex: 0 0 28px;
    height: 28px;
    border-radius: 8px;
    display: grid;
    place-items: center;
    font-size: 12.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.wyt-n.brand  { background: var(--accent-bg); color: var(--accent-text); }
.wyt-n.warn   { background: var(--warning-bg);   color: var(--warning-text); }
.wyt-n.danger { background: var(--danger-bg); color: var(--danger-text); }
/* Zero is grey whatever the list's tone: an empty list is not a warning. */
.wyt-n.zero   { background: var(--neutral-bg); color: var(--text-muted); }

.wyt-lab { flex: 1; min-width: 0; }
.wyt-lab b { display: block; font-size: 13px; font-weight: 600; }
.wyt-lab i {
    display: block;
    font-style: normal;
    font-size: 11.5px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
.wyt-chev { color: var(--text-muted); font-size: 13px; transition: transform .18s ease; }
.wyt-row[aria-expanded="true"] .wyt-chev { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .wyt-chev { transition: none; } }

/* The open list sits on a tinted ground, so it belongs to the row above it
   rather than reading as the next thing on the page. */
.wyt-panel {
    padding: 8px 12px 12px;
    background: var(--neutral-bg);
    border-top: 1px solid var(--border);
}
/* ONE LINE, NOT A PARAGRAPH. Four headings each followed by an explanation is
   what made this page four screens long. */
.wyt-why { font-size: 11.5px; color: var(--text-muted); line-height: 1.5; margin-bottom: 8px; }

/* ---- paging the long lists (2026-08-31) ----------------------------------
   Leads was 1,114 rows on one page. The pager is deliberately quiet: it sits
   under the table, in the same greys as a table heading, because it is
   furniture rather than something to look at. */
.pager { display:flex; flex-wrap:wrap; gap:10px 16px; align-items:center;
  justify-content:space-between; margin-top:12px; }
.pagenums { display:flex; gap:4px; align-items:center; flex-wrap:wrap; }
.pg { min-width:32px; height:32px; padding:0 9px; border-radius:8px;
  border:1px solid var(--border-strong); background:var(--surface);
  color:var(--text-secondary); font-size:12.5px; font-weight:600; cursor:pointer;
  font-variant-numeric:tabular-nums; }
.pg:hover:not(:disabled) { border-color:var(--accent); color:var(--accent-text); }
.pg.on { background:var(--accent); border-color:var(--accent); color:#fff; }
.pg:disabled { opacity:.4; cursor:default; }
.pg-gap { color:var(--text-muted); padding:0 3px; }
.perpage { display:flex; gap:6px; align-items:center; font-size:12px;
  color:var(--text-secondary); }
.perpage select { font:inherit; font-size:12px; padding:5px 8px; border-radius:7px;
  border:1px solid var(--border-strong); background:var(--surface);
  color:var(--text-primary); }
.showing { font-size:12px; color:var(--text-secondary); font-variant-numeric:tabular-nums; }
.showing b { color:var(--text-primary); }

/* A numbered page is a poor target for a thumb, so narrow screens get
   Prev / page N of M / Next instead. Same pager, fewer buttons. */
.pg-narrow { display:none; }
@media (max-width: 700px) {
  .pg-wide { display:none; }
  .pg-narrow { display:inline; font-size:12px; color:var(--text-secondary);
    padding:0 8px; font-variant-numeric:tabular-nums; }
  .pager { justify-content:center; }
}

/* Sortable column headings. The arrow shows the CURRENT sort only, so a heading
   never claims a direction the table is not in. */
th.sortable { cursor:pointer; user-select:none; white-space:nowrap; }
th.sortable:hover { color:var(--accent-text); }
th.sortable.sorted { color:var(--accent-text); }
.sort-arrow { display:inline-block; width:11px; text-align:center; font-size:10px; }

/* ==========================================================================
   THE MANAGER'S GLANCE ROW
   Five figures, each carrying what it should be measured against, plus the
   twelve-month shape and the pipeline. Before this the page opened with one
   revenue number and nothing to compare it with, which on the third of the
   month is not a fact anybody can act on.
   ========================================================================== */
.glance-row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; margin-bottom: 12px; }
.glance-kpi { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 12px 13px 11px; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.glance-lab { font-size: 11px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
    color: var(--text-muted); }
.glance-val { font-size: 23px; font-weight: 660; letter-spacing: -.02em; line-height: 1.2; margin-top: 1px;
    font-variant-numeric: tabular-nums; color: var(--text-primary); }
.glance-sub { font-size: 11.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.glance-delta { display: inline-flex; align-items: center; gap: 3px; align-self: flex-start; margin-top: 3px;
    font-size: 11.5px; font-weight: 600; padding: 1px 6px; border-radius: 999px; }
.glance-delta.down { background: var(--danger-bg); color: var(--danger-text); }
.glance-delta.up { background: var(--success-bg); color: var(--success-text); }
.glance-delta.flat { background: var(--neutral-bg); color: var(--neutral-text); }
/* Twelve bars in 22px. Shape only — the real chart is directly below. */
.glance-spark { display: flex; align-items: flex-end; gap: 2px; height: 22px; margin-top: 7px; }
.glance-spark i { flex: 1; background: var(--accent); opacity: .28; border-radius: 1px; min-height: 2px; }
.glance-spark i.partial { opacity: 1;
    background: repeating-linear-gradient(135deg, var(--accent), var(--accent) 2px, #b48fd0 2px, #b48fd0 4px); }
.glance-bar { display: flex; height: 6px; border-radius: 3px; overflow: hidden; margin-top: 8px;
    background: var(--neutral-bg); }
.glance-bar span { display: block; height: 100%; }

.glance-note { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; cursor: pointer;
    font-size: 12.5px; padding: 9px 12px; border-radius: var(--radius); margin-bottom: 12px;
    background: var(--warning-bg); color: var(--warning-text); border: 1px solid #f3dfae; }
.glance-note .go { margin-left: auto; font-weight: 600; white-space: nowrap; }
.glance-note:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.glance-band { display: grid; grid-template-columns: 1.55fr 1fr; gap: 12px; margin-bottom: 12px; }
.glance-band .dash-block { margin-bottom: 0; }

/* A wide chart must scroll inside its own box, never take the page sideways. */
.trend-wrap { overflow-x: auto; }
/* STRETCH, not flex-end. With flex-end the columns shrink to their own content
   -- measured on the live page, 35px inside a 132px chart -- so every bar's
   height percentage resolved against 35px and drew a 3px sliver. The column
   must fill the chart; `justify-content: flex-end` inside it is what sits the
   bar on the baseline. */
.trend { display: flex; align-items: stretch; gap: 6px; height: 132px; min-width: 320px; }
.trend-col { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; align-items: center;
    gap: 5px; min-width: 0; }
.trend-col .bar { width: 100%; background: var(--accent); opacity: .82; border-radius: 3px 3px 0 0; min-height: 3px; }
/* The month still running is hatched wherever it appears. A three-day-old bar
   beside eleven full months would otherwise read as a collapse. */
.trend-col.partial .bar { opacity: 1;
    background: repeating-linear-gradient(135deg, var(--accent), var(--accent) 3px, #c7a9dd 3px, #c7a9dd 6px); }
.trend-col .m { font-size: 9.5px; color: var(--text-muted); white-space: nowrap; }
.trend-col .v { font-size: 9.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }

.stage-line { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: center; margin-bottom: 9px; }
.stage-line .nm { font-size: 12.5px; }
.stage-line .nm small { color: var(--text-muted); font-size: 11px; margin-left: 5px; }
.stage-line .amt { font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.stage-line .track { grid-column: 1 / 3; height: 7px; background: var(--neutral-bg); border-radius: 4px;
    overflow: hidden; margin-top: -4px; }
.stage-line .track i { display: block; height: 100%; background: var(--accent); border-radius: 4px; }

.glance-callout { margin-top: 12px; padding: 10px 12px; border-radius: var(--radius);
    background: var(--accent-bg); color: var(--accent-text); font-size: 12px; }

@media (max-width: 1000px) {
    .glance-row { grid-template-columns: repeat(2, 1fr); }
    .glance-band { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
    .glance-row { grid-template-columns: 1fr; }
    .trend { height: 104px; }
}

/* Revenue on the team line, beside the effort bar. They routinely disagree —
   the rep at the top of one is often at the bottom of the other — and seeing
   both on one row is the only way that shows. */
.team-rev { min-width: 132px; text-align: right; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.team-rev-bar { display: block; height: 5px; border-radius: 3px; background: var(--neutral-bg);
    overflow: hidden; margin-top: 4px; }
.team-rev-bar i { display: block; height: 100%; background: var(--accent); border-radius: 3px; }
.muted-sm { color: var(--text-muted); font-size: 11.5px; }
/* The revenue column adds ~132px to a row that already carries a name, a bar and
   a sentence. On a phone that is more than the row has, and `.team-n` is nowrap —
   so the row is allowed to wrap here rather than push the page sideways. Written
   defensively: the browsers available in this session render at a fixed 1440 CSS
   pixels whatever the window size, so these breakpoints could NOT be exercised. */
@media (max-width: 700px) {
    .team-line { flex-wrap: wrap; row-gap: 2px; }
    .team-bar { flex-basis: 100%; order: 3; }
    .team-n { white-space: normal; }
    .team-rev { min-width: 0; margin-left: auto; }
    .team-rev-bar { display: none; }
}

/* Months / Days, in the revenue card's own header. */
.dash-head .view-toggle { margin-left: auto; display: flex; gap: 4px; background: var(--neutral-bg);
    padding: 3px; border-radius: 999px; align-self: flex-start; }
.dash-head .view-toggle button { font: inherit; font-size: 11.5px; padding: 3px 11px; border: 0;
    border-radius: 999px; background: none; color: var(--neutral-text); cursor: pointer; }
.dash-head .view-toggle button.on { background: var(--surface); color: var(--accent-text);
    font-weight: 650; box-shadow: 0 1px 2px rgba(16, 24, 40, .08); }
.dash-head .view-toggle button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ONE DAY PER BAR, SPLIT BY PRODUCT. Same colours as the product bars on Sales,
   so the two read as one system. */
.legend { display: flex; gap: 14px; flex-wrap: wrap; margin: 0 0 10px; font-size: 11.5px;
    color: var(--text-secondary); }
.legend .lg { display: inline-flex; align-items: center; gap: 5px; }
.legend .lg i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }
.legend .lg b { font-variant-numeric: tabular-nums; color: var(--text-primary); font-weight: 600; }
.daywrap { overflow-x: auto; }
.days { display: flex; align-items: stretch; gap: 3px; height: 158px; min-width: 340px; position: relative; }
/* Capped, because a month is only ever as old as it is: on the 3rd, three bars
   sharing the full width came out ~190px each and read as a broken chart rather
   than an early month. At 31 days a bar is ~15px, so the cap only ever bites at
   the start of a month. */
.day { flex: 1; max-width: 42px; display: flex; flex-direction: column; justify-content: flex-end;
    align-items: center; gap: 3px; min-width: 0; }
/* column-reverse so the segments stack from the baseline up. */
.day .dbar { width: 100%; min-height: 2px; border-radius: 2px 2px 0 0; overflow: hidden;
    display: flex; flex-direction: column-reverse; background: var(--border-strong); }
.day .dbar span { display: block; width: 100%; }
.day.dead .dbar { background: var(--border-strong); opacity: .5; }
/* Today is still coming in -- the shipping system is read at 2pm and 9pm, so at
   11am it reads a fraction of the day and must never look like a collapse. */
.day.today .dbar { outline: 2px dashed #c7a9dd; outline-offset: 1px; }
.day.today .dn { color: var(--accent-text); font-weight: 700; }
.day .dv { font-size: 8.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.day .dn { font-size: 9px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.day .dd { font-size: 8px; color: var(--text-muted); text-transform: uppercase; }
.avgline { position: absolute; left: 0; right: 0; border-top: 1px dashed var(--border-strong); pointer-events: none; }
.avgline span { position: absolute; right: 0; top: -14px; font-size: 9.5px; color: var(--text-muted);
    background: var(--surface); padding: 0 4px; }
@media (max-width: 560px) { .days { height: 120px; } }
