/* ============================================================================
   Value Wholesaler Portal — portal-specific additions + Bootstrap mapping
   ----------------------------------------------------------------------------
   The Value One design system itself is crm.css — a VERBATIM copy from
   Value-CRM (kept verbatim, crm- class names and all, so CRM shell markup,
   components, and future page borrows work copy-paste and the file can be
   re-synced by re-copying). This file layers on top of it:
     1. --vw-* tokens (same values as crm.css's palette) for portal-only rules
     2. Bootstrap 5 component mapping — the pages ported from the ERP are
        Bootstrap/DataTables-based and live inside the CRM shell until they
        are re-skinned to CRM components page by page
     3. Small vw-* shell add-ons (text brand, avatar circle, sign-out form)
   Load order: bootstrap → fontawesome → crm.css → portal.css (this file).
   ============================================================================ */

:root {
    /* Type */
    --vw-font-display: 'Fraunces', 'Iowan Old Style', Cambria, Georgia, serif;
    --vw-font-body:    'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI Variable', 'Segoe UI', sans-serif;
    --vw-font-mono:    'Geist Mono', ui-monospace, 'Cascadia Mono', Menlo, monospace;

    /* Text */
    --vw-text:        #16325c;   /* primary navy */
    --vw-text-strong: #0e2240;   /* headings, active labels */
    --vw-text-muted:  #5e6b7c;   /* secondary copy */
    --vw-text-faint:  #99a4b3;   /* disabled / placeholders */

    /* Surfaces */
    --vw-surface-app:     #f6f7f3;   /* app backdrop */
    --vw-surface-sidebar: #fbfaf5;   /* warm cream */
    --vw-surface-content: #ffffff;
    --vw-surface-subtle:  #fafaf9;
    --vw-hover:           #f1f3ee;

    /* Lines */
    --vw-border:  #e2e0d8;
    --vw-divider: rgba(42, 143, 45, 0.16);

    /* Brand */
    --vw-brand:         #2a8f2d;   /* Value green */
    --vw-brand-strong:  #1f6f22;
    --vw-brand-bg:      #f1f8ed;
    --vw-brand-bg-soft: #f7faf3;

    /* Semantic */
    --vw-link:       #0070d2;
    --vw-link-hover: #005fb2;
    --vw-danger:     #ea001e;
}

/* ── Base ────────────────────────────────────────────────────────────────── */

body {
    font-family: var(--vw-font-body);
    color: var(--vw-text);
    background-color: var(--vw-surface-app);
}

h1, h2, h3, .navbar-brand {
    font-family: var(--vw-font-display);
    color: var(--vw-text-strong);
}

a {
    color: var(--vw-link);
    /* BS4/ERP behavior: links underline on hover only (BS5 underlines always —
       made the NS Stock numbers and grid links look wrong). */
    text-decoration: none;
}
a:hover {
    color: var(--vw-link-hover);
    text-decoration: underline;
}

/* …but never in the shell chrome: the sidebar (brand wordmark, nav items, menus),
   the search overlay, and the tab strip stay underline-free like the CRM. */
aside.crm-sidebar a:hover,
.crm-search-results a:hover,
.crm-avatar-menu a:hover,
.crm-workspace a:hover,
.crm-subtabs-row a:hover,
a.btn:hover {
    text-decoration: none;
}

/* BS5 underlines .btn-link permanently; BS4/ERP underlined on hover only
   ("Don't Know the Exact SKU?", grid × buttons, etc.). */
.btn-link { text-decoration: none; }
.btn-link:hover { text-decoration: underline; }

code {
    font-family: var(--vw-font-mono);
    color: var(--vw-brand-strong);
}

/* ── Bootstrap component mapping ─────────────────────────────────────────── */

.btn-primary {
    --bs-btn-bg: var(--vw-brand);
    --bs-btn-border-color: var(--vw-brand);
    --bs-btn-hover-bg: var(--vw-brand-strong);
    --bs-btn-hover-border-color: var(--vw-brand-strong);
    --bs-btn-active-bg: var(--vw-brand-strong);
    --bs-btn-active-border-color: var(--vw-brand-strong);
    --bs-btn-disabled-bg: var(--vw-brand);
    --bs-btn-disabled-border-color: var(--vw-brand);
    --bs-btn-focus-shadow-rgb: 42, 143, 45;
}

.btn-outline-primary {
    --bs-btn-color: var(--vw-brand-strong);
    --bs-btn-border-color: var(--vw-brand);
    --bs-btn-hover-bg: var(--vw-brand);
    --bs-btn-hover-border-color: var(--vw-brand);
    --bs-btn-active-bg: var(--vw-brand-strong);
    --bs-btn-active-border-color: var(--vw-brand-strong);
    --bs-btn-focus-shadow-rgb: 42, 143, 45;
}

.form-control:focus,
.form-check-input:focus {
    border-color: var(--vw-brand);
    box-shadow: 0 0 0 0.25rem rgba(42, 143, 45, 0.15);
}

.form-check-input:checked {
    background-color: var(--vw-brand);
    border-color: var(--vw-brand);
}

.card {
    border-color: var(--vw-border);
    background-color: var(--vw-surface-content);
}

/* Status badges — the EXACT BS4 palette the ERP's order pages were designed on.
   BS5 shifted these hexes (info went pale cyan, success went dark green) and stopped
   setting text color on plain .bg-* badges, so both are pinned here. */
.badge.bg-primary   { background-color: #007bff !important; color: #fff; }
.badge.bg-success   { background-color: #28a745 !important; color: #fff; }
.badge.bg-info      { background-color: #17a2b8 !important; color: #fff; }
.badge.bg-warning   { background-color: #ffc107 !important; color: #212529; }
.badge.bg-danger    { background-color: #dc3545 !important; color: #fff; }
.badge.bg-secondary { background-color: #6c757d !important; color: #fff; }

/* ── Shell (template navbar/footer) ──────────────────────────────────────── */

.navbar.bg-white {
    background-color: var(--vw-surface-sidebar) !important;
    border-bottom: 1px solid var(--vw-border) !important;
}

.navbar .nav-link.text-dark,
.navbar .btn-link.text-dark {
    color: var(--vw-text) !important;
}

.navbar .nav-link.text-dark:hover,
.navbar .btn-link.text-dark:hover {
    color: var(--vw-brand-strong) !important;
}

.navbar-brand {
    color: var(--vw-brand-strong) !important;
    font-weight: 600;
}

.footer {
    color: var(--vw-text-muted);
    border-top-color: var(--vw-border) !important;
}

/* ── CRM-shell add-ons (portal-specific slots in the copied shell) ───────── */

/* NO .crm-sidebar-head::before override here. The Portal/Viterra layer shrank the CRM's
   28px head spacer to 10px to pull their brand near-left; that override is exactly what
   made this app's sidebar logo sit left of the CRM's. Deleted so crm.css's own centering
   (28px spacer balancing the collapse toggle) applies — the CRM's exact logo position. */

/* .vw-brand-portal (the "Portal"/"CRM" wordmark beside the sidebar logo) also removed:
   this app's sidebar brand is the logo alone, same as the CRM's. */

/* ── AdminLTE card-outline reproduction ──────────────────────────────────── */
/* The ERP's order pages were designed on AdminLTE's `card-outline card-<color>` accents
   (3px colored top border). Reproduced here with the SAME class names + colors so ported
   views keep their carefully-designed look verbatim. */
.card-outline { border-top: 3px solid transparent !important; }
.card-primary.card-outline   { border-top-color: #007bff !important; }
.card-secondary.card-outline { border-top-color: #6c757d !important; }
.card-success.card-outline   { border-top-color: #28a745 !important; }
.card-info.card-outline      { border-top-color: #17a2b8 !important; }
.card-warning.card-outline   { border-top-color: #ffc107 !important; }
.card-danger.card-outline    { border-top-color: #dc3545 !important; }
.card-dark.card-outline      { border-top-color: #343a40 !important; }

/* AdminLTE's card-title sizing, for ported headers that use it. */
.card-title {
    font-size: 1.1rem;
    font-weight: 400;
    margin: 0;
}

/* ── Select2 — Value One skin ────────────────────────────────────────────── */
/* The customer pickers (Catalog "Ordering for", Quick Order, Users) ship with Select2's
   generic gray theme — restyled to the system: navy text, vw borders, brand-green focus
   and highlight, sized like form-select-sm, dropdown shadowed like the shell's menus. */
.select2-container--default .select2-selection--single {
    height: calc(1.5em + 0.5rem + 2px);
    border: 1px solid var(--vw-border);
    border-radius: 0.25rem;
    background: var(--vw-surface-content);
    display: flex;
    align-items: center;
    transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
    color: var(--vw-text);
    font-size: 0.875rem;
    line-height: normal;
    padding-left: 0.5rem;
}
.select2-container--default .select2-selection--single .select2-selection__placeholder {
    color: var(--vw-text-faint);
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
    height: 100%;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
    border-color: var(--vw-text-muted) transparent transparent transparent;
}
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
    border-color: transparent transparent var(--vw-brand) transparent;
}
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--single {
    border-color: var(--vw-brand);
    box-shadow: 0 0 0 0.2rem rgba(42, 143, 45, 0.15);
}
.select2-dropdown {
    border: 1px solid var(--vw-border);
    border-radius: 0.375rem;
    box-shadow: 0 6px 18px rgba(22, 50, 92, 0.14);
    overflow: hidden;
    font-size: 0.875rem;
    color: var(--vw-text);
}
.select2-search--dropdown {
    padding: 0.45rem;
}
.select2-container--default .select2-search--dropdown .select2-search__field {
    border: 1px solid var(--vw-border);
    border-radius: 0.25rem;
    padding: 0.3rem 0.5rem;
    outline: none;
    transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
.select2-container--default .select2-search--dropdown .select2-search__field:focus {
    border-color: var(--vw-brand);
    box-shadow: 0 0 0 0.15rem rgba(42, 143, 45, 0.15);
}
.select2-results__option {
    padding: 0.4rem 0.6rem;
}
.select2-container--default .select2-results__option--highlighted[aria-selected],
.select2-container--default .select2-results__option--highlighted[data-selected] {
    background-color: var(--vw-brand);
    color: #fff;
}
.select2-container--default .select2-results__option[aria-selected=true],
.select2-container--default .select2-results__option[data-selected=true] {
    background-color: var(--vw-brand-bg);
    color: var(--vw-text-strong);
}
.select2-container--default .select2-results > .select2-results__options {
    max-height: 260px;
}

/* ── SweetAlert2 — Value One skin ────────────────────────────────────────── */
/* All Swal dialogs (catalog's "Pick a customer first", Quick Order's submit confirm,
   warnings): Fraunces title, Geist body, Value-green confirm, outlined cancel. The
   !importants beat Swal's inline confirmButtonColor styles so every dialog matches
   without per-call colors. */
.swal2-popup {
    border-radius: 0.75rem;
    padding: 1.75rem;
    font-family: var(--vw-font-body);
    color: var(--vw-text);
}
.swal2-title {
    font-family: var(--vw-font-display);
    color: var(--vw-text-strong);
}
.swal2-content {
    color: var(--vw-text);
    font-size: 0.95rem;
}
.swal2-styled.swal2-confirm {
    background-color: var(--vw-brand) !important;
    border-radius: 0.375rem;
    box-shadow: none;
}
.swal2-styled.swal2-confirm:hover {
    background-color: var(--vw-brand-strong) !important;
}
.swal2-styled.swal2-cancel {
    background-color: #fff !important;
    color: var(--vw-text) !important;
    border: 1px solid var(--vw-border) !important;
    border-radius: 0.375rem;
}
.swal2-styled.swal2-cancel:hover {
    background-color: var(--vw-hover) !important;
}
.swal2-styled:focus {
    box-shadow: 0 0 0 0.2rem rgba(42, 143, 45, 0.25) !important;
}
/* !important because sweetalert2.min.css loads AFTER portal.css on the pages
   (page @section Styles render below the global sheets) and would win the tie. */
.swal2-icon.swal2-info {
    border-color: rgba(0, 112, 210, 0.4) !important;
    color: var(--vw-link) !important;
}
.swal2-icon.swal2-question {
    border-color: rgba(42, 143, 45, 0.4) !important;
    color: var(--vw-brand) !important;
}

/* Quick Order button — purple with a proper hover darken (was an inline style,
   which can't have hover states). */
.vw-btn-quickorder {
    color: #fff;
    background-color: #6f42c1;
    border-color: #6f42c1;
}
.vw-btn-quickorder:hover,
.vw-btn-quickorder:focus {
    color: #fff;
    background-color: #5d37a8;
    border-color: #58339e;
}
.vw-btn-quickorder:active {
    color: #fff;
    background-color: #533093;
    border-color: #4e2d8a;
}

/* Catalog toolbar — ALWAYS one row (owner): as horizontal space tightens, label words are
   dropped progressively; they must NEVER wrap into two-line buttons (flex was compressing
   the buttons before the tiers fired — hence the nowrap + shrink lock below). Tier 1 sheds
   the low-value words ("Ordering for:", "per page"); tier 2 shrinks buttons to icon+verb
   ("Add", "Sync", cart icon) and narrows the search box and customer picker. */
.vw-catalog-card .card-header .btn,
.vw-catalog-card .card-header .cart-icon-btn,
.vw-catalog-card .card-header .fw-bold {
    white-space: nowrap;
    flex-shrink: 0;
}
@media (max-width: 1750px) {
    .vw-tb-t1 { display: none !important; }
}
@media (max-width: 1500px) {
    .vw-tb-t2 { display: none !important; }
    .vw-catalog-card #dtSearchContainer .dataTables_filter input { width: 130px !important; }
    #portalCustomerPicker + .select2-container { width: 190px !important; min-width: 190px !important; }
}
@media (max-width: 1250px) {
    .vw-tb-t3 { display: none !important; }
}

/* The NS-Stock location selector (stock-visible users only) takes ~220px of the same row,
   so for toolbars that contain it every hide tier fires ~230px EARLIER — the row must
   never wrap. Below the last tier the selector itself gives ground (clipped, full name
   in the title tooltip and the open list). */
@media (max-width: 1980px) {
    .vw-catalog-card:has(#nsStockLocSel) .vw-tb-t1 { display: none !important; }
}
@media (max-width: 1730px) {
    .vw-catalog-card:has(#nsStockLocSel) .vw-tb-t2 { display: none !important; }
    .vw-catalog-card:has(#nsStockLocSel) #dtSearchContainer .dataTables_filter input { width: 130px !important; }
    .vw-catalog-card:has(#nsStockLocSel) #portalCustomerPicker + .select2-container { width: 190px !important; min-width: 190px !important; }
}
@media (max-width: 1480px) {
    .vw-catalog-card:has(#nsStockLocSel) .vw-tb-t3 { display: none !important; }
}
@media (max-width: 1250px) {
    #nsStockLocSel { max-width: 150px; }
}

/* DataTables pagination — Value One skin (the catalog grids in both modules). Bootstrap's
   default blue active page clashed with the system; active = brand green, quiet borders,
   green focus ring. ERP-shell pages (Audit Logs, Login History) keep AdminLTE's look. */
.dataTables_wrapper .pagination .page-link {
    color: var(--vw-text);
    border-color: var(--vw-border);
    padding: 0.25rem 0.6rem;
    font-size: 0.85rem;
}
.dataTables_wrapper .pagination .page-link:hover {
    background-color: var(--vw-brand-bg);
    color: var(--vw-brand-strong);
    text-decoration: none;
}
.dataTables_wrapper .pagination .page-item.active .page-link {
    background-color: var(--vw-brand);
    border-color: var(--vw-brand);
    color: #fff;
}
.dataTables_wrapper .pagination .page-item.disabled .page-link {
    color: var(--vw-text-faint);
}
.dataTables_wrapper .pagination .page-link:focus {
    box-shadow: 0 0 0 0.2rem rgba(42, 143, 45, 0.15);
}

/* Segmented control (Orders page's My/Internal/All filter) — modern pill style: a soft
   rounded track, the active option a raised white pill with brand-green text (same accent
   language as the sidebar's active item). */
.vw-seg {
    display: inline-flex;
    align-items: center;
    background: var(--vw-hover);
    border: 1px solid var(--vw-border);
    border-radius: 999px;
    padding: 3px;
    gap: 2px;
}
.vw-seg .vw-seg-opt {
    border: 0;
    background: transparent;
    color: var(--vw-text-muted);
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1;
    padding: 0.42rem 0.9rem;
    border-radius: 999px;
    text-decoration: none;
    white-space: nowrap;
    transition: background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.vw-seg .vw-seg-opt:hover {
    color: var(--vw-text-strong);
    text-decoration: none;
}
.vw-seg .vw-seg-opt.active {
    background: var(--vw-surface-content);
    color: var(--vw-brand-strong);
    box-shadow: 0 1px 3px rgba(22, 50, 92, 0.18);
}

/* Clickable order numbers — brand green; the NetSuite SO# wears the NetSuite navy
   (swapped by owner request: green = ours, navy = NetSuite's number). */
.vw-order-link {
    color: var(--vw-brand-strong);
}
.vw-order-link:hover {
    color: #17541a;
}
.vw-so-num {
    color: #003865 !important;
}
a.vw-so-num:hover {
    color: #002a4d !important;
}

/* NetSuite-branded indicator color — the same navy the "Sync NetSuite" button wears
   (#003865, NetSuite's theme color). Used for NetSuite-related badges/timeline points
   instead of Bootstrap's light-blue bg-info. */
.vw-bg-nsnavy {
    background-color: #003865 !important;
    color: #fff !important;
}

/* "Viewing as" bar — internal preview of the Wholesaler Portal (layout-rendered, customers
   never see it). Soft amber so it reads as a preview notice, not part of the storefront. */
.vw-viewas-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 1rem;
    background: #fff8e6;
    border-bottom: 1px solid #f0e2bb;
    color: #7a5d1c;
    font-size: 0.85rem;
}
.vw-viewas-bar .fa-eye { color: #b08a2e; }
.vw-viewas-bar .vw-viewas-label { font-weight: 600; white-space: nowrap; }
.vw-viewas-bar .select2-container { max-width: 300px; }

/* Soft Value-blue modal header (stock-by-location popup, etc.) — light blue tint with
   the system's navy heading, instead of Bootstrap's loud teal bg-info. */
.vw-modal-header-blue {
    background-color: #e8f1fb;
    color: var(--vw-text-strong);
    border-bottom: 1px solid #cfe2f6;
}
.vw-modal-header-blue .modal-title { color: var(--vw-text-strong); }

/* Font Awesome glyph sitting in a CRM sidebar icon slot (used where SLDS has no
   matching glyph, e.g. the Quick Order lightning). Sized/colored like the SLDS icons. */
.crm-sidebar-item-icon .vw-fa-nav-icon {
    font-size: 17px;
    line-height: 1;
}

/* NO .crm-sidebar-item sizing overrides here. The Portal/Viterra layer sized nav items up
   one step; removed so crm.css's own 13px/8px applies — the CRM sidebar, exactly. */

/* Sidebar text one shade darker than the CRM's for readability: items muted→full text
   color, icons and eyebrows faint→muted. Colors only — sizing/spacing stay crm.css's. */
.crm-sidebar-item { color: var(--crm-text); }
.crm-sidebar-item-icon { color: var(--crm-text-muted); }
.crm-sidebar-eyebrow { color: var(--crm-text-muted); }

/* Sign-out lives in a <form> (antiforgery POST) inside the CRM's avatar-menu bottom row —
   display:contents makes the button a direct flex child of .crm-avatar-menu-row, so the
   Exit/Sign Out split renders exactly as the CRM's (button styling comes from
   .crm-avatar-menu-signout in crm.css). */
.vw-signout-form { display: contents; }

/* ── Confirm modal — Max asks the question ───────────────────────────────── */
/* Layout for the crmConfirm dialog body: Max (question-marks sticker) beside the
   message text. The sticker has a white background, invisible on the white card. */
.vt-confirm-row {
    display: flex;
    align-items: center;
    gap: 14px;
    text-align: left;
}
.vt-confirm-max {
    width: 122px;   /* Max is the one asking — let him be seen */
    height: auto;
    flex-shrink: 0;
}

/* Confirm-dialog-only chrome tweaks: slimmer top/bottom bands (it's a one-line
   question, not a form) and Viterra-navy accents so the card reads on-brand. */
.crm-confirm-dialog .crm-post-modal-header {
    padding: 10px 18px;
    border-bottom: 2px solid var(--crm-brand);
}
.crm-confirm-dialog .crm-post-modal-header h3 {
    /* Fraunces looks cramped below ~18px — keep the title at a size the serif carries. */
    font-size: 19px;
    color: var(--crm-brand-strong);
}
.crm-confirm-dialog .crm-post-modal-footer {
    padding: 10px 18px;
    background: var(--crm-brand-bg-soft);
    border-top: 1px solid var(--crm-brand-bg);
}
.crm-confirm-dialog .crm-confirm-message {
    font-size: 15px;
}


/* ============================================================================
   ValueCMMS app-layer additions.
   crm.css is vendored verbatim from Value-CRM and must never be edited, so
   anything this app needs beyond it lives here.
   ============================================================================ */

/* Overdue dates, low stock — the CRM has .crm-btn-danger but no text utility. */
.crm-text-danger { color: var(--crm-danger); font-weight: 600; }




/* ── Work-order record: photos, docs, checklist, feed; Files page thumbs ───── */

.cmms-photo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
    gap: 10px;
    margin-bottom: 0.75rem;
}
.cmms-photo-tile {
    display: block;
    aspect-ratio: 4 / 3;
    border: 1px solid var(--crm-border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--crm-surface-subtle);
}
.cmms-photo-tile img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 120ms ease;
}
.cmms-photo-tile:hover img { transform: scale(1.04); }

.cmms-doc-line {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 2px;
    border-top: 1px solid var(--crm-border);
    font-size: 13px;
}
.cmms-doc-line:first-of-type { border-top: 0; }
.cmms-doc-line svg { width: 15px; height: 15px; fill: var(--crm-text-muted); flex-shrink: 0; }
.cmms-doc-line .crm-placeholder-text { margin-left: auto; }

/* ── Photos & files on a work order ───────────────────────────────────────── */
/* The carousel above is for looking; this strip is for managing. Thumbs are small
   on purpose — it is a management view, not a second gallery. */
.cmms-att-thumbs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 10px;
}

.cmms-att-thumb {
    position: relative;
    width: 62px;
    height: 62px;
}

.cmms-att-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--crm-border);
    display: block;
}

/* Sits over the corner of the thumbnail. Kept at 22px so it stays a comfortable
   tap target on a phone, which is where most of these get taken. */
.cmms-att-remove {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1px solid var(--crm-border);
    background: var(--crm-surface-content);
    color: var(--crm-text-muted);
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}

.cmms-att-remove:hover,
.cmms-doc-remove:hover { color: var(--crm-text-strong); }

.cmms-doc-remove {
    border: 0;
    background: none;
    color: var(--crm-text-muted);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    padding: 0 2px;
    margin-left: 8px;
}
/* The size label claims margin-left:auto, so the remove button must not also push. */
.cmms-doc-line .crm-placeholder-text + .cmms-doc-remove { margin-left: 8px; }

.cmms-att-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
}

/* A <label> wrapping a hidden file input — styled as a button, so it needs the
   pointer cursor a real button gets for free. */
.cmms-att-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
}

.cmms-att-btn svg { width: 15px; height: 15px; fill: currentColor; }

.cmms-att-status { font-size: 12px; }

/* ── Register create/edit forms (cmms-record-form.js) ─────────────────────── */
/* Everything under here is filled on a minority of records, so it starts closed —
   the common case is a short form. */
.cmms-form-more {
    margin-top: 14px;
    border-top: 1px solid var(--crm-border);
    padding-top: 10px;
}

.cmms-form-more > summary {
    cursor: pointer;
    font-size: 12px;
    font-weight: 700;
    color: var(--crm-text-strong);
    list-style: none;
    padding: 4px 0;
}

.cmms-form-more > summary::-webkit-details-marker { display: none; }

.cmms-form-more > summary::before {
    content: "\25B8";               /* right-pointing triangle; rotates when open */
    display: inline-block;
    margin-right: 6px;
    transition: transform 120ms ease;
}

.cmms-form-more[open] > summary::before { transform: rotate(90deg); }

.cmms-record-form-error {
    padding: 0 0 10px;
    font-size: 12px;
}

/* Edit button sitting beside a detail panel's title. */
.cmms-detail-head-actions {
    margin-top: 8px;
    display: flex;
    gap: 8px;
}

/* Checkbox lines in a record form (non-stock, critical spare…). */
.cmms-mini-check {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 8px 0;
    font-size: 13px;
    cursor: pointer;
}

.cmms-mini-check input { margin-top: 2px; flex-shrink: 0; }

/* A multi-select needs to show several rows without becoming a wall. */
.cmms-multi-select {
    min-height: 84px;
    padding: 4px;
}

.cmms-field-hint {
    display: block;
    margin: -4px 0 8px;
    font-size: 11px;
}

/* Free-text instructions on a PM plan — authored with line breaks that carry meaning
   (step lists, part numbers one per line), so they are preserved. */
.cmms-detail-note {
    white-space: pre-wrap;
    font-size: 13px;
    line-height: 1.5;
}

/* Weekday picker in the recurrence editor. Seven boxes that must stay tappable and must
   wrap rather than scroll on a phone. */
.cmms-daypick {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 10px;
}

.cmms-daypick-day {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 9px;
    border: 1px solid var(--crm-border);
    border-radius: 6px;
    font-size: 12px;
    cursor: pointer;
    user-select: none;
}

.cmms-daypick-day:has(input:checked) {
    border-color: var(--crm-brand, #2e7d32);
    background: var(--crm-hover);
    font-weight: 600;
}

/* ── One-time password + account actions (People) ─────────────────────────── */
/* Deliberately loud. This is the only moment the password exists anywhere a person can
   read it, so it must not look like another field on a form. */
.cmms-temp-password {
    margin: 12px 0 4px;
    padding: 12px 14px;
    border: 2px solid var(--crm-brand, #2e7d32);
    border-radius: 8px;
    background: var(--crm-surface-subtle);
}

.cmms-temp-password-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--crm-text-strong);
    margin-bottom: 6px;
}

.cmms-temp-password code {
    display: inline-block;
    font-size: 19px;
    font-weight: 700;
    letter-spacing: .06em;
    /* Selectable in one gesture — people copy this by hand into a message. */
    user-select: all;
    padding: 4px 8px;
    border-radius: 6px;
    background: var(--crm-hover);
}

.cmms-note-box {
    margin: 10px 0;
    padding: 10px 12px;
    border-left: 3px solid var(--crm-border);
    background: var(--crm-surface-subtle);
    font-size: 12px;
    line-height: 1.5;
}

.cmms-account-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}

/* ── The ⋯ menu on a detail panel ─────────────────────────────────────────── */
/* Anchored top-right of the panel head, out of the way of the title, which can run to
   several lines on a bilingual work order. */
/* In the flow at the end of the meta row, pinned right. Relative only so the dropdown
   below can anchor to it. */
.cmms-kebab {
    position: relative;
    margin-left: auto;
}

/* Always a visible chip, never a bare glyph. This sits at the top of a panel whose
   backdrop can be a photo, so "transparent with muted text" disappears entirely against
   anything but an empty record — which is exactly how it was first shipped. */
.cmms-kebab-btn {
    border: 1px solid var(--crm-border);
    background: var(--crm-surface-content);
    color: var(--crm-text-strong);
    font-size: 17px;
    line-height: 1;
    padding: 3px 9px;
    border-radius: 6px;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
}

.cmms-kebab-btn:hover {
    background: var(--crm-hover);
}

.cmms-kebab-menu {
    position: absolute;
    top: 100%;
    right: 0;
    z-index: 20;
    min-width: 168px;
    padding: 4px;
    border: 1px solid var(--crm-border);
    border-radius: 8px;
    background: var(--crm-surface-content);
    box-shadow: 0 6px 20px rgba(0, 0, 0, .13);
}

.cmms-kebab-item {
    display: block;
    width: 100%;
    padding: 7px 10px;
    border: 0;
    border-radius: 6px;
    background: none;
    text-align: left;
    font-size: 13px;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

.cmms-kebab-item:hover { background: var(--crm-hover); }

/* ── Feed composer (contenteditable, so the mention picker can attach) ─────────── */
.cmms-composer-editor {
    min-height: 54px;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}
/* A contenteditable has no placeholder attribute; paint one until there is content. */
.cmms-composer-editor:empty::before {
    content: attr(data-placeholder);
    color: var(--crm-text-faint);
    pointer-events: none;
}

/* ── Notifications page (the bell's "view all") — the bell's own row styling, full width ── */
.cmms-notif-page {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 8px 0;
}
.cmms-notif-page-item {
    width: 100%;
    text-align: left;
}

/* Total line under a cost breakdown — ruled off and bold, the way a figure people
   read off a screen should be. */
.cmms-cost-total {
    border-top: 1px solid var(--crm-border);
    margin-top: 4px;
    padding-top: 6px;
    font-weight: 700;
}

/* ── Invoice form (Views/WorkOrders/_WorkOrderInvoice.cshtml) ─────────────── */
/* Line rows are a fixed grid so the amounts column lines up with the totals below it. */
.cmms-inv-lines { margin-top: 4px; }
.cmms-inv-row {
    display: grid;
    grid-template-columns: 74px minmax(0, 1fr) 64px 78px 78px 22px;
    gap: 6px;
    align-items: center;
    padding: 4px 0;
    border-top: 1px solid var(--crm-border);
}
.cmms-inv-row:first-of-type { border-top: 0; }
.cmms-inv-row--head {
    font-size: 11px;
    font-weight: 700;
    color: var(--crm-text-muted);
    padding-bottom: 2px;
}
.cmms-inv-row--head span:nth-child(n+3) { text-align: right; }
.cmms-inv-row .cmms-mini-input { padding: 5px 7px; font-size: 12.5px; }
.cmms-inv-num { text-align: right; }
.cmms-inv-amount {
    text-align: right;
    font-size: 12.5px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.cmms-inv-remove {
    width: 22px; height: 22px;
    border: 0; border-radius: 6px;
    background: transparent;
    color: var(--crm-text-muted);
    font-size: 16px; line-height: 1;
    cursor: pointer;
}
.cmms-inv-remove:hover { background: var(--crm-surface-2, #f1f3f2); color: var(--crm-text); }

.cmms-inv-totals {
    margin: 12px 0 4px auto;
    width: 260px;
    max-width: 100%;
}
.cmms-inv-total-line {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    padding: 4px 0;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
}
.cmms-inv-total-line > span:first-child { color: var(--crm-text-muted); }
.cmms-inv-total-line--sum {
    border-top: 1px solid var(--crm-border);
    margin-top: 2px;
    padding-top: 6px;
    font-weight: 700;
}
.cmms-inv-total-line--sum > span:first-child { color: var(--crm-text); }
.cmms-inv-total-input .cmms-mini-input { width: 96px; padding: 4px 7px; font-size: 12.5px; }

/* System Settings: the company block form sits on a list page, not in the panel — its own
   block, not a table wrap (that has a capped height and its own scrollbar). */
.cmms-admin-form-wrap {
    background: #fff;
    border-bottom: 1px solid var(--crm-border);
    padding: 10px 16px 14px;
}
.cmms-admin-form { max-width: 720px; }
.cmms-admin-form .cmms-mini-actions { justify-content: flex-start; margin-top: 12px; }

/* ── Repeatable rows (checklist steps) ────────────────────────────────────── */
.cmms-rows {
    margin-bottom: 8px;
    counter-reset: cmms-step;
}

.cmms-row {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin-bottom: 6px;
    counter-increment: cmms-step;
}

/* The step number. Fixed width so the labels line up however many digits it has.
   Counted in CSS, not written into the markup: rows are added, removed and reordered
   after render, and anything stamped server-side is wrong the moment someone presses
   Add step. The number is the row's POSITION, which is exactly what a counter gives. */
.cmms-row-handle {
    flex: 0 0 22px;
    padding-top: 7px;
    font-size: 11px;
    color: var(--crm-text-muted);
    text-align: right;
}

.cmms-row-handle::before { content: counter(cmms-step); }

/* The step text takes the room; a long instruction is the common case, so it grows. */
.cmms-row-label {
    flex: 1 1 auto;
    min-height: 34px;
    resize: vertical;
}

/* Wide enough for the longest type name ("Multiple choice") to read in full when the
   select is CLOSED — a step whose type you cannot see is a step you cannot check. */
.cmms-row-type { flex: 0 0 138px; }

.cmms-row-btn {
    flex: 0 0 auto;
    width: 26px;
    height: 30px;
    border: 1px solid var(--crm-border);
    border-radius: 6px;
    background: var(--crm-surface-content);
    color: var(--crm-text-muted);
    cursor: pointer;
    line-height: 1;
    padding: 0;
}

.cmms-row-btn:hover {
    color: var(--crm-text-strong);
    background: var(--crm-hover);
}

/* On a phone the controls wrap under the text rather than squeezing it to nothing. */
@media (max-width: 560px) {
    .cmms-row { flex-wrap: wrap; }
    .cmms-row-label { flex: 1 1 100%; }
    .cmms-row-type { flex: 1 1 auto; }
}

.cmms-file-thumb-cell { width: 56px; }
.cmms-file-thumb {
    width: 48px;
    height: 36px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--crm-border);
    display: block;
}

.cmms-signature-img {
    max-width: 260px;
    max-height: 110px;
    border: 1px solid var(--crm-border);
    border-radius: 8px;
    background: #fff;
    padding: 4px;
}

.cmms-check-line {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    padding: 5px 2px;
    font-size: 13px;
    border-top: 1px solid var(--crm-border);
}
.cmms-check-line:first-of-type { border-top: 0; }
.cmms-check-mark svg { width: 13px; height: 13px; fill: var(--crm-text-faint); }
.cmms-check-line.is-done .cmms-check-mark svg { fill: var(--crm-brand); }
.cmms-check-line.is-done .cmms-check-label { color: var(--crm-text-muted); }
.cmms-check-status {
    font-size: 11px;
    font-weight: 600;
    color: var(--crm-gauge-yellow-text);
    text-transform: uppercase;
}
.cmms-check-value {
    flex-basis: 100%;
    color: var(--crm-text-muted);
    padding-left: 21px;
    white-space: pre-line;
}

.cmms-feed-item {
    padding: 8px 2px;
    border-top: 1px solid var(--crm-border);
    font-size: 13px;
}
.cmms-feed-item:first-of-type { border-top: 0; }
.cmms-feed-meta { display: flex; gap: 10px; align-items: baseline; margin-bottom: 2px; }
.cmms-feed-author { font-weight: 600; color: var(--crm-text-strong); }
.cmms-feed-when { color: var(--crm-text-faint); font-size: 12px; }
.cmms-feed-text { color: var(--crm-text); white-space: pre-line; }

.cmms-part-line {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    padding: 5px 2px;
    font-size: 13px;
    border-top: 1px solid var(--crm-border);
}
.cmms-part-line:first-of-type { border-top: 0; }
.cmms-part-qty { color: var(--crm-text-muted); white-space: nowrap; }


/* ── Interactive list tables: filter bar, sort arrows, load more ───────────── */

.cmms-filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 10px 1.25rem 0;
}
.cmms-filter-bar select {
    max-width: 200px;
    padding: 5px 26px 5px 10px;
    font-size: 12.5px;
    color: var(--crm-text);
    background-color: var(--crm-surface-content);
    border: 1px solid var(--crm-border);
    border-radius: 6px;
    appearance: auto;
    cursor: pointer;
}
.cmms-filter-bar select:focus {
    border-color: var(--crm-brand);
    outline: none;
    box-shadow: 0 0 0 2px rgba(42, 143, 45, 0.15);
}
.cmms-filter-reset {
    font-size: 12.5px;
    color: var(--crm-link);
    margin-left: 4px;
    white-space: nowrap;
}

th.cmms-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
th.cmms-sortable:hover { color: var(--crm-text-strong); }
th.cmms-sortable::after {
    content: '\2195';           /* ↕ idle */
    margin-left: 5px;
    font-size: 10px;
    color: var(--crm-text-faint);
}
th.cmms-sortable.is-sort-asc::after  { content: '\25B2'; color: var(--crm-brand-strong); }  /* ▲ */
th.cmms-sortable.is-sort-desc::after { content: '\25BC'; color: var(--crm-brand-strong); }  /* ▼ */

.cmms-load-more {
    display: flex;
    justify-content: center;
    padding: 12px 0 16px;
}


/* Multi-select filter chip (UpKeep's "Status: Open +2") */
.cmms-multi { position: relative; display: inline-block; }
.cmms-multi-btn {
    padding: 5px 12px;
    font-size: 12.5px;
    color: var(--crm-text);
    background-color: var(--crm-surface-content);
    border: 1px solid var(--crm-border);
    border-radius: 6px;
    cursor: pointer;
    white-space: nowrap;
}
.cmms-multi-btn::after {
    content: '\25BE';
    margin-left: 6px;
    color: var(--crm-text-faint);
    font-size: 10px;
}
.cmms-multi-btn:hover { border-color: var(--crm-brand); }
.cmms-multi-panel {
    position: absolute;
    z-index: 60;
    top: calc(100% + 4px);
    left: 0;
    min-width: 180px;
    background: var(--crm-surface-content);
    border: 1px solid var(--crm-border);
    border-radius: 10px;
    box-shadow: 0 10px 30px rgba(22, 50, 92, 0.14);
    padding: 6px;
}
.cmms-multi-option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    font-size: 13px;
    border-radius: 6px;
    cursor: pointer;
    white-space: nowrap;
}
.cmms-multi-option:hover { background: var(--crm-hover); }
.cmms-multi-option input { accent-color: var(--crm-brand); cursor: pointer; }


.cmms-multi-search {
    width: calc(100% - 12px);
    margin: 4px 6px 6px;
    padding: 5px 9px;
    font-size: 12.5px;
    border: 1px solid var(--crm-border);
    border-radius: 7px;
    color: var(--crm-text);
}
.cmms-multi-search:focus { outline: none; border-color: var(--crm-brand); }
.cmms-multi-options { max-height: 260px; overflow-y: auto; }
.cmms-multi-panel { max-width: 320px; }
.cmms-multi-option { white-space: normal; }

/* ── Cool-tint theme experiment (Quick Settings toggle, per device) ──────────
   The Value One system uses warm cream surfaces (crm.css: #f6f7f3 app, #fbfaf5
   sidebar, #e2e0d8 borders). UpKeep uses cool neutral grays. html.cmms-cool
   re-tokens ONLY surfaces and lines to the cool ramp — brand green, type and
   layout untouched — so the two tints can be compared live on the same pages.
   Delete this block (and the toggle) once a winner is picked. */
html.cmms-cool {
    --crm-surface-app:     #f5f6f8;
    --crm-surface-sidebar: #fafbfc;
    --crm-surface-content: #ffffff;
    --crm-surface-subtle:  #f8f9fb;
    --crm-hover:           #eef1f4;
    --crm-border:          #e4e6ea;
    --crm-border-subtle:   #eaf1ee;
    --crm-brand-bg:        #edf6ec;
    --crm-brand-bg-soft:   #f4faf3;
    --vw-surface-app:      #f5f6f8;
    --vw-surface-sidebar:  #fafbfc;
    --vw-surface-content:  #ffffff;
    --vw-surface-subtle:   #f8f9fb;
    --vw-hover:            #eef1f4;
    --vw-border:           #e4e6ea;
    --vw-brand-bg:         #edf6ec;
    --vw-brand-bg-soft:    #f4faf3;
}

/* ── Resizable list-table columns (initCmmsColResize) ────────────────────────
   Grip = a slim hit area hugging each header's right edge; its ::after paints
   the visible line. is-col-fixed lands on the first drag (or on load when a
   device has saved widths): fixed layout + single-line ellipsis cells, so one
   column can change width without reflowing the rest. */
table[data-resize-key] thead th { position: relative; }
/* The resizer stores and re-applies offsetWidth (border-box). Under the default
   content-box, a re-applied width gains the 24px of cell padding on EVERY load —
   columns crept wider each visit and never matched what was dragged. */
table[data-resize-key] thead th,
table[data-resize-key] tbody td { box-sizing: border-box; }

.cmms-col-grip {
    position: absolute;
    top: 0;
    right: 0;
    width: 8px;
    height: 100%;
    cursor: col-resize;
    user-select: none;
    z-index: 2;
}

.cmms-col-grip::after {
    content: '';
    position: absolute;
    top: 22%;
    bottom: 22%;
    right: 3px;
    width: 1px;
    background: var(--crm-border);
}

.cmms-col-grip:hover::after {
    background: var(--crm-brand-strong);
    width: 2px;
}

.crm-list-table.is-col-fixed { table-layout: fixed; }

.crm-list-table.is-col-fixed thead th,
.crm-list-table.is-col-fixed tbody td {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── In-place field translation (cmms-translate.js) ──────────────────────────
   Translated text replaces the original inside the same element, so the only
   footprint is this marker: a soft brand-green wash + dashed underline that
   says "this was translated" without costing any layout space. Hover shows the
   original via the title attribute. */
.cmms-translated {
    background: color-mix(in srgb, var(--crm-brand) 12%, transparent);
    border-bottom: 1px dashed var(--crm-brand);
    border-radius: 2px;
    cursor: help;
    animation: cmmsTranslatedIn 0.6s ease;
}

@keyframes cmmsTranslatedIn {
    from { background: color-mix(in srgb, var(--crm-brand) 32%, transparent); }
}

/* Second list section on a combined page (People & Teams). */
.cmms-section-spaced { margin-top: 28px; }

/* ════════════════════════════════════════════════════════════════════════════
   2026-09 layout redesign (Paul): full-bleed workspace + right detail panel.
   ──────────────────────────────────────────────────────────────────────────
   1. The green gradient mat and the floating page card are gone — the page
      surface runs edge to edge so the table gets every pixel.
   2. Record pages are replaced by a right slide-in detail panel (old-UpKeep
      style); rows carrying data-detail-url open it (cmms-detail-panel.js).
   3. The workspace tab strip is removed from the layout — the panel plays
      the record role, and the row saves vertical space.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Full-bleed workspace ── */
.crm-main {
    padding: 0;
    background: var(--crm-surface-content);
}

/* The one place the old Value-green gradient survives (Paul's call): the soft-nav
   in-between loader, so the "Value One" + spinner moment keeps the brand wash while
   every real page stays full-bleed white. */
.crm-soft-nav-skeleton {
    background:
        linear-gradient(180deg,
            #bee4bc 0%,
            #d8eed5 18%,
            #ecf5e9 35%,
            var(--crm-brand-bg) 55%,
            #ffffff 75%);
}

.crm-list-page {
    border: none;
    border-radius: 0;
    height: 100%;
    min-height: 100%;
    /* A column whose TABLE WRAP is the scroller (below). Before this, main scrolled and
       the wrap grew to the full height of 100 rows — 6,500px — so its horizontal
       scrollbar sat at the bottom of the table, a long way under the fold. With a
       panel open and columns clipped, the bar people needed was unreachable. */
    display: flex;
    flex-direction: column;
}

/* The wrap scrolls both ways, so the horizontal bar is pinned to the bottom of the
   viewport and the column headers stay put while rows scroll — the same fixed-window
   shape the CRM's reports use (.crm-report-fixed), and how UpKeep's tables behave.
   Load More lives inside the wrap after the table, so it scrolls in after the last row. */
.crm-list-page > .crm-list-table-wrap {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
}

.crm-list-page > .crm-list-table-wrap .crm-list-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
}

/* ── Content row: page + detail panel side by side ──
   The panel takes width from the row; the page content is left-anchored, so
   nothing left of the panel moves when it opens — the table just gets less
   room and its own horizontal scrollbar handles the overflow. */
.cmms-content-row {
    flex: 1 1 auto;
    display: flex;
    min-height: 0;
}

.cmms-content-row > .crm-main {
    flex: 1 1 auto;
    min-width: 0;
}

.cmms-detail {
    flex: 0 0 auto;
    width: 0;
    overflow: hidden;
    border-left: 1px solid var(--crm-border);
    /* A clear step off the page's white so the record zone reads as its own
       surface. Deliberately a NEUTRAL gray, not a token: the warm tokens carry a
       green cast Paul didn't want here, and the gray works under both tints. */
    background: #f4f5f6;
    position: relative;
    transition: width 0.22s ease;
}

/* The open width is a custom property so the drag-resize grip can override it
   per device (cmms-detail-panel.js persists it) without touching the closed state. */
.cmms-detail.is-open { width: var(--cmms-detail-w, 460px); }
.cmms-detail.is-resizing { transition: none; }

.cmms-detail-grip {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 7px;
    cursor: col-resize;
    z-index: 6;
    user-select: none;
}
.cmms-detail-grip:hover { background: linear-gradient(90deg, var(--crm-brand) 0, transparent 70%); opacity: 0.35; }

/* Fixed inner width so content doesn't squish during the slide. */
.cmms-detail-scroll {
    width: var(--cmms-detail-w, 460px);
    height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
}

.cmms-detail-close {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 5;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 1px solid var(--crm-border);
    background: rgba(255, 255, 255, 0.92);
    color: var(--crm-text-strong);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
}

.cmms-detail-close:hover { background: #fff; }

.cmms-detail-loading {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100%;
    padding: 20px;
    text-align: center;
    color: var(--crm-text-muted);
    font-size: 13px;
}

/* When the panel holds only the loader, stretch the content wrapper to the full
   scroll height so the spinner centers vertically too (crm.css already relies on
   :has() being baseline). */
#cmmsDetailContent:has(> .cmms-detail-loading:only-child) { height: 100%; }

/* Rows that open the panel */
tr[data-detail-url] { cursor: pointer; }
.crm-list-table tbody tr.is-selected td { background: var(--crm-brand-bg); }

/* ── Detail panel content (old-UpKeep grammar) ── */

/* Photo carousel: a dark band the image floats in, arrows at the sides,
   counter top-right, dots underneath. */
.cmms-car {
    position: relative;
    background: #191b1d;
    height: 235px;
    overflow: hidden;
}

.cmms-car-slide {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    cursor: zoom-in;
}

/* display:flex on the class beats the browser's [hidden]{display:none} — restate it,
   or every slide renders and the stack spills out of the band. */
.cmms-car-slide[hidden] { display: none; }

.cmms-car-slide img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    display: block;
}

.cmms-car-count {
    position: absolute;
    /* Bottom-right: the top-right corner now belongs to the pop-out button. */
    bottom: 10px;
    right: 12px;
    color: #fff;
    font-size: 12px;
    background: rgba(0, 0, 0, 0.45);
    padding: 2px 8px;
    border-radius: 10px;
    pointer-events: none;
}

.cmms-car-prev,
.cmms-car-next {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 32px;
    height: 32px;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}

.cmms-car-prev { left: 8px; }
.cmms-car-next { right: 8px; }
.cmms-car-prev:hover, .cmms-car-next:hover { background: rgba(255, 255, 255, 0.34); }

.cmms-car-dots {
    position: absolute;
    bottom: 8px;
    left: 0;
    right: 0;
    display: flex;
    justify-content: center;
    gap: 5px;
    pointer-events: none;
}

.cmms-car-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.45);
}

.cmms-car-dot.is-current { background: #fff; }

/* Head block under the carousel. When a record has NO photo band the head is the
   panel's first element — clear the floating ✕ so it never sits on the pills. */
.cmms-detail-head { padding: 14px 18px 0; }
#cmmsDetailContent > .cmms-detail-head:first-child { padding-top: 50px; }

.cmms-detail-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 12px;
    color: var(--crm-text-muted);
}

.cmms-detail-meta .cmms-detail-id {
    margin-left: auto;
    font-weight: 700;
    color: var(--crm-text);
}

.cmms-pill {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 10px;
    font-size: 12px;
    font-weight: 700;
}

.cmms-pill--high   { background: #fdd9dd; color: #c4314b; }
.cmms-pill--medium { background: #fdeacc; color: #a05a00; }
.cmms-pill--low    { background: #d9e8fd; color: #1d5bb9; }
.cmms-pill--none   { background: var(--crm-hover); color: var(--crm-text-muted); }
.cmms-pill--ok     { background: var(--crm-brand-bg); color: var(--crm-brand-strong); }

.cmms-detail-title {
    margin: 8px 0 0;
    font-size: 19px;
    line-height: 1.3;
    font-weight: 700;
    color: var(--crm-text-strong);
    overflow-wrap: anywhere;
}

/* Status row: a select-look chip (read-only for now) + the Time chip */
.cmms-detail-statusbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 18px 0;
}

.cmms-detail-status {
    flex: 1 1 auto;
    border: 1px solid var(--crm-border);
    border-radius: 10px;
    padding: 8px 12px;
    font-size: 14px;
    color: var(--crm-text-strong);
    background: var(--crm-surface-content);
}

.cmms-detail-time {
    flex-shrink: 0;
    border: 1px solid var(--crm-brand);
    border-radius: 10px;
    padding: 8px 14px;
    font-size: 13px;
    font-weight: 700;
    color: var(--crm-brand-strong);
    white-space: nowrap;
}

/* Label / value rows */
.cmms-detail-rows { padding: 14px 18px 4px; }

.cmms-detail-row {
    display: grid;
    grid-template-columns: 100px 1fr;
    gap: 12px;
    padding: 5px 0;
    font-size: 13px;
}

.cmms-detail-row > label {
    color: var(--crm-text-muted);
    text-align: right;
}

.cmms-detail-row > div {
    color: var(--crm-text);
    min-width: 0;
    overflow-wrap: anywhere;
}

/* Sections below the rows (checklist, parts, files, activity, ...) */
.cmms-detail-sec { padding: 10px 18px 6px; }

.cmms-detail-sec > h3 {
    margin: 0 0 8px;
    padding-top: 12px;
    border-top: 1px solid var(--crm-hover);
    font-size: 12px;
    font-weight: 700;
    color: var(--crm-text-strong);
}

.cmms-detail-end { height: 18px; }

/* ── Detail panel editing (Step 1: the tech loop) ──────────────────────────── */
.cmms-sec-add {
    float: right;
    border: 1px solid var(--crm-border);
    background: var(--crm-surface-content);
    border-radius: 8px;
    padding: 2px 10px;
    font-size: 12px;
    font-weight: 700;
    color: var(--crm-brand-strong);
    cursor: pointer;
}
.cmms-sec-add:hover { background: var(--crm-brand-bg); }

.cmms-mini-form,
.cmms-complete-flow {
    margin: 10px 0;
    padding: 12px;
    border: 1px solid var(--crm-border);
    border-radius: 10px;
    background: var(--crm-surface-subtle);
}
.cmms-complete-flow { margin: 12px 18px 0; }

.cmms-mini-label {
    display: block;
    font-size: 11px;
    font-weight: 700;
    color: var(--crm-text-muted);
    margin: 8px 0 3px;
}
.cmms-mini-label:first-child { margin-top: 0; }

.cmms-mini-input {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid var(--crm-border);
    border-radius: 8px;
    padding: 6px 10px;
    font-size: 13px;
    font-family: inherit;
    background: var(--crm-surface-content);
    color: var(--crm-text);
}
.cmms-mini-input:focus { outline: none; border-color: var(--crm-brand); }

.cmms-mini-cols { display: flex; gap: 10px; }
.cmms-mini-cols > div { flex: 1; }

.cmms-mini-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 10px;
}

/* Status select stays a select but keeps the chip look. */
select.cmms-detail-status { cursor: pointer; }

/* Clickable checklist lines */
.cmms-check-line.is-clickable { cursor: pointer; border-radius: 6px; }
.cmms-check-line.is-clickable:hover { background: var(--crm-surface-subtle); }
.cmms-check-text { margin-top: 4px; }

/* Feed composer */
.cmms-composer {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    margin-top: 10px;
}
.cmms-composer textarea { resize: vertical; }

/* Part picker results */
.cmms-part-results { max-height: 180px; overflow-y: auto; margin-top: 4px; }
.cmms-part-option,
.cmms-asset-option {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1px;
    width: 100%;
    text-align: left;
    border: none;
    border-bottom: 1px solid var(--crm-hover);
    background: var(--crm-surface-content);
    padding: 6px 8px;
    font-size: 13px;
    cursor: pointer;
}
.cmms-part-option:hover,
.cmms-asset-option:hover { background: var(--crm-brand-bg); }

/* Signature pad */
.cmms-sigpad {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}
.cmms-sigpad canvas {
    width: 100%;
    border: 1px dashed var(--crm-border);
    border-radius: 8px;
    background: #fff;
    touch-action: none;
    cursor: crosshair;
}

/* ── New Work Order form (in the panel) ────────────────────────────────────── */
.cmms-newwo { padding: 0 18px; }

.cmms-newwo-sec {
    margin: 18px 0 6px;
    padding-top: 12px;
    border-top: 1px solid var(--crm-hover);
    font-size: 12px;
    font-weight: 700;
    color: var(--crm-text-strong);
}

.cmms-chiplist { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }

.cmms-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--crm-brand-bg);
    border: 1px solid var(--crm-border);
    border-radius: 12px;
    padding: 2px 8px;
    font-size: 12px;
    color: var(--crm-text);
}

.cmms-chip-remove {
    border: none;
    background: none;
    color: var(--crm-text-muted);
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
.cmms-chip-remove:hover { color: var(--crm-danger, #c4314b); }

/* ── Slimmer sidebar gutter ──────────────────────────────────────────────────
   The nav's scrollbar (short viewports) sat 14px off the sidebar's right border —
   dead space. Trim the right padding and hand exactly those pixels to the main
   section by narrowing the sidebar column the same amount (248 → 238). The
   collapsed rail keeps its own width from crm.css. */
:root { --crm-sidebar-width: 238px; }

.crm-sidebar { padding-right: 5px; }

/* Keep the nav items' own right edge breathing next to the closer scrollbar. */
.crm-sidebar-nav { padding-right: 3px; }

/* The search bar sits outside the scrollable nav, so the slimmed 5px right gutter
   left it lopsided (14px left gap, 5px right). End it sooner instead of starting
   earlier — everything in the sidebar shares the 14px left rail (brand, eyebrows,
   items), so the symmetric 14/14 look comes from matching the right side to it. */
.crm-sidebar-search { margin-right: 9px; }

/* 14 search scopes now — keep the picker usable on short viewports. */
.crm-search-scope-menu { max-height: 60vh; overflow-y: auto; }

/* Filter chips inlined onto the toolbar row, left of the count + search (Work
   Orders): the bar is the row's flexible left side, chips wrap when the window
   narrows, and the standalone filter row's vertical space goes to the table. */
.cmms-filter-bar--inline {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0;
    margin: 0 0 0 -4px;   /* nudge: the chip's rounded border hangs left so its TEXT
                             sits optically on the 12px alignment line */
    align-self: center;
}

/* Tighter left edge: header + toolbar rows start at 12px like the table cells,
   so the title, filter chips and first-column text share one alignment line. */
.crm-list-header,
.crm-list-toolbar { padding-left: 12px; }

/* ── Professional-pass polish for panel forms ─────────────────────────────── */

/* Styled upload zone (replaces the native "Choose Files" chrome). */
.cmms-upload {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 12px;
    border: 1px dashed var(--crm-border);
    border-radius: 8px;
    background: var(--crm-surface-content);
    font-size: 13px;
    color: var(--crm-text);
    cursor: pointer;
    text-align: center;
}
.cmms-upload:hover,
.cmms-upload.is-drag {
    border-color: var(--crm-brand);
    background: var(--crm-brand-bg-soft);
}
.cmms-upload .crm-icon { color: var(--crm-brand-strong); }
.cmms-upload-count { font-size: 12px; font-weight: 700; color: var(--crm-brand-strong); }
/* One-line note inside a filter chip's panel (the Location chip's branch rule). */
.cmms-multi-hint { font-size: 11px; padding: 2px 8px 6px; }
/* Picked-but-not-yet-uploaded previews under a create-form upload zone. */
.cmms-upload-previews { margin-top: 8px; }
.cmms-upload-previews:empty { display: none; }
.cmms-upload-list { margin-top: 4px; }
.cmms-upload-list .cmms-doc-line > span:first-child { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Checkbox picklist (replaces raw <select multiple> + its Ctrl-click lore). */
.cmms-picklist {
    border: 1px solid var(--crm-border);
    border-radius: 8px;
    background: var(--crm-surface-content);
    max-height: 132px;
    overflow-y: auto;
    padding: 4px;
}
.cmms-picklist-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 8px;
    border-radius: 6px;
    font-size: 13px;
    cursor: pointer;
}
.cmms-picklist-item:hover { background: var(--crm-hover); }

/* Section headings: one notch more presence than the field labels below them. */
.cmms-newwo-sec {
    font-size: 13px;
    margin-top: 22px;
}

/* ── Detached detail window ─────────────────────────────────────────────────── */
/* Far from the close button (Paul, 2026-09-22): a misclick next to × used to close the
   record instead of popping it out. Right edge, clear of the scrollbar. */
.cmms-detail-detach { left: auto; right: 22px; }

/* The "record is in another window" tab on the main window's right edge — where the
   panel would be, so the eye finds it. Vertical, brand green, gone once docked again. */
/* Vertical and slim (Paul, 2026-09-22): a side tab, text running top to bottom. */
.cmms-detach-tab {
    position: fixed;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    z-index: 40;
    display: flex;
    align-items: center;
    gap: 14px;
    writing-mode: vertical-rl;
    padding: 28px 6px 28px 5px;
    border: 1px solid var(--crm-brand);
    border-right: 0;
    border-radius: 10px 0 0 10px;
    background: var(--crm-brand-bg);
    color: var(--crm-text-muted);
    font-size: 11.5px;
    line-height: 1;
    letter-spacing: 0.04em;
    word-spacing: 0.3em;
    white-space: nowrap;
    cursor: pointer;
    box-shadow: -3px 2px 10px rgba(0, 0, 0, 0.12);
}
.cmms-detach-tab[hidden] { display: none; }
.cmms-detach-tab .crm-icon { width: 14px; height: 14px; fill: var(--crm-brand-strong); flex-shrink: 0; }
.cmms-detach-tab strong { color: var(--crm-brand-strong); font-weight: 700; }
.cmms-detach-tab:hover { background: #d9efd9; }
.cmms-detail-detach .crm-icon { width: 14px; height: 14px; }

.cmms-popout {
    margin: 0;
    display: flex;
    flex-direction: column;
    height: 100vh;
    background: #f4f5f6;
    font-family: var(--vw-font-body, sans-serif);
}

.cmms-popout-bar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    background: var(--crm-surface-content);
    border-bottom: 1px solid var(--crm-border);
}

.cmms-popout-brand {
    font-weight: 700;
    font-size: 13px;
    color: var(--crm-brand-strong);
}

.cmms-popout-bar .crm-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* In the popout the panel IS the page: full width, no border, no slide. */
.cmms-popout .cmms-detail {
    flex: 1 1 auto;
    width: auto !important;
    min-height: 0;
    border-left: none;
    transition: none;
}
.cmms-popout .cmms-detail-scroll { width: 100%; height: 100%; }

/* Maximized popout: a record is a document, not a liquid layout — cap the content
   column and center it. On big screens the column also ZOOMS (Paul's call): same
   layout, everything proportionally bigger, occupying a wider slice of the screen
   instead of stretching controls. Side hairlines define the column on the gray. */
.cmms-popout #cmmsDetailContent {
    max-width: 900px;
    min-height: 100%;
    margin: 0 auto;
    border-left: 1px solid var(--crm-border);
    border-right: 1px solid var(--crm-border);
}

@media (min-width: 1400px) {
    .cmms-popout #cmmsDetailContent { zoom: 1.15; max-width: 1000px; }
}

@media (min-width: 1900px) {
    .cmms-popout #cmmsDetailContent { zoom: 1.3; max-width: 1060px; }
}

/* Translation target picker (Quick Settings, under the toggle). */
.cmms-translate-langrow { padding: 2px 10px 6px 40px; }
.cmms-translate-langrow select {
    width: 100%;
    font-size: 12px;
    color: var(--crm-text);
    background: var(--crm-surface-content);
    border: 1px solid var(--crm-border);
    border-radius: 6px;
    padding: 3px 8px;
    cursor: pointer;
}
/* Hidden alongside the label text when the sidebar collapses to the icon rail. */
.crm-shell.is-sidebar-collapsed .cmms-translate-langrow { display: none; }

/* ── Checklist step types ─────────────────────────────────────────────────── */
/* A section heading groups the lines beneath it; it is structure, not a step, so it
   deliberately looks nothing like one. */
.cmms-check-section {
    margin: 14px 0 6px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--crm-border);
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--crm-text-strong);
}

/* A warning has to be read, so it is the one line that shouts. */
.cmms-check-warning {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 6px 0;
    padding: 8px 10px;
    border-left: 3px solid #c62828;
    border-radius: 4px;
    background: rgba(198, 40, 40, .07);
    font-size: 13px;
}

.cmms-check-warning svg { width: 15px; height: 15px; fill: #c62828; flex-shrink: 0; margin-top: 1px; }

/* Marks a step that must be answered before the work order can close. */
.cmms-check-req {
    color: #c62828;
    font-weight: 700;
    margin-left: 3px;
}

.cmms-check-select { max-width: 150px; margin-left: auto; }

.cmms-check-multi {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-left: auto;
}

/* A signature captured against one checklist step — small, since the line is a row in a
   list rather than a document. */
.cmms-check-signature {
    max-height: 46px;
    max-width: 170px;
    margin-left: auto;
    border: 1px solid var(--crm-border);
    border-radius: 4px;
    background: #fff;
}

/* The label and its choices box stack and take the free width in a step row; without this
   they size to content and the row collapses. */
.cmms-row-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* Hidden unless the step type reads choices — see data-show-when on the input. */
.cmms-row-options { font-size: 12px; }

/* "Req" toggle at the end of a step row. Narrow and centred so the row stays readable. */
.cmms-row-req {
    flex: 0 0 auto;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    font-size: 10px;
    color: var(--crm-text-muted);
    cursor: pointer;
    padding-top: 2px;
}

.cmms-row-req input { margin: 0; }

/* ── Classes crm.css references but never defines ─────────────────────────── */
/* These belong to the ported list-page shell. crm.css is vendored verbatim and must not be
   edited, so the missing rules live here. Found by scratchpad/classcheck.py — nothing at
   build time connects a class in markup to a rule in CSS, so a name can sit inert for months. */

/* The page title on every list header. Its eyebrow above it (11px muted) and its container
   are both styled in crm.css; only the title itself was missed, so it has been rendering at
   inherited body size. Matches .crm-list-heading, which is what it was clearly modelled on. */
.crm-list-view-label {
    font-size: 18px;
    font-weight: 700;
    line-height: 1.25;
    color: var(--crm-text);
}

/* Text half of the search scope button, beside .crm-search-scope-caret. The caret is sized
   in crm.css; this keeps the label from inheriting the page font size next to it. */
.crm-search-scope-label {
    font-size: 12px;
    line-height: 1;
}

/* ── Account / settings pages (My Account, two-factor) ────────────────────────
   Full-page forms in the console shell. They reuse the panel's form vocabulary
   (cmms-mini-*) inside cards; the shell loads no Bootstrap, which is why the
   ported views rendered bare until 2026-09-22. */
.cmms-settings-page > .cmms-settings-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
}
/* Centered, two columns: Profile (the tall one) on the left spanning both rows, Password
   above Two-factor on the right. One column on narrow windows. */
.cmms-settings-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-auto-rows: min-content;
    gap: 16px;
    align-items: start;
    width: 100%;
    max-width: 880px;
    margin: 0 auto;
    padding: 24px 1.25rem 40px;
    box-sizing: border-box;
}
.cmms-settings-body > .cmms-settings-card:first-of-type { grid-row: span 2; }
.cmms-settings-body--single { grid-template-columns: minmax(0, 560px); justify-content: center; }
.cmms-settings-body--single > .cmms-settings-card:first-of-type { grid-row: auto; }
.cmms-settings-flash { grid-column: 1 / -1; margin: 0; }
@media (max-width: 760px) {
    .cmms-settings-body { grid-template-columns: minmax(0, 1fr); }
    .cmms-settings-body > .cmms-settings-card:first-of-type { grid-row: auto; }
}

.cmms-settings-card {
    padding: 18px 20px 16px;
    border: 1px solid var(--crm-border);
    border-radius: 12px;
    background: var(--crm-surface-content);
}
.cmms-settings-card > h2 {
    margin: 0 0 12px;
    font-family: var(--vw-font-display);
    font-size: 18px;
    font-weight: 700;
    line-height: 1.25;
    color: var(--crm-text-strong);
}
.cmms-settings-text {
    max-width: 60ch;
    margin: 0 0 12px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--crm-text);
}
.cmms-settings-status {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 12px;
    font-size: 13px;
    color: var(--crm-text);
}
.cmms-settings-avatar {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 12px;
}
.cmms-settings-avatar img {
    width: 72px;
    height: 72px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid var(--crm-border);
    background: var(--crm-surface-subtle);
}
.cmms-settings-avatar .crm-btn { cursor: pointer; }
.cmms-settings-avatar .cmms-field-hint { margin: 6px 0 0; }
.cmms-settings-pills { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }
.cmms-settings-form .cmms-mini-input:disabled {
    color: var(--crm-text-muted);
    background: var(--crm-surface-subtle);
}
/* The panel's hint hugs its input (-4px); on these taller full-page fields it needs air. */
.cmms-settings-form .cmms-field-hint { margin: 5px 0 10px; }
.cmms-mini-actions--start { justify-content: flex-start; }

.cmms-form-errors { margin-bottom: 8px; font-size: 12px; }
.cmms-form-errors ul { margin: 0; padding-left: 18px; }
.cmms-note-box--ok   { border-left-color: var(--crm-brand); }
.cmms-note-box--warn { border-left-color: #e0a000; background: #fff8e6; }
.cmms-msg--ok { color: var(--crm-brand-strong); }

/* The six-digit code: big, spaced, monospace — typed from a phone screen. */
.cmms-code-input {
    max-width: 220px;
    font-family: var(--vw-font-mono);
    font-size: 20px;
    letter-spacing: .18em;
    text-align: center;
}
.cmms-steps {
    margin: 0 0 14px;
    padding-left: 20px;
    font-size: 13px;
    line-height: 1.6;
    color: var(--crm-text);
}
.cmms-qr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 18px;
    margin: 0 0 16px;
}
.cmms-qr #qrCode {
    padding: 8px;
    line-height: 0;
    border: 1px solid var(--crm-border);
    border-radius: 10px;
    background: #fff;
}
.cmms-qr-key code {
    display: inline-block;
    padding: 6px 10px;
    border-radius: 6px;
    background: var(--crm-hover);
    font-family: var(--vw-font-mono);
    font-size: 13px;
    letter-spacing: .06em;
    overflow-wrap: anywhere;
    user-select: all;
}
.cmms-codes {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px 16px;
    margin: 4px 0 16px;
}
.cmms-codes code {
    padding: 8px 10px;
    border: 1px solid var(--crm-border);
    border-radius: 8px;
    background: var(--crm-surface-subtle);
    font-family: var(--vw-font-mono);
    font-size: 15px;
    letter-spacing: .06em;
    text-align: center;
    user-select: all;
}
.cmms-btn-danger { color: #c4314b; border-color: #f0b3bc; }
.cmms-btn-danger:hover { background: #fdd9dd; }

/* ── Audit Log ─────────────────────────────────────────────────────────────── */
.cmms-audit-key {
    margin-left: 6px;
    font-size: 12px;
    font-weight: 400;
    color: var(--crm-text-muted);
}
.cmms-audit-changed {
    max-width: 380px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Before / after per field in the detail panel. Tinted cells carry the meaning: the
   old value on a faint red, the new one on the brand green; bookkeeping stamps
   (ModifiedBy/Date) sink to the bottom in muted type. */
.cmms-diff {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
    font-size: 12.5px;
}
.cmms-diff th, .cmms-diff td {
    padding: 6px 8px;
    border-bottom: 1px solid var(--crm-hover);
    text-align: left;
    vertical-align: top;
    overflow-wrap: anywhere;
}
.cmms-diff thead th {
    font-size: 11px;
    font-weight: 700;
    color: var(--crm-text-muted);
    border-bottom: 1px solid var(--crm-border);
}
.cmms-diff tbody th {
    width: 34%;
    font-weight: 600;
    color: var(--crm-text-strong);
}
.cmms-diff--single tbody th { width: 40%; }
.cmms-diff-before { background: #fdf1f2; color: var(--crm-text-muted); }
.cmms-diff-after  { background: var(--crm-brand-bg); color: var(--crm-text-strong); }
.cmms-diff--single .cmms-diff-before,
.cmms-diff--single .cmms-diff-after { background: transparent; color: var(--crm-text); }
.cmms-diff-row--meta th,
.cmms-diff-row--meta td {
    font-size: 11.5px;
    color: var(--crm-text-muted);
    background: transparent;
}
.cmms-diff td:empty::after { content: "—"; opacity: .5; }
.cmms-diff-note { margin: 8px 0 0; }

/* "who · when" under a ticked checklist step or a booked-out part. */
.cmms-check-by { display: block; margin-top: 2px; font-size: 11px; }
