/* Segoe UI - Microsoft's own UI font (pre-installed on Windows, matched by
   San Francisco/Roboto's own metrics closely enough on Mac/Linux/mobile via
   this exact fallback stack) - no web font loaded, same as OWA itself never
   ships one. */
body {
    background-color: #faf9f8;
    font-family: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
}

.auth-body {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #004578, #0078D4);
}

.auth-card {
    background: #fff;
    padding: 2.5rem;
    border-radius: 0.75rem;
    box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.2);
    width: 100%;
    max-width: 400px;
}

/* Solid Microsoft-blue nav rail - the active item carries the weight via a
   lighter translucent fill + a white left bar, since the rail itself is no
   longer a neutral surface to contrast against. */
.portal-sidebar {
    width: 240px;
    min-height: 100vh;
    background: var(--portal-sidebar-bg, #003366);
    color: rgba(255, 255, 255, 0.9);
}

.portal-sidebar .nav-link {
    color: rgba(255, 255, 255, 0.85);
    border-radius: 0.25rem;
    border-left: 3px solid transparent;
}

.portal-sidebar .nav-link:hover {
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
}

.portal-sidebar .nav-link.active {
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
    border-left-color: #fff;
    font-weight: 600;
}

.portal-sidebar .nav-link[data-bs-toggle="collapse"] .bi-chevron-down {
    transition: transform 0.2s ease;
}

.portal-sidebar .nav-link[data-bs-toggle="collapse"]:not(.collapsed) .bi-chevron-down {
    transform: rotate(180deg);
}

.portal-sidebar .brand {
    color: #fff;
    font-weight: 600;
}

/* assets/img/admin_logo.svg is transparent/white already (reuses the same
   mark as the public website/emails - see that file's own doc comment), so
   it sits directly on the navy sidebar - no backdrop chip needed, unlike
   the old wesite2_logo.jpeg this replaced. */
.portal-sidebar .brand a {
    display: inline-block;
    padding: 0.3rem 0.5rem;
}
.portal-sidebar .brand img {
    height: 3rem;
    width: auto;
    display: block;
}

/* Mobile off-canvas drawer toggle - rendered once by includes/sidebar.php
   so every page gets it for free, rather than touching each page's own
   topbar markup individually. Hidden entirely above the mobile breakpoint. */
.sidebar-toggle-btn {
    display: none;
    position: fixed;
    top: 0.65rem;
    left: 0.65rem;
    z-index: 2050;
    width: 2.5rem;
    height: 2.5rem;
    align-items: center;
    justify-content: center;
    background: #fff;
    border: 1px solid #edebe9;
    border-radius: 0.375rem;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
    color: #201f1e;
    font-size: 1.1rem;
}
.sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.35);
    z-index: 1999;
}

@media (max-width: 767.98px) {
    .sidebar-toggle-btn {
        display: flex;
    }
    .portal-sidebar {
        position: fixed;
        top: 0;
        left: 0;
        height: 100vh;
        width: 82vw;
        max-width: 300px;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        box-shadow: 2px 0 16px rgba(0, 0, 0, 0.15);
        z-index: 2040;
    }
    .portal-sidebar.open {
        transform: translateX(0);
    }
    .sidebar-backdrop.show {
        display: block;
    }
    /* Clears the fixed toggle button every page's own topbar would
       otherwise sit under. */
    .portal-topbar {
        padding-left: 3.5rem !important;
        flex-wrap: wrap;
        row-gap: 0.5rem;
    }
}

/* Buttons - same classes used throughout the portal's CRUD pages, just
   re-themed via their own Bootstrap custom properties (no markup changes
   needed anywhere). Fluent/OWA buttons are only barely rounded, not pills. */
.btn-primary {
    --bs-btn-bg: var(--portal-primary, #0078D4);
    --bs-btn-border-color: var(--portal-primary, #0078D4);
    --bs-btn-hover-bg: #106ebe;
    --bs-btn-hover-border-color: #106ebe;
    --bs-btn-active-bg: #005a9e;
    --bs-btn-active-border-color: #005a9e;
    border-radius: 2px;
}
.btn-outline-primary {
    --bs-btn-color: var(--portal-primary, #0078D4);
    --bs-btn-border-color: var(--portal-primary, #0078D4);
    --bs-btn-hover-bg: var(--portal-primary, #0078D4);
    --bs-btn-hover-border-color: var(--portal-primary, #0078D4);
    border-radius: 2px;
}
.btn-outline-secondary, .btn-outline-danger, .btn-danger, .btn-sm {
    border-radius: 2px;
}
.text-primary {
    color: var(--portal-primary, #0078D4) !important;
}
.page-item.active .page-link {
    background-color: var(--portal-primary, #0078D4);
    border-color: var(--portal-primary, #0078D4);
}
.page-link {
    color: var(--portal-primary, #0078D4);
}

.portal-main {
    flex: 1;
    min-width: 0;
}

.portal-topbar {
    background: #fff;
    border-bottom: 1px solid #e5e7eb;
}

@media (max-width: 767.98px) {
    .portal-sidebar {
        width: 100%;
        min-height: auto;
    }
}

/* Actions dropdowns sit inside DataTables FixedColumns' pinned region, above
   pagination/info controls that would otherwise intercept clicks on the menu. */
.dropdown-menu {
    z-index: 3000;
}

/* Invoice row status colors. table-striped paints backgrounds on the <td>
   elements (via a CSS variable), not the <tr>, so target cells directly and
   use !important to reliably win over the zebra stripe on odd rows. */
#crud-table tr.row-status-partial > td {
    background-color: #fff3cd !important;
}
#crud-table tr.row-status-paid > td {
    background-color: #d1e7dd !important;
}
#crud-table tr.row-status-overdue > td {
    background-color: #f8d7da !important;
}
#crud-table tr.row-status-cancelled > td {
    background-color: #e2e3e5 !important;
    color: #6c757d;
}

/* Incoming Payments: not yet matched (ratified) against an invoice - same
   amber as a partially-paid invoice, since it also needs action. */
#crud-table tr.row-status-unmatched > td {
    background-color: #fff3cd !important;
}
/* Incoming Payments: ratified against an invoice - same green as 'paid'. */
#crud-table tr.row-status-matched > td {
    background-color: #d1e7dd !important;
}

/* Biller: soft-deleted (is_deleted=1 - see sql/add_biller_is_deleted.sql) -
   only ever visible at all with "Show deleted billers" checked, and takes
   priority over every other biller highlight below, see TableRegistry.php's
   own row_status_sql for 'biller'. */
#crud-table tr.row-status-deleted > td {
    background-color: #e2e3e5 !important;
    color: #6c757d;
    text-decoration: line-through;
}

/* Biller: an unreviewed application (or anything else staff flagged) -
   takes priority over the balance highlight below, see TableRegistry.php's
   own row_status_sql for 'biller'. */
#crud-table tr.row-status-needs-attention > td {
    background-color: #ffe5b4 !important;
}

/* Biller: highlight billers carrying a non-zero balance. */
#crud-table tr.row-status-balance > td {
    background-color: #fff3cd !important;
}

/* Participant: highlight participants with at least one active product assignment.
   CRM reuses this same "active" class for status_cd = 'Active' contacts. */
#crud-table tr.row-status-active > td {
    background-color: #f0fff0 !important;
}

/* CRM: status_cd = 'Inactive' contacts. */
#crud-table tr.row-status-inactive > td {
    background-color: #e2e3e5 !important;
    color: #6c757d;
}

/* Participant: app access locked (participant.disabled=1) - takes priority
   over the active/inactive billing status above, see TableRegistry.php's
   own row_status_sql for 'participant'. */
#crud-table tr.row-status-disabled > td {
    background-color: #f8d7da !important;
    color: #842029;
}

/* Contact Messages: status_cd = 'New' submissions, not yet actioned. */
#crud-table tr.row-status-new > td {
    background-color: #fff3cd !important;
}

/* Contact Messages: the whole row opens the message (see crud.js's own
   row click handler) - signal that with a pointer cursor and a hover tint,
   the same affordance an email inbox row gives. */
#crud-table tr.row-clickable {
    cursor: pointer;
}
#crud-table tr.row-clickable:hover > td {
    background-color: #f3f9fd !important;
}

/* Contact Messages: the email-client-style modal body (see
   includes/contact_message_modal.php) - the message itself reads like an
   open email, and the reply trail reads like quoted history underneath it. */
.contact-message-body {
    white-space: pre-wrap;
    line-height: 1.6;
}
.contact-message-trail {
    white-space: pre-wrap;
    line-height: 1.6;
    font-size: .9rem;
    color: #6c757d;
    background: #f8f9fa;
    border-left: 3px solid #c8c6c4;
    padding: .75rem 1rem;
    border-radius: 0 .375rem .375rem 0;
}

/* Contact Messages: the structured conversation thread (see
   sql/add_contact_message_reply_table.sql) - an inbound entry (the
   contact's own follow-up) reads like the quoted trail above it; an
   outbound entry (a staff reply) is tinted with the portal's own accent so
   the two directions are visually distinguishable at a glance. */
.contact-message-thread-entry {
    white-space: pre-wrap;
    line-height: 1.6;
    font-size: .9rem;
    padding: .75rem 1rem;
    border-radius: .375rem;
    margin-bottom: .5rem;
}
.contact-message-thread-entry.inbound {
    color: #6c757d;
    background: #f8f9fa;
    border-left: 3px solid #c8c6c4;
}
.contact-message-thread-entry.outbound {
    color: #004578;
    background: #deecf9;
    border-left: 3px solid var(--portal-primary, #0078D4);
}
.contact-message-thread-entry .thread-entry-meta {
    font-size: .75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    opacity: .7;
    margin-bottom: .25rem;
}

/* Messages (messages.php/assets/js/messages.js) - a real split-pane email
   client, replacing the old DataTables list + popup modal for this one
   table. Scoped to .messages-page-main (only used on this page) rather than
   changing the shared .portal-main rule above, which every other admin page
   still relies on scrolling normally (unbounded height). */
.messages-page-main {
    height: 100vh;
}
.messages-layout {
    display: flex;
    min-height: 0;
}
.messages-list-pane {
    width: 320px;
    flex-shrink: 0;
    border-right: 1px solid #e5e7eb;
    background: #fff;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.messages-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}
.messages-reading-pane {
    flex: 1;
    min-width: 0;
    background: #fff;
    overflow-y: auto;
}

.message-row {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    padding: .65rem .75rem;
    border-bottom: 1px solid #f1eee6;
    cursor: pointer;
}
.message-row:hover {
    background: #f3f2f1;
}
.message-row.selected {
    background: #deecf9;
    border-left: 3px solid var(--portal-primary, #0078D4);
    padding-left: calc(.75rem - 3px);
}
.message-row.unread .message-row-sender {
    font-weight: 700;
    color: #201f1e;
}
.message-row.unread {
    background: #f8fafd;
}
.message-row-check {
    margin-top: .3rem;
    flex-shrink: 0;
}
.message-row-avatar {
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: var(--portal-primary, #0078D4);
    color: #fff;
    font-size: .75rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.message-row-main {
    min-width: 0;
    flex: 1;
}
.message-row-top {
    display: flex;
    justify-content: space-between;
    gap: .5rem;
}
.message-row-sender {
    font-size: .9rem;
    color: #374151;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.message-row-time {
    font-size: .75rem;
    color: #9ca3af;
    flex-shrink: 0;
}
.message-row-subject {
    font-size: .8rem;
    font-weight: 600;
    color: #4b5563;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.message-row-preview {
    font-size: .8rem;
    color: #6b7280;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.message-row-status {
    font-size: .65rem;
    margin-top: .25rem;
}

/* Hidden on desktop - crud.js/messages.js (both) toggle it in only below the
   mobile breakpoint, where the list and reading pane are never shown side
   by side (see the media query below), so there's always a way back. */
.messages-back-btn {
    display: none;
}

@media (max-width: 767.98px) {
    .messages-layout {
        flex-direction: column;
    }
    .messages-list-pane {
        width: 100%;
    }
    .messages-reading-pane {
        display: none;
        width: 100%;
    }
    /* Toggled by messages.js on selecting/clearing a message - only one of
       the two panes is ever visible at a time on a phone-width screen,
       matching how every mobile email client already does this. */
    .messages-layout.showing-detail .messages-list-pane {
        display: none;
    }
    .messages-layout.showing-detail .messages-reading-pane {
        display: block;
    }
    .messages-back-btn {
        display: inline-block;
    }
}

/* General list/toolbar wrapping - a filter+button bar that's a plain
   d-flex (e.g. htdocs/index.php's own toolbar row) overflows/clips at
   phone width otherwise; Bootstrap's own flex-wrap utility classes cover
   the rest where markup already uses them. */
@media (max-width: 575.98px) {
    .d-flex.justify-content-between.align-items-center.gap-2.mb-3 {
        flex-wrap: wrap;
        row-gap: 0.5rem;
    }
}
