/* Weaver Technologies brand tokens - see Weaver brand standards (Montserrat primary,
   Arial fallback; primary blues #0079C2/#00A4E4; accents navy/gold/orange/red/gray).

   Values below are taken verbatim from the Weaver Sales CRM (crm.weavertech.us), read straight
   out of its stylesheet on 8/14/2026 rather than matched by eye off a screenshot. That app is
   the house design system; anything here that disagrees with it is a bug, not a preference.
   Its token names are noted in comments so the two can be diffed later. */
:root {
    --navy: #1F3467; /* CRM --blue-deeper */
    --blue: #0079C2; /* CRM --blue-primary */
    --blue2: #00A4E4; /* CRM --blue-bright */
    --gold: #EEBB3F;
    --orange: #F1592B;
    --red: #BF1E2C;
    --gray: #484848;
    /* Body text is navy-tinted, not near-black. This one token is most of why the old build read
       as a different app: #1A1A1A puts hard black on a blue-gray page, the CRM never does. */
    --ink: #1a2b49; /* CRM --text-primary */
    --ink2: #44607e; /* CRM --text-secondary */
    --bg: #f5f7fa; /* CRM --bg-base */
    --card: #ffffff; /* CRM --bg-card */
    --line: rgba(31, 52, 103, .12); /* CRM --border */
    --line-faint: rgba(31, 52, 103, .08); /* CRM --border-faint */
    --muted: #8299b3; /* CRM --text-muted */
    --green: #16a34a; /* CRM --green */
    --amber: #d97706; /* CRM --amber */
    /* Arial is the only sanctioned fallback per brand standards - "Segoe UI" used to sneak in a
       different personality on Windows during the font-swap window. */
    --font: "Montserrat", Arial, sans-serif; /* CRM --font-ui, identical */
    /* Figures only - KPI values, currency, numeric table columns. The CRM sets every dollar
       amount in JetBrains Mono and it is the single biggest reason its numbers read differently
       from Montserrat bold. Loaded next to Montserrat from Google Fonts in App.razor; the
       fallbacks cover a blocked-CDN case without falling back to a proportional face. */
    --font-data: "JetBrains Mono", ui-monospace, SFMono-Regular, Consolas, monospace; /* CRM --font-data */
    /* Hover/active shades of --blue, used by the button re-theme below. */
    --blue-hover: #005e97; /* CRM --blue-dark */
    --blue-active: #004f80;
    /* Light brand-blue tint for selection; --hover is the softer one for row/cell hover. */
    --tint: #e6f4fb; /* CRM --blue-light */
    --blue-subtle: rgba(0, 121, 194, .10); /* CRM --blue-subtle - fill of its secondary button */
    --border-bright: rgba(0, 121, 194, .45); /* CRM --border-bright - card hover edge */
    --hover: #f2f7fc; /* CRM --bg-card-hover */
    /* Editable form field fill - neither of the two CRM tokens above landed right once actually
       sitting inside every input on the page (8/14): --tint read too saturated, --hover (tried
       next) read too washed-out. This splits the difference - not a CRM token, just the midpoint
       between the two the CRM does define. */
    --field-fill: #ecf6fc;
    /* Table interior is white, same as the card holding it. I briefly tinted this on 8/14 after
       misreading "the background inside the tables needs to be different than outside" as "tint
       the rows"; he meant the data pod is white and the PAGE behind it is the gray. Only the
       header band is tinted, matching the CRM's own .data-table th. */
    --table-bg: var(--card);
    --table-head-bg: var(--bg);
    --radius-sm: 6px;
    --radius-md: 10px;
    /* 18px, two notches softer than the CRM's 16px. Jason's call 8/14: he wants the pods
       rounder than the reference, not merely equal to it. */
    --radius-lg: 18px;
    /* Two very light stops. The old shadow was roughly twice this and made every pod read as a
       floating dialog instead of a sheet of paper on a desk. */
    --shadow-card: 0 1px 3px rgba(26, 43, 73, .08), 0 1px 2px rgba(26, 43, 73, .04);
    --shadow-btn: 0 4px 14px rgba(0, 121, 194, .28);
}

/* Re-theme Bootstrap 5.3 through its own CSS variables rather than chasing individual classes
   with !important. This is what keeps .text-primary (the standard card-header style, ~100 uses),
   progress bars, pills, links, checked inputs, and pagination on Weaver blue instead of stock
   Bootstrap #0d6efd. */
:root, [data-bs-theme=light] {
    --bs-primary: var(--blue);
    --bs-primary-rgb: 0, 121, 194;
    --bs-secondary: var(--gray);
    --bs-secondary-rgb: 72, 72, 72;
    --bs-success: var(--green);
    --bs-success-rgb: 22, 163, 74;
    --bs-danger: var(--red);
    --bs-danger-rgb: 191, 30, 44;
    --bs-warning: var(--gold);
    --bs-warning-rgb: 238, 187, 63;
    --bs-info: var(--blue2);
    --bs-info-rgb: 0, 164, 228;
    --bs-link-color: var(--blue);
    --bs-link-color-rgb: 0, 121, 194;
    --bs-link-hover-color: var(--blue-hover);
    --bs-link-hover-color-rgb: 0, 104, 168;
    --bs-body-font-family: var(--font);
    --bs-body-color: var(--ink);
    /* .text-muted resolves to this. The CRM's secondary body copy is navy-gray (#44607e), never
       Bootstrap's neutral #6c757d - that gray was reading as a different palette next to a
       blue-tinted page. Labels stay on the lighter --muted via the label recipe below. */
    --bs-secondary-color: var(--ink2);
    --bs-body-bg: var(--bg);
    --bs-border-radius: var(--radius-sm);
    /* Bootstrap's own default is --bs-card-bg: var(--bs-body-bg) - meaning every .card on the
       page was rendering the exact same light gray-blue as the page behind it, so pods never
       actually stood out from the page the way they're supposed to (see the reference screenshot
       Jason shared, 8/13: light gray/blue page, white pods). One variable here fixes every card
       across the whole app at once - no per-page edits needed. */
    --bs-card-bg: var(--card);
    --bs-card-cap-bg: var(--card);
}

/* Bootstrap compiles utility values at build time, so a handful of classes carry literal hex and
   need explicit overrides on top of the variables above. */
/* .bg-light is Bootstrap's neutral #f8f9fa and is used on ~32 sub-panels that sit INSIDE white
   cards (Company Detail, Project Detail, Ticket Detail, the workbench log-time block...). Two
   problems: it is a gray fill inside a pod that is supposed to be white edge to edge, and the gray
   is neutral rather than blue-tinted, so it reads as a different palette. White here; the panels
   that need to stay delineated already carry Bootstrap's .border .rounded next to it. */
.bg-light { background-color: var(--card) !important; }

/* .table-light marks a totals/summary row, which IS meaningful emphasis rather than decoration, so
   it keeps a fill - just the page tint instead of Bootstrap's neutral gray. */
.table-light { --bs-table-bg: var(--bg); }

.text-primary { color: var(--blue) !important; }
.bg-primary { background-color: var(--blue) !important; }
.progress-bar { background-color: var(--blue); }
.nav-pills .nav-link.active, .nav-pills .show > .nav-link { background-color: var(--blue); }
.form-check-input:checked { background-color: var(--blue); border-color: var(--blue); }
.page-link { color: var(--blue); }
.active > .page-link, .page-link.active { background-color: var(--blue); border-color: var(--blue); }

html {
    /* The CRM sets this, and it is a real part of why its type looks crisper: without it Windows
       renders Montserrat noticeably heavier. */
    -webkit-font-smoothing: antialiased;
    /* The MyTracker section chips and the existing scrollIntoView interop both jump within long
       pages - easing the jump makes them read as navigation instead of teleportation. */
    scroll-behavior: smooth;
}

html, body {
    font-family: var(--font);
    background-color: var(--bg);
    color: var(--ink);
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--font);
    color: var(--navy);
    font-weight: 700;
}

/* Bootstrap's 2.5rem h1 towers over 11px table headers on a dense internal tool. Bring the page
   title down to something proportionate and tighten section headers to match. */
h1 {
    font-size: 1.5rem;
    letter-spacing: -0.01em;
    margin-bottom: .25rem;
}

h4, h5 {
    font-size: 1.05rem;
}

a, .btn-link {
    color: var(--blue);
}

/* ---- Bootstrap overrides so existing pages pick up the brand automatically ---- */

/* Buttons re-themed through Bootstrap 5.3's per-button variables - covers hover, active,
   focus, and disabled states in one block each, with no !important hacks. */
.btn {
    transition: background-color .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
}

    .btn:active {
        transform: translateY(1px);
    }

.btn-primary {
    --bs-btn-bg: var(--blue);
    --bs-btn-border-color: var(--blue);
    --bs-btn-hover-bg: var(--blue-hover);
    --bs-btn-hover-border-color: var(--blue-hover);
    --bs-btn-active-bg: var(--blue-active);
    --bs-btn-active-border-color: var(--blue-active);
    --bs-btn-disabled-bg: var(--blue);
    --bs-btn-disabled-border-color: var(--blue);
}

/* The CRM's secondary button is a light blue tint fill with a hairline border and blue text
   (its .btn-ghost), not a white button with a saturated blue outline. That outline was reading as
   a much heavier control than anything on the reference screen. */
.btn-outline-primary {
    --bs-btn-color: var(--blue);
    --bs-btn-bg: var(--blue-subtle);
    --bs-btn-border-color: var(--line);
    --bs-btn-hover-color: var(--blue);
    --bs-btn-hover-bg: var(--tint);
    --bs-btn-hover-border-color: var(--border-bright);
    --bs-btn-active-bg: var(--blue-active);
    --bs-btn-active-border-color: var(--blue-active);
    --bs-btn-disabled-color: var(--blue);
    --bs-btn-disabled-border-color: var(--blue);
}

.btn-outline-secondary {
    --bs-btn-color: var(--gray);
    --bs-btn-border-color: var(--line);
    --bs-btn-hover-color: var(--gray);
    --bs-btn-hover-bg: #eef2f8;
    --bs-btn-hover-border-color: var(--line);
    --bs-btn-active-color: var(--gray);
    --bs-btn-active-bg: #e3e9f2;
    --bs-btn-active-border-color: var(--line);
    --bs-btn-disabled-color: var(--muted);
    --bs-btn-disabled-border-color: var(--line);
}

.btn-outline-danger {
    --bs-btn-color: var(--red);
    --bs-btn-border-color: #f3c9cc;
    --bs-btn-hover-bg: var(--red);
    --bs-btn-hover-border-color: var(--red);
    --bs-btn-active-bg: var(--red);
    --bs-btn-active-border-color: var(--red);
    --bs-btn-disabled-color: var(--red);
    --bs-btn-disabled-border-color: #f3c9cc;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem var(--blue2);
}

/* Editable fields get a light brand-blue fill (--field-fill) rather than inheriting
   --bs-body-bg, which is set to the page's own gray-blue tint (--bg) further up for the page
   background itself - left alone, every input/select on the page silently read as the same gray
   as the page behind it, which is what Jason spotted on Project Detail (8/14). Took three passes
   to land: --tint (too saturated once on every field) -> --hover (over-corrected, too washed out)
   -> --field-fill, the midpoint between them defined above. --tint and --hover stay untouched for
   their existing jobs (selection state, hover/active button and tab backgrounds) elsewhere in this
   file. Disabled/readonly fields (e.g. computed Budget Dollars) are unaffected - Bootstrap's own
   :disabled/[readonly] rule already gives them a separate light gray, which still reads as
   "not editable" against this blue. */
.form-control, .form-select {
    background-color: var(--field-fill);
    transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}

.form-control:focus, .form-select:focus {
    border-color: var(--blue2);
}

.card {
    background-color: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    /* Soft, low-contrast shadow - not a heavy drop shadow - so a white pod reads as "raised"
       off the light gray-blue page without looking like a dialog box. Matches the CRM exactly. */
    box-shadow: var(--shadow-card);
    transition: box-shadow .15s ease;
}

    .card-header {
        border-bottom: 1px solid var(--line);
        font-weight: 700;
    }

.table thead th, table thead th {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: var(--muted);
    font-weight: 600;
    border-bottom-width: 1px;
}

/* Long lists (Service Board list view, Companies, Audit Trail...) keep their headers while
   scrolling. Safe with the page as the scroll container since there's no fixed top bar; the
   box-shadow stands in for the border, which sticky headers otherwise scroll away from. */
.table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background-color: var(--table-head-bg);
    box-shadow: inset 0 -1px 0 var(--line);
}

/* Row-click navigation used to be an invisible inline cursor swap. One shared class gives every
   clickable list row a pointer plus a brand-tint hover so "you can open this" is discoverable. */
.row-clickable {
    cursor: pointer;
    transition: background-color .12s ease;
}

    .row-clickable:hover {
        background-color: var(--hover);
    }

/* Sortable column headers - same idea: make the affordance visible on hover. */
.th-sortable {
    cursor: pointer;
    user-select: none;
    transition: color .12s ease;
}

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

/* Brand-tinted row hover, the CRM's --bg-card-hover. */
.table-hover > tbody > tr:hover > * {
    --bs-table-bg-state: var(--hover);
}

.nav-tabs .nav-link.active {
    color: var(--blue);
    border-color: var(--line) var(--line) #fff;
    font-weight: 700;
}

.badge.bg-success { background-color: var(--green) !important; }
.badge.bg-secondary { background-color: var(--muted) !important; }
.badge.bg-danger { background-color: var(--red) !important; }
.badge.bg-warning { background-color: var(--gold) !important; color: var(--ink) !important; }

.content {
    padding-top: 1.1rem;
}

/* Page title pod - matches the reference screenshot Jason shared (8/13): even the "MY DAY /
   Good afternoon" header text sits inside its own implicit white treatment rather than bare on
   the gray-blue page. Most pages here start with a bare <h1> + <p class="text-muted"> subtitle
   directly on `main`'s --bg background (see CLAUDE.md/app.css history on the .card fix - same
   root complaint, just for title text instead of card bodies). Wrap that title block in
   <div class="page-header">...</div> to give it a white pod; reuses .card's bg/border/shadow so
   it reads as the same family of pod as everything below it. Rolling this out page-by-page, not
   a single global selector, since title-block markup varies (some have inline buttons/badges/a
   viewing picker next to the h1) and each one is worth a quick look after wrapping. */
.page-header {
    background-color: var(--card);
    border: 1px solid var(--line);
    border-radius: 12px;
    box-shadow: 0 1px 3px rgba(15, 35, 65, .06);
    padding: 1rem 1.25rem;
    margin-bottom: 1.5rem;
}

    .page-header h1 {
        margin-bottom: .25rem;
    }

    .page-header > :last-child {
        margin-bottom: 0 !important;
    }

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* ---- KPI tiles (Home dashboard + Reporting + board health rows) ---- */
.kpis {
    display: grid;
    /* auto-fit, not a fixed 4: tiles wrap gracefully on narrow windows instead of crushing. */
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 14px;
}

/* No colored left edge. The CRM's stat tiles are plain white pods and the accent bar was the
   most obvious "this is a different app" tell after the shadow. .k1-.k4 stay valid class names
   so no page markup had to change; they simply no longer paint anything. */
.kpi {
    border-left: 1px solid var(--line);
}

    .kpi .kpi-value {
        font-size: 28px;
        font-weight: 800;
        color: var(--navy);
    }

    .kpi .kpi-label {
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: .04em;
        color: var(--muted);
        font-weight: 700;
    }

    /* Denser rows (board health strips, PM summary) use the same tile anatomy at a smaller
       scale, so the whole app shares one KPI idiom. */
    .kpi .kpi-value-sm, .kpi-value-sm {
        font-size: 20px;
        font-weight: 800;
        color: var(--navy);
    }

/* ---- Services Scoreboard progress bar (Home) - bullet-chart style: darker fill = Actual
   achieved so far, lighter track = remaining to Goal, tick marks = Planned/Goal reference
   points. ---- */
.scoreboard-bar-track {
    position: relative;
    height: 22px;
    background-color: var(--line);
    border-radius: 4px;
    overflow: visible;
}

.scoreboard-bar-fill {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    background-color: var(--blue);
    border-radius: 4px 0 0 4px;
    transition: width 0.3s ease;
}

.scoreboard-bar-marker {
    position: absolute;
    top: -4px;
    bottom: -4px;
    width: 0;
    border-left: 3px solid var(--navy);
    transform: translateX(-1.5px);
}

    .scoreboard-bar-marker.goal {
        border-left: 3px solid var(--navy);
    }

.scoreboard-legend-swatch {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 2px;
    margin-right: 4px;
    vertical-align: middle;
}

.scoreboard-legend-tick {
    display: inline-block;
    width: 0;
    height: 12px;
    border-left: 3px solid var(--navy);
    margin-right: 6px;
    vertical-align: middle;
}

/* ---- Gantt timeline (Project Detail) ---- */
.gantt-axis {
    display: flex;
    justify-content: space-between;
    font-size: 11px;
    color: var(--muted);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    margin-bottom: 6px;
}

.gantt {
    position: relative;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    padding: 4px 0;
}

.gantt-row {
    position: relative;
    height: 48px;
}

.gantt-bar {
    position: absolute;
    top: 4px;
    height: 26px;
    min-width: 2%;
    border-radius: 6px;
    background-color: var(--blue);
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    display: flex;
    align-items: center;
    padding: 0 8px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    box-shadow: 0 1px 2px rgba(0,0,0,.15);
}

    .gantt-bar.is-overdue {
        background-color: var(--red);
    }

    .gantt-bar.is-complete {
        background-color: var(--green);
    }

/* Visible date range under every bar (9/8) - was tooltip-only, which fails at a glance and on a
   phone that has no hover. Anchored to the bar's left edge by default; .align-end anchors to the
   bar's right edge instead and grows left, for a bar near the far end of the timeline that would
   otherwise spill its date range past the card. */
/* P30: a phase bar opens its task list. */
.gantt-bar-click { cursor: pointer; }
.gantt-bar-click:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

.gantt-bar-dates {
    position: absolute;
    top: 32px;
    font-size: 10px;
    color: var(--muted);
    white-space: nowrap;
}

    .gantt-bar-dates.align-end {
        transform: translateX(-100%);
    }

.gantt-today-line {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    background-color: var(--orange);
    z-index: 2;
}

/* Phase dependency connectors (9/10) - an elbow (2 horizontal + 1 vertical) between a
   predecessor's edge and a successor's start, with a small CSS-triangle arrowhead. Plain
   percentage/pixel positioned divs, same idiom as .gantt-milestone's own drop-line - not SVG,
   which would need a viewBox scaled independently on each axis (X in %, Y in real pixels) and
   that non-uniform scaling distorts any shape that isn't axis-aligned, an arrowhead included.
   Rendered before the phase rows in DOM order so a bar's own background paints over the last
   pixel of rounding at its edge. */
.gantt-connector-h {
    position: absolute;
    height: 2px;
    background-color: var(--muted);
}

.gantt-connector-v {
    position: absolute;
    width: 2px;
    background-color: var(--muted);
}

.gantt-connector-h.violated, .gantt-connector-v.violated {
    background-color: var(--red);
}

.gantt-connector-arrow {
    position: absolute;
    width: 0;
    height: 0;
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
}

    .gantt-connector-arrow.points-right {
        border-left: 6px solid var(--muted);
    }

    .gantt-connector-arrow.points-left {
        border-right: 6px solid var(--muted);
    }

    .gantt-connector-arrow.points-right.violated {
        border-left-color: var(--red);
    }

    .gantt-connector-arrow.points-left.violated {
        border-right-color: var(--red);
    }

.gantt-legend-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 2px;
    margin-right: 4px;
    vertical-align: middle;
}

/* Milestone callout - a flag glyph above the row plus a thin line dropping through the
   bar height, so an "invoice the phase" style task is visible right on the timeline. */
.gantt-milestone {
    position: absolute;
    top: -14px;
    transform: translateX(-50%);
    font-size: 14px;
    line-height: 1;
    z-index: 3;
    cursor: default;
}

    .gantt-milestone::after {
        content: "";
        position: absolute;
        top: 16px;
        left: 50%;
        width: 2px;
        height: 26px;
        background-color: var(--gold);
        transform: translateX(-50%);
    }

/* The milestone's own date (9/8), answering "maybe the Milestone Flags can show dates" directly.
   A SEPARATE element from .gantt-milestone on purpose: that box's drop-line is centered on its own
   width via left:50%, and widening the box with a date label would drag the line off the real
   milestone point on the axis. Positioned a few px clear of the flag glyph; .align-end flips to the
   flag's other side near the right edge of the chart, same reasoning as .gantt-bar-dates. */
.gantt-milestone-date {
    position: absolute;
    top: -14px;
    transform: translateX(9px);
    font-size: 10px;
    font-weight: 700;
    color: var(--navy);
    line-height: 14px;
    white-space: nowrap;
    z-index: 3;
}

    .gantt-milestone-date.align-end {
        transform: translateX(calc(-100% - 9px));
    }

/* ---- Schedule board ---- */
.sched-scroll {
    overflow-x: auto;
    border: 1px solid var(--line);
    border-radius: 8px;
}

.sched-grid {
    display: grid;
    grid-template-columns: 200px repeat(28, 34px);
    width: max-content;
    font-size: 12px;
}

.sched-corner, .sched-dayhdr {
    position: sticky;
    top: 0;
    background-color: var(--card);
    border-bottom: 2px solid var(--line);
    padding: 4px 2px;
    text-align: center;
    font-size: 10px;
    color: var(--muted);
    font-weight: 700;
    z-index: 1;
}

.sched-corner {
    text-align: left;
    padding-left: 8px;
    z-index: 2;
}

.sched-dayhdr.we {
    background-color: #f4f6f9;
}

/* Today callout: red date text on the header, plus a light-grey translucent band running down
   the whole column (header + every row) so today reads at a glance across the full grid. */
.sched-dayhdr.today {
    color: var(--red);
    background-color: rgba(0, 0, 0, 0.06);
}

.sched-daycell.today {
    background-color: rgba(0, 0, 0, 0.06);
}

    .sched-daycell.today:hover {
        background-color: rgba(0, 0, 0, 0.1);
    }

.sched-depthdr {
    grid-column: 1 / -1;
    background-color: #eef2f8;
    font-weight: 700;
    font-size: 11px;
    padding: 4px 8px;
    color: var(--navy);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
}

.sched-rescell {
    padding: 6px 8px;
    border-bottom: 1px solid var(--line);
    display: flex;
    align-items: center;
    background-color: var(--card);
    position: sticky;
    left: 0;
    z-index: 1;
}

.sched-daycell {
    border-bottom: 1px solid var(--line);
    border-left: 1px solid #f0f2f6;
    min-height: 30px;
    cursor: pointer;
}

    .sched-daycell.we {
        background-color: #f9fafc;
    }

    .sched-daycell:hover {
        background-color: #eef6fd;
    }

.sched-book {
    margin: 2px;
    border-radius: 4px;
    border-left: 3px solid;
    padding: 2px 4px;
    font-size: 10px;
    font-weight: 700;
    cursor: pointer;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    height: calc(100% - 4px);
    display: flex;
    align-items: center;
}

.sched-legend-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 2px;
    margin-right: 4px;
    vertical-align: middle;
    border-left: 3px solid;
}

/* ---- Resourcing Gantt ---- */
.rgantt-name {
    width: 150px;
    flex: 0 0 auto;
    font-size: 11px;
}

/* ---- Bonus Tracker roster ---- */
.bonus-icon-badge {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background-color: rgba(255, 255, 255, 0.14);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.bonus-avatar {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: #eef2f8;
    color: var(--navy);
    font-weight: 800;
    font-size: 13px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.bonus-roster-card {
    transition: border-color .15s, box-shadow .15s;
}

    .bonus-roster-card:hover {
        border-color: var(--blue);
        box-shadow: 0 0 0 1px var(--blue);
    }

.rgantt-track {
    position: relative;
    flex: 1 1 auto;
    height: 20px;
    background-color: #eef1f6;
    border-radius: 5px;
}

.rgantt-bar {
    position: absolute;
    top: 0;
    bottom: 0;
    border-radius: 5px;
    border-left: 3px solid;
    font-size: 9px;
    font-weight: 700;
    padding: 3px 5px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* KPI tile/chip click-through, used on My Workbench, Book of Business, Service Board, and the Project
   Board. Kept global (rather than a per-page .razor.css) since Blazor's CSS isolation scopes
   .razor.css rules to the component that defines them - a copy living only in AccountManagerView
   .razor.css never actually applied on Service Board or here, even though the class name was
   already in use there. */
.kpi-clickable {
    cursor: pointer;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.kpi-clickable:hover {
    box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);
    transform: translateY(-1px);
}

/* ================= Facelift additions (2026-08) ================= */

/* ---- Sub-navigation tab strip (Reporting section + My Workbench tabs) ----
   Replaces the copy-pasted rows of gray outline buttons with a disabled blue button standing in
   for "active". Rendered by the shared ReportingNav / WorkbenchNav components. */
.subnav {
    display: flex;
    flex-wrap: wrap;
    gap: .25rem;
    border-bottom: 2px solid var(--line);
    margin-bottom: 1rem;
}

    .subnav a, .subnav .subnav-active, .subnav-btn {
        padding: .45rem .8rem;
        font-size: .85rem;
        font-weight: 600;
        color: var(--muted);
        border-radius: 8px 8px 0 0;
        text-decoration: none;
        border-bottom: 2px solid transparent;
        margin-bottom: -2px;
        transition: color .12s ease, background-color .12s ease;
        white-space: nowrap;
    }

    /* .subnav-btn is the same tab look as .subnav a, just on a <button> instead of an <a> - used
       where a tab switches content in place on the same page (e.g. Project Detail's tabs) rather
       than navigating to a different route. A real <a href="#"> here was intercepted by the
       browser/Blazor's own navigation before @onclick:preventDefault could stop it, sending the
       click to the app's base route instead of just switching tabs (found 8/14) - a <button> with
       no href can't navigate at all, so this sidesteps that entirely rather than fighting it. */
    .subnav-btn {
        background: none;
        border: none;
        border-bottom: 2px solid transparent;
        cursor: pointer;
        font-family: inherit;
    }

        .subnav a:hover, .subnav-btn:hover {
            color: var(--blue);
            background-color: var(--tint);
        }

    .subnav .subnav-active {
        color: var(--blue);
        border-bottom-color: var(--blue);
    }

/* ---- Section chip-nav (My Tracker wayfinding) ---- */
.section-chips {
    position: sticky;
    top: 0;
    z-index: 5;
    background-color: var(--bg);
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    padding: .5rem 0;
    margin-bottom: .5rem;
}

    .section-chips button, .section-chips a {
        border: 1px solid var(--line);
        background-color: var(--card);
        color: var(--gray);
        border-radius: 999px;
        padding: .2rem .7rem;
        font-size: .78rem;
        font-weight: 600;
        text-decoration: none;
        transition: color .12s ease, border-color .12s ease, background-color .12s ease;
    }

        .section-chips button:hover, .section-chips a:hover {
            color: var(--blue);
            border-color: var(--blue);
            background-color: var(--tint);
        }

/* Anchored sections land just below the sticky chip bar instead of underneath it. */
.section-anchor {
    scroll-margin-top: 64px;
}

/* ---- Loading skeletons ----
   Pages render Bootstrap 5.3 placeholder-glow blocks instead of a bare "Loading..." line, so
   the incoming layout is sketched before the data lands and content stops slamming in. */
.skeleton-block {
    min-height: 120px;
}

.skeleton-tall {
    min-height: 240px;
}

/* ---- Empty states - same copy, designed clothes ---- */
.empty-state {
    text-align: center;
    color: var(--muted);
    /* No fill and no outline. This is the box Jason called out on 8/14: a blue-gray panel inside
       an otherwise white card, with white below it, so one pod read as two. The CRM's equivalents
       ("Nothing due. Log a task..." / "No open opps with stale active quotes.") are plain muted
       text directly on the card's white. A pod holding data is white edge to edge; the only gray
       in the layout is the page behind the pods. */
    background-color: transparent;
    border: 0;
    padding: 1.75rem 1rem;
    font-style: normal;
}

    .empty-state em {
        font-style: normal;
    }

/* ---- Shared utilities replacing repeated inline styles ---- */
.color-dot {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 3px;
    vertical-align: middle;
}

.filter-w-sm { min-width: 160px; }
.filter-w-md { min-width: 200px; }
.filter-w-lg { min-width: 220px; }

.form-panel {
    max-width: 960px;
}

.tabular-nums {
    font-variant-numeric: tabular-nums;
}

/* ---- Ticket preview drawer (Service Board) ---- */
.drawer-backdrop {
    position: fixed;
    inset: 0;
    background-color: rgba(26, 26, 26, .35);
    z-index: 1040;
    animation: fadeIn .18s ease;
}

.drawer {
    position: fixed;
    top: 0;
    right: 0;
    height: 100%;
    width: 380px;
    max-width: 92vw;
    background-color: #fff;
    box-shadow: -6px 0 24px rgba(0, 0, 0, .12);
    z-index: 1050;
    overflow-y: auto;
    padding: 1rem;
    animation: drawerIn .18s ease;
}

@keyframes drawerIn {
    from { transform: translateX(24px); opacity: 0; }
    to { transform: none; opacity: 1; }
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* ---- Kanban board (Service Board card view) ---- */
.kanban {
    display: flex;
    gap: 1rem;
    overflow-x: auto;
    padding-bottom: .5rem;
    align-items: flex-start;
}

.kanban-col {
    min-width: 280px;
    flex: 1;
    background-color: #eef2f8;
    border-radius: 12px;
    padding: .5rem;
    max-height: calc(100vh - 220px);
    display: flex;
    flex-direction: column;
}

.kanban-col-hdr {
    position: sticky;
    top: 0;
    background-color: inherit;
    padding: .35rem .5rem;
    z-index: 1;
}

.kanban-col-body {
    overflow-y: auto;
    min-height: 40px;
}

/* ---- Timesheet week grid ---- */
.ts-weekend {
    background-color: #f7f9fc;
}

.ts-today {
    background-color: var(--tint);
}

/* ---- Toolbar row (Schedule controls + legend) ---- */
.toolbar-card {
    display: flex;
    flex-wrap: wrap;
    gap: .75rem;
    align-items: center;
}

/* ================= Pod pass - "text on white, rounded" =================
   8/13/2026: built from Jason's screenshot of the Weaver Sales CRM's My Day page.
   8/14/2026: rebuilt against the CRM's real stylesheet (crm.weavertech.us/static/css/main.css),
   read directly rather than eyeballed. Every value below now has a named counterpart in that
   app's token set, noted inline. If the two ever diverge again, diff the tokens first - the
   remaining differences were never layout, they were type color, shadow weight, and figures.

   The only per-page work this aesthetic needs is wrapping each title block in .page-header,
   which is a markup change on every page rather than a selector here (title-block markup varies
   too much - some carry inline buttons, badges, or a "Viewing:" picker next to the h1). */

/* ---- The label recipe ----
   One rule the CRM reuses for every small-caps label in the product: stat-tile captions, card
   titles, the line above a page title, table headers. 11px / 600 / .1em / --text-muted. Getting
   this wrong in four slightly different ways is what made the first pass read as a near-miss:
   the old build had them at .74rem / 700 / .07em and colored brand blue, which is louder and
   more saturated than anything in the CRM. */
.page-eyebrow, .kpi .kpi-label, .card-header strong {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--muted);
}

/* ~104 card headers carry .text-primary in markup. Rather than edit every one, out-specify the
   .text-primary utility here: in the CRM a card's title is a muted label, never brand blue. */
.card-header strong.text-primary {
    color: var(--muted) !important;
}

/* .empty-state is deliberately NOT in this list: it is text inside a pod, not a pod of its own,
   and the card shadow was still drawing a ghost outline around it after the fill was removed. */
.card, .pod, .subnav {
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    /* clip, NOT hidden. A pod's children paint their own square backgrounds - .card-header carries
       bg-white, a table's thead carries the page tint, a card-body p-0 is white to its edges - and
       those squares were covering the pod's rounded corners. That is the notched, broken-corner
       look Jason circled on 8/14.

       overflow: hidden would fix the corners and break every sticky table header in the app:
       hidden makes the element a scroll container, so a sticky <th> inside it stops sticking to
       the viewport and just sits there. overflow: clip crops to the same box WITHOUT becoming a
       scroll container, so the five sticky-header rules keep working (verified by scrolling a long
       table in a card). Chrome/Edge 90+, which is what this app runs in. */
    overflow: clip;
}

    /* The CRM brightens a card's edge on hover rather than lifting it with a bigger shadow. */
    .card:hover {
        border-color: var(--border-bright);
    }

/* 16px/18px and a 1px rule, measured off the CRM's card header. I removed this rule in the
   previous pass on the assumption the CRM had none; measuring the live DOM proved the opposite. */
.card-header {
    padding: 16px 18px;
    border-bottom: 1px solid var(--line);
}

    /* A handful of headers are a long sentence or carry interpolated dates/names, where all-caps
       reads badly. Those opt out with .card-title-plain on the <strong>. */
    .card-header strong.card-title-plain {
        text-transform: none;
        font-size: .95rem;
        font-weight: 700;
        letter-spacing: 0;
        color: var(--navy);
    }

    /* .card-header carries font-weight: 700, which the one-line sub-caption underneath it was
       inheriting - so every "Tickets closed in the last two weeks" style explainer rendered bold
       and competed with its own heading. */
    .card-header .text-muted, .card-header .small {
        font-weight: 500;
    }

.card-body {
    padding: 16px 18px;
}

/* ---- Page title: bare on the page, NOT a white pod ----
   Measured on the CRM's My Day page 8/14/2026: the element wrapping its eyebrow + h1 computes to
   background transparent, padding 0, border 0, box-shadow none. The title sits directly on the
   page background and the white pods start below it.

   This reverses the "wrap every title in a white pod" decision from 8/13. That was the right read
   of a screenshot but the wrong read of the app: putting the title in a pod gave every page two
   stacked white slabs before any content, which is most of why the two apps still looked unlike
   each other even after the tokens matched. The .page-header class stays exactly where it is on
   all 52 pages, so this is one block to flip if the pod is ever wanted back - restore
   background-color: var(--card), border, box-shadow, and padding here and nothing else changes. */
.page-header {
    background-color: transparent;
    border: 0;
    box-shadow: none;
    padding: 0;
    margin-bottom: 20px;
}

    .page-header h1 {
        font-size: 1.6rem;
        margin-bottom: 0;
    }

    /* A subtitle under a bare title reads as page furniture, so it gets the secondary text color
       and a little air rather than sitting tight under the h1 the way it did inside a pod. */
    .page-header > p {
        margin-top: 6px;
    }

.page-eyebrow {
    margin-bottom: 6px;
}

/* Back-links and title-row actions belong inside the pod, so nothing floats bare on the page
   background above it. */
.page-header-actions {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

/* ---- Sub-nav becomes a rounded white tab bar instead of an underlined strip ----
   Overrides the earlier .subnav block rather than replacing it, so the component markup
   (ReportingNav / WorkbenchNav) needs no change. Not a 999px pill on the container: the
   Reporting strip has eleven tabs and wraps to two rows on a narrow window, where a pill
   outline looks broken. */
.subnav {
    background-color: var(--card);
    border: 1px solid var(--line);
    padding: .3rem .4rem;
    gap: .15rem;
    margin-bottom: 1.25rem;
}

    .subnav a, .subnav .subnav-active, .subnav-btn {
        border-radius: var(--radius-md);
        border-bottom: none;
        margin-bottom: 0;
        padding: .38rem .85rem;
    }

    .subnav .subnav-active {
        background-color: var(--tint);
        color: var(--blue);
        border-bottom-color: transparent;
    }

/* Generic pod, for the odd block of content that isn't a .card and isn't a title block but was
   still sitting bare on the page background (legends, standalone control rows). */
.pod {
    background-color: var(--card);
    border: 1px solid var(--line);
    padding: 1.1rem 1.35rem;
    margin-bottom: 1.25rem;
}

.alert {
    border-radius: var(--radius-md);
}

.badge {
    border-radius: 999px;
}

/* The CRM's primary button carries a colored glow rather than a neutral drop shadow. */
.btn-primary {
    box-shadow: var(--shadow-btn);
}

/* ---- Figures in JetBrains Mono (CRM --font-data) ----
   Jason's call, 8/14: mono for figures only. KPI values, anything tagged .mono, and the numeric
   table columns already marked .tabular-nums. Body copy, labels, and headings stay Montserrat,
   so the brand type standard still holds everywhere text is read as language rather than as a
   number. Weight 600 and line-height 1.25 match .kpi-value in the CRM. */
.mono, .kpi .kpi-value, .kpi .kpi-value-sm, .kpi-value-sm, .tabular-nums {
    font-family: var(--font-data);
    font-variant-numeric: tabular-nums;
}

.kpi .kpi-value {
    font-size: 1.35rem;
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: 0;
}

.kpi .kpi-value-sm, .kpi-value-sm {
    font-weight: 600;
}

.kpi .kpi-label {
    margin-bottom: .15rem;
}

/* ================= CRM parity: tables, controls, tiles (2026-08-14) =================
   All measured off crm.weavertech.us's live DOM and stylesheet. Its .data-table / .btn / .kpi-card
   are the spec; these rules map Bootstrap's equivalents onto them so no page markup changes. */

/* ---- Tables ----
   The CRM's table is the densest, most distinctive part of its look: 13.5px body text, a header
   row painted the PAGE color rather than white, muted small-caps headers, secondary-color cell
   text that goes full-strength on hover, and no rule under the final row. */
.table {
    --bs-table-cell-padding-y: 12px;
    --bs-table-cell-padding-x: 16px;
    --bs-table-border-color: var(--line-faint);
    /* Cells are white, like the card. Do NOT set --bs-table-bg-state here: Bootstrap paints that
       as an inset shadow across every cell and it silently overrides --bs-table-bg. It belongs
       only on the .table-hover rule above. */
    --bs-table-bg: var(--table-bg);
    font-size: 13.5px;
}

.table-sm {
    --bs-table-cell-padding-y: 8px;
    --bs-table-cell-padding-x: 14px;
}

.table thead th, table thead th {
    background-color: var(--table-head-bg);
    padding: 10px 16px;
    letter-spacing: .08em;
    border-bottom: 1px solid var(--line);
}

.table > tbody > tr > td {
    color: var(--ink2);
    vertical-align: middle;
}

    /* Numbers are the exception: they stay full-strength ink so a column of figures reads as the
       point of the row rather than as supporting text. */
    .table > tbody > tr > td.mono, .table > tbody > tr > td.tabular-nums {
        color: var(--ink);
        font-size: 13px;
    }

    .table > tbody > tr:last-child > td {
        border-bottom-width: 0;
    }

.table > tbody > tr:hover > td {
    color: var(--ink);
}

.pod > .table, article > .table, article > .table-responsive > .table {
    border: 1px solid var(--line);
    border-radius: var(--radius-md);
    overflow: hidden;
}

/* ---- Controls ----
   6px radius, 14px/500, 10px/20px padding; the small variant is 13px with 6px/14px. Bootstrap's
   defaults are both rounder and chunkier than anything on the reference screen. */
.btn {
    --bs-btn-padding-y: 10px;
    --bs-btn-padding-x: 20px;
    --bs-btn-font-size: 14px;
    --bs-btn-font-weight: 500;
    --bs-btn-border-radius: var(--radius-sm);
}

.btn-sm {
    --bs-btn-padding-y: 6px;
    --bs-btn-padding-x: 14px;
    --bs-btn-font-size: 13px;
}

/* ---- Stat tiles ----
   18px/22px inside, 12px between, 20px below the row. !important only because the markup carries
   Bootstrap's p-3 utility on ~61 tiles and that utility is itself !important; the alternative was
   editing every one of them. */
.kpis {
    gap: 12px;
    margin-bottom: 20px;
}

.kpi {
    padding: 18px 22px !important;
}

.badge {
    font-size: 11px;
    font-weight: 600;
}

/* ---- Service Board KPI strip (2026-09-02) ----
   Jason: "reduce the size of the KPI tiles and add some color on the end of the tiles to give the
   page some character."

   Scoped to .board-kpis on purpose. The generic `.kpi { padding: 18px 22px !important; }` rule above
   is shared by ~61 tiles across the app and carries !important, so resizing it here would resize
   every page that has tiles. The accent colour is set per tile as an inline --kpi-accent so this
   stays a single rule rather than one class per colour. */
.board-kpis .kpi {
    padding: 0 !important;
    position: relative;
    overflow: hidden;
}

.board-kpis .kpi .card-body {
    padding: .45rem .6rem .55rem !important;
}

.board-kpis .kpi::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: var(--kpi-accent, #0079C2);
}

.board-kpis .kpi .kpi-label {
    font-size: 10px;
    margin-bottom: 0;
}

.board-kpis .kpi .kpi-value-sm {
    font-size: 1.1rem;
    line-height: 1.2;
}

/* The hover border picks up the tile's own accent, so the colour reads as the tile's identity
   rather than as decoration bolted on the bottom. */
.board-kpis .kpi-clickable:hover {
    border-color: var(--kpi-accent, #0079C2);
}

/* ---- Save notices (2026-09-03, finding X1) ----
   Fixed to the bottom-right so a notice never pushes page content around - several of these pages
   reload their own data on save, and a banner that appears in the flow would shift the row the user
   was looking at. Above Bootstrap's modal backdrop (1050) so the New Ticket dialog's own saves are
   still visible. */
.toast-stack {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 1080;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    max-width: min(26rem, calc(100vw - 2rem));
    pointer-events: none;
}

.toast-note {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    background: #fff;
    border: 1px solid var(--line);
    border-left: 4px solid var(--blue);
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(31, 52, 103, .18);
    padding: .65rem .8rem;
    font-size: .875rem;
    color: var(--ink);
}

.toast-note.toast-success { border-left-color: #2E9E5B; }
.toast-note.toast-warning { border-left-color: var(--gold, #EEBB3F); }
.toast-note.toast-error { border-left-color: #BF1E2C; }

.toast-success .toast-icon { color: #2E9E5B; }
.toast-warning .toast-icon { color: #EEBB3F; }
.toast-error .toast-icon { color: #BF1E2C; }

.toast-icon { flex: 0 0 auto; line-height: 1.4; }
.toast-text { flex: 1 1 auto; }

.toast-close {
    flex: 0 0 auto;
    background: none;
    border: 0;
    color: #8299b3;
    font-size: 1.1rem;
    line-height: 1;
    padding: 0 .1rem;
    cursor: pointer;
}

.toast-close:hover { color: var(--ink); }
.toast-close:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* ---- "Saves as you type" marker (2026-09-03, finding X2) ----
   Project Detail mixes two save models: some cards persist on change, others wait for a Save button,
   and they were visually identical. Four "it isn't saving" investigations trace to that ambiguity. The
   fix is to say which is which, rather than to make them uniform - saving on change is the safer
   behaviour to keep now that phone circuits drop (see M1), so it is labelled instead of removed. */
.saves-live {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #2E9E5B;
    background: rgba(46, 158, 91, .09);
    border: 1px solid rgba(46, 158, 91, .25);
    border-radius: 999px;
    padding: .1rem .45rem;
    white-space: nowrap;
}

.saves-live .bi { font-size: 9px; }

/* A card that needs its Save pressed says so next to the button, for the same reason. */
.needs-save-note {
    font-size: 11px;
    color: #8299b3;
}

/* ================= Phone and tablet (2026-09-03) =================
   Added after Jason confirmed the app is used on phones and may be used on tablets. Findings X7, M2,
   M3 and M4 from the usability review.

   What was already right and is untouched: the viewport meta tag, NavMenu's hamburger under 641px,
   Bootstrap's grid collapsing the multi-column card rows on its own, full-size .form-control at 16px,
   and the kanban / schedule board / timesheet grid which already scroll inside themselves. */

/* ---- X7: wide tables scroll inside their own container, at every width ----
   96 of the app's 117 tables had no scroll container, so a table wider than the page pushed the whole
   body sideways - the most visible defect on a phone, and it also bites a 1366px laptop once the
   220px sidebar is taken out.

   Scoped with :has() rather than a blanket rule on .card-body, so only containers that actually hold
   a table become scroll containers. That matters: overflow-x on a box whose overflow-y is visible
   promotes overflow-y to auto as well, which would clip an absolutely-positioned child. The gantt
   bars, scoreboard markers and Home's pace marker all rely on that, and none of them share a
   container with a table. Verified there are no Bootstrap dropdown-menus anywhere in the app, which
   is the usual thing this rule breaks. */
.card-body:has(table),
.pod:has(table),
/* The four tables in the app that sit outside a .card-body or .pod, by their real containers:
   Team's unmatched-billing-role warning, Company Detail's per-rate-card editor, and the two on
   /schedule-approval. That last one matters most of the four - it is the page Andrew and Ryan open
   from an approval email, which is to say on a phone, so its billing-impact table is the one most
   likely to be read on a small screen. */
.signin-card:has(table),
.border.rounded:has(table) {
    overflow-x: auto;
}

/* NOTE: min-width on these tables is deliberately phone-only - see the media query below. Forcing
   max-content at desktop made every table demand its natural width, which is what put Jason on 90%
   zoom to see a full row. Compressing columns to fit is the desktop behaviour and it was correct. */

@media (max-width: 640px) {
    /* ---- M2: stop iOS zooming the page on every field tap ----
       Mobile Safari zooms whenever a focused input's text is under 16px. The app's full-size controls
       are 1rem and behave; the compact variants are .875rem, and there are 317 of them across Ticket
       Detail's condensed pods, Project Detail and most tables. The result was: tap a field, the page
       jumps and zooms, pinch back out, tap the next one. 16px is the threshold, not a preference. */
    .form-control-sm,
    .form-select-sm,
    .form-control,
    .form-select,
    textarea.form-control {
        font-size: 16px;
    }

    /* A table under phone width cannot usefully compress 8 columns into 380px - it produces
       unreadable slivers. Here, and only here, let it take its natural width and scroll sideways
       inside the container X7 gave it. */
    .card-body:has(table) > .table,
    .pod:has(table) > .table,
    .signin-card:has(table) > .table,
    .border.rounded:has(table) > .table {
        min-width: max-content;
    }

    /* ---- M3: tap targets ----
       The app uses .btn-sm almost everywhere (261 uses), which lands near 31px. Apple asks 44px and
       Android 48px. Raised on phones only, so desktop density is unchanged - the whole point of the
       compact styling elsewhere. Pairs with X3: small delete buttons beside small edit buttons is how
       a mis-tap destroys a logged time entry. */
    .btn-sm,
    .btn {
        min-height: 44px;
        padding-top: .5rem;
        padding-bottom: .5rem;
    }

    /* Buttons that sit inside a table row stay compact - a 44px target in every cell of a 20-row
       table makes the table unusable, and those rows are reached by scrolling rather than thumbing. */
    .table .btn-sm {
        min-height: 32px;
        padding-top: .2rem;
        padding-bottom: .2rem;
    }

    /* Checkboxes and radios are the smallest targets in the app and appear on every form. */
    .form-check-input {
        width: 1.15rem;
        height: 1.15rem;
    }

    /* ---- M4: let Home's panels grow ----
       Home pins its three panels to a fixed height with the content scrolling inside, which is what
       keeps the desktop page to a single view. On a phone that produces nested scrolling: a drag
       inside a panel moves the panel, not the page, so the reader gets stuck part-way down with no
       clue why. A phone was never going to show that page in one view, so the panels grow instead.
       !important because the height is set inline from Home.razor's PanelHeight constant. */
    .home-panel-scroll {
        max-height: none !important;
        overflow-y: visible !important;
    }

    /* The Home hero's headline figure is sized for a desktop column. */
    .home-page .home-hero .home-hero-value-lg {
        font-size: 1.75rem;
    }

    /* Page headers carry a title plus controls in a flex row that assumes desktop width. */
    .page-header-actions {
        width: 100%;
    }

    .page-header-actions .btn,
    .page-header-actions .form-select {
        flex: 1 1 auto;
    }
}

/* ---- Accessibility: honor reduced-motion preferences across everything above ---- */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *, *::before, *::after {
        transition-duration: .01ms !important;
        animation-duration: .01ms !important;
    }
}

/* ---------------------------------------------------------------------------
   Signed-out shell (SignIn, NoAccess, ScheduleApproval)

   These lived in SignIn.razor.css, which is SCOPED css - so it only ever applied
   to SignIn.razor. NoAccess.razor and ScheduleApproval.razor use the same class
   names and got none of it: no navy backdrop, no centring, and the logo at its
   natural size. Since weaver-logo-white.png is a WHITE logo, losing the navy
   background is what made it look "very light and hardly visible" on the
   approval page (Jason, 8/27) - it was white-on-near-white.

   Global here rather than duplicated per page so the three can't drift apart.
   Every selector is `signin-` prefixed, so nothing else can pick them up.
   --------------------------------------------------------------------------- */

.signin-shell {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;
    background-color: var(--navy, #1F3467);
}

.signin-inner {
    width: 100%;
    max-width: 27rem;
}

/* 17.5rem = 280px, comfortably clear of the 2in (~192px at 96dpi) minimum width the brand
   standards set for the primary logo. Aspect ratio is preserved - never stretched. */
.signin-logo {
    display: block;
    width: 17.5rem;
    max-width: 100%;
    height: auto;
    margin: 0 auto 2.5rem;
}

.signin-card {
    background-color: #ffffff;
    border-radius: 0.75rem;
    padding: 2.5rem 2rem;
    box-shadow: 0 1.25rem 2.5rem rgba(0, 0, 0, 0.25);
}

.signin-card h1 {
    font-family: var(--font, "Montserrat", Arial, sans-serif);
    font-size: 1.75rem;
    font-weight: 700;
    color: var(--navy, #1F3467);
    margin: 0 0 0.35rem;
}

.signin-sub {
    font-size: 0.9375rem;
    color: var(--gray, #484848);
    margin: 0 0 1.75rem;
}

.signin-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.625rem;
    width: 100%;
    padding: 0.8125rem 1rem;
    background-color: var(--blue, #0079C2);
    color: #ffffff;
    font-family: var(--font, "Montserrat", Arial, sans-serif);
    font-size: 1rem;
    font-weight: 600;
    border-radius: 0.375rem;
    text-decoration: none;
    transition: background-color 0.15s ease-in-out;
}

.signin-btn:hover {
    /* Darker shade of the primary blue rather than a second palette colour. */
    background-color: #00629F;
    color: #ffffff;
    text-decoration: none;
}

.signin-btn:focus-visible {
    outline: 3px solid var(--blue2, #00A4E4);
    outline-offset: 2px;
}

.signin-btn-mark {
    width: 1.25rem;
    height: 1.25rem;
    flex: 0 0 auto;
}

.signin-note {
    margin: 1.5rem 0 0;
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--muted, #6b7482);
    text-align: center;
}

@media (max-width: 24rem) {
    .signin-card {
        padding: 2rem 1.25rem;
    }

    .signin-logo {
        width: 14rem;
        margin-bottom: 2rem;
    }
}

/* The approval page carries a billing-forecast table and a note field, so it needs
   more room than a sign-in button. Widening the inner rather than the card, so the
   card stays centred in the shell. */
.signin-inner-wide {
    max-width: 42rem;
}

/* ---------------------------------------------------------------------------
   Home command centre (8/27)

   Jason: "Lets give the Services Scorecard some POP. It looks like everything
   else... Lets add some color on this page in general... make all things a
   little smaller. The idea is not to have to scroll on this page."

   Two rules held while doing it: every colour is off the Weaver palette already
   declared at the top of this file (no new hues invented), and the density comes
   from smaller type and tighter padding rather than from hiding information.
   Scoped under .home-page so nothing here leaks into the rest of the app.
   --------------------------------------------------------------------------- */

/* The scorecard, promoted from "another white card" to the one band of real
   colour on the page. Navy -> primary blue -> light blue, all brand. */
.home-hero {
    background: linear-gradient(135deg, #1F3467 0%, #0079C2 58%, #00A4E4 100%);
    color: #ffffff;
    border-radius: .75rem;
    box-shadow: var(--shadow-card);
}

.home-hero a {
    color: #ffffff;
    text-decoration: underline;
}

.home-hero-label {
    text-transform: uppercase;
    font-size: .625rem;
    font-weight: 700;
    letter-spacing: .08em;
    color: rgba(255, 255, 255, .78);
}

.home-hero-value {
    font-family: var(--font-data);
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.1;
}

/* Each revenue figure in its own translucent block, so the breakout reads as a
   set of figures rather than a paragraph of numbers. */
.home-chip {
    background: rgba(255, 255, 255, .14);
    border-radius: .5rem;
    padding: .4rem .6rem;
}

.home-chip-value {
    font-family: var(--font-data);
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.2;
}

.home-progress {
    height: .625rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, .22);
    overflow: hidden;
}

.home-progress-bar {
    height: 100%;
    background: #EEBB3F;
}

/* Pulse tiles: a colour-coded left edge and a coloured figure, instead of a dot
   on a plain white card. Smaller than the cards they replace. */
.pulse-tile {
    background: #ffffff;
    border-radius: .5rem;
    border-left: .25rem solid var(--blue);
    box-shadow: var(--shadow-card);
    padding: .5rem .7rem;
    cursor: pointer;
    height: 100%;
    transition: transform .12s ease-in-out, box-shadow .12s ease-in-out;
}

.pulse-tile:hover {
    transform: translateY(-1px);
    box-shadow: 0 .25rem .75rem rgba(26, 43, 73, .14);
}

.pulse-value {
    font-family: var(--font-data);
    font-size: 1.4rem;
    font-weight: 700;
    line-height: 1.1;
}

.pulse-label {
    font-size: .625rem;
    text-transform: uppercase;
    font-weight: 700;
    letter-spacing: .04em;
    color: var(--gray);
}

/* Density pass for the three panels along the bottom - they have to share one
   screen with the pulse strip and the hero. */
.home-page .card-header {
    padding: .45rem .75rem;
}

.home-page .card-body {
    padding: .7rem .75rem;
}

.home-page .table-sm > tbody > tr > td {
    padding: .15rem .35rem;
    font-size: .8125rem;
}

.home-panel-scroll {
    overflow-y: auto;
}

/* The day heading inside the two-week schedule - a coloured rule rather than a
   grey one, so the eye can find the day breaks while scanning. */
.home-day-heading {
    font-size: .6875rem;
    text-transform: uppercase;
    font-weight: 700;
    letter-spacing: .05em;
    color: var(--navy);
    border-bottom: .125rem solid #39B9DF;
    padding-bottom: .15rem;
    margin-bottom: .35rem;
}

.home-badge {
    font-size: .625rem;
    font-weight: 700;
    padding: .15rem .4rem;
    border-radius: .25rem;
    color: #ffffff;
}

.home-quote {
    border-left: .1875rem solid #00A4E4;
    padding-left: .6rem;
    font-size: .8125rem;
}

/* Home's own title pod, shorter than the app-wide one - the page has to fit a
   single screen, so the greeting gives up its second line and its subtitle. */
.home-header h1 {
    font-size: 1.4rem;
}

/* The financial band took over the space the KPI tiles used to occupy (8/28), so
   its figures step up a size and the goal bar gets a pace marker. */
.home-hero-value-lg {
    font-size: 2.5rem;
}

.home-chip-value-lg {
    font-size: 1.15rem;
}

.home-progress-lg {
    height: .875rem;
    position: relative;
}

/* Where the bar would be if the quarter's goal were earned evenly day by day. */
.home-pace-marker {
    position: absolute;
    top: -.15rem;
    bottom: -.15rem;
    width: .125rem;
    background: #ffffff;
    box-shadow: 0 0 0 .0625rem rgba(31, 52, 103, .55);
}

.home-pace {
    border-left: .1875rem solid #ffffff;
    padding-left: .6rem;
    font-size: .8125rem;
}

/* ---------------------------------------------------------------------------------------------
   Team page (9/3) - one card per person, every field saves on change. Scoped to .team-page.
   --------------------------------------------------------------------------------------------- */
.team-page .team-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:.75rem}
.team-page .team-tabs{display:inline-flex;background:#eef2f8;border-radius:999px;padding:3px}
.team-page .team-tabs button{border:0;background:transparent;border-radius:999px;padding:4px 14px;font-size:.8125rem;font-weight:600;color:#484848}
.team-page .team-tabs button.active{background:#fff;color:#0079C2;box-shadow:0 1px 2px rgba(26,43,73,.12)}
.team-page .team-count{display:inline-block;min-width:1.4em;margin-left:4px;padding:0 5px;border-radius:999px;background:rgba(31,52,103,.08);font-size:.7rem;font-weight:700}
.team-page .team-tabs button.active .team-count{background:rgba(0,121,194,.12)}
.team-page .team-search{max-width:260px}
.team-page .team-chip{display:inline-block;margin:2px 4px 0 0;padding:1px 8px;border-radius:999px;background:rgba(255,255,255,.7);font-size:.75rem}
.team-page .team-minw0{min-width:0}
.team-page .team-card{background:#fff;border:1px solid rgba(31,52,103,.12);border-radius:12px;padding:14px 16px;box-shadow:0 1px 3px rgba(26,43,73,.08);height:100%;display:flex;flex-direction:column;gap:10px}
.team-page .team-card.inactive{opacity:.72;background:#f8f9fb}
.team-page .team-card-head{display:flex;align-items:center;gap:12px}
.team-page .team-avatar{width:40px;height:40px;font-size:14px}
.team-page .team-name,.team-page .team-email{display:block;width:100%;border:1px solid transparent;border-radius:6px;padding:1px 6px;margin-left:-6px;background:transparent}
.team-page .team-name{font-weight:700;font-size:1rem;color:#1A1A1A}
.team-page .team-email{font-size:.8125rem;color:#484848}
.team-page .team-name:hover:not(:disabled),.team-page .team-email:hover:not(:disabled){border-color:rgba(31,52,103,.15)}
.team-page .team-name:focus,.team-page .team-email:focus{outline:0;border-color:#00A4E4;background:#fff}
.team-page .team-role-badge{font-size:.7rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:#0079C2;background:rgba(0,121,194,.08);border-radius:999px;padding:3px 10px;white-space:nowrap}
.team-page .team-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px 12px}
.team-page .team-grid label{display:block;font-size:.7rem;text-transform:uppercase;letter-spacing:.04em;color:#8299b3;font-weight:600;margin:0}
.team-page .team-grid label > *{margin-top:2px}
.team-page .team-grid .team-workday{grid-column:span 2}
.team-page .team-grid .team-workday-row{display:flex;align-items:center;gap:5px;flex-wrap:wrap;text-transform:none;letter-spacing:0;font-size:.75rem}
.team-page .team-grid .team-workday-row input[type=time]{width:auto;min-width:0;flex:0 1 auto}
.team-page .team-grid .team-lunch{width:64px;flex:none}
@media (max-width:480px){.team-page .team-grid .team-workday{grid-column:span 1}}
.team-page .team-grid .team-inline-check{display:flex;align-items:center;gap:6px;text-transform:none;letter-spacing:0;font-size:.8125rem;color:#484848;font-weight:500;align-self:end}
.team-page .team-grid .team-inline-check .form-check-input{margin:0}
.team-page .team-flags{display:flex;flex-wrap:wrap;align-items:center;gap:6px 18px;font-size:.8125rem}
.team-page .team-switch{display:flex;align-items:center;gap:6px;padding-left:0;margin:0;font-size:.8125rem;color:#484848;cursor:pointer;white-space:nowrap}
.team-page .team-switch .form-check-input{float:none;margin:0;width:2.2em;height:1.2em}
.team-page .team-profile{border-top:1px dashed rgba(31,52,103,.15);padding-top:10px;margin-top:auto}
.team-page .team-drop{position:relative;margin-top:8px;border:1.5px dashed rgba(0,121,194,.45);border-radius:8px;padding:9px 10px;text-align:center;font-size:.8125rem;color:#484848;background:rgba(0,164,228,.04)}
.team-page .team-drop:hover{background:rgba(0,164,228,.1)}
.team-page .team-drop input[type=file]{position:absolute;inset:0;width:100%;height:100%;opacity:0;cursor:pointer}
.team-page .team-md{font-family:var(--font-data, ui-monospace, monospace);font-size:.8rem}
.team-page .team-md-view{margin:8px 0 0;max-height:280px;overflow:auto;white-space:pre-wrap;font-family:var(--font-data, ui-monospace, monospace);font-size:.78rem;background:#f5f7fa;border-radius:8px;padding:10px 12px;color:#1A1A1A}

/* Avatars (Components/Shared/Avatar.razor): Entra photo over coloured initials. The img removes
   itself on a 404 from /photos/resource/{id}, leaving the initials that were always there. */
.avatar{position:relative;overflow:hidden}
.avatar .avatar-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:50%}

/* ---- Help page table of contents (finding N6, 9/4) ----
   A wrapping row of jump links rather than a sidebar: the page is one column of cards, and a
   sticky sidebar would fight the 220px nav for width on a laptop. Anchors only - no script. */
.help-toc {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem .5rem;
}

.help-toc a {
    display: inline-block;
    padding: .3rem .7rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--blue, #0079C2);
    text-decoration: none;
    white-space: nowrap;
}

.help-toc a:hover {
    background-color: rgba(0, 121, 194, .07);
    border-color: var(--blue, #0079C2);
}

/* Jumping to a card leaves its header flush against the top of the viewport otherwise. */
.card[id] {
    scroll-margin-top: 1rem;
}

/* ================================================================== Reporting redesign (9/4)
   Spec v2 §9. The twelve-tab .subnav strip is replaced by three category nav cards across the top of
   every reporting page - v1's left rail is gone, per v2's "There is no left sidebar."

   .subnav itself STAYS: Project Detail, Company Detail, the CW Mapping Workbook and WorkbenchNav all
   use it. The spec's step 5 says to delete it, which would break four things outside Reporting. */

.rpt-content { min-width: 0; }

/* ---- nav cards ---- */
.rpt-navcards {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
    position: relative;
    z-index: 20;           /* above the navy briefing band, so a menu is never clipped by it */
    margin-bottom: 1.25rem;
}

/* Equal heights, and flex is not interchangeable with height:100% here - the card is content-box
   with 15px/18px padding, so a percentage height overflows its slot. Without this a card whose
   sublabel wraps is taller than its siblings and the short ones float with dead space beneath. */
.rpt-navcard-slot { position: relative; display: flex; flex-direction: column; }

.rpt-navcard {
    flex: 1;
    text-align: left;
    background: var(--card, #fff);
    border: 1px solid rgba(31, 52, 103, .12);
    border-top: 3px solid #0079C2;
    border-radius: 14px;
    padding: 15px 18px;
    cursor: pointer;
    font-family: inherit;
    transition: box-shadow .12s ease, border-color .12s ease;
}

.rpt-navcard:hover { box-shadow: 0 8px 22px rgba(26, 43, 73, .16); border-color: rgba(0, 121, 194, .4); }
.rpt-navcard:focus-visible { outline: 2px solid #0079C2; outline-offset: 2px; }
.rpt-navcard.active { border-color: #0079C2; background: #e6f4fb; }

.rpt-navcard-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }

.rpt-navcard-label {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #1F3467;
}

.rpt-navcard-chevron { color: #8299b3; transition: transform .12s ease; transform: rotate(90deg); }
.rpt-navcard-chevron.open { transform: rotate(-90deg); }

.rpt-navcard-sub { font-size: 12px; color: #44607e; margin-top: .2rem; display: flex; gap: .3rem; flex-wrap: wrap; }
.rpt-navcard-cue { color: #BF1E2C; font-weight: 600; }

.rpt-navcard-dots { display: flex; gap: 4px; margin-top: .55rem; }
.rpt-navcard-dot { width: 8px; height: 8px; border-radius: 50%; }

/* ---- dropdown menu ---- */
.rpt-navmenu {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    right: 0;
    background: var(--card, #fff);
    border: 1px solid rgba(31, 52, 103, .12);
    border-radius: 14px;
    box-shadow: 0 18px 44px rgba(26, 43, 73, .22);
    overflow: hidden;
    z-index: 30;
}

.rpt-navmenu-item {
    display: flex;
    align-items: flex-start;
    gap: .55rem;
    padding: 11px 16px;
    border-top: 1px solid rgba(31, 52, 103, .12);
    text-decoration: none;
    color: #1a2b49;
}

.rpt-navmenu-item:first-child { border-top: none; }
.rpt-navmenu-item:hover, .rpt-navmenu-item:focus-visible { background: #f2f7fc; }
.rpt-navmenu-item.current { background: #e6f4fb; }

.rpt-navmenu-dot { width: 8px; height: 8px; border-radius: 50%; margin-top: .35rem; flex: 0 0 auto; }
.rpt-navmenu-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.rpt-navmenu-name { font-size: 13.5px; font-weight: 600; }
.rpt-navmenu-note { font-size: 11.5px; color: #8299b3; }
.rpt-navmenu-figure { font-size: 12.5px; color: #1F3467; font-weight: 600; white-space: nowrap; }

/* ---- pace bar ---- */
.rpt-pace-bar { position: relative; height: 10px; border-radius: 999px; background: rgba(31, 52, 103, .1); overflow: hidden; }
.rpt-pace-bar.compact { height: 6px; }
.rpt-pace-actual, .rpt-pace-projected { position: absolute; inset: 0 auto 0 0; border-radius: 999px; }
.rpt-pace-projected { opacity: .32; }   /* behind the solid fill - a ghost of the real figure */
.rpt-pace-marker { position: absolute; top: -2px; bottom: -2px; width: 0; border-left: 2px dashed #1F3467; }

/* ---- delta chip and status chip ---- */
.rpt-delta { font-size: 11.5px; font-weight: 600; white-space: nowrap; }
.rpt-chip { display: inline-block; border-radius: 999px; font-size: 12px; font-weight: 600; padding: .1rem .55rem; }
.rpt-chip-red { background: #fbe9ea; color: #BF1E2C; }
.rpt-chip-amber { background: #fdf4e0; color: #9a6c00; }
.rpt-chip-green { background: #e7f6ec; color: #15803d; }
.rpt-chip-neutral { background: #eef2f8; color: #44607e; }

/* A panel with too little data to chart says so on one line instead of drawing one bar (§7). */
.rpt-thin-note { font-size: 13.5px; color: #44607e; }

/* Below ~900px the cards stack and the menus expand IN PLACE rather than overlaying - an absolute
   dropdown on a phone covers the content it is supposed to be navigating to. */
@media (max-width: 900px) {
    .rpt-navcards { grid-template-columns: 1fr; gap: 10px; }
    .rpt-navmenu { position: static; box-shadow: none; margin-top: 6px; }
}

/* ---- Overview: briefing band, attention rows, report index (spec v2 §9/§10) ---- */
.rpt-briefing {
    background: #1F3467;
    border-radius: 18px;
    padding: 22px 26px;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 26px;
    margin-bottom: 1.25rem;
    color: #fff;
}

/* Dividers BETWEEN columns only - a trailing rule on the last column reads as a cut-off band. */
.rpt-briefing-col + .rpt-briefing-col { border-left: 1px solid rgba(255, 255, 255, .16); padding-left: 26px; }

.rpt-briefing-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.rpt-briefing-label { font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: #9fb6dd; }
.rpt-briefing-headline { font-size: 1.15rem; font-weight: 700; margin-top: .35rem; line-height: 1.25; }
.rpt-briefing-detail { font-size: .8125rem; color: #cfe0f5; margin-top: .3rem; }
.rpt-briefing-bar { margin-top: .6rem; }
.rpt-briefing .rpt-pace-bar { background: rgba(255, 255, 255, .18); }
.rpt-briefing .rpt-pace-marker { border-left-color: #EEBB3F; }
.rpt-briefing-caption { font-size: 11px; color: #9fb6dd; margin-top: .4rem; }

/* The .rpt-attention-* rules went with the Needs Attention pod (Jason removed it 9/4). .rpt-thin-note
   below STAYS - §7's thin-data collapse still applies to the individual reports, it is only the
   Overview's copy of it that went. */

/* ---- report index ---- */
.rpt-index-row {
    display: grid;
    grid-template-columns: 28px 1.5fr 1fr 1fr 100px 84px;
    gap: .75rem;
    align-items: center;
    padding: .6rem 1rem;
    border-top: 1px solid rgba(31, 52, 103, .12);
    text-decoration: none;
    color: #1a2b49;
}
.rpt-index-row:hover { background: #f2f7fc; }

.rpt-index-head {
    border-top: none;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #8299b3;
}
.rpt-index-head:hover { background: transparent; }

.rpt-pin {
    background: none;
    border: none;
    padding: 0;
    font-size: 15px;
    line-height: 1;
    color: #cbd5e1;
    cursor: pointer;
}
.rpt-pin.on { color: #EEBB3F; }

@media (max-width: 900px) {
    .rpt-briefing { grid-template-columns: 1fr; gap: 18px; }
    .rpt-briefing-col + .rpt-briefing-col { border-left: none; padding-left: 0; border-top: 1px solid rgba(255,255,255,.16); padding-top: 18px; }
    /* Owner and Updated are the first things to go on a phone - the report, its figure and its
       status are what the index is for. */
    .rpt-index-row { grid-template-columns: 28px 1.4fr 1fr; }
    .rpt-index-row > :nth-child(5), .rpt-index-row > :nth-child(6) { display: none; }
}

/* ---------------------------------------------------------------------------------------------
   Read-then-Edit (walkthrough P15, P32, P41, P46 - 29 Sep)

   Jason's call: a record reads cleanly at a glance and cannot be changed on the fly. Edit
   unlocks one record, Save persists, Cancel reloads. These are the shared bits - the button
   group and the read-view label/value pairs - so the four pages that use it look like one
   convention rather than four takes on it. See Components/Shared/EditActions.razor.
   --------------------------------------------------------------------------------------------- */

.edit-actions { display: flex; gap: .375rem; align-items: center; flex-wrap: wrap; }

/* A record's read view: label above value, wrapping into as many columns as fit. Deliberately
   NOT a table - these blocks sit inside cards of very different widths, and a table would force
   a shared column width that suits none of them. */
.read-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
    gap: .5rem 1.25rem;
}

.read-field { min-width: 0; }

.read-label {
    display: block;
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-muted, #6c757d);
    margin-bottom: .0625rem;
}

/* Values wrap rather than clip. A truncated agreement name or rate card is the thing the reader
   came for, so losing it to an ellipsis defeats the point of a read view. */
.read-value {
    font-size: .875rem;
    color: var(--text-primary, #1A1A1A);
    overflow-wrap: anywhere;
}

/* An unset value reads as a dash rather than as blank space, so "nothing here" is visibly a
   fact rather than a rendering gap. */
.read-value.is-empty { color: var(--text-muted, #6c757d); }

/* The strip that says a record is open for editing. Gold rather than blue: it is a state to
   notice and leave, not a primary action. */
.editing-banner {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    font-size: .8125rem;
    padding: .375rem .625rem;
    margin-bottom: .625rem;
    border-radius: .375rem;
    border: 1px solid #EEBB3F;
    background: rgba(238, 187, 63, .12);
    color: #7a5c00;
}

/* A record currently being edited, so the open one is obvious in a list of many. */
.is-editing { box-shadow: 0 0 0 2px rgba(238, 187, 63, .55); }

@media (max-width: 640px) {
    /* One column on a phone - two 9.5rem columns plus a gutter does not fit, and a squeezed
       label/value pair is harder to read than a longer list. */
    .read-grid { grid-template-columns: 1fr; }
}

/* ---- Click-to-copy control (P38) ----------------------------------------------------------
   Components/Shared/CopyButton.razor. DELIBERATELY NOT .btn: the phone media query above gives
   every .btn a 44px minimum height, and this sits inside table cells and an <h1>, where that
   would push rows apart and break the heading's line. It therefore carries its own sizing and
   inherits the caller's font, so a copyable ticket number looks exactly like the plain text it
   replaced until you hover it.

   The icon rests at .5 opacity rather than appearing on hover: a phone has no hover, and an
   affordance nobody can discover is the X4 finding from the 3 Sep review. */
.copy-id {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: 0 .2rem;
    margin-left: -.2rem; /* keeps the text optically aligned with whatever preceded it */
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: inherit;
    font: inherit;
    line-height: inherit;
    cursor: pointer;
    vertical-align: baseline;
}

.copy-id:hover {
    background: var(--hover);
}

.copy-id:hover .copy-id-ico {
    opacity: .9;
}

.copy-id-ico {
    width: .8em;
    height: .8em;
    flex: none;
    opacity: .5;
}

.copy-id-ok {
    color: var(--green);
    opacity: 1;
}

.copy-id-say {
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--green);
    white-space: nowrap;
}

.copy-id-failed .copy-id-say {
    color: var(--red);
}

.copy-id-failed .copy-id-ico {
    color: var(--red);
    opacity: .9;
}


/* Bonus Talking Points (P51, 10/2): print one engineer per page-flow, no app chrome. A person's block
   is kept whole so a page break never splits a name from their reasons. */
@media print {
    .no-print, .sidebar, .top-corner-bar, .app-footer, .nav-search { display: none !important; }
    .tp-person { break-inside: avoid; box-shadow: none; }
    .tp-project { break-inside: avoid; }
    main { margin: 0 !important; }
    .rpt-navcards, .rpt-content .page-header-actions { display: none !important; }
    .print-only { display: block !important; }
    .irl-customer { break-inside: avoid; }
    .irl-table thead { display: table-header-group; }
    .irl-total td { border-top: 1px solid #484848; }
    .irl-grand td { border-top: 2px solid #1A1A1A; font-size: 1.05rem; }
}
.print-only { display: none; }

/* Leadership Workbench -------------------------------------------------------------------------
   The three leadership views of My Workbench (Executive, Operations, Team Delivery). Brand palette only -
   no green anywhere. Built from the existing pod vocabulary and tokens; the pieces below are the few new
   ones, defined once. */

/* SummaryBand: the navy band. */
.summary-band {
    background: var(--navy);
    color: #fff;
    border-radius: 16px;
    padding: 28px;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 28px;
}
.summary-band.compact { padding: 20px 28px; gap: 20px; }
.summary-band .sb-eyebrow { color: #39B9DF; font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; }
.summary-band .sb-headline { font-size: 15px; font-weight: 700; margin-top: 6px; }
.summary-band .sb-big { font-size: 1.5rem; font-weight: 700; margin-top: 6px; line-height: 1.15; }
.summary-band.compact .sb-big { font-size: 1.25rem; }
.summary-band .sb-suffix { font-size: .85rem; font-weight: 500; margin-left: .4em; }
.summary-band .sb-bar { position: relative; display: flex; height: 8px; border-radius: 4px; margin-top: 12px; background: rgba(255,255,255,.18); }
.summary-band .sb-fill { display: block; height: 100%; border-radius: 4px; background: var(--blue2); }
.summary-band .sb-seg { display: block; height: 100%; }
.summary-band .sb-seg:first-child { border-radius: 4px 0 0 4px; }
.summary-band .sb-seg:last-child { border-radius: 0 4px 4px 0; }
.summary-band .sb-marker { position: absolute; top: -4px; height: 16px; border-left: 2px dashed var(--gold); }
.summary-band .sb-caption { font-size: 12px; margin-top: 10px; }

/* SectionBand: MONEY / DELIVERY / TEAM. */
.section-band {
    font-size: 13px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
    color: var(--navy); display: flex; align-items: center; gap: 12px; margin: 8px 0 0;
}
.section-band-tick { width: 4px; height: 18px; border-radius: 2px; background: var(--blue); }

/* StatusPill: the dot and the label carry the status; the text is always the near-black body colour. */
.status-pill {
    display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px;
    font-size: 12px; font-weight: 700; color: #1A1A1A; white-space: nowrap; background: rgba(72,72,72,.10);
}
.status-pill .status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--gray); flex: none; }
.status-pill.status-offtrack { background: rgba(191,30,44,.10); }
.status-pill.status-offtrack .status-dot { background: var(--red); }
.status-pill.status-atrisk { background: rgba(241,89,43,.12); }
.status-pill.status-atrisk .status-dot { background: var(--orange); }
.status-pill.status-watch { background: rgba(238,187,63,.20); }
.status-pill.status-watch .status-dot { background: var(--gold); }
.status-pill.status-ontrack, .status-pill.status-clean { background: rgba(0,164,228,.12); }
.status-pill.status-ontrack .status-dot, .status-pill.status-clean .status-dot { background: var(--blue2); }

/* Dashed marker for the pace line and the 70% floor, positioned with an inline left %. */
.bar-marker { position: absolute; top: -4px; height: 16px; border-left: 2px dashed var(--gold); }

/* Small layout helpers shared by the three views. */
.lw-context { font-size: 12px; margin: 4px 0 12px; }
.lw-list { list-style: none; margin: 0; padding: 0; }
.lw-row { display: flex; align-items: flex-start; gap: 10px; padding: 10px 0; border-top: 1px solid var(--border, #e3e9f2); }
.lw-row:first-child { border-top: 0; }
.lw-dot { width: 10px; height: 10px; border-radius: 50%; margin-top: 5px; flex: none; }
.lw-dot.red { background: var(--red); }
.lw-dot.orange { background: var(--orange); }
.lw-dot.blue { background: var(--blue2); }
.lw-dot.gold { background: var(--gold); }
.lw-dot.gray { background: var(--gray); }
.lw-row-main { flex: 1; min-width: 0; }
.lw-row-title { font-weight: 700; font-size: .875rem; }
.lw-row-sub { font-size: .8125rem; }
.lw-bigfigs { display: flex; flex-wrap: wrap; gap: 24px; }
.lw-fig { min-width: 110px; }
.lw-fig-value { font-size: 1.35rem; font-weight: 700; line-height: 1.1; }
.lw-fig-label { font-size: 12px; }
.lw-minibar { position: relative; height: 8px; border-radius: 4px; background: var(--tint); }
.lw-minibar > span.fill { display: block; height: 100%; border-radius: 4px; background: var(--blue); }
.lw-minibar > span.fill.gold { background: var(--gold); }
.lw-minibar > span.fill.navy { background: var(--navy); }
.lw-minibar > span.fill.red { background: var(--red); }
.lw-minibar > span.fill.orange { background: var(--orange); }
.lw-minibar > span.fill.gray { background: var(--gray); }
.lw-barrow { display: grid; grid-template-columns: 150px 1fr 90px; gap: 12px; align-items: center; padding: 6px 0; font-size: .8125rem; }
.lw-barrow .lw-val { text-align: right; }
.lw-groupheader th { background: var(--tint); color: var(--navy); font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.lw-count-pill { font-size: 12px; font-weight: 700; padding: 2px 10px; border-radius: 999px; background: var(--tint); color: var(--navy); }
.lw-hyg { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.lw-hyg a { text-decoration: none; color: inherit; display: block; padding: 10px; border-radius: 10px; border: 1px solid var(--border, #e3e9f2); }
.lw-hyg .n { font-size: 1.35rem; font-weight: 700; }
.lw-orange { color: var(--orange); }
@media (max-width: 575px) {
    .lw-barrow { grid-template-columns: 1fr; }
    .lw-barrow .lw-val { text-align: left; }
    .summary-band { padding: 20px; }
}

/* Admin hub (10/14) */
.admin-hub-heading {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--navy, #1F3467);
    margin: 0 0 2px;
}

.admin-hub-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 8px;
}

.admin-hub-tool {
    display: block;
    padding: 10px 12px;
    border: 1px solid var(--border, #dde3ed);
    border-radius: 8px;
    background: #fff;
    text-decoration: none;
    color: inherit;
}

.admin-hub-tool:hover { border-color: var(--blue, #0079C2); }

.admin-hub-title { font-weight: 600; color: var(--blue, #0079C2); }

.admin-hub-desc {
    display: block;
    margin-top: 2px;
    font-size: .8rem;
    color: #484848;
}

/* Read-only pods (Project Detail, 10/23): a disabled <fieldset> locks every control inside until the pod's Edit button is
   pressed. Reset the fieldset chrome, and keep locked values at full contrast so they read as text, not as greyed-out. */
fieldset.pod-lock { border: 0; margin: 0; min-width: 0; }
fieldset.pod-lock:disabled .form-control,
fieldset.pod-lock:disabled .form-select,
fieldset.pod-lock:disabled textarea {
    opacity: 1;
    color: var(--text-primary, #1a1a1a);
    -webkit-text-fill-color: currentColor;
    background-color: transparent;
    border-color: transparent;
    background-image: none;
    appearance: none;
    padding-left: 0;
}
fieldset.pod-lock:disabled .btn { opacity: .45; }

/* Project stage bar (Project Detail, under the tabs) */
.stage-bar { display: flex; gap: 2px; }
.stage-step { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: .35rem .75rem; background: #eef2f8; color: #484848; font-size: .75rem; line-height: 1.2; text-align: center;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 0 100%, 10px 50%); }
.stage-step:first-child { clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 0 100%); }
.stage-step.past { background: #cfe5f4; color: #1F3467; }
.stage-step.current { background: #0079C2; color: #fff; font-weight: 600; }
.stage-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.stage-time { font-size: .6875rem; opacity: .9; font-variant-numeric: tabular-nums; }
@media (max-width: 640px) { .stage-step { padding: .3rem .5rem; font-size: .6875rem; } }
