html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

.login-page {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background-color: #f5f5f5;
}

.login-card {
    width: 100%;
    max-width: 360px;
    padding: 2rem;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 12px rgba(0,0,0,0.1);
}

.login-card h1 {
    font-size: 1.5rem;
    margin-bottom: 1.5rem;
    text-align: center;
}

.legal-page {
    width: 100%;
    max-width: 760px;
    padding: 2rem;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 12px rgba(0,0,0,0.1);
    line-height: 1.6;
}

.legal-page h2 {
    font-size: 1.15rem;
    margin-top: 1.75rem;
}

.login-logo {
    display: block;
    max-width: 100%;
    height: auto;
    margin: 0 auto 1.5rem;
}

/* Reusable "show/hide password" toggle - wrap a password <input> (or SfTextBox root)
   in .password-field, add a .password-toggle button inside it. Works for both plain
   HTML inputs and Syncfusion's rendered markup since it just targets input padding/position. */
.password-field {
    position: relative;
}

    .password-field input,
    .password-field .e-input-group {
        padding-right: 2.5rem;
    }

.password-toggle {
    position: absolute;
    top: 50%;
    right: 0.5rem;
    transform: translateY(-50%);
    background: none;
    border: none;
    padding: 0.25rem;
    color: #6c757d;
    cursor: pointer;
    line-height: 1;
    z-index: 2;
}

    .password-toggle:hover {
        color: #343a40;
    }

.detail-panel {
    border: 1px solid #dee2e6;
    border-radius: 4px;
    margin-bottom: 1rem;
    background: #fff;
}

.detail-panel-header {
    background: #f1f3f5;
    padding: 0.5rem 0.75rem;
    font-weight: 600;
    font-size: 0.85rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #495057;
    display: flex;
    align-items: center;
    user-select: none;
}

.detail-panel-header-text {
    cursor: pointer;
}

.detail-panel-chevron {
    margin-left: auto;
    cursor: pointer;
    transition: transform 0.15s ease;
}

.detail-panel-mobile-hint {
    font-size: 0.75rem;
    color: #adb5bd;
    margin-left: 0.15rem;
}

.detail-panel-chevron.expanded {
    transform: rotate(180deg);
}

.detail-panel-body {
    padding: 0.75rem;
}

/* Panels with no required fields (CollapsiblePanel NoRequiredFields="true") default to
   collapsed on a narrow/phone viewport - so the detail screen doesn't feel overwhelming there -
   and expanded on a wider one, matching how every other panel already behaves on desktop. Pure
   CSS, no JS/interop: it reacts live to browser resize, and ".toggled" (added by the header's
   click handler) always flips whichever default the current viewport would otherwise apply. */
.detail-panel-body.optional.toggled {
    display: none;
}

@media (max-width: 768px) {
    .detail-panel-body.optional {
        display: none;
    }

    .detail-panel-body.optional.toggled {
        display: block;
    }
}

/* MobileTabSelector.razor - the phone-sized single-line "List: [dropdown]" replacement for the
   entity detail pages' real SfTab header (which wraps to several rows on a narrow viewport,
   pushing the actual form fields below the fold). Same pure-CSS, no-JS-interop pattern and same
   768px breakpoint as CollapsiblePanel above - hidden by default, shown only on phone, with the
   real .e-tab-header doing the opposite so exactly one of the two is ever visible. */
.mobile-tab-selector {
    display: none;
}

@media (max-width: 768px) {
    .mobile-tab-selector {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        padding: 0.5rem 0.75rem;
    }

    .mobile-tab-selector-label {
        margin: 0;
        font-weight: 600;
        white-space: nowrap;
    }

    .mobile-tab-selector select {
        flex: 1;
    }

    .e-tab .e-tab-header {
        display: none !important;
    }
}

/* Syncfusion's Tab component sometimes fails to detect header overflow (its own
   scroll-nav arrows never get injected), leaving .e-tab-header at its default
   overflow-x: hidden and silently clipping tabs past the visible width with no
   way to reach them. Force native browser scrolling as a reliable fallback. */
.e-tab .e-tab-header {
    overflow-x: auto !important;
}

/* Tab content (button rows, grids, etc.) rendered flush against the tab strip's
   bottom border with zero breathing room - Syncfusion's theme ships no top padding
   on .e-content .e-item by default. One global rule covers every SfTab-based
   detail page instead of a per-sub-tab-component fix. */
.e-tab .e-content .e-item {
    padding-top: 1rem;
}

.detail-map {
    width: 100%;
    height: 220px;
    border: 0;
    border-radius: 4px;
    margin-top: 0.5rem;
}

a, .btn-link {
    color: #006bb7;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.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 #258cfb;
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.page-title {
    font-size: 1.5rem;
    font-weight: 700;
    margin-bottom: 1rem;
}

/* Toolbar icon-button color treatment ("Option C" - tinted icon chip, white button), trial on
   the Leads page first. Semantic per action, not decorative: purple = print, green = Excel/
   export, pink = map/location. */
/* The button itself becomes the flex container - aligning the chip against the text via
   vertical-align is fragile (depends on exact font metrics); flex + align-items:center is not. */
.e-btn:has(.icon-chip) {
    display: inline-flex !important;
    align-items: center;
}
.icon-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 6px;
    margin-right: 0.45rem;
    flex-shrink: 0;
}
.icon-chip i {
    font-size: 0.78rem;
    line-height: 1;
}

.chip-purple { background-color: #f1e9fb; }
.chip-purple i { color: #6f42c1; }

/* Trial: same light-green tint on every toolbar button, not just the icon ones, to see the
   uniform effect. */
.btn-tint-green-all.e-btn { background-color: #e3f6e9 !important; border-color: #c8ecd4 !important; color: #14532d !important; }
.btn-tint-green-all.e-btn:hover { background-color: #d2f0dc !important; }

.chip-green { background-color: #e3f6e9; }
.chip-green i { color: #1e7e34; }

/* Icon-only "+" create/add buttons - a real circle, matching the nav-profile-avatar badge shape
   (NavMenu.razor.css) rather than Syncfusion's default rounded-rect. */
.btn-circle-add.e-btn {
    width: 2rem;
    height: 2rem;
    min-width: 2rem;
    padding: 0 !important;
    border-radius: 50% !important;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

/* Sub-item grid toolbars (Proposals/Notes/Attachments/etc. inside an entity's edit dialog) end
   their button row with this "+" as the last flex item, so on a narrow viewport where the row
   wraps, it drops to a new line at the far left instead of staying grouped with the other
   toolbar buttons. Moving it to the front keeps it consistently placed on both desktop and
   mobile - scoped to this specific toolbar shape (d-flex gap-2 flex-wrap mb-2) only, not
   .btn-circle-add generally, since the top-level entity pages (Companies, Projects, etc.) use
   the same button class in their own page-title row, where reordering would push it in front
   of the heading text instead. */
.d-flex.gap-2.flex-wrap.mb-2 > .btn-circle-add.e-btn {
    order: -1;
}
.btn-circle-add.e-btn i { margin: 0; }

.chip-pink { background-color: #fbe6f0; }
.chip-pink i { color: #d63384; }

/* Global (unscoped) override for the "you are here" active state on a direct-link NavGroup
   header (My Tasks, Reference Admin) - NavGroup.razor.css's own scoped text-decoration:none
   and NavMenu.razor.css's a.active background/color don't reliably reach the <a> a <NavLink>
   component renders (its scope attribute doesn't propagate the same way a literal element's
   does), so the browser's default active-link underline was showing through. Global CSS has
   no scope-attribute matching requirement, so this wins regardless of that mechanism. */
.nav-group-header-main.active {
    text-decoration: none !important;
    background-color: rgba(13, 110, 253, 0.12);
    color: #0d6efd !important;
}

/* Small teal "directions" diamond badge next to a Project's Address field
   (ProjectEditForm.razor) - a rotated square gives the diamond shape, the
   icon inside is rotated back to stay upright. */
.directions-icon-link {
    display: inline-flex;
    vertical-align: middle;
    text-decoration: none;
}
.directions-icon-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    background-color: #00838f;
    border-radius: 3px;
    transform: rotate(45deg);
}
.directions-icon-badge i {
    display: inline-block;
    transform: rotate(-45deg);
    color: #fff;
    font-size: 9px;
}

/* Click-to-reveal distance/travel-time popover anchored under the directions
   icon (DirectionsButton.razor). */
.directions-button-wrap {
    position: relative;
    display: inline-flex;
}
.directions-popover {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 1000;
    margin-top: 4px;
    padding: 8px 10px;
    background-color: #fff;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    white-space: nowrap;
}

/* Small green "call" badge next to a phone number (CallButton.razor) - deliberately the same
   16px badge geometry as the directions diamond above, but left square and tinted green so the
   two actions read as siblings without being mistaken for each other at a glance. */
.call-icon-link {
    display: inline-flex;
    vertical-align: middle;
    text-decoration: none;
}
.call-icon-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    background-color: #198754;
    border-radius: 3px;
}
.call-icon-badge i {
    color: #fff;
    font-size: 9px;
}

/* Click-to-reveal call-status popover anchored under the call icon (CallButton.razor) - same
   anchoring and shape as .directions-popover, but allowed to wrap: a failure message here is a
   full sentence ("Add your own mobile number..."), not a short distance string. */
.call-button-wrap {
    position: relative;
    display: inline-flex;
}
.call-popover {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 1000;
    margin-top: 4px;
    padding: 8px 10px;
    background-color: #fff;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    max-width: 260px;
}

.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;
}

/* Global (non-scoped) override - the component-scoped .nav-group-header rule in
   NavGroup.razor.css wasn't taking effect on this specific NavLink for reasons
   that resisted diagnosis without live DOM access, so this bypasses component
   CSS isolation entirely by targeting the link directly. */
a[href="reference-admin"] {
    color: #343a40 !important;
    text-decoration: none !important;
    font-weight: 500 !important;
}

/* Quick Print: a purpose-built read-only "Label | Value" view (not the live
   interactive form), so a Print button just needs CssClass="no-print" calling
   JS.InvokeVoidAsync("print"). The container-freeing rules below still matter
   because the print view renders inside the same Syncfusion Dialog/Tab, whose
   own fixed-height/overflow would otherwise clip it to one screenful. */
.quick-print-title {
    text-align: center;
}

.quick-print-table {
    width: 100%;
    border-collapse: collapse;
}

.quick-print-table td {
    padding: 0.35rem 0.5rem;
    border-bottom: 1px solid #dee2e6;
    vertical-align: top;
}

.quick-print-label {
    font-weight: bold;
    width: 30%;
    white-space: nowrap;
}

.quick-print-footer {
    margin-top: 1rem;
    font-size: 0.85rem;
    color: #6c757d;
}

/* Maximize/restore toggle for SfDialog headers (matches the desktop app's dialog
   chrome). SfDialog has no built-in maximize, so HeaderTemplate replaces the title
   area and this sits to the left of Syncfusion's own close icon (.e-close-icon,
   ~2.5rem wide) rather than overlapping it. */
.dialog-header-with-maximize {
    width: 100%;
    padding-right: 2.5rem;
}

/* Entity edit dialogs (Project/Company/Person/Lead/Opportunity/Employee/Cost Database/Expense)
   put Cancel/Save in the header bar next to the title. On "Edit X" the title also carries the
   record's own name/description ("Edit Project - <name>"), which on a phone-width dialog leaves
   Cancel/Save squeezed to a sliver next to a long title. Same 768px breakpoint as
   MobileTabSelector/CollapsiblePanel above - stacks the title above a left-aligned Cancel/Save
   row instead of forcing them to share one line. "New X" titles are short and never hit this,
   so they just render the same two-row layout with plenty of room to spare. */
@media (max-width: 768px) {
    /* !important because Bootstrap 5's own .align-items-center utility class (also present on
       this element, for the desktop row layout) is itself !important by design - a normal
       declaration here, no matter how specific the selector, can never beat that. */
    .entity-dialog-header-titlebar {
        flex-direction: column;
        align-items: flex-start !important;
        gap: 0.5rem;
    }
}

.dialog-maximize-toggle {
    cursor: pointer;
    font-size: 1rem;
    opacity: 0.85;
    padding: 0 0.5rem;
}

.dialog-maximize-toggle:hover {
    opacity: 1;
}

.dialog-maximized.e-dialog {
    top: 0 !important;
    left: 0 !important;
    max-width: 100vw !important;
    max-height: 100vh !important;
    margin: 0 !important;
}

.dialog-maximized .e-dlg-content {
    max-height: calc(100vh - 100px);
    overflow-y: auto;
}

@media print {
    .sidebar, .top-row, .no-print, .e-dlg-header-content, .e-close-icon, .e-tab-header {
        display: none !important;
    }

    .e-dialog {
        position: static !important;
        box-shadow: none !important;
        width: 100% !important;
        height: auto !important;
        max-width: none !important;
    }

    .e-dlg-content,
    .e-tab .e-content,
    .e-tab .e-content .e-item,
    .e-tab .e-content .e-item.e-active {
        overflow: visible !important;
        height: auto !important;
        max-height: none !important;
    }
}
.copyright-footer {
    text-align: center;
    font-size: 0.8rem;
    color: #6c757d;
    padding: 1rem 0 0.5rem;
}

/* ---------------------------------------------------------------------------------------------
   Grid toolbars on a phone: icons only.

   Every grid carries the same row of actions - Show/Hide Filters, Advanced Filter, Print List,
   Excel Export, Choose Columns, Reset Columns, and on some grids Map or Kanban View. With their
   labels that row is far wider than a phone screen, so it wraps into four or five stacked lines
   and pushes the actual grid off the bottom. The icons alone fit on one line.

   Done here rather than in eighty-four razor files: they all share .btn-tint-green-all, and the
   labels are bare text nodes next to the <i>, which cannot be targeted individually by CSS. So
   the button's font-size goes to zero - which collapses any text inside it, wrapped or not - and
   the icon gets its size back explicitly. One rule, every grid, nothing to keep in sync.

   Buttons carry a title attribute, so a long-press still says what each one does.
   --------------------------------------------------------------------------------------------- */
@media (max-width: 576px) {
    .btn-tint-green-all.e-btn {
        font-size: 0;
        padding-left: 0.6rem;
        padding-right: 0.6rem;
    }

    .btn-tint-green-all.e-btn i {
        font-size: 1rem;
        margin-right: 0 !important;
    }

    /* The toolbar itself can breathe a little tighter once the labels are gone. */
    .btn-tint-green-all.e-btn + .btn-tint-green-all.e-btn {
        margin-left: 0.25rem;
    }
}

/* ---------------------------------------------------------------------------------------------
   Banded grid rows, when a site asks for them (Site Settings -> "Use alternating grid row colour").

   The grids already mark every second row with .e-altrow - Syncfusion does that by default. What
   was missing is any colour: the bootstrap5 theme styles .e-altrow in exactly one place, inside a
   multicolumn dropdown popup, and leaves grid rows alone. Bootstrap 5's own tables are unstriped
   by default and the theme follows it, so every row came out white.

   So this is the paint, switched on by a class on the page shell rather than a property set on
   eighty-four grids.

   A very light green, picked to sit with the green-tinted toolbar buttons (btn-tint-green-all,
   #e3f6e9) rather than introduce a second accent. Deliberately far lighter than those buttons:
   this is behind every second row of a dense grid all day, so it has to be noticeable on a wide
   row and invisible the rest of the time. It must also never fight the hover highlight, which is
   what actually tells you where the pointer is.
   --------------------------------------------------------------------------------------------- */
.alt-rows .e-grid .e-row.e-altrow > .e-rowcell,
.alt-rows .e-grid .e-altrow > .e-rowcell {
    background-color: #f4fbf6;
}

/* Hover has to win, or the banding swallows it. */
.alt-rows .e-grid .e-row.e-altrow:hover > .e-rowcell {
    background-color: #e8f4ec;
}

/* Selection is Syncfusion's own colour and must come through untouched. */
.alt-rows .e-grid .e-row.e-altrow > .e-rowcell.e-selectionbackground,
.alt-rows .e-grid .e-altrow.e-active > .e-rowcell {
    background-color: inherit;
}

@media print {
    /* On paper there is no hover at all, which is where banding earns its keep - it becomes the
       only thing helping the eye stay on one row across a wide printed list. A shade stronger,
       because print washes very light tints out, and print-color-adjust because browsers drop
       background colours when printing unless told not to. */
    .alt-rows .e-grid .e-row.e-altrow > .e-rowcell,
    .alt-rows .e-grid .e-altrow > .e-rowcell {
        background-color: #e9f5ed !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
}

/* Build info strip - Site 1 only. Deliberately quiet: it is for whoever is debugging
   which environment they are actually looking at, not something to read every day. */
.build-info-footer {
    text-align: center;
    font-size: 0.72rem;
    color: #8a8279;
    padding: 2px 12px 10px;
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    word-break: break-word;
}
.build-info-footer .bi-sep { opacity: 0.45; margin: 0 5px; }
.build-info-footer .bi-env { font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.build-info-footer .bi-db { color: #6b655d; }
.build-info-footer a.bi-commit { color: #8a8279; text-decoration: underline dotted; }
.build-info-footer a.bi-commit:hover { color: #c8102e; }
