html, body {
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    margin: 0px;
    padding: 0px;
}
.page {
    padding: 0px;
}

:root, [data-bs-theme="light"] {
    --bs-success: #024230;
    --bs-success-rgb: 2, 66, 48;
}

[data-bs-theme="dark"] {
    --bs-success: #024230;
    --bs-success-rgb: 2, 66, 48;
}

/* Three-tier header hierarchy, darkest to lightest: the site menu (plain bg-success,
   solid brand green, same in both themes) > section/card headers (bg-header-tier-2) >
   table headings within a card (bg-header-tier-3 / .table-header).

   These used to be derived by blending the brand green with the page's own body
   background - bg-opacity-50 for tier 2, color-mix(..., var(--bs-body-bg)) for tier 3.
   That reliably LIGHTENS each tier in light mode (blending toward white), but blending
   the same dark green toward dark mode's near-black body background doesn't preserve
   the same darkest-to-lightest ordering - it can come out reading as a different,
   oddly-saturated color rather than a clean step up in lightness, which is what broke
   here. Explicit, deliberately-chosen colors per theme avoid that entirely - each tier
   is simply defined, not computed from whatever background happens to be behind it. */
:root, [data-bs-theme="light"] {
    --header-tier-2: #81a198;
    --header-tier-3: #c0d0cb;
}

[data-bs-theme="dark"] {
    --header-tier-2: #0e5a41;
    --header-tier-3: #1b7355;
}

.bg-header-tier-2 {
    background-color: var(--header-tier-2) !important;
}

.bg-header-tier-3 {
    /* --bs-table-bg: Bootstrap 5's own table rules give every <th>/<td> an explicit
       background-color: var(--bs-table-bg) (not "transparent" - noticeable mainly in dark mode,
       where that resolves to the page's near-black default rather than "whatever's behind it").
       A cell always paints its OWN background over an ancestor's, so setting background-color
       !important here on <thead> (below) was never reaching any <th> inside it - only visible on
       a literal <table>'s header (e.g. every Admin/*.aspx list), not on .table-header's own
       div-row headers (Pages/MessageBoardForum.aspx and friends), which have no such per-cell
       override to fight. Setting this custom property here instead lets it inherit normally down
       to each <th>, which already reads it for its own background - no !important fight needed. */
    --bs-table-bg: var(--header-tier-3);
    background-color: var(--header-tier-3) !important;
}



.font-size-xs {
    font-size: clamp(.6rem, 3vw, 1rem);
}

.font-size-small {
    font-size: clamp(.5rem, 3vw, .85rem);
}


.icon-filled {
    font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}


/* Disable hover, focus, and click color changes */
.list-group-item-action.no-hover:hover,
.list-group-item-action.no-hover:focus,
.list-group-item-action.no-hover:active {
    background-color: transparent;
    color: inherit;
    border-color: inherit; /* Optional: prevents border highlight changes */
}



.sitemenu-large-menu {
    /*--bs-dropdown-link-color: var(--bs-secondary-color) !important;*/ /* Text color */
    /*--bs-dropdown-link-hover-color: #000;*/ /* Text color on hover */
    /*--bs-dropdown-link-hover-bg: #678D82;*/ /* Background on hover */
    /*--bs-dropdown-link-active-color: #000;*/ /* Text color on click */
    /*--bs-dropdown-link-active-bg: #678D82;*/ /* Background on click */
}


.hover-bg-light:hover {
    /*background-color: #f8f9fa !important;*/ /* Bootstrap's 'light' gray */
    /*transition: background-color 0.2s ease-in-out;*/
}


.btn-breadcrumb .btn {
    /* Create the arrow shape using clip-path */
    clip-path: polygon( calc(100% - 15px) 0%, 100% 50%, calc(100% - 15px) 100%, 0% 100%, 15px 50%, 0% 0% );
    padding-left: 25px; /* Space for the inward notch */
    padding-right: 25px; /* Space for the outward point */
    border: none; /* Borders look messy with clip-path */
    margin-right: -10px; /* Overlap the buttons to close the gap */
}

/* Fix the first button (no notch on the left) */
.btn-breadcrumb .btn:first-child {
    clip-path: polygon( calc(100% - 15px) 0%, 100% 50%, calc(100% - 15px) 100%, 0% 100%, 0% 0% );
    padding-left: 15px;
}

/* Fix the last button (no point on the right) */
.btn-breadcrumb .btn:last-child {
    clip-path: polygon( 100% 0%, 100% 100%, 0% 100%, 15px 50%, 0% 0% );
}



.table-header {
    z-index: 500 !important;
    background-color: var(--header-tier-3);
}






/* Hover effect for the quote headers */
/*.quote-header:hover {
    background-color: #e9ecef !important;*/ /* Slightly darker than bg-light */
    /*color: #495057 !important;
}*/

/* Base rotation icon style */
/*.rotate-icon {
    display: inline-block;
    transition: transform 0.3s ease;
    transform: rotate(0deg);
    user-select: none;
}*/

/* Rotate icon to point right when collapsed */
/*.quote-header.collapsed .rotate-icon {
    transform: rotate(-90deg);
}*/


/* Hover effect for the quote headers (Light Mode Default) */
.quote-header:hover {
    background-color: #e9ecef !important;
    color: #495057 !important;
}

/* Hover effect for the quote headers (Dark Mode Override) */
[data-bs-theme="dark"] .quote-header:hover {
    background-color: #343a40 !important; /* Muted dark gray */
    color: #f8f9fa !important; /* Off-white text */
}

/* Base rotation icon style */
.rotate-icon {
    display: inline-block;
    transition: transform 0.3s ease;
    transform: rotate(0deg);
    user-select: none;
}

/* Rotate icon to point right when collapsed */
.quote-header.collapsed .rotate-icon {
    transform: rotate(-90deg);
}








/* Container for the switch */
.form-switch-custom {
    display: inline-block;
    width: 40px;
    height: 20px;
    background-color: #ccc;
    border-radius: 20px;
    position: relative;
    cursor: pointer;
    vertical-align: middle;
    transition: background-color 0.2s;
    overflow: hidden; /* Keeps the invisible input contained */
}

    /* Make the hidden input the ACTUAL clickable area */
    .form-switch-custom input[type="checkbox"] {
        opacity: 0;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%; /* Spans full width of the toggle */
        height: 100%; /* Spans full height of the toggle */
        margin: 0;
        cursor: pointer;
        z-index: 2; /* Sits on top of the 'after' circle */
    }

    /* The toggle circle */
    .form-switch-custom::after {
        content: '';
        position: absolute;
        width: 16px;
        height: 16px;
        border-radius: 50%;
        background-color: white;
        top: 2px;
        left: 2px;
        transition: transform 0.2s;
        z-index: 1;
    }

    /* On state - Background */
    .form-switch-custom:has(input:checked) {
        background-color: #0d6efd;
    }

    /* On state - Circle move */
    .form-switch-custom:has(input:checked)::after {
        transform: translateX(20px);
    }






/* Hide the actual radio button circle */
.avatar-radio-list input[type="radio"] {
    display: none;
}

/* Style the label (which holds our image) */
.avatar-radio-list label {
    cursor: pointer;
    margin: 10px;
    display: inline-block;
    border: 3px solid transparent; /* Placeholder for the highlight */
    padding: 2px;
}

    /* Hover effect */
    .avatar-radio-list label:hover {
        background-color: #f8f9fa;
    }

/* THE HIGHLIGHT: When the hidden radio is checked, style the adjacent label */
.avatar-radio-list input[type="radio"]:checked + label {
    border-color: #0d6efd; /* Bootstrap Primary Blue */
}

/* Ensure images fit well */
.avatar-radio-list img {
    width: 80px;
    height: 80px;
    object-fit: cover;
    display: block;
}





/* 1. Remove spacing and manage overlap */
.nav-tabs .nav-item {
    margin-bottom: -1px;
}

.nav-tabs .nav-link {
    background-color: #6C757D;
    color: #fff;
    border: 1px solid #dee2e6;
    margin-right: -1px;
    /* Restore top rounded corners */
    border-top-left-radius: 0.6rem;
    border-top-right-radius: 0.6rem;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}

    /* 2. Selected tab: White and Black */
    .nav-tabs .nav-link.active {
        background-color: #fff !important;
        color: #000 !important;
        border-bottom-color: transparent;
        z-index: 1; /* Ensures active tab sits "above" the neighbors */
        font-weight: bold;
    }

/* 3. Clean up the last tab */
.nav-tabs .nav-item:last-child .nav-link {
    margin-right: 0;
}

/* Dark mode tabs: the mirror of light mode's - inactive tabs are DARKER than the page, the selected tab is filled with the page's
   own background (so it reads as one piece with the form below, the way the white tab does in light mode) and has light text. */
[data-bs-theme="dark"] .nav-tabs .nav-link {
    background-color: #14171a;
    color: #adb5bd;
    border-color: var(--bs-border-color);
}

[data-bs-theme="dark"] .nav-tabs .nav-link:hover:not(.active) {
    background-color: #1b1f23;
    color: #fff;
}

[data-bs-theme="dark"] .nav-tabs .nav-link.active {
    background-color: var(--bs-body-bg) !important;
    color: #fff !important;
    border-color: var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg);
}

.material-symbols-outlined {
    vertical-align: middle;
    line-height: 1;
}

/* ============================================================
   Private Messages - Outlook-style layout (Pages/PrivateMessages.aspx,
   Pages/PrivateMessageThread.aspx, Controls/PrivateMessageFolderNav.ascx).

   .pm-shell is a CSS Grid holding two regions - the grouped conversation
   list (.pm-list-slot) and the reading pane (.pm-content-pane) - sitting
   side by side on a "large" screen, or stacked (list, then pane) on a
   "small" one. There used to be a third region (folder nav tabs) and
   several more moving parts here (per-folder mobile accordion layouts,
   a sticky nav strip) - removed once a data migration script properly
   threaded dbo.PrivateMessage, which made the whole Inbox/Sent/Deleted
   folder split unnecessary (see Documentation/PrivateMessages.md's
   "Threaded messages, no more folders" section).

   "Large" here is deliberately NOT Bootstrap's own plain `lg` breakpoint
   (min-width: 992px, monotonic - lg and everything above it) - this
   page sits inside the site's own layout, which adds side rail(s) that
   eat into the actual available content-column width starting at `lg`
   specifically, so a raw `lg`-and-up viewport doesn't actually have `lg`
   worth of width left for this two-column layout to use. Every
   breakpoint below therefore uses two explicit, non-monotonic bundles
   instead of a single min-width/max-width split:

   - PM "small" (stacked, single column): xs, sm, AND lg
     -> (max-width: 767.98px), (min-width: 992px) and (max-width: 1199.98px)
   - PM "large" (two-column): md, xl, AND xxl
     -> (min-width: 768px) and (max-width: 991.98px), (min-width: 1200px)

   md counts as "large" because the side rail(s) haven't appeared yet
   there, so the content column still has the full viewport width to
   itself; xl/xxl count as "large" again because the viewport is wide
   enough there to comfortably fit both the side rail(s) AND this
   two-column layout. There's no single CSS custom-media equivalent in
   plain CSS (no preprocessor is used in this file), so both bundles are
   repeated verbatim at each of the several places below that need them,
   rather than defined once - keep them in sync with each other and with
   this comment if either one ever needs to change. Bootstrap's own
   responsive utility classes (`d-lg-*`, `d-none d-lg-flex`, etc.) can't
   express this non-monotonic pattern at all, so markup in this feature
   uses purpose-built classes with these bundles baked in instead,
   wherever visibility needs to follow "PM small" vs "PM large" (e.g.
   `.pm-content-empty`, `.pm-mobile-new-message`) rather than reaching
   for those utilities directly.
   ============================================================ */

.pm-shell {
    display: grid;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.375rem;
    background-color: var(--bs-body-bg);
    /* Loading a message can resize .pm-shell itself (e.g. a long message growing past a short
       topic list's own height) - opts the whole widget out of being used as a CSS Scroll
       Anchoring reference point for that resize, on top of .pm-content-pane's own
       overflow-anchor: none below. Belt-and-suspenders alongside the JS in
       Controls/PrivateMessageFolderNav.ascx's settleScrollPosition(), which corrects the page's
       scroll position directly after render regardless of what caused any mismatch. */
    overflow-anchor: none;
}

/* On a PM "small" screen, opened (via JS) once a message has actually been loaded into the
   reading pane - hides the topic list so the message takes the full screen, per the "drill down"
   ask. Its counterpart, the reading pane's own "Back to Messages" link, is a REAL navigation link
   (not a JS toggle back) - a fresh page load already starts back in the normal list view, so there
   is nothing to reverse in JS. */
@media (max-width: 767.98px), (min-width: 992px) and (max-width: 1199.98px) {
    .pm-shell.pm-mobile-reading {
        display: block;
    }

    .pm-shell.pm-mobile-reading .pm-list-slot {
        display: none;
    }

    .pm-shell.pm-mobile-reading .pm-content-pane {
        display: block;
    }
}

/* Pages/PrivateMessageThread.aspx hides the list entirely on a PM "small" screen, so it shows
   only its reading pane there. */
.pm-list-hidden-mobile {
    display: none;
}

@media (min-width: 768px) and (max-width: 991.98px), (min-width: 1200px) {
    .pm-list-hidden-mobile {
        display: block;
    }
}

@media (max-width: 767.98px), (min-width: 992px) and (max-width: 1199.98px) {
    .pm-shell {
        grid-template-columns: 1fr;
        grid-template-areas: "list" "content";
    }
}

@media (min-width: 768px) and (max-width: 991.98px), (min-width: 1200px) {
    .pm-shell {
        grid-template-columns: minmax(260px, 340px) 1fr;
        grid-template-areas: "list content";
        min-height: 32rem;
    }
}

.pm-list-slot {
    grid-area: list;
    border-right: 1px solid var(--bs-border-color);
    min-width: 0;
}

/* .pm-content-pane's own grid-area="content" slot, but a plain flex column rather than the pane
   itself directly - the reply editor (.pm-reply-slot, Pages/PrivateMessages.aspx and
   Pages/PrivateMessageThread.aspx each host their own real, always-in-the-DOM copy - see
   Documentation/PrivateMessages.md) sits right after the pane here, in normal block flow, not a
   separate grid row of its own - a second grid row ("list content" / "list reply", with "list"
   spanning both to keep it out from under the reply row) was tried first and reported back putting
   the reply editor "way down the page" behind a large empty gap, since a spanning grid item forces
   CSS Grid to distribute whatever extra row height it needs (here, the much-taller list) across
   every row it spans. Nesting instead of spanning sidesteps that entirely - .pm-list-slot and
   .pm-content-col are simple, non-spanning, single-row grid cells, so neither one's height has any
   bearing on the other's, and everything inside .pm-content-col (the pane, then the reply editor)
   just stacks at its own natural height. */
.pm-content-col {
    grid-area: content;
    display: flex;
    flex-direction: column;
    /* A grid item stretches to fill its whole row by default - as tall as the list column next to
       it, which would leave a large empty gap below a short thread+reply pair. */
    align-self: start;
    min-width: 0;
}

/* Matches .pm-content-pane's own padding (1rem on every side) so the reply editor lines up with
   the message thread above it - it's a sibling of .pm-content-pane, not nested inside it, so it
   doesn't inherit that padding automatically the way actual pane content does. */
.pm-reply-slot {
    min-width: 0;
    padding: 1rem;
}

@media (max-width: 767.98px), (min-width: 992px) and (max-width: 1199.98px) {
    .pm-list-slot {
        border-right: 0;
        border-top: 1px solid var(--bs-border-color);
        border-bottom: 1px solid var(--bs-border-color);
    }
}

/* PM-"small"-screen-only "New Message" entry point - a fixed-width flex item sharing
   .pm-search-box's own row with the search input (see that class below), not a separate row of
   its own - see Controls/PrivateMessageFolderNav.ascx's own markup comment on why. See that
   control's own ShowMobileNewMessageButton comment for why this exists separately from the pane's
   own PM-"large"-screen placeholder button. Visibility is baked in here (rather than a `d-lg-none`
   utility in the markup, which can't express this feature's own non-monotonic "small"/"large"
   bundles - see this file's own Private Messages section intro) so the markup only ever needs this
   one class. */
.pm-mobile-new-message {
    flex: 0 0 auto;
}

@media (min-width: 768px) and (max-width: 991.98px), (min-width: 1200px) {
    .pm-mobile-new-message {
        display: none;
    }
}

/* --- Search box (searches every conversation partner's topics at once, by partner name, subject,
   or message body) --- */
.pm-search-box {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.pm-search-input-wrap {
    position: relative;
    display: flex;
    align-items: center;
    /* Fills whatever width .pm-mobile-new-message (a fixed-width sibling when it's visible)
       doesn't take up, rather than the two splitting the row evenly or overflowing it. */
    flex: 1 1 auto;
    min-width: 0;
}

.pm-search-icon {
    position: absolute;
    left: 0.6rem;
    font-size: 1.1rem;
    color: var(--bs-secondary-color);
    pointer-events: none;
}

.pm-search-input {
    width: 100%;
    padding: 0.375rem 2rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.375rem;
    background-color: var(--bs-body-bg);
    color: var(--bs-body-color);
    font-size: 0.9rem;
}

.pm-search-input:focus {
    outline: 0;
    border-color: var(--bs-primary);
}

.pm-search-clear {
    position: absolute;
    right: 0.35rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: 0;
    color: var(--bs-secondary-color);
    cursor: pointer;
    padding: 0.15rem;
    line-height: 1;
}

.pm-search-clear:hover {
    color: var(--bs-body-color);
}

/* --- "To" type-ahead (Pages/PrivateMessageNew.aspx) - same debounced-search pattern as the
   message list's own search box above, styled to match, but without that box's icon/clear button
   (so no left/right icon-clearance padding is needed here). --- */
.pm-to-input {
    padding: 0.375rem 0.75rem;
}

#pmNewToSearchWrap {
    position: relative;
}

.pm-to-results {
    position: absolute;
    z-index: 20;
    left: 0;
    right: 0;
    margin-top: 0.25rem;
    max-height: 300px;
    overflow-y: auto;
    background-color: var(--bs-body-bg);
    border: 1px solid var(--bs-border-color);
    border-radius: 0.375rem;
    box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.15);
}

.pm-to-result-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0.75rem;
    cursor: pointer;
}

.pm-to-result-item:hover {
    background-color: var(--bs-tertiary-bg);
}

.pm-to-result-item + .pm-to-result-item {
    border-top: 1px solid var(--bs-border-color);
}

.pm-to-result-main {
    flex: 1 1 auto;
    min-width: 0;
}

.pm-to-result-name {
    overflow-wrap: break-word;
}

.pm-to-result-meta {
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
}

/* Once a recipient is chosen, this replaces the search box entirely (only one can ever be
   selected) - "Change" (the × button) clears it and brings the search box back. */
.pm-to-chip {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    border: 1px solid var(--bs-border-color);
    border-radius: 0.375rem;
    padding: 0.4rem 0.6rem;
}

.pm-to-chip-avatar {
    flex: 0 0 auto;
    display: flex;
}

.pm-to-chip-name {
    flex: 1 1 auto;
    font-weight: bold;
    overflow-wrap: break-word;
}

.pm-to-chip-remove {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: 0;
    color: var(--bs-secondary-color);
    cursor: pointer;
    padding: 0.15rem;
    line-height: 1;
}

.pm-to-chip-remove:hover {
    color: var(--bs-body-color);
}

/* --- Topic list --- */
.pm-topic-item {
    display: flex;
    align-items: stretch;
    border-bottom: 1px solid var(--bs-border-color);
}

.pm-topic-item.active {
    background-color: var(--bs-secondary-bg);
}

.pm-topic-link {
    flex: 1 1 auto;
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.6rem 0.75rem;
    color: inherit;
    text-decoration: none;
    min-width: 0;
}

.pm-topic-link:hover {
    background-color: var(--bs-tertiary-bg);
    color: inherit;
}

/* Top-right corner, not vertically centered like the conversation-partner row's own badge - this
   row's already flex-start-aligned (.pm-topic-link above), so overriding .pm-unread-badge's own
   align-self: center back to flex-start here is all this takes. */
.pm-topic-link > .pm-unread-badge {
    align-self: flex-start;
}

.pm-topic-avatar {
    flex: 0 0 auto;
}

.pm-topic-main {
    flex: 1 1 auto;
    min-width: 0;
}

/* Three stacked lines - full sender name, then subject, then date - rather than sharing a row
   (which was cramping the sender name down to a couple of characters before it ellipsized). */
.pm-topic-sender {
    overflow-wrap: break-word;
}

.pm-topic-subject {
    font-size: 0.9rem;
    color: var(--bs-secondary-color);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pm-topic-date {
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
    white-space: nowrap;
}

.pm-topic-item.pm-unread .pm-topic-sender,
.pm-topic-item.pm-unread .pm-topic-subject {
    font-weight: bold;
    color: var(--bs-body-color);
}

/* Red "New" pill, added as a plain flex-item sibling at the END of the row it belongs to
   (.pm-topic-link below, and .pm-user-group-header further down) rather than inline next to the
   bold text itself - sits in its own space at the row's right edge (before the expand caret on a
   conversation-partner row, top-right corner on a topic row - see the .pm-topic-link override right
   below, since that row's own align-items: flex-start is what actually puts it there). */
.pm-unread-badge {
    flex: 0 0 auto;
    align-self: center;
    display: inline-block;
    background-color: var(--bs-danger);
    color: #fff;
    font-size: 0.65rem;
    font-weight: bold;
    line-height: 1;
    padding: 0.2rem 0.5rem;
    border-radius: 999px;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* --- Grouped topic list (one accordion section per conversation partner) --- */
.pm-user-group {
    border-bottom: 1px solid var(--bs-border-color);
}

.pm-user-group-heading {
    /* This is an <h2> purely for accordion-header semantics (matches the pattern's usual markup) -
       without resetting the browser's default h2 font-size/font-weight/margin, that huge, bold
       styling was cascading down into .pm-user-group-header's own text (the button/spans inherit
       font-size unless something overrides it), not just this element itself. */
    margin: 0;
    font-size: 1rem;
    font-weight: normal;
}

.pm-user-group-header {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.6rem 0.75rem;
    background: none;
    border: 0;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.pm-user-group-header:hover {
    background-color: var(--bs-tertiary-bg);
}

.pm-user-group-info {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.pm-user-group-name {
    overflow-wrap: break-word;
}

.pm-user-group-header.pm-unread .pm-user-group-name {
    font-weight: bold;
}

.pm-user-group-meta {
    font-size: 0.8rem;
    color: var(--bs-secondary-color);
}

.pm-user-group-caret {
    flex: 0 0 auto;
    transition: transform 0.15s ease;
}

.pm-user-group-header[aria-expanded="true"] .pm-user-group-caret {
    transform: rotate(180deg);
}

.pm-user-group-body .pm-topic-item:first-child {
    border-top: 1px solid var(--bs-border-color);
}

.pm-user-group-body .pm-topic-item:last-child {
    border-bottom: 0;
}

/* A bit of extra indent so a group's own topics read as nested under its header, now that they
   have no avatar of their own (the group header's avatar already covers every topic inside it). */
.pm-user-group-body .pm-topic-link {
    padding-left: 1.75rem;
}

/* --- Reading pane --- */
.pm-content-pane {
    padding: 1rem;
    min-width: 0;
    /* Without this, loading a long message (replacing the short "Loading..." placeholder with a
       much taller thread) can trigger the browser's own CSS Scroll Anchoring - it tries to keep
       whatever's currently on screen from visually jumping when content off-screen resizes, by
       silently adjusting scrollTop, which here meant the page landed partway down the newly-tall
       pane instead of at its top. This element's own size changes are exactly what was tripping
       it, so it's opted out of being used as an anchor. */
    overflow-anchor: none;
}

/* A column now (was a single centered row) - .pm-content-empty-actions (the "New Message" button)
   sits in its own row at the top, and .pm-content-empty-body (the icon/placeholder text) is
   pushed down from center via its own top padding rather than sharing the empty row's center.
   Hidden by default, shown (as a flex column) only on a PM "large" screen - baked in here rather
   than a `d-none d-lg-flex` utility in the markup, which can't express this feature's own
   non-monotonic "small"/"large" bundles (see this file's own Private Messages section intro). On a
   PM "small" screen there's no room for this placeholder at all - the list takes the full page
   there instead, same as it always has. */
.pm-content-empty {
    display: none;
    flex-direction: column;
    align-items: stretch;
    color: var(--bs-secondary-color);
}

@media (min-width: 768px) and (max-width: 991.98px), (min-width: 1200px) {
    .pm-content-empty {
        display: flex;
    }
}

.pm-content-empty-actions {
    display: flex;
    justify-content: flex-end;
}

.pm-content-empty-body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    padding-top: 4rem;
}

.pm-empty-icon {
    font-size: 2.5rem;
    display: block;
}

.pm-thread-message {
    display: flex;
    gap: 0.75rem;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--bs-border-color);
}

.pm-thread-message:last-of-type {
    border-bottom: 0;
}

/* A more formal, card-style header bar for a loaded thread - see CSS/site.css's own three-tier
   header hierarchy comment (top of this file) for what "tier 3" means; used here because this bar
   sits inside a card-like pane rather than being a page/section header of its own (those get tier
   2, e.g. Admin/Users.aspx's own .card-header). Close is pinned to the header's own corner
   (position: absolute) rather than laid out as a flex sibling of the subject - a flex row (tried
   first) pushed Close down onto its own wrapped line, left-aligned, once a long subject wrapped
   past one line on a narrow screen, since justify-content/margin-left: auto only control alignment
   *within* whatever line an item ends up on, not which line it's on in the first place. The
   subject's own right padding here reserves the corner button's width so wrapped text never runs
   underneath it. */
.pm-thread-header {
    position: relative;
    /* Right padding reserves room for the corner-pinned Close button below - generously more than
       the button's own actual width needs (a first attempt at 3.25rem measured the button's width
       too tightly and still let wrapped subject text run right up against it), so there's a real,
       always-visible gap between wrapped text and the button regardless of exactly how wide it
       renders. */
    padding: 0.6rem 4.5rem 0.6rem 0.9rem;
    border-radius: 0.375rem;
    margin-bottom: 0.75rem;
}

.pm-thread-header h5 {
    margin: 0;
    overflow-wrap: break-word;
}

.pm-thread-close-btn {
    position: absolute;
    /* Vertically centered against the header's own actual height (top: 0.6rem alone pinned it
       near the top instead, which only matched a single-line subject - a wrapped, multi-line
       subject made the bar taller without moving the button down to match). */
    top: 50%;
    transform: translateY(-50%);
    right: 0.9rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: 1px solid currentColor;
    border-radius: 0.375rem;
    color: inherit;
    cursor: pointer;
    padding: 0.2rem 0.35rem;
    line-height: 1;
    opacity: 0.75;
    /* This class also backs a real <a> (Pages/PrivateMessageNew.aspx's own Close, which navigates
       rather than resetting the pane in place) alongside the AJAX pane's own <button> version -
       without this, the <a> version picked up the browser's default link underline under its icon. */
    text-decoration: none;
}

.pm-thread-close-btn:hover {
    opacity: 1;
    background-color: rgba(0, 0, 0, 0.08);
}

/* Private message thread pane: Reply and Close sit together in the header bar, both with the Close button's look (outlined in the
   header's text color, slightly faded, fading in with a light wash on hover). The pair is pinned to the header's right edge as a
   group - inside it the buttons are laid out normally rather than each being absolutely positioned. The header reserves extra
   right padding for the pair. Pages/PrivateMessageNew.aspx's lone Close keeps the original absolute positioning. */
.pm-thread-header-has-actions {
    padding-right: 9.5rem;
}

.pm-thread-header-actions {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    right: 0.9rem;
    display: flex;
    /* stretch, so the text-only Reply button is exactly as tall as the icon-sized Close button beside it (its label is centered inside) */
    align-items: stretch;
    gap: 0.4rem;
}

.pm-thread-header-actions .pm-thread-close-btn {
    position: static;
    transform: none;
}

.pm-thread-reply-btn {
    padding: 0.2rem 0.6rem;
    font-size: 0.875rem;
}
/* ==========================================================================
   Game status banner (Controls/GameStatusBanner.ascx) - site-wide sticky bar for "today's" game,
   added 2026-09-18. See Documentation/GameStatusBanner.md.
   ========================================================================== */

.gsb-banner {
    /* Moved from a fixed bar at the BOTTOM to the TOP of the page (2026-09-20): sticky, not fixed, and
       rendered first inside the master pages' <form> (before the site menu), so it takes up its own
       room at the top of the page instead of floating over content, then stays pinned to the top of
       the viewport as the page scrolls. Bootstrap's own sticky headers (.sticky-top) are pushed down
       to sit beneath it - see the body.gsb-banner-visible rules below. */
    position: sticky;
    top: 0;
    /* Above Bootstrap's own sticky headers (.sticky-top, 1020) but BELOW the offcanvas menu (1045),
       modals (1055) and Controls/PleaseWait.ascx's 1090 override - a passive score notice should never
       sit on top of the mobile menu or an in-progress action. */
    z-index: 1030;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.75rem;
    /* Dark green, exactly halfway between the site menu's brand green (#024230, --bs-success) and black:
       each RGB channel halved (2,66,48 -> 1,33,24). Hardcoded rather than a theme variable, same as the
       black it replaced, so it reads identically in light and dark mode. */
    background-color: #012118;
    color: #fff;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .25);
}

.gsb-content {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    flex: 1 1 auto;
    min-width: 0;
}

.gsb-team {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
}

/* Opponent side is score, name, logo in markup order (no row-reverse), so both scores sit right
   next to the status pill in the middle and both logos are on the outside edges. */

.gsb-logo {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
}

.gsb-logo img,
.gsb-logo .material-symbols-outlined {
    max-height: 28px;
}

.gsb-name {
    font-weight: bold;
    font-size: 0.85rem;
    /* Without this, the browser's default line-height (~1.2x the font size) gives this span's own
       flex-item box extra space below the text's actual glyphs (normal font ascent/descent
       allocation isn't symmetric around the visual center of the letters) - .gsb-team's own
       align-items: center then centers that whole taller box, which reads as the text itself
       sitting slightly above center next to the logo/score beside it. Pinning line-height to the
       text's own single line removes that mismatch. */
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 120px;
}

.gsb-score {
    font-weight: bold;
    font-size: 1.5rem;
    min-width: 1.75rem;
    text-align: center;
    /* The old number fades out over this; the new one then fades in via .gsb-score-in below. */
    transition: opacity 0.3s ease;
}

/* Score-change emphasis (Controls/GameStatusBanner.ascx's own script): when a poll notices a team's
   score changed, the current number gets .gsb-score-out (fades to nothing), the text is swapped, then
   .gsb-score-in fades the new number in - popped slightly larger and in amber, settling back to white
   - so a score change catches the eye of someone glancing at the bar rather than silently changing.
   Skipped entirely under prefers-reduced-motion (the script just swaps the text). */
.gsb-score-out {
    opacity: 0;
}

.gsb-score-in {
    animation: gsb-score-in 1.6s ease-out;
}

@keyframes gsb-score-in {
    0% {
        opacity: 0;
        color: #ffc107;
        transform: scale(1.4);
    }

    25% {
        opacity: 1;
        color: #ffc107;
        transform: scale(1.4);
    }

    100% {
        opacity: 1;
        color: #fff;
        transform: scale(1);
    }
}

.gsb-status {
    flex: 0 0 auto;
    font-size: 0.8rem;
    white-space: nowrap;
    background-color: rgba(255, 255, 255, 0.15);
    border-radius: 999px;
    padding: 0.15rem 0.6rem;
}

.gsb-close {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: 0;
    color: #fff;
    cursor: pointer;
    padding: 0.25rem;
}

.gsb-close:hover {
    opacity: 0.8;
}

/* While the banner is showing (class toggled on <body> by Controls/GameStatusBanner.ascx's own script,
   which also keeps --gsb-height set to the banner's actual rendered height): Bootstrap's sticky headers
   (.sticky-top - the message board / forum table headers) stick just BELOW the banner instead of
   sliding underneath it at top: 0. Pages that jump to an anchor also add --gsb-height to their own
   scroll-margin-top, so a target never lands hidden behind the banner. */
body.gsb-banner-visible .sticky-top {
    top: var(--gsb-height, 0px);
}

@media (max-width: 575.98px) {
    .gsb-name {
        max-width: 70px;
        font-size: 0.75rem;
    }

    .gsb-score {
        font-size: 1.15rem;
        min-width: 1.4rem;
    }

    .gsb-status {
        font-size: 0.7rem;
        padding: 0.1rem 0.4rem;
    }
}

/* ==========================================================================
   Schedule page - "#game_{id}" scroll/highlight target (Controls/ScheduleGame.ascx's own top-level
   id, Controls/Schedule.ascx's own <script> block), added 2026-09-18. See Documentation/Schedule.md.
   ========================================================================== */

/* Offsets the scroll position so the target row doesn't land directly under Controls/Schedule.ascx's
   own sticky column-header row (.table-header below) - an approximation of that header's typical
   rendered height (it can wrap to two lines on the narrowest screens), not measured exactly. */
[id^="game_"] {
    /* + the game status banner's own height when it's up (0 otherwise) - it now sits at the TOP. */
    scroll-margin-top: calc(70px + var(--gsb-height, 0px));
}

/* Negates Controls/Schedule.ascx's own .container-fluid ps-2/pe-2 padding (Bootstrap's spacing
   scale, 0.5rem each side) with an equal negative margin + matching padding of its own, so
   .schedule-game-highlight's flash can reach that container's own true left/right edge - the
   schedule table's own "section" - instead of stopping at its padded content box.
   Deliberately does NOT try to reach any further out than that (e.g. into
   Pages/Schedule.aspx's own surrounding .card-body padding) - a version that did was reported back
   as bleeding out past the table's own section into the page's outer whitespace ("this expanded out
   too much... it should fill up the inner section only"), which is a worse problem than the
   original small gap this is fixing. The extra 3px (added 2026-09-18, on top of the 0.5rem above) is
   a small, deliberately conservative nudge for a leftover 2-3px gap reported after that - most
   likely some fractional-pixel rounding among the several nested Bootstrap .card/.row layers this
   sits inside, nothing with one single clean source worth chasing further than this. */
.schedule-game-row {
    margin-left: calc(-0.5rem - 3px);
    margin-right: calc(-0.5rem - 3px);
    padding-left: calc(0.5rem + 3px);
    padding-right: calc(0.5rem + 3px);
}

.schedule-game-highlight {
    animation: schedule-game-highlight-flash 2.5s ease-out;
}

@keyframes schedule-game-highlight-flash {
    0% {
        background-color: rgba(255, 193, 7, .35);
    }

    100% {
        background-color: transparent;
    }
}

/* ==========================================================================
   GameScoreImage (Controls/GameScoreImage.ascx.vb) - the score-card graphic ArticleLeadin falls
   back to when an article has no photo but does have a ScheduleGameID. Light/dark theme support
   added 2026-09-19 - this used to be one hardcoded dark gradient (an inline style, not a class, so
   it couldn't respond to the site's own [data-bs-theme] toggle at all) with plain Bootstrap
   text-light/bg-light utilities for its text and "vs." divider lines, which only ever worked against
   that one dark background. Moving the gradient into a real class here is what makes a per-theme
   override possible in the first place; .game-score-image's own color/.game-score-image-divider's
   own background-color replace text-light/bg-light on every child element that used to hardcode
   white, so they follow the same light/dark switch instead of staying white (illegible against the
   new light-mode gray gradient) in both themes.
   ========================================================================== */

/* 2026-10-13: the gradient now runs DARK (top) to LIGHT (bottom), and Controls/ArticleLeadin.ascx's card header
   (.article-leadin-header) is filled with the gradient's darkest value (revised later the same day: dark end halved, light end = the card/page background so the card fades into the article), so the header flows down into the score
   card and on into the article. --gsi-dark/--gsi-light are the two ends per theme; --gsi-text is the text color
   that reads on the dark end (the header). */
:root {
    --gsi-dark: color-mix(in srgb, var(--bs-secondary) 25%, var(--bs-body-bg)); /* = bg-secondary bg-opacity-25 over the page background, as on the message board topic rows */
    --gsi-light: var(--bs-card-bg, var(--bs-body-bg));
    --gsi-text: #212529;
}

[data-bs-theme="dark"] {
    --gsi-dark: #242424;
    --gsi-light: var(--bs-card-bg, var(--bs-body-bg));
    --gsi-text: #ffffff;
}

.article-leadin-header {
    background-color: var(--gsi-dark);
    color: var(--gsi-text);
}

.article-leadin-header .article-leadin-subheadline {
    color: inherit;
    opacity: 0.7;
}

.article-leadin-header .article-leadin-date {
    /* the same gray as the month/year bands inside it (bg-secondary), not the header's text color (white in dark mode, black in light) */
    border-color: var(--bs-secondary) !important;
}

.game-score-image {
    background: linear-gradient(to bottom, var(--gsi-dark) 0%, var(--gsi-light) 100%);
    color: var(--bs-body-color);
}

.game-score-image-divider {
    background-color: #6c757d;
}

[data-bs-theme="dark"] .game-score-image-divider {
    background-color: #fff;
}

/* Controls/ArticleLeadin.ascx - "Photo By:" credit overlaid on the photo's own bottom-right corner,
   and the caption footer directly beneath it. The credit's own text color is picked per-photo,
   server-side (CommonUtil.GetPhotoCreditTextColor samples that corner's own brightness) and set
   inline, since it depends on the photo itself rather than the site's light/dark theme - only this
   class's position/padding belong here. The caption footer uses Bootstrap's own --bs-secondary-color
   variable so it still follows the theme switch without a hardcoded color of its own. */
.article-photo-credit {
    position: absolute;
    right: 0;
    bottom: 0;
    padding: .15rem .5rem;
    font-size: .75rem;
    font-style: italic;
}

.article-photo-caption {
    padding: .35rem .75rem;
    font-size: .8rem;
    font-style: italic;
    color: var(--bs-secondary-color);
}

/* ==========================================================================
   Message board poll results (Pages/MessageBoardTopic.aspx.vb's BuildPollOptionsHtml,
   Pages/MessageBoardTopic.aspx's renderPollResults()), added 2026-09-22. The viewer's own choice used
   plain Bootstrap bg-success/text-success at first, which is this site's brand green (--bs-success,
   #024230 - the same dark green in both themes, by design, see near the top of this file) - too dark
   to read against a dark background, and not especially green-looking even on a light one. These are
   dedicated colors instead, tuned for each theme rather than tied to the shared brand variable.
   ========================================================================== */
.poll-vote-bar {
    background-color: #1e8e5a;
}

.poll-vote-text {
    color: #1e8e5a;
}

[data-bs-theme="dark"] .poll-vote-bar {
    background-color: #3ddc84;
}

[data-bs-theme="dark"] .poll-vote-text {
    color: #3ddc84;
}

/* ==========================================================================
   Joined pager - "Previous | page dropdown | Next" (message board forum topic list, message board topic
   messages, article list - .pagination.pager-joined). One connected group: Previous/Next look like Bootstrap
   outlined secondary buttons (no link-blue text, solid secondary fill on hover) and the page dropdown sits
   between them with square corners. Only the group's two OUTER ends are rounded - Previous (or the dropdown
   when there is no Previous) on the left, Next (or the dropdown when there is no Next) on the right - which
   falls out of :first-child/:last-child, since a hidden Previous/Next isn't rendered at all.
   ========================================================================== */
.pager-joined {
    gap: 0;
}

.pager-joined > .page-item {
    padding-right: 0 !important;
}

/* No overlapping margins: a neighbor's border is simply dropped where two items meet (below), so each divider is exactly
   one 1px line - overlapping by -1px left a doubled line at fractional pixel positions. */
.pager-joined > .page-item:not(:empty) + .page-item > .page-link,
.pager-joined > .page-item:not(:empty) + .page-item > .form-select {
    border-left-width: 0;
}

.pager-joined .page-link,
.pager-joined .form-select {
    border: 1px solid var(--bs-secondary);
    border-radius: 0;
}

.pager-joined .page-link {
    /* Bootstrap pulls every non-first .page-link left by 1px to collapse borders; the shared-border rule above replaces that. */
    margin-left: 0;
    color: var(--bs-secondary);
    background-color: transparent;
}

.pager-joined .page-link:hover,
.pager-joined .page-link:focus {
    color: #fff;
    background-color: var(--bs-secondary);
    border-color: var(--bs-secondary);
}

.pager-joined > .page-item:first-child > .page-link,
.pager-joined > .page-item:first-child > .form-select {
    border-top-left-radius: var(--bs-border-radius);
    border-bottom-left-radius: var(--bs-border-radius);
}

.pager-joined > .page-item:last-child > .page-link,
.pager-joined > .page-item:last-child > .form-select {
    border-top-right-radius: var(--bs-border-radius);
    border-bottom-right-radius: var(--bs-border-radius);
}

/* A hidden Previous/Next is a server control that renders nothing, but its wrapping <li> is plain markup and stays
   behind EMPTY - so it still counts as the group's first/last child, and the :first-child/:last-child rules above never
   reach the dropdown. Hide the empty <li>s and round the dropdown's matching side explicitly instead. */
.pager-joined > .page-item:empty {
    display: none;
}

.pager-joined > .page-item:empty + .page-item > .form-select {
    border-top-left-radius: var(--bs-border-radius);
    border-bottom-left-radius: var(--bs-border-radius);
}

.pager-joined > .page-item:has(+ .page-item:empty) > .form-select {
    border-top-right-radius: var(--bs-border-radius);
    border-bottom-right-radius: var(--bs-border-radius);
}

/* Message board topic page - post header row (Pages/MessageBoardTopic.aspx). With the small avatar beside the name (below
   md, and lg up to xl) it is a grid: avatar on the left spanning two rows, the name and Admin/Edit buttons on the first row,
   and "Posted: date time" on the second row beneath them - on one line, never wrapped. With the side avatar column (md up
   to lg, and xl+) it is a plain flex row with Posted beside the buttons. Breakpoints match the d-md-none/d-lg-block/
   d-xl-none classes on the avatar and name. */
.mb-post-header {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
}

.mb-post-avatar {
    grid-column: 1;
    grid-row: 1 / span 2;
    align-self: start;
}

.mb-post-name {
    grid-column: 2;
    grid-row: 1;
    min-width: 0;
}

.mb-post-buttons {
    grid-column: 3;
    grid-row: 1;
    /* stays at the top of the row when a long poster name wraps to two lines */
    align-self: start;
}

.mb-post-meta {
    grid-column: 2 / span 2;
    grid-row: 2;
}

@media (min-width: 768px) and (max-width: 991.98px), (min-width: 1200px) {
    .mb-post-header {
        display: flex;
        align-items: flex-start;
    }

    .mb-post-meta {
        flex: 1 1 0;
        min-width: 0;
    }
}

/* Message board forum topic list - the little "Page: 1 2 3 4" links beside each topic title (built in
   Pages/MessageBoardForum.aspx.vb's rptTopics_ItemDataBound). Same look as a small Bootstrap outlined secondary button -
   secondary text/border, solid secondary fill on hover - with a little less vertical padding. Each page number stays its
   own button with the existing gap between them, and only the outer two keep Bootstrap's rounded corners (first/last
   child), which this does not touch. */
.pager-topic .page-link {
    color: var(--bs-secondary);
    background-color: transparent;
    border-color: var(--bs-secondary);
    padding-top: 0.125rem;
    padding-bottom: 0.125rem;
}

.pager-topic .page-link:hover,
.pager-topic .page-link:focus {
    color: #fff;
    background-color: var(--bs-secondary);
    border-color: var(--bs-secondary);
}

/* Schedule - the "More Details" toggle under each game (Controls/ScheduleGame.ascx). Same disclosure look as the Search
   page's "Search tips": a small triangle before the text that points right when closed and down when open. Bootstrap's
   collapse keeps aria-expanded on the toggle current, including when Controls/Schedule.ascx opens a game through the
   Collapse API. Glyphs are written as CSS escapes (U+25B6 / U+25BC, the larger solid triangles - the small U+25B8 / U+25BE pair looked noticeably smaller than the native marker on the Search tips disclosure). */
.sg-more-toggle {
    cursor: pointer;
}

.sg-more-toggle::before {
    content: "\25B6";
    display: inline-block;
    /* sized to match the native marker on the Search page's "Search tips" (the glyph at full size looked larger than it) */
    font-size: 0.8em;
    width: 1.55em;
}

.sg-more-toggle[aria-expanded="true"]::before {
    content: "\25BC";
}

.sg-more-toggle:hover {
    color: var(--bs-body-color) !important;
}

/* Account page - quick highlight on the profile fields still needing a value, when the posting gate's "complete your profile"
   modal sends the user here (Pages/Account.aspx.vb's OpenProfileTabAndHighlightIfRequested). A yellow wash and glow that
   fade out over ~2.5s; the same class is removed by the script afterwards. */
.profile-field-flash {
    animation: profile-field-flash 2.5s ease-out;
}

@keyframes profile-field-flash {
    0%, 30% {
        background-color: rgba(255, 193, 7, .35);
        box-shadow: 0 0 0 .25rem rgba(255, 193, 7, .45);
    }
    100% {
        background-color: var(--bs-body-bg);
        box-shadow: 0 0 0 0 rgba(255, 193, 7, 0);
    }
}

/* Message board forum page - the footer row under the topic list (Pages/MessageBoardForum.aspx): "Showing Topics", Mark Forum
   Read and the pager. Small screens: two top-aligned columns - the text with the pager right beneath it on the left, the
   button on the right beside the text. md and up: one row of three, the button centered between the text and the pager. */
.mb-forum-footer {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 0.5rem;
    align-items: start;
    /* Cancels the page container's own side padding (0.75rem) so the controls run edge to edge with the topic list above, which
       reaches that outer edge through .row's negative margins - small screens only, where every pixel of width matters. */
    margin-left: -0.75rem;
    margin-right: -0.75rem;
}

.mb-ff-text {
    grid-column: 1;
    grid-row: 2;
}

.mb-ff-pager {
    grid-column: 1;
    grid-row: 1;
    justify-content: flex-start;
}

.mb-ff-pager .pagination {
    margin-bottom: 0;
}

.mb-ff-btn {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: start;
    /* narrow on purpose: the button's label wraps onto several lines so the (single-line) pager gets the room */
    max-width: 7.25rem;
}

/* Very narrow phones: the single-line pager needs most of the width, so the button's label wraps onto three lines (Mark / Forum / Read)
   instead of the two buttons running over each other. */
@media (max-width: 420px) {
    .mb-ff-btn {
        max-width: 5.5rem;
    }
}

@media (min-width: 768px) {
    .mb-forum-footer {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        align-items: start;
        margin-left: 0;
        margin-right: 0;
    }

    .mb-ff-text {
        grid-column: 1;
        grid-row: 1;
    }

    .mb-ff-btn {
        grid-column: 2;
        grid-row: 1;
        text-align: center;
        max-width: none;
    }

    .mb-ff-pager {
        grid-column: 3;
        grid-row: 1;
        justify-content: flex-end;
    }
}