/* ---- Global link colour: replaces Bootstrap's coral default (a { color: #E56455 }) ---- */
#content.bpbytes-content a,
#pagecontent a {
    color: var(--bp-primary);
}

#content.bpbytes-content a:hover,
#pagecontent a:hover {
    color: var(--bp-primary-hover);
}

/* Popup menus (action menus etc.) */
a.yuimenuitemlabel,
.yui-skin-sam .yuimenuitemlabel {
    color: var(--bp-text);
}

a.yuimenuitemlabel:hover,
.yui-skin-sam .yuimenuitem-selected .yuimenuitemlabel {
    color: var(--bp-primary);
}

/* File picker button, instead of the browser default */
input[type="file"]::file-selector-button {
    margin-right: 10px;
    padding: 7px 14px;
    border: 1px solid var(--bp-border-strong);
    border-radius: var(--bp-radius-sm);
    background: var(--bp-surface);
    color: var(--bp-text);
    font-family: var(--bp-font);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color var(--bp-transition), color var(--bp-transition);
}

input[type="file"]::file-selector-button:hover {
    border-color: var(--bp-primary);
    color: var(--bp-primary);
}

/* BPBytes shared components: buttons, badges, cards, dropdown menus */

/*
 * Module title bar — raw HTML from SugarView::getModuleTitle() (include/MVC/View/SugarView.php),
 * shared by every view type (list/detail/edit) and never passed through any theme template, so
 * it previously rendered with zero BPBytes styling at all: plain black <h2>, a browser-default-
 * blue "Create" link, and a stray create-record.gif icon stacked above it.
 */
/*
 * No horizontal padding here — SugarView::getModuleTitle()'s <h2> always starts with a literal
 * "&nbsp;" (core, meant as a separator after a breadcrumb icon this theme never renders before
 * it), so its own rendered width already pushes the visible title text a few pixels in. That
 * happens to land the text right where the studio tabs row below it (and the ListView table's
 * left edge) starts, so no padding is added on top of it here.
 */
#content.bpbytes-content .moduleTitle {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 22px;
}

#content.bpbytes-content .moduleTitle .clear {
    display: none;
}

#content.bpbytes-content .moduleTitle .module-title-text {
    margin: 0;
    font-size: 22px;
    font-weight: 700;
    color: var(--bp-title);
    flex: 1 1 auto;
}

#content.bpbytes-content .moduleTitle .module-title-text a {
    color: inherit;
    text-decoration: none;
}

#content.bpbytes-content .moduleTitle .module-title-text .pointer {
    margin: 0 8px;
    color: var(--bp-text-faint);
    font-weight: 400;
}

#content.bpbytes-content .moduleTitle .favorite {
    flex: 0 0 auto;
    display: flex;
    cursor: pointer;
}

#content.bpbytes-content .moduleTitle .favorite_icon_fill,
#content.bpbytes-content .moduleTitle .favorite_icon_outline {
    display: flex;
}

#content.bpbytes-content .moduleTitle .suitepicon-favorite-star,
#content.bpbytes-content .moduleTitle .suitepicon-favorite-star-outline {
    width: 18px;
    height: 18px;
    color: var(--bp-warning);
}

#content.bpbytes-content .moduleTitle .utils {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 10px;
}

/* The raw create-record.gif icon link — redundant next to the styled #create_link pill below */
#content.bpbytes-content .moduleTitle #create_image {
    display: none;
}

#content.bpbytes-content .moduleTitle #create_link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: var(--bp-btn-h);
    padding: 0 16px;
    border-radius: var(--bp-radius-sm);
    background: var(--bp-primary);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
}

#content.bpbytes-content .moduleTitle #create_link:hover {
    background: var(--bp-primary-hover);
}

#content.bpbytes-content .moduleTitle #create_link::before {
    content: "";
    width: 12px;
    height: 12px;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='12' y1='5' x2='12' y2='19'/%3E%3Cline x1='5' y1='12' x2='19' y2='12'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='12' y1='5' x2='12' y2='19'/%3E%3Cline x1='5' y1='12' x2='19' y2='12'/%3E%3C/svg%3E");
}

/* ListView-only search toggle button next to the title — route Bootstrap's default green to
   the theme's own brand color instead */
#content.bpbytes-content .moduleTitle .showsearch.btn-success {
    background: var(--bp-primary);
    border-color: var(--bp-primary);
}

/*
 * A few modules' view.list.php override getModuleTitle() to add one extra action next to
 * Create — a generic hook, not tied to any one feature. Originally rendered as a bare
 * <input class="button" style="float:right"> sitting as a sibling BEFORE .moduleTitle in the
 * markup — floating it clear out of the title's flex layout, with zero theme styling. Moved
 * into the .utils flex row itself (each such view.list.php inserts it right after
 * "<span class='utils'>") so it sits inline with search/Create properly, and styled here as a
 * generic outline secondary button — same height/radius/font as #create_link, but bordered
 * rather than filled, so Create still reads as the one primary action in the row. Reuse this
 * same class for any future module-specific title-bar action rather than inventing a new style.
 */
#content.bpbytes-content .moduleTitle .secondary-action-btn {
    /* Forces leftmost position within .utils's flex row (before the search icon and Create)
       regardless of where each module's view.list.php happens to insert it in the markup —
       more reliable than relying on DOM order alone. */
    order: -1;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: var(--bp-btn-h);
    padding: 0 16px;
    border: 1px solid var(--bp-border-strong);
    border-radius: var(--bp-radius-sm);
    background: var(--bp-surface);
    color: var(--bp-text);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}

#content.bpbytes-content .moduleTitle .secondary-action-btn:hover {
    background: var(--bp-surface-alt);
    border-color: var(--bp-primary);
    color: var(--bp-primary);
    text-decoration: none;
}

#content.bpbytes-content .moduleTitle .secondary-action-btn::before {
    content: "";
    width: 13px;
    height: 13px;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3Cline x1='16' y1='13' x2='8' y2='13'/%3E%3Cline x1='16' y1='17' x2='8' y2='17'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3Cline x1='16' y1='13' x2='8' y2='13'/%3E%3Cline x1='16' y1='17' x2='8' y2='17'/%3E%3C/svg%3E");
}

/*
 * "Studio tabs" (All / My Items / <status> filter row with counts) — a custom feature added in
 * custom/include/MVC/View/views/view.list.php's renderStudioTabs(), not stock SuiteCRM, also
 * reused by the compliance dashlets' Outstanding/Completed tabs. It emits <ul class="nav
 * nav-tabs nav-dashboard"><li class="active|utilsLink"><a class="plus-active|plus-inactive">
 * Label (count)</a></li>...</ul> — classes that exist only in that PHP file, with no CSS written
 * for them anywhere before now, so they rendered as bare unstyled links.
 */
#content.bpbytes-content ul.nav-tabs.nav-dashboard {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    list-style: none;
    margin: 0 0 14px;
    padding: 0;
    border-bottom: 1px solid var(--bp-border);
}

#content.bpbytes-content ul.nav-tabs.nav-dashboard > li {
    list-style: none;
}

#content.bpbytes-content ul.nav-tabs.nav-dashboard > li > a {
    display: inline-block;
    padding: 7px 12px;
    font-size: 12px;
    font-weight: 600;
    color: var(--bp-text-muted);
    text-decoration: none;
    border-radius: var(--bp-radius-sm) var(--bp-radius-sm) 0 0;
    white-space: nowrap;
}

/* .moduleTitle above this tab row has no padding of its own (see the comment on that rule) -
   its <h2> text starts a few px in purely from core's own leading "&nbsp;". Trimming just the
   first tab's left padding from the usual 12px to 8px lands its label closer to that same
   offset, without touching the spacing between the other tabs. */
#content.bpbytes-content ul.nav-tabs.nav-dashboard > li:first-child > a {
    padding-left: 8px;
}

#content.bpbytes-content ul.nav-tabs.nav-dashboard > li > a:hover {
    color: var(--bp-primary);
    background: var(--bp-surface-alt);
    text-decoration: none;
}

#content.bpbytes-content ul.nav-tabs.nav-dashboard > li.active > a {
    color: var(--bp-primary);
    box-shadow: inset 0 -2px 0 var(--bp-primary);
}

/*
 * Loading state for AJAX-driven tabs (e.g. the compliance dashlets' Outstanding/Approval
 * Pending/Completed tabs, set via renderComplianceTabs()'s onclick before calling
 * SUGAR.mySugar.retrieveDashlet()). The whole bar dims and stops accepting clicks — the AJAX
 * response replaces this entire markup anyway, so there's nothing to manually reset afterward.
 *
 * The spinner itself is the same conic-gradient ring + bpbytes-spin animation used everywhere
 * else in the app (#loadingPage, .bpbytes-loading-spinner) — just a small inline size, not a
 * different spinner design, so every loading state in the app reads as one system.
 */
#content.bpbytes-content ul.nav-tabs.nav-dashboard.nav-tabs-loading {
    pointer-events: none;
    opacity: 0.6;
}

#content.bpbytes-content ul.nav-tabs.nav-dashboard > li > a.is-loading::after {
    content: "";
    display: inline-block;
    width: 11px;
    height: 11px;
    margin-left: 6px;
    vertical-align: middle;
    border-radius: 50%;
    background: conic-gradient(from 0deg, transparent 0deg, var(--bp-accent) 110deg, var(--bp-primary) 340deg, transparent 360deg);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
    animation: bpbytes-spin 0.85s linear infinite;
}

/*
 * The theme's ONE base button treatment — shared by every "class=button" control anywhere in
 * the app, not just inside #content.bpbytes-content. .modal-content covers every Bootstrap
 * modal (search filter, column chooser, and any future one) so none of them need their own
 * copy of these same properties. Previously re-implemented separately (and each time slightly
 * differently — different radius, different padding) for #searchDialog and
 * #columnsFilterDialog; those now only add what's genuinely specific to them.
 */
#content.bpbytes-content .button,
#content.bpbytes-content input[type="submit"],
#content.bpbytes-content input[type="button"],
#content.bpbytes-content button.button,
.modal-content .button,
.modal-content input[type="submit"],
.modal-content input[type="button"] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: var(--bp-btn-h);
    padding: 0 18px;
    border-radius: var(--bp-radius-sm);
    border: 1px solid var(--bp-border-strong);
    background: var(--bp-surface);
    color: var(--bp-text);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background var(--bp-transition), border-color var(--bp-transition);
}

#content.bpbytes-content .button:hover,
#content.bpbytes-content input[type="submit"]:hover,
#content.bpbytes-content input[type="button"]:hover,
.modal-content .button:hover,
.modal-content input[type="submit"]:hover,
.modal-content input[type="button"]:hover {
    background: var(--bp-surface-alt);
    border-color: var(--bp-text-faint);
}

#content.bpbytes-content .button:disabled,
#content.bpbytes-content input:disabled,
.modal-content .button:disabled,
.modal-content input:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/*
 * The theme's ONE filled "primary action" button — every place that needs to say "this is the
 * important button" points at this same rule instead of re-declaring the same blue fill:
 *   - EditView/DetailView's class="button primary" (#SAVE_HEADER/#SAVE_FOOTER, etc.)
 *   - the Column Chooser's Save button, class="button red" (a legacy/odd class name — same
 *     "primary CTA" semantic, not an actual danger action)
 *   - the login page's #bigbutton / #generate_pwd_button / input[name="Login"] (login.css adds
 *     only their full-width sizing on top of this)
 *   - the search filter's #search_form_submit (Quick Filter's Search button - actually
 *     name="button" like every other sugar_button-rendered button, not name="search"; keyed
 *     off its id instead) and #search_form_submit_advanced (Advanced Filter's own Search
 *     button, a separate element) - search.css adds only its own margin on top of this
 *   - a subpanel's own top "Create ..." button (the left-hand cell of its pagination row,
 *     detailview.css) — plain class="button" otherwise, same as every other subpanel/dashlet
 *     button, but called out here to match the (now-removed) page-level "+Create" it replaces
 *   - the search filter's own "Save filter as:" button (SearchFormGenericAdvanced.tpl,
 *     name="saved_search_submit", no id) - previously plain class="button" like Update/Delete
 *     next to it, which read as equally weighted with them even though it's the one action that
 *     actually commits something (same "this is the important one" case as Search vs Clear)
 * Previously each of these restyled the same blue fill from scratch with small, inconsistent
 * differences (e.g. only some got a hover box-shadow lift).
 */
#content.bpbytes-content .button.primary,
#content.bpbytes-content input.button.primary,
#content.bpbytes-content input#bigbutton,
#content.bpbytes-content input[name="Login"],
#content.bpbytes-content #generate_pwd_button,
#content.bpbytes-content tr.pagination table td[align="left"] .button,
#content.bpbytes-content .modal-content .button.primary,
#content.bpbytes-content .modal-content .button.red,
.modal-content .button.primary,
.modal-content .button.red,
#searchDialog input.button#search_form_submit,
#searchDialog input.button#search_form_submit_advanced,
#searchDialog input.button[name="saved_search_submit"],
.bpbytes-login__card #bigbutton,
.bpbytes-login__card #generate_pwd_button {
    background: var(--bp-primary);
    border-color: var(--bp-primary);
    color: #fff;
    box-shadow: 0 4px 12px rgba(85, 71, 181, 0.25);
}

#content.bpbytes-content .button.primary:hover,
#content.bpbytes-content input.button.primary:hover,
#content.bpbytes-content input#bigbutton:hover,
#content.bpbytes-content input[name="Login"]:hover,
#content.bpbytes-content #generate_pwd_button:hover,
#content.bpbytes-content tr.pagination table td[align="left"] .button:hover,
#content.bpbytes-content .modal-content .button.primary:hover,
#content.bpbytes-content .modal-content .button.red:hover,
.modal-content .button.primary:hover,
.modal-content .button.red:hover,
#searchDialog input.button#search_form_submit:hover,
#searchDialog input.button#search_form_submit_advanced:hover,
#searchDialog input.button[name="saved_search_submit"]:hover,
.bpbytes-login__card #bigbutton:hover,
.bpbytes-login__card #generate_pwd_button:hover {
    background: var(--bp-primary-hover);
    border-color: var(--bp-primary-hover);
    box-shadow: 0 6px 16px rgba(85, 71, 181, 0.32);
}

/*
 * DetailView header "Actions" dropdown (custom/themes/BPBytes/js/detailViewTabs.js's
 * buildHeaderActionsMenu()/relocateHeaderActions()) — Edit/Duplicate/Delete/Audit folded into
 * one trigger and moved into .moduleTitle's flex row, landing top-right for free next to
 * .module-title-text's flex:1 1 auto (above, earlier in this file). Same relative/absolute
 * dropdown shape as .bpbytes-profile (topbar.css), reused here for visual consistency with that
 * pattern. Placed after the shared .button/.button.primary rules above (same specificity as
 * .button.primary, so this only wins on the actual Edit input by coming later in the cascade).
 */
#content.bpbytes-content .bpbytes-header-actions {
    position: relative;
    flex: 0 0 auto;
    list-style: none;
    margin: 0;
    padding: 0;
}

#content.bpbytes-content .bpbytes-header-actions > li {
    list-style: none;
}

#content.bpbytes-content .bpbytes-header-actions__trigger {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: var(--bp-btn-h);
    padding: 0 16px;
    border: 1px solid var(--bp-primary);
    border-radius: var(--bp-radius-sm);
    background: var(--bp-primary);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}

#content.bpbytes-content .bpbytes-header-actions__trigger:hover {
    background: var(--bp-primary-hover);
    border-color: var(--bp-primary-hover);
}

#content.bpbytes-content .bpbytes-header-actions__trigger::after {
    content: "";
    width: 10px;
    height: 10px;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}

#content.bpbytes-content .bpbytes-header-actions__menu {
    display: none;
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    min-width: 180px;
    margin: 0;
    padding: 6px;
    list-style: none;
    background: var(--bp-surface);
    border-radius: var(--bp-radius);
    box-shadow: var(--bp-shadow-lg);
    z-index: var(--bp-z-dropdown);
}

#content.bpbytes-content .bpbytes-header-actions.is-open .bpbytes-header-actions__menu {
    display: block;
}

#content.bpbytes-content .bpbytes-header-actions__menu li {
    list-style: none;
}

#content.bpbytes-content .bpbytes-header-actions__menu li + li {
    margin-top: 2px;
}

/* Overrides the shared pill-button look (.button/.button.primary above) with a plain,
   full-width menu row — these are the exact same <input>s core rendered (onclick/name/id/form
   untouched), just re-skinned now that they're menu items instead of standalone buttons. */
#content.bpbytes-content .bpbytes-header-actions__menu .button,
#content.bpbytes-content .bpbytes-header-actions__menu input[type="button"],
#content.bpbytes-content .bpbytes-header-actions__menu input[type="submit"] {
    display: block;
    width: 100%;
    height: auto;
    padding: 9px 12px;
    border: none;
    border-radius: var(--bp-radius-sm);
    background: transparent;
    color: var(--bp-text);
    font-size: 13px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
}

#content.bpbytes-content .bpbytes-header-actions__menu .button:hover,
#content.bpbytes-content .bpbytes-header-actions__menu input[type="button"]:hover,
#content.bpbytes-content .bpbytes-header-actions__menu input[type="submit"]:hover {
    background: var(--bp-surface-alt);
}

/*
 * A subpanel's own inline "Create ..." quick-create form renders its Save button through
 * function.sugar_button.php's "SUBPANELSAVE" case, which (unlike every OTHER Save button in
 * the app - EditView/DetailView's own #SAVE_HEADER/#SAVE_FOOTER) only ever gets plain
 * class="button", never "button primary" - a genuine core inconsistency between this one Save
 * button variant and every other one, not something introduced here. Matched to the same
 * filled-primary look via the id function.sugar_button.php always builds it with
 * ("{module}_subpanel_save_button") since there's no shared class to hook instead. Cancel is
 * left alone - it's plain class="button" everywhere else too (function.sugar_button.php's
 * CANCEL case), so it already matches.
 */
#content.bpbytes-content input[id$="_subpanel_save_button"] {
    background: var(--bp-primary);
    border-color: var(--bp-primary);
    color: #fff;
    box-shadow: var(--bp-shadow-sm);
}

#content.bpbytes-content input[id$="_subpanel_save_button"]:hover {
    background: var(--bp-primary-hover);
    border-color: var(--bp-primary-hover);
    box-shadow: var(--bp-shadow);
}

/*
 * The email address widget (include/SugarEmailAddress/templates/forEditView.tpl) hardcodes
 * Bootstrap's class="btn btn-danger" on BOTH its add (+) and remove (x) buttons — the same
 * "hardcoded danger button with no relation to the theme" issue already worked around for the
 * date-field calendar trigger below. Scoped to these two widget-specific classes so a genuine
 * destructive action elsewhere keeps its real btn-danger styling untouched.
 */
#content.bpbytes-content .email-address-add-button.btn-danger,
#content.bpbytes-content .email-address-remove-button.btn-danger {
    background: var(--bp-surface);
    border: 1px solid var(--bp-border-strong);
    color: var(--bp-text-muted);
    border-radius: 50%;
    width: 30px;
    height: 30px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: none;
}

#content.bpbytes-content .email-address-add-button.btn-danger:hover {
    background: var(--bp-primary-soft);
    color: var(--bp-primary);
    border-color: var(--bp-primary);
}

#content.bpbytes-content .email-address-remove-button.btn-danger:hover {
    background: var(--bp-surface-alt);
    color: var(--bp-danger);
    border-color: var(--bp-danger);
}

#content.bpbytes-content .bpbytes-card {
    background: var(--bp-surface);
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius-lg);
    box-shadow: var(--bp-shadow);
    padding: 18px 20px;
    margin-bottom: 16px;
}

/*
 * YUI's own generic "hidden until JS shows it" utility class (class="yui-hidden") — used
 * pervasively across core markup for placeholders/dialogs that start hidden and get shown on
 * demand (e.g. the Email Settings popup in modules/Users/_baseEmail.tpl — the SMTP/Outgoing
 * Email/signature fields that were dumping onto the Users EditView page below the tabs).
 * include/javascript/yui/build/tabview/assets/skins/sam/tabview-skin.css only defines this
 * scoped to .yui-navset (for TabView's own tab panels), so anywhere it's used outside a
 * TabView needs this bare rule too — SuiteP's yui.scss carries it, BPBytes never did.
 */
.yui-hidden {
    display: none;
}

/* Shared DetailView/EditView YUI TabView shell (#{module}_detailview_tabs / #{form_name}_tabs) */
#content.bpbytes-content .yui-navset .yui-nav {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid var(--bp-border);
    margin: 0 0 16px;
    padding: 0;
    list-style: none;
}

#content.bpbytes-content .yui-navset .yui-nav li {
    list-style: none;
}

#content.bpbytes-content .yui-navset .yui-nav li a {
    display: inline-block;
    padding: 10px 16px;
    font-size: 13px;
    font-weight: 600;
    color: var(--bp-text-muted);
    text-decoration: none;
    border-radius: var(--bp-radius-sm) var(--bp-radius-sm) 0 0;
}

#content.bpbytes-content .yui-navset .yui-nav li a:hover {
    color: var(--bp-primary);
    background: var(--bp-surface-alt);
}

/* tabview-skin.css (loaded in _head.tpl) sets its own background sprite-gradient on the
   selected tab (a hard blue) that this rule never touched before — only color/box-shadow — so it
   kept showing through untouched underneath. */
#content.bpbytes-content .yui-navset .yui-nav li.selected a,
#content.bpbytes-content .yui-navset .yui-nav li.selected a:focus,
#content.bpbytes-content .yui-navset .yui-nav li.selected a:hover {
    color: var(--bp-primary);
    background: var(--bp-surface-alt);
    box-shadow: inset 0 -2px 0 var(--bp-primary);
}

/*
 * Studio's closable tabs (YAHOO.SUGAR.ClosableTab, include/javascript/sugarwidgets/
 * SugarYUIWidgets.js) append a bare <a class="sugar-tab-close"> straight into the tab's own
 * label text with no theme CSS for it at all (SuiteP styles it via a sprite image — a resource
 * BPBytes doesn't have/want) — it was rendering as an unstyled, oddly-sized default link
 * overlapping the label text instead of a small "x" set apart from it.
 */
#content.bpbytes-content a.sugar-tab-close {
    display: inline-block;
    position: relative;
    top: -1px;
    width: 12px;
    height: 12px;
    margin-left: 8px;
    vertical-align: middle;
    background-color: var(--bp-text-faint);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3C/svg%3E");
}

#content.bpbytes-content a.sugar-tab-close:hover {
    background-color: var(--bp-danger);
}

/*
 * Studio (#mbtabs, same YUI TabView widget) loads each tab's content asynchronously via AJAX
 * after the panel is already created, so YUI's own JS computes .yui-content's height once, early
 * — before the DataTable (see the .yui-dt rules further down) has actually rendered its rows —
 * and never revisits it. The result is a real, fully-populated panel stuck inside a leftover
 * inline height:22px scroll box. !important is required here since it's overriding that inline
 * style, not a stylesheet rule.
 */
#content.bpbytes-content #mbtabs .yui-content {
    height: auto !important;
    overflow: visible !important;
}

/*
 * Studio's layout editors (Edit View, Detail View, Search, List View, ...) have a list of fields to drag from, and a
 * panel or column list to drop them in. Studio's script sizes these lists from the height of #mbtabs; with the rule
 * above #mbtabs is as tall as its content, so the lists end up as tall as their contents too and nothing scrolls:
 * the fields at the bottom of the list are out of reach. SuiteP gives #toolbox its own scrollbar for the same reason
 * (themes/SuiteP/css/studio.css), which this independent theme never copied. A height cap in the window's terms
 * wins over the script's inline height, and each list then scrolls inside it. Adjust the 300px to the height of
 * the header, title and buttons above the lists.
 */
#content.bpbytes-content #mbtabs #toolbox,
#content.bpbytes-content #mbtabs #panels,
#content.bpbytes-content #mbtabs #editor-content.list-editor ul[id^="ul"] {
    max-height: calc(100vh - 300px);
    min-height: 240px;
    overflow-y: auto;
    overflow-x: hidden;
}

/*
 * SuiteCRM Studio's module tree (Admin > Studio > a module > Layouts > Dashlet, etc.) — a YUI 2
 * TreeView widget rendered client-side into #package_tree (modules/ModuleBuilder/tpls/index.tpl).
 * ModuleBuilder's own includes.tpl already links include/ytree/TreeView/css/folders/tree.css for
 * the expand/collapse folder-icon sprites, so those already work; it's just the text labels and
 * breadcrumb heading that render with zero styling, since Studio's own YUI TabView is loaded with
 * the "blank" skin (no SuiteP dependency here either) and nothing in BPBytes touched them before.
 */
#content.bpbytes-content #package_tree {
    font-size: 13px;
}

/* Each node's expand/collapse toggle (.ygtvtp/.ygtvtm/.ygtvtn etc.) is a fixed-width table cell
   with the +/- icon baked directly into its background-image sprite, sitting flush against the
   folder-icon cell right next to it — border-spacing (not margin, which <td> ignores) opens up
   breathing room between cells without disturbing those sprite positions. Horizontal only, so the
   vertical connector lines between parent/child rows stay unbroken. */
#content.bpbytes-content #package_tree table {
    border-collapse: separate;
    border-spacing: 4px 0;
}

#content.bpbytes-content #package_tree .ygtvlabel,
#content.bpbytes-content #package_tree .ygtvlabel:link,
#content.bpbytes-content #package_tree .ygtvlabel:visited {
    color: var(--bp-text-muted);
    text-decoration: none;
    padding: 2px 6px;
    border-radius: var(--bp-radius-sm);
}

#content.bpbytes-content #package_tree .ygtvlabel:hover {
    color: var(--bp-primary);
    background: var(--bp-surface-alt);
    text-decoration: none;
}

/* Studio's breadcrumb has no wrapping element — ModuleBuilder.js's getTitle() returns a raw
   "<h2>title</h2><br>breadcrumb text" string dropped straight into the tab panel — so the
   heading it's always paired with is the only thing there is to style. */
#content.bpbytes-content #mbcenter h2 {
    margin: 0 0 6px;
    font-size: 16px;
    font-weight: 700;
    color: var(--bp-text);
}

/* Enum / status field pill badges rendered by SugarFieldEnum */
#content.bpbytes-content .sugar_field.enum,
#content.bpbytes-content select ~ .sugar_field {
    font-weight: 500;
}

/*
 * Core's jquery.sugarMenu.js (ul.clickMenu / ul.subnav / ul.subnav-sub) is a pure-JS dropdown
 * widget — it toggles inline display/height styles at runtime but relies entirely on CSS for
 * the *default* hidden state (previously only ever supplied by SuiteP's own stylesheet). Without
 * this, every action/bulk-action menu across list/edit/detail views renders permanently expanded.
 */
#content.bpbytes-content ul.clickMenu {
    display: inline-block;
    position: relative;
    list-style: none;
    margin: 0 6px 0 0;
    padding: 0;
    vertical-align: middle;
}

#content.bpbytes-content ul.clickMenu > li {
    list-style: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    border-radius: var(--bp-radius-sm);
    border: 1px solid var(--bp-border-strong);
    background: var(--bp-surface);
    font-size: 12px;
    font-weight: 600;
    color: var(--bp-text);
    cursor: pointer;
    white-space: nowrap;
}

#content.bpbytes-content ul.clickMenu > li:hover {
    background: var(--bp-surface-alt);
}

/* The trigger <li>'s own color:var(--bp-text) above only covers text not otherwise targeted —
   it doesn't win against listview.css's blanket "td a { color: var(--bp-primary) }" rule for
   genuine data links, since that rule targets the <a>/<input> here directly rather than
   inheriting. Toolbar controls like "Action"/"Bulk Action" should read as neutral UI, not as
   blue data links. :not(.primary) — DetailView's own Edit button (function.sugar_button.php)
   renders as class="button primary" and happens to share this same ul.clickMenu > li structure
   when action-menu grouping is on; this rule's !important was winning over .button.primary's
   white text regardless of specificity, forcing dark text onto its solid blue background. */
#content.bpbytes-content ul.clickMenu > li > a:not(.primary),
#content.bpbytes-content ul.clickMenu > li > input[type="button"]:not(.primary) {
    color: var(--bp-text) !important;
    text-decoration: none;
}

/*
 * sugar_action_menu (function.sugar_action_menu.php) marks the wrapping <li> "single" instead
 * of "sugar_action_button" whenever there's exactly one button and no dropdown (e.g. a DetailView
 * with Edit but no Duplicate/Delete per ACL) — that <li> would otherwise carry the SAME
 * border/background/padding as the .button it wraps, doubling up into a border-around-a-border.
 * A lone button needs no menu chrome of its own. :has(> .button) covers the same case when core
 * marks the <li> "sugar_action_button" instead of "single" (DetailView's Edit does this even
 * with no other visible action beside it) — either way, a <li> directly wrapping a .button
 * never needs its own separate box.
 */
#content.bpbytes-content ul.clickMenu > li.single,
#content.bpbytes-content ul.clickMenu > li:has(> .button) {
    background: transparent;
    border: none;
    padding: 0;
}

#content.bpbytes-content ul.clickMenu > li.single:hover,
#content.bpbytes-content ul.clickMenu > li:has(> .button):hover {
    background: transparent;
}

/* A row action such as a subpanel's Edit: the <ul> itself is the button (class "button"), so the <li> inside it carries
   no box of its own, only the label's padding. */
#content.bpbytes-content ul.clickMenu.button {
    display: inline-flex;
    align-items: stretch;
}

#content.bpbytes-content ul.clickMenu.button > li {
    padding: 0 16px;
    border: none;
    background: transparent;
    font-size: 13px;
}

#content.bpbytes-content ul.clickMenu > li .suitepicon-action-caret {
    width: 10px;
    height: 10px;
    opacity: 0.6;
}

/* A short label like "Edit" reads a little narrow as the one prominent colored action here —
   same widening treatment as the subpanel's own Create button. */
#content.bpbytes-content ul.clickMenu > li > input.button.primary {
    padding: 0 22px;
    min-width: 110px;
    justify-content: center;
}

#content.bpbytes-content ul.clickMenu ul.subnav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 190px;
    margin-top: 6px;
    background: var(--bp-surface);
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius);
    box-shadow: var(--bp-shadow-lg);
    padding: 6px;
    z-index: var(--bp-z-dropdown);
    list-style: none;
    overflow: hidden;
}

#content.bpbytes-content ul.clickMenu ul.subnav > li {
    list-style: none;
    display: block;
}

#content.bpbytes-content ul.clickMenu ul.subnav > li > a,
#content.bpbytes-content ul.clickMenu ul.subnav > li > input[type="button"],
#content.bpbytes-content ul.clickMenu ul.subnav > li > input[type="submit"] {
    display: block;
    width: 100%;
    text-align: left;
    padding: 8px 10px;
    border: none;
    background: transparent;
    color: var(--bp-text);
    font-size: 12.5px;
    font-weight: 400;
    text-decoration: none;
    cursor: pointer;
    border-radius: var(--bp-radius-sm);
}

#content.bpbytes-content ul.clickMenu ul.subnav > li > a:hover,
#content.bpbytes-content ul.clickMenu ul.subnav > li > input:hover {
    background: var(--bp-surface-alt);
    text-decoration: none;
}

#content.bpbytes-content ul.clickMenu ul.subnav-sub {
    display: none;
    position: absolute;
    min-width: 190px;
    background: var(--bp-surface);
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius);
    box-shadow: var(--bp-shadow-lg);
    padding: 6px;
    z-index: var(--bp-z-dropdown);
    list-style: none;
}

#content.bpbytes-content ul.clickMenu ul.subnav-sub.hover {
    display: block;
}

#content.bpbytes-content ul.clickMenu ul.subnav-sub > li {
    list-style: none;
}

#content.bpbytes-content ul.clickMenu ul.subnav-sub > li > a {
    display: block;
    padding: 8px 10px;
    border-radius: var(--bp-radius-sm);
    color: var(--bp-text);
    text-decoration: none;
    font-size: 12.5px;
}

#content.bpbytes-content ul.clickMenu ul.subnav-sub > li > a:hover {
    background: var(--bp-surface-alt);
}

/*
 * Core's AJAX loading indicator — YAHOO.widget.Panel("ajaxloading"), shown/hidden by
 * SUGAR.ajaxUI.showLoadingPanel()/hideLoadingPanel() (include/javascript/ajaxUI.js) on every
 * single in-app AJAX navigation and form submit, application-wide. Restyled in place rather
 * than replaced, since it's already the one loading indicator that fires everywhere; the
 * default img_loading.gif is swapped for a self-contained CSS spinner to match the theme.
 * IDs below (ajaxloading_mask / ajaxloading_c / ajaxloading, classes yui-panel-container /
 * yui-panel) come from YUI's Panel widget's own id/class-generation convention.
 *
 * YUI's own container skin CSS (which would normally give .mask/.yui-panel/.yui-panel-container
 * their base position/display rules) isn't loaded anywhere in this theme, and YUI's JS only ever
 * sets the panel's page (x,y) coordinates inline — it never forces `position`. So every
 * positioning rule here (fixed/left/top/z-index, not just cosmetics) is load-bearing on its own,
 * not just an override of some other default. Values are pinned with !important because YUI
 * re-applies its own inline left/top on every show and on window resize (JS inline styles lose to
 * !important stylesheet rules regardless of write order, so this is safe rather than fighting it).
 */
#ajaxloading_mask {
    position: fixed !important;
    /* Default assumes no sidebar/topbar chrome at all (a standalone Popups search window, e.g.
       the classic relate-field record picker, has neither) — dims its own full viewport. */
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    width: auto !important;
    height: auto !important;
    background: rgba(30, 27, 75, 0.45) !important;
    /* Loading body.yui-skin-sam's container skin (for the calendar widget below) also adds
       opacity:.25 to any .mask element with no property conflict to fight — since that's a
       different property than the background-color our shorthand above already wins on, it
       would otherwise silently stack on top and wash out the dimming to ~10% instead of 40%. */
    opacity: 1 !important;
    /* !important is load-bearing here (unlike everything else in this rule already had it): YUI's
       own stackMask() sets an inline z-index style on this element directly, and a plain
       stylesheet rule loses to an inline style — without !important the mask was rendering at
       whatever low z-index YUI picked, letting the sticky ListView header (z-index: 5) paint
       over it, undimmed, during every AJAX page navigation. */
    z-index: var(--bp-z-dropdown) !important;
    transition: left var(--bp-transition), top var(--bp-transition);
}

/* Only once the main app's own sidebar/topbar genuinely exist in this document (never true
   inside a Popups window) does the mask dim just the content area instead of the whole page. */
body:has(.bpbytes-sidebar) #ajaxloading_mask {
    top: var(--bp-topbar-height) !important;
    left: var(--bp-sidebar-width) !important;
}

body.bpbytes-sidebar-collapsed #ajaxloading_mask {
    left: var(--bp-sidebar-collapsed-width) !important;
}

#ajaxloading.yui-panel {
    position: fixed !important;
    /* Default: dead center of whatever viewport this document actually has (a Popups window's
       own, not the main app's) — see the body:has() override below for when real sidebar/topbar
       chrome exists to offset around. Without this, the panel's old hardcoded sidebar/topbar
       offset math ran everywhere INCLUDING inside popups (which have no sidebar to offset for),
       drifting it down into whatever content — like a sticky ListView header — happened to sit
       where that phantom offset placed it. */
    left: 50% !important;
    /* Clamped, not a flat 50% — on a short page (few rows, so the content area itself is
       short), pure vertical centering lands the card right on top of the sticky column-header
       row and the first rows beneath it, hiding them. 140px keeps it clear of that header
       regardless of how short the page is; on any normal-height page the centered value below
       is larger and wins instead, so this only ever kicks in for the short-page case. */
    top: max(140px, 50%) !important;
    transform: translate(-50%, -50%) !important;
    z-index: calc(var(--bp-z-dropdown) + 1) !important;
    background: var(--bp-surface);
    border: none;
    border-radius: var(--bp-radius-lg);
    box-shadow: var(--bp-shadow-lg);
    transition: left var(--bp-transition), top var(--bp-transition);
}

/* Centered over the content area (viewport minus the sidebar) once real sidebar/topbar chrome
   exists in this document. */
body:has(.bpbytes-sidebar) #ajaxloading.yui-panel {
    left: calc(var(--bp-sidebar-width) + (100vw - var(--bp-sidebar-width)) / 2) !important;
    /* Same clamp as the default rule above, applied to this offset centering formula instead of
       a flat 50% — the actual bug reported: on a short listview, dead-center math placed the
       card right over the sticky header + first couple of rows. */
    top: max(
        calc(var(--bp-topbar-height) + 140px),
        calc(var(--bp-topbar-height) + (100vh - var(--bp-topbar-height) - var(--bp-footer-total, var(--bp-footer-height))) / 2)
    ) !important;
}

body.bpbytes-sidebar-collapsed #ajaxloading.yui-panel {
    left: calc(var(--bp-sidebar-collapsed-width) + (100vw - var(--bp-sidebar-collapsed-width)) / 2) !important;
}

#ajaxloading .hd,
#ajaxloading .ft {
    display: none;
}

#ajaxloading .bd {
    padding: 34px 40px;
}

#loadingPage {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 26px;
    font-family: var(--bp-font);
}

/* Hide the default core gif; the spinner below replaces it */
#loadingPage img {
    display: none;
}

/* Core's LBL_LOADING_PAGE app_string ships empty by default (include/language/en_us.lang.php),
   so the <b>...</b> label ajaxUI.js always writes into #loadingPage is empty text — CSS supplies
   the caption instead of overriding a core language file just for this */
#loadingPage b {
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.01em;
}

#loadingPage b {
    display: none;
}

/* A two-tone conic ring (brand blue sweeping into teal) rather than a plain two-color
   border spinner — drawn with a masked conic-gradient, no image asset required */
/* (the mark and bar for #loadingPage are defined with the shared loading styles below) */
#loadingPage::before {
    order: -1;
}

#loadingPage::after {
    order: 1;
}

@keyframes bpbytes-spin {
    to {
        transform: rotate(360deg);
    }
}

/*
 * Shared loading overlay — a plain JS-created/removed div (no YUI Panel involved), so it needs
 * none of #ajaxloading's positioning workarounds above; centering with fixed + flex is enough.
 * Reuses the same conic-gradient spinner and card/backdrop treatment as #ajaxloading/#loadingPage
 * so every loading state in the app looks like one system rather than a one-off per feature.
 * Currently used by the "PDF Report" download flow (custom/include/SugarFields/Fields/Pdf/
 * pdf_template_popup.js) — swap the message text, not the look, for other loading states.
 */
.bpbytes-loading-overlay {
    position: fixed;
    inset: 0;
    background: rgba(255, 255, 255, 0.82);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    z-index: calc(var(--bp-z-dropdown) + 1);
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Cover the page area only, so the sidebar and top bar stay visible (as on the mobile app,
   where the header stays visible under the loader) */
body:has(.bpbytes-sidebar) .bpbytes-loading-overlay {
    top: var(--bp-topbar-height);
    left: var(--bp-sidebar-width);
}

body.bpbytes-sidebar-collapsed .bpbytes-loading-overlay {
    left: var(--bp-sidebar-collapsed-width);
}

@media (max-width: 991px) {
    body:has(.bpbytes-sidebar) .bpbytes-loading-overlay {
        left: var(--bp-sidebar-collapsed-width);
    }
}

.bpbytes-loading-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 26px;
    font-family: var(--bp-font);
}

/* The logo mark, drawn from the white "bP" PNG used as a mask so it can carry the brand gradient */
.bpbytes-loading-mark,
#loadingPage::before {
    position: relative;
    width: 56px;
    height: 56px;
    background: linear-gradient(135deg, #02c5f3 0%, #3693d9 50%, #5547b5 100%);
    -webkit-mask: url("../images/company_logo_sort.png") center / contain no-repeat;
    mask: url("../images/company_logo_sort.png") center / contain no-repeat;
    animation: bpbytes-pulse 1.4s ease-out infinite;
}

/* The soft ring that spreads out from behind the mark */
.bpbytes-loading-ring {
    position: absolute;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: rgba(85, 71, 181, 0.35);
    animation: bpbytes-ring 1.4s ease-out infinite;
}

.bpbytes-loading-logo {
    position: relative;
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The sliding bar: a short pill moving along a track */
.bpbytes-loading-bar,
#loadingPage::after {
    content: "";
    display: block;
    width: 96px;
    height: 4px;
    border-radius: 2px;
    background-color: rgba(85, 71, 181, 0.2);
    background-image: linear-gradient(var(--bp-primary), var(--bp-primary));
    background-repeat: no-repeat;
    background-size: 56px 100%;
    background-position: -56px 0;
    animation: bpbytes-slide 1.1s ease-in-out infinite;
}

/* ---- Ring variant: ring spinner in a white card over a dimmed page ---- */
.bpbytes-loading-overlay--ring {
    background: rgba(30, 27, 75, 0.45);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}

body:has(.bpbytes-sidebar) .bpbytes-loading-overlay--ring,
body.bpbytes-sidebar-collapsed .bpbytes-loading-overlay--ring {
    top: 0;
    left: 0;
}

@media (max-width: 991px) {
    body:has(.bpbytes-sidebar) .bpbytes-loading-overlay--ring {
        left: 0;
    }
}

.bpbytes-loading-overlay--ring .bpbytes-loading-card {
    gap: 14px;
    width: 172px;
    height: 148px;
    padding: 16px;
    box-sizing: border-box;
    background: var(--bp-surface);
    border-radius: var(--bp-radius-lg);
    box-shadow: var(--bp-shadow-lg);
}

.bpbytes-loading-spinner {
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background: conic-gradient(from 0deg, transparent 0deg, var(--bp-accent) 110deg, var(--bp-primary) 340deg, transparent 360deg);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 5px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 5px));
    animation: bpbytes-spin 0.85s linear infinite;
}

.bpbytes-loading-overlay--ring .bpbytes-loading-message {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip: auto;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--bp-text-muted);
}

/* Small inline version of the same ring, for a loading state sitting next to a button or in a line of text
   (e.g. "Add Note" in the Activities and Notes panel) - replaces the old img_loading.gif. */
.bpbytes-inline-spinner {
    display: inline-block;
    width: 16px;
    height: 16px;
    margin-left: 8px;
    vertical-align: middle;
    border-radius: 50%;
    background: conic-gradient(from 0deg, transparent 0deg, var(--bp-accent) 110deg, var(--bp-primary) 340deg, transparent 360deg);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
    animation: bpbytes-spin 0.85s linear infinite;
}

.bpbytes-loading-message {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

@keyframes bpbytes-pulse {
    0%   { transform: scale(1); }
    30%  { transform: scale(1.12); }
    100% { transform: scale(1); }
}

@keyframes bpbytes-ring {
    0%   { transform: scale(1); opacity: 0.35; }
    100% { transform: scale(2.1); opacity: 0; }
}

@keyframes bpbytes-slide {
    0%   { background-position: -56px 0; }
    100% { background-position: 96px 0; }
}

/* Core's inline AJAX status flash (SUGAR.ajaxStatusClass, sugar_3.js — e.g. "Saving...")
   appended straight to <body> with no positioning of its own beyond a JS-computed left offset,
   so a theme is expected to supply the rest (see themes/default/css/style.css for the
   equivalent baseline, which isn't loaded here since BPBytes ships its own style.css) */
#ajaxStatusDiv {
    position: fixed !important;
    top: calc(var(--bp-topbar-height) + 14px) !important;
    z-index: var(--bp-z-dropdown);
    background: var(--bp-text) !important;
    color: #fff !important;
    border-radius: var(--bp-radius);
    box-shadow: var(--bp-shadow-lg);
    padding: 8px 16px !important;
    font-size: 12.5px;
    font-family: var(--bp-font);
    opacity: 0.95 !important;
}

/*
 * External report embed (Analytics & Dashboards sidebar links, see style.js's
 * .bpbytes-nav-item__link--embed click handler) — the iframe fills #pagecontent edge to edge,
 * the same as any other page's content, with no card border/title bar of its own (an earlier
 * version had both; removed per feedback that it read as extra whitespace around a smaller box
 * rather than a full page). The only remaining trade-off: if a given report ever refuses to be
 * framed (cross-origin X-Frame-Options — invisible to script either way), there's no longer a
 * built-in "open in new tab" escape hatch in the embed itself.
 */
#content.bpbytes-content .bpbytes-embed-frame {
    display: flex;
    height: calc(100vh - var(--bp-topbar-height) - var(--bp-footer-total, var(--bp-footer-height)) - 64px);
}

#content.bpbytes-content .bpbytes-embed-frame__iframe {
    flex: 1 1 auto;
    width: 100%;
    height: 100%;
    border: none;
}

/*
 * Mini calendar date-picker popup (YUI's Calendar widget — every date field's calendar-trigger
 * icon, and the Calendar module's own header) — re-pointing a handful of the "sam" skin's
 * hardcoded colors (loaded via _head.tpl) at the theme's own palette instead of YUI's defaults.
 * Everything else (layout, borders, hover/selected/disabled states) comes from that skin as-is.
 */
.yui-skin-sam .yui-calcontainer {
    /* NOT position:absolute here (an earlier, wrong fix for the "showing over the sidebar" bug —
       the actual cause was the outer YAHOO.widget.SimpleDialog wrapper missing position:absolute,
       fixed by loading container.css above; forcing this INNER element absolute too left it with
       no JS-computed top/left of its own to size against, which is what produced the double,
       misaligned box). Structural calendar.css's own position:relative is correct here — this
       container just needs to sit in normal flow inside the dialog body that positions it. */
    /* Borderless/transparent — the outer SimpleDialog's .yui-panel already carries its own
       border/shadow/radius/background below, and having BOTH nested elements each draw one
       produced two overlapping cards instead of a single one enclosing the whole widget. */
    background-color: transparent;
    border: none;
    /* Structural calendar.css floats this (meant for laying out multiple calendar-group pages
       side by side, irrelevant for a single calendar like this one) — left floated, its
       dynamically-id'd parent div never clears it, so that parent's box collapses to roughly
       zero height and the panel's own white background/border stopped right after "Today"
       while the floated grid itself kept rendering, visibly escaping past that boundary
       unbordered. Un-floating it lets it contribute its real height normally instead. */
    float: none;
    box-shadow: none;
    font-family: var(--bp-font);
}

.yui-skin-sam .yui-calcontainer .title {
    background: var(--bp-surface);
    border-bottom: 1px solid var(--bp-border);
    color: var(--bp-text);
}

.yui-skin-sam .yui-calendar td.calcell {
    border-color: var(--bp-border);
    background: var(--bp-surface);
}

.yui-skin-sam .yui-calendar td.calcell a {
    color: var(--bp-primary);
}

.yui-skin-sam .yui-calendar td.calcell.calcellhover,
.yui-skin-sam .yui-calendar td.calcell.calcellhover a {
    background-color: var(--bp-primary);
    color: #fff;
}

.yui-skin-sam .yui-calendar td.calcell.selected a {
    background-color: var(--bp-primary-soft);
    color: var(--bp-primary);
    font-weight: 700;
}

.yui-skin-sam .yui-calendar td.calcell.today {
    background-color: var(--bp-accent);
}

.yui-skin-sam .yui-calendar td.calcell.oom,
.yui-skin-sam .yui-calendar td.calcell.oom a {
    background-color: var(--bp-surface-alt);
    color: var(--bp-text-faint);
}

/* The calendar-trigger icon's YAHOO.widget.SimpleDialog wrapper (container.css, loaded above) —
   its own gray/sprite-based chrome re-pointed at the theme's palette. Doesn't touch #ajaxloading,
   which is ID-scoped and wins over these class-only selectors regardless. */
.yui-skin-sam .yui-panel-container.cal_panel .yui-panel {
    border-color: var(--bp-border-strong);
    background: var(--bp-surface);
    box-shadow: var(--bp-shadow-lg);
    border-radius: var(--bp-radius);
    /* .hd/.bd below have their own flat-cornered background colors — without clipping to the
       parent's rounded shape, tiny square corners of those backgrounds would peek out past the
       rounded border. */
    overflow: hidden;
}

.yui-skin-sam .yui-panel-container.cal_panel .yui-panel .hd {
    background: var(--bp-surface-alt);
    border-color: var(--bp-border-strong);
    color: var(--bp-text);
}

.yui-skin-sam .yui-panel-container.cal_panel .yui-panel .bd {
    background: var(--bp-surface);
    border-color: var(--bp-border-strong);
}

.yui-skin-sam .yui-panel-container.cal_panel #callnav_today {
    color: var(--bp-primary);
}

::selection {
    background: var(--bp-accent-soft);
}

/* Scrollbars inside content area */
#content.bpbytes-content ::-webkit-scrollbar {
    height: 8px;
    width: 8px;
}

#content.bpbytes-content ::-webkit-scrollbar-thumb {
    background: var(--bp-border-strong);
    border-radius: 4px;
}

/*
 * YUI2 DataTable (YAHOO.widget.DataTable / ScrollingDataTable) — used by Studio's "Fields" list
 * (modules/ModuleBuilder/tpls/MBModule/fields.tpl, #field_table) and other admin screens built on
 * the same widget. SuiteP "just works" here because its own bundled style.css hard-bakes in the
 * full YUI2 DataTable sam-skin CSS, loaded globally; BPBytes ships its own style.css instead (see
 * the #ajaxStatusDiv comment above for the same situation) and never carried any .yui-dt-* rule
 * over, so the widget's header/scroll-body wrapper divs had no overflow/height/border rules at
 * all and rendered as a collapsed sliver instead of an actual table.
 */
#content.bpbytes-content .yui-dt {
    position: relative;
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius);
    background: var(--bp-surface);
}

#content.bpbytes-content .yui-dt table {
    border-collapse: collapse;
    width: 100%;
}

#content.bpbytes-content .yui-dt-scrollable .yui-dt-hd {
    overflow: hidden;
}

#content.bpbytes-content .yui-dt-scrollable .yui-dt-bd {
    overflow-y: auto;
    overflow-x: hidden;
    max-height: 420px;
}

#content.bpbytes-content .yui-dt th {
    background: var(--bp-surface-alt);
    padding: 8px 10px;
    text-align: left;
    font-size: 12.5px;
    font-weight: 700;
    color: var(--bp-text-muted);
    border-bottom: 1px solid var(--bp-border);
    white-space: nowrap;
}

#content.bpbytes-content .yui-dt th .yui-dt-liner {
    padding: 0;
}

#content.bpbytes-content .yui-dt td {
    padding: 8px 10px;
    font-size: 13px;
    color: var(--bp-text);
    border-bottom: 1px solid var(--bp-border);
    vertical-align: middle;
}

#content.bpbytes-content .yui-dt td .yui-dt-liner {
    overflow: hidden;
    text-overflow: ellipsis;
}

#content.bpbytes-content .yui-dt tr.yui-dt-even {
    background: var(--bp-surface);
}

#content.bpbytes-content .yui-dt tr.yui-dt-odd {
    background: var(--bp-surface-alt);
}

#content.bpbytes-content .yui-dt tr.yui-dt-selected td {
    background: var(--bp-primary-soft);
}

/*
 * YUI2 Layout Manager (Studio's three-region "Modules" / center / "Help" screen, #mblayout) —
 * now that layout.css/layout-skin.css (loaded in _head.tpl) give it working structure/positioning,
 * its stock skin underneath is the raw YUI2 look: a hard blue sprite-image header bar, bold white
 * Arial text, square 2005-era borders. Re-pointing it at BPBytes's own tokens instead.
 */
#content.bpbytes-content .yui-layout {
    background-color: var(--bp-surface-alt);
}

#content.bpbytes-content .yui-layout-hd {
    background: var(--bp-title);
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius) var(--bp-radius) 0 0;
}

#content.bpbytes-content .yui-layout-unit div.yui-layout-hd h2 {
    font-size: 13px;
    font-weight: 700;
    color: #fff;
    padding: 10px 14px;
    margin: 0;
}

#content.bpbytes-content .yui-layout-unit div.yui-layout-bd {
    border: 1px solid var(--bp-border);
    border-top: none;
    background-color: var(--bp-surface);
}

#content.bpbytes-content .yui-layout-unit div.yui-layout-bd-noft {
    border-bottom: 1px solid var(--bp-border);
}

#content.bpbytes-content .yui-layout-unit div.yui-layout-bd-nohd {
    border-top: 1px solid var(--bp-border);
}

#content.bpbytes-content .yui-layout-clip {
    background-color: var(--bp-surface-alt);
    border: 1px solid var(--bp-border);
}

/*
 * Bootstrap modal popups (custom/include/javascript/custom_popup.js's showCustomPopup()) are
 * appended straight to <body> ($('body').append(...)), entirely outside #content.bpbytes-content
 * — nothing else in this theme reaches them (same reason listview.css needed a separate
 * .modal-body table.list.view rule for the sibling "View X/Y" popups). This covers the modal
 * chrome itself plus the "Submit" form pattern (custom/modules/Users/tpls/add_document.tpl and
 * its siblings): a plain Bootstrap form with no theme styling of its own at all.
 */
.modal-content {
    border-radius: var(--bp-radius-lg);
    border: none;
    box-shadow: var(--bp-shadow-lg);
}

.modal-header {
    padding: 20px 24px;
    border-bottom: 1px solid var(--bp-border);
}

.modal-header .modal-title {
    font-size: 20px;
    font-weight: 700;
    color: var(--bp-text);
}

.modal-header .close {
    font-size: 22px;
    color: var(--bp-text-faint);
    opacity: 1;
    text-shadow: none;
}

.modal-header .close:hover {
    color: var(--bp-text-muted);
}

.modal-body {
    padding: 24px;
}

.modal-footer {
    padding: 16px 24px;
    border-top: 1px solid var(--bp-border);
}

/*
 * "Select PDF Template" picker (custom/include/SugarFields/Fields/Pdf/pdf_template_popup.js,
 * shown when a PDF Report has more than one template). It's built by hand with
 * insertAdjacentHTML() rather than through showCustomPopup(), but reuses the exact same
 * .modal-backdrop/.modal/.modal-dialog/.modal-content/.modal-header/.modal-body/.modal-footer
 * markup so it inherits the one modal chrome above instead of its own one-off styling.
 */
.bpbytes-pdf-template-modal .modal-dialog {
    max-width: 420px;
    margin: 80px auto 0;
}

.bpbytes-pdf-template-list {
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius);
    overflow: hidden;
}

.bpbytes-pdf-template-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    background: var(--bp-surface);
    color: var(--bp-text);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid var(--bp-border);
    transition: background var(--bp-transition);
}

.bpbytes-pdf-template-item:last-child {
    border-bottom: none;
}

.bpbytes-pdf-template-item:hover {
    background: var(--bp-surface-alt);
    color: var(--bp-text);
}

.bpbytes-pdf-template-item__icon {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    background-color: var(--bp-primary);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3C/svg%3E");
}

.modal-body .control-label {
    display: block;
    margin-bottom: 6px;
    font-size: 13px;
    font-weight: 700;
    color: var(--bp-text);
}

.modal-body .form-group {
    margin-bottom: 18px;
}

.modal-body .form-control {
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius);
    font-size: 14px;
    color: var(--bp-text);
    background: var(--bp-surface);
    box-shadow: none;
}

.modal-body .form-control:focus {
    outline: none;
    border-color: var(--bp-primary);
    box-shadow: 0 0 0 3px var(--bp-primary-soft);
}

/* Date-picker trigger — Bootstrap's own glyphicon font isn't loaded by this theme, so
   .glyphicon-calendar rendered as an empty gray box with no visible icon at all; swapped for the
   theme's own SVG mask icon, the same currentColor + mask-image technique used everywhere else. */
.modal-body .input-group.date {
    display: flex;
}

.modal-body .input-group.date .form-control {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

.modal-body .input-group-addon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    flex: 0 0 auto;
    border: 1px solid var(--bp-border);
    border-left: none;
    border-top-right-radius: var(--bp-radius);
    border-bottom-right-radius: var(--bp-radius);
    background: var(--bp-surface-alt);
    color: var(--bp-text-muted);
}

.modal-body .input-group-addon .glyphicon-calendar {
    display: inline-block;
    width: 16px;
    height: 16px;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E");
}

/* File input — modern browsers let ::file-selector-button be styled directly, no JS/markup
   change needed to replace the raw OS-native "Choose file" button. */
.modal-body input[type="file"] {
    font-size: 13px;
    color: var(--bp-text-muted);
}

.modal-body input[type="file"]::file-selector-button {
    padding: 8px 14px;
    margin-right: 10px;
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius);
    background: var(--bp-surface-alt);
    color: var(--bp-text);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}

.modal-body input[type="file"]::file-selector-button:hover {
    background: var(--bp-primary-soft);
    color: var(--bp-primary);
}

/* The remove-attachment "x" carries its own inline style (add_document.tpl/the equivalent JS
   template string) — color/padding/border/border-radius all need !important to win over that. */
.modal-body .attachments_gallery .remove_button {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    width: 18px !important;
    height: 18px !important;
    padding: 0 !important;
    border-radius: 50% !important;
    border: 1px solid var(--bp-danger) !important;
    color: var(--bp-danger) !important;
    text-decoration: none;
    vertical-align: middle;
}

/* Same consistent rounded/padded look for every .btn everywhere it appears — not just inside a
   modal, but the "View 1/1" / "Start Course" style action buttons rendered directly in dashlets,
   listviews, and subpanels too (those live inside #content.bpbytes-content, modals don't, hence
   both selectors below). Previously unstyled anywhere, relying on raw Bootstrap 3 defaults.
   Radius matches the shared .button rule above (var(--bp-radius-sm), not this file's other
   --bp-radius) — .btn and .button are two different class conventions core templates use for
   what's conceptually the same control, and they used to disagree on how rounded it should be. */
#content.bpbytes-content .btn,
.modal-footer .btn,
.modal-body .btn {
    border-radius: var(--bp-radius-sm);
    padding: 6px 12px;
    font-size: 12.5px;
    font-weight: 600;
    text-align: center;
}

/* Bootstrap's default nowrap kept a long label like "Approve/Reject" forced onto one line, which
   is what pushed it past a narrow subpanel/dashlet column's edge in the first place — wrapping
   is the fallback for whenever a label is too long to fit at the smaller size above. max-width
   was tried alongside this first, but some of these columns are defined with a fixed percentage
   width (e.g. bp_ComplianceDocument's dashletviewdefs.php: 'document_action' => width '10%') —
   capping the button itself to that width, rather than just letting it wrap, squeezed its
   padding unevenly for a label wide enough to need it. Wrapping alone doesn't have that problem.
*/
#content.bpbytes-content .btn {
    white-space: normal;
}

/*
 * ListView "Choose columns" dialog (include/ListView/ListViewColumnsFilterDialog.tpl) — a
 * jQuery UI sortable dual-list column chooser with zero styling anywhere before this: bare
 * default <h1> section headers, a plain bulleted <ul> with "Displayed" and "Hidden" just
 * stacked one after another rather than laid out as two parallel drag targets, and a "Save
 * changes" button that never even got the base .modal-footer .btn treatment above since it's
 * missing the .btn class entirely (class="button red", not "btn button red"). Redesigned as two
 * side-by-side cards with a clean draggable-row list in each, colour-accented via the existing
 * .chooserList.green ("Displayed")/.red ("Hidden") classes instead of the raw <h1>s.
 */
#columnsFilterDialog .chooserContent {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto auto;
    column-gap: 20px;
}

#columnsFilterDialog .chooserContent h1 {
    grid-row: 1;
    margin: 0 0 10px;
    padding-bottom: 8px;
    font-size: 14px;
    font-weight: 700;
    color: var(--bp-text);
    border-bottom: 2px solid var(--bp-border);
}

#columnsFilterDialog .chooserContent h1:nth-of-type(1) {
    grid-column: 1;
    border-bottom-color: var(--bp-success);
}

#columnsFilterDialog .chooserContent h1:nth-of-type(2) {
    grid-column: 2;
    border-bottom-color: var(--bp-danger);
}

#columnsFilterDialog .chooserList {
    grid-row: 2;
    list-style: none;
    margin: 0;
    padding: 8px;
    min-height: 220px;
    max-height: 360px;
    overflow-y: auto;
    background: var(--bp-surface-alt);
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius);
}

#columnsFilterDialog .chooserList.green {
    grid-column: 1;
}

#columnsFilterDialog .chooserList.red {
    grid-column: 2;
}

#columnsFilterDialog .chooserList li {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    margin-bottom: 4px;
    background: var(--bp-surface);
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius-sm);
    font-size: 13px;
    color: var(--bp-text);
    cursor: grab;
    box-shadow: var(--bp-shadow-sm);
}

#columnsFilterDialog .chooserList li:last-child {
    margin-bottom: 0;
}

#columnsFilterDialog .chooserList li:hover {
    border-color: var(--bp-primary);
}

/* A small drag-handle glyph (6-dot grip), the same mask-icon technique used everywhere else in
   the theme — makes it visually obvious these rows are draggable, not just clickable text. */
#columnsFilterDialog .chooserList li::before {
    content: "";
    flex: 0 0 auto;
    width: 12px;
    height: 12px;
    background-color: var(--bp-text-faint);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='9' cy='6' r='1'/%3E%3Ccircle cx='9' cy='12' r='1'/%3E%3Ccircle cx='9' cy='18' r='1'/%3E%3Ccircle cx='15' cy='6' r='1'/%3E%3Ccircle cx='15' cy='12' r='1'/%3E%3Ccircle cx='15' cy='18' r='1'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='9' cy='6' r='1'/%3E%3Ccircle cx='9' cy='12' r='1'/%3E%3Ccircle cx='9' cy='18' r='1'/%3E%3Ccircle cx='15' cy='6' r='1'/%3E%3Ccircle cx='15' cy='12' r='1'/%3E%3Ccircle cx='15' cy='18' r='1'/%3E%3C/svg%3E");
}

/* jQuery UI's sortable helper (the element being dragged) — lifted look while in motion. */
#columnsFilterDialog .chooserList li.ui-sortable-helper {
    box-shadow: var(--bp-shadow-lg);
    opacity: 0.95;
}

#columnsFilterDialog #error-displayed-columns {
    grid-row: 3;
    grid-column: 1 / -1;
    margin-top: 10px;
    font-size: 12px;
    color: var(--bp-danger);
}

#columnsFilterDialog #error-displayed-columns:empty {
    display: none;
}

/* The Save button here (class="button red", no .btn) and Close (class="btn button purple
   btn-default") both now come from the shared .modal-content .button / .button.red rules
   above — nothing dialog-specific left to add here. */

/* Session timeout warning (jquery.userTimeout.js): a card under the top bar that turns red for the last 15 seconds. */
.bpbytes-session-banner {
    position: fixed;
    top: calc(var(--bp-topbar-height) + 12px);
    right: 24px;
    z-index: 1100;
    width: min(640px, calc(100% - 48px));
}

@media (max-width: 991px) {
    .bpbytes-session-banner {
        right: 12px;
        left: 12px;
        width: auto;
    }
}

.bpbytes-session-banner__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 16px;
    padding: 14px 18px;
    border: 1px solid var(--bp-border);
    border-left: 4px solid var(--bp-warning);
    border-radius: var(--bp-radius);
    background: var(--bp-surface);
    color: var(--bp-text);
    font-size: 13.5px;
    box-shadow: var(--bp-shadow-lg);
}

.bpbytes-session-banner.is-urgent .bpbytes-session-banner__inner {
    border-left-color: var(--bp-danger);
    background: var(--bp-danger-soft);
}

.bpbytes-session-banner__text {
    flex: 1 1 260px;
    line-height: 1.5;
}

.bpbytes-session-banner__text b {
    color: var(--bp-warning);
    font-variant-numeric: tabular-nums;
}

.bpbytes-session-banner.is-urgent .bpbytes-session-banner__text b {
    color: var(--bp-danger);
}

.bpbytes-session-banner__actions {
    display: flex;
    gap: 8px;
}

.bpbytes-session-banner__stay,
.bpbytes-session-banner__logoff {
    height: var(--bp-btn-h);
    padding: 0 16px;
    border: 1px solid var(--bp-primary);
    border-radius: var(--bp-radius-sm);
    background: var(--bp-primary);
    color: #fff;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}

.bpbytes-session-banner__stay:hover {
    background: var(--bp-primary-hover);
    border-color: var(--bp-primary-hover);
}

.bpbytes-session-banner__logoff {
    border-color: var(--bp-border-strong);
    background: var(--bp-surface);
    color: var(--bp-text);
}

.bpbytes-session-banner__logoff:hover {
    background: var(--bp-surface-alt);
}


.bpbytes-session-banner button:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--bp-primary-soft);
}

/* Worker ID card popup: the markup is the "Worker ID Card" PDF template */
.bpbytes-idcard {
    --idcard-accent: var(--bp-text-faint);
    --idcard-soft: var(--bp-bg);
    overflow: hidden;
    border: 1px solid var(--bp-border);
    border-top: 6px solid var(--idcard-accent);
    border-radius: var(--bp-radius-lg);
    background: var(--bp-surface);
    color: var(--bp-text);
    font-family: var(--bp-font);
}

.bpbytes-idcard.is-good {
    --idcard-accent: var(--bp-success);
    --idcard-soft: var(--bp-success-soft);
}

.bpbytes-idcard.is-bad {
    --idcard-accent: var(--bp-danger);
    --idcard-soft: var(--bp-danger-soft);
}

.bpbytes-idcard__head {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 20px 22px 16px;
}

.bpbytes-idcard__photo {
    flex: 0 0 auto;
    width: 76px;
    height: 76px;
    border-radius: var(--bp-radius);
    background: var(--bp-surface-alt);
    object-fit: cover;
}

.bpbytes-idcard__who {
    min-width: 0;
}

.bpbytes-idcard__name {
    font-size: 20px;
    font-weight: 700;
    line-height: 1.25;
}

.bpbytes-idcard__role {
    margin-top: 2px;
    color: var(--bp-primary);
    font-size: 13.5px;
    font-weight: 600;
}

.bpbytes-idcard__company {
    margin-top: 4px;
    color: var(--bp-text-muted);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.bpbytes-idcard__banner {
    margin: 0 22px;
    padding: 10px 16px;
    border-radius: var(--bp-radius-sm);
    background: var(--idcard-soft);
    color: var(--idcard-accent);
    font-size: 14px;
    font-weight: 700;
    text-align: center;
}

.bpbytes-idcard.is-neutral .bpbytes-idcard__banner {
    color: var(--bp-text-muted);
}

.bpbytes-idcard__main {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 18px 22px;
}

.bpbytes-idcard__qr {
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    color: var(--bp-text-muted);
    font-size: 11px;
    font-weight: 600;
}

.bpbytes-idcard__qr img {
    padding: 6px;
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius);
    background: #fff;
}

.bpbytes-idcard__details {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}

.bpbytes-idcard__key,
.bpbytes-idcard__heading {
    color: var(--bp-text-faint);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.bpbytes-idcard__value {
    margin-top: 2px;
    font-size: 13.5px;
    overflow-wrap: anywhere;
}

.bpbytes-idcard__value:empty::before {
    content: "-";
}

.bpbytes-idcard__compliance {
    padding: 14px 22px 18px;
    border-top: 1px solid var(--bp-border);
    background: var(--bp-surface-alt);
}

.bpbytes-idcard__heading {
    margin-bottom: 4px;
}

.bpbytes-idcard__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 7px 0;
    border-bottom: 1px solid var(--bp-border);
    font-size: 13px;
}

.bpbytes-idcard__row:last-child {
    border-bottom: 0;
}

.bpbytes-idcard__none {
    color: var(--bp-text-faint);
    font-size: 13px;
    font-style: italic;
}

.bpbytes-idcard__pill {
    flex: 0 0 auto;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 700;
}

.bpbytes-idcard__pill.is-good {
    background: var(--bp-success-soft);
    color: var(--bp-success);
}

.bpbytes-idcard__pill.is-bad {
    background: var(--bp-danger-soft);
    color: var(--bp-danger);
}

.bpbytes-idcard__pill.is-neutral {
    background: var(--bp-bg);
    color: var(--bp-text-muted);
}

@media (max-width: 420px) {
    .bpbytes-idcard__main {
        flex-direction: column;
        align-items: stretch;
    }

    .bpbytes-idcard__qr {
        align-self: center;
    }
}

/*
 * Bulk notification popups (Users list: push, SMS, email). A recipient summary on top, the
 * fields, then Cancel / primary action right-aligned. Everything else comes from the shared
 * .modal-body form rules above.
 */
.bpbytes-notify__summary {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 18px;
    padding: 10px 14px;
    border-radius: var(--bp-radius);
    background: var(--bp-primary-soft, #eef2ff);
    color: var(--bp-text);
    font-size: 13px;
}

.bpbytes-notify__icon {
    flex: 0 0 18px;
    height: 18px;
    background: var(--bp-primary);
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
}

.bpbytes-notify__icon--push {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9'/%3E%3Cpath d='M13.7 21a2 2 0 0 1-3.4 0'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9'/%3E%3Cpath d='M13.7 21a2 2 0 0 1-3.4 0'/%3E%3C/svg%3E");
}

.bpbytes-notify__icon--sms {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z'/%3E%3C/svg%3E");
}

.bpbytes-notify__icon--email {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m22 7-10 6L2 7'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='4' width='20' height='16' rx='2'/%3E%3Cpath d='m22 7-10 6L2 7'/%3E%3C/svg%3E");
}

.bpbytes-notify__hint {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    margin-top: 6px;
    font-size: 12px;
    color: var(--bp-text-muted);
}

.bpbytes-notify__actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 22px;
    padding-top: 16px;
    border-top: 1px solid var(--bp-border);
}
