/*
    Customer + Customer Item history (CustomerItem-History-Schedule-Design.md section 5). Originally
    ported from the Sales client's Components.css (.Sales* -> .Ch*) - Sales and Schedule duplicate
    rather than share client CSS by this codebase's convention (see Data.SalesTasks.js's own comment
    on the equivalent JS duplication). Sales' tokens (--brand/--border/--surface/...) come from
    Tokens.css (shared with Mobile); Schedule has no such file, so every value below is translated
    to Modern.css's own --totm-* tokens instead. Light-only: Schedule has no dark-mode system
    (Calendar.css's own comment), so no dark variants are defined here.

    These screens have since been brought onto the Create/Edit Booking dialog's visual language,
    which is the app's newest and is documented inline in Scheduler.css's "Create Booking dialog"
    section. What that means concretely:

      - Section titles are the small uppercase muted label over a hairline rule
        (.CreateBookingSectionTitle, and Modern.css section 6's table headers), not 16px <h3>s.
        Blue is left to mean an action or a selection.
      - Text inputs carry --totm-border-strong at 32px tall, and focus with a brand border plus a
        2px --totm-brand-tint ring (#CreateBookingBody input:focus).
      - Buttons come in the dialog's primary/secondary pair: .ChButtonPrimary is the brand fill,
        plain .ChButton is white with a strong hairline and an #F3F4F6 hover.
      - Surfaces (cards, grids, inset panels) take the 4px radius .ModalDialog and
        .CreateBookingJobCard use. Only surfaces - Modern.css section 2 already gives every button
        and input its own 3px, and job cards/tags stay square.

    !important on the button rules: Scheduler.css's global "button, input[type=button]" rule paints
    EVERY button solid brand blue with !important on background, colour and padding, and its
    "button:hover" is !important too. Source order cannot beat that, which is why the Create Booking
    footer buttons state their own !important - and why, before this, every .ChButton on these
    screens (the remove buttons and the .ChJobLink accordion rows included) rendered as an identical
    blue slab no matter what .ChButton asked for.

    Loaded after Modern.css in index.html so its rules win on source order.
*/

/* -- Breadcrumbs -------------------------------------------------------------
   #SettingsDialogBreadcrumb is a fixed strip between the dialog's title bar and its scrolling
   content pane, so the trail stays put while the content scrolls. Sentence case, not the uppercase
   eyebrow the section titles use: crumbs are customer and item names, and uppercasing a name makes
   it harder to recognise, not easier. */

#SettingsDialogBreadcrumb {
    padding: 8px 10px;
    background: #fff;
    border-bottom: 1px solid var(--totm-border);
}

.ChBreadcrumb {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 2px;
    font-size: var(--totm-fs-xs, 12px);
    line-height: 1.4;
}

/* The global "button, input[type=button]" blue-slab rule again - see the file header. */
.ChBreadcrumbCrumb {
    background: none !important;
    border: none !important;
    color: var(--totm-brand) !important;
    font-family: inherit;
    font-size: var(--totm-fs-xs, 12px) !important;
    font-weight: normal !important;
    padding: 2px 4px !important;
    margin: 0 !important;
    cursor: pointer;
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ChBreadcrumbCrumb:hover {
    background: var(--totm-brand-tint, #E8F1FB) !important;
    color: var(--totm-brand-ink, #0C447C) !important;
    text-decoration: underline;
}

.ChBreadcrumbSeparator {
    color: var(--totm-text-muted);
    padding: 0 2px;
}

/* The screen you are already on: named, but not offered as somewhere to go. */
.ChBreadcrumbCurrent {
    color: var(--totm-text);
    font-weight: 600;
    padding: 2px 4px;
    max-width: 320px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ChSection {
    background: #fff;
    border: 1px solid var(--totm-border);
    border-radius: 4px;
    padding: 16px;
    margin-bottom: 16px;
}

/* -- Section titles ----------------------------------------------------------
   The eyebrow. A .ChSection's own h3 carries the hairline; inside a .ChSectionHeader
   (title + action button on one line) the hairline moves to the header row itself so
   it spans the button too, the same shape .CreateBookingSectionTitle has. */

.ChSection h3,
.ChSection h4 {
    margin: 0 0 10px 0;
    font-size: var(--totm-fs-2xs, 11px);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--totm-text-muted);
}

.ChSection > h3 {
    padding-bottom: 4px;
    border-bottom: 1px solid var(--totm-border);
}

.ChSection h4 {
    margin-top: 16px;
}

.ChSectionHeader {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 10px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--totm-border);
}

.ChSectionHeader h3 {
    margin: 0;
    padding-bottom: 0;
    border-bottom: none;
}

/* The action sitting beside a title is a title-sized control, not a full-height button. */
.ChSectionHeader .ChButton {
    margin: 0 !important;
    padding: 3px 10px !important;
    font-size: var(--totm-fs-2xs, 11px);
}

/* -- Grid / tables ---------------------------------------------------------- */

.ChGridContainer {
    overflow-x: auto;
    background: #fff;
    border: 1px solid var(--totm-border);
    border-radius: 4px;
}

.ChGridContainer .UserTable {
    border: none;
}

.ChRowClickable:hover {
    background: var(--totm-brand-tint);
    cursor: pointer;
}

.ChJobDetailRow > td {
    background: var(--totm-brand-tint, #E8F1FB);
    padding: 4px 16px 16px !important;
    border-top: none;
}

.ChJobDetailRow .ChForm {
    border: none;
    background: transparent;
    padding: 0;
    max-width: none;
}

.ChEmptyState {
    text-align: center;
    color: var(--totm-text-muted);
    padding: 24px !important;
}

.ChShowMoreToggle {
    font-size: var(--totm-fs-sm, 13px);
    color: var(--totm-text-muted);
    margin: 8px 0;
}

/* -- Contacts --------------------------------------------------------------- */

.ChContactsList {
    list-style: none;
    margin: 0;
    padding: 4px 0;
}

.ChContactRow {
    padding: 8px 0;
    border-bottom: 1px solid var(--totm-border);
}

.ChContactRow:last-child {
    border-bottom: none;
}

.ChContactName {
    font-weight: 600;
    color: var(--totm-text);
}

.ChContactPosition {
    color: var(--totm-text-muted);
    margin-left: 6px;
}

.ChContactMeta {
    margin-top: 2px;
    font-size: var(--totm-fs-sm, 13px);
    color: var(--totm-text-muted);
}

/* -- Job / item detail form ------------------------------------------------- */

.ChForm {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px 24px;
    background: #fff;
    border: 1px solid var(--totm-border);
    border-radius: 4px;
    padding: 16px;
    max-width: 900px;
}

@media (max-width: 900px) {
    .ChForm {
        grid-template-columns: 1fr;
    }
}

.ChFormRow {
    display: flex;
    flex-direction: column;
    margin-bottom: 12px;
    font-size: var(--totm-fs-sm, 13px);
    color: var(--totm-text-muted);
    min-width: 0;
}

.ChFormRow label {
    margin-bottom: 4px;
}

.ChDetailValue {
    padding: 4px 0;
    font-size: 14px;
    color: var(--totm-text);
    word-break: break-word;
}

.ChJobDescriptionRow {
    grid-column: 1 / -1;
}

.ChJobMemoList {
    list-style: none;
    margin: 8px 0;
    padding: 0;
}

.ChJobMemoList li {
    padding: 6px 10px;
    background: #fff;
    border: 1px solid var(--totm-border);
    border-radius: 4px;
    margin-bottom: 6px;
    font-size: var(--totm-fs-sm, 13px);
}

.ChJobTransactions {
    margin-top: 12px;
}

/* Used on both an <a> (attachment links) and a <button class="ChButton ChJobLink"> (the item and
   checklist accordion rows). The button half needs !important on background, colour, weight and
   padding to clear the global blue-slab rule; the anchor half is unaffected by it either way.
   The compound .ChButton.ChJobLink is what makes the link treatment win over .ChButton's own
   !important below - two classes to one, so it does not depend on which block comes first. */
.ChJobLink,
.ChButton.ChJobLink {
    background: none !important;
    border: none !important;
    color: var(--totm-brand) !important;
    text-decoration: underline;
    cursor: pointer;
    font-size: 14px;
    font-weight: normal !important;
    font-family: inherit;
    padding: 4px 0 !important;
    margin: 0 !important;
    text-align: left;
    display: block;
}

.ChJobLink:hover,
.ChButton.ChJobLink:hover {
    background: none !important;
    color: var(--totm-brand-ink, #0C447C) !important;
}

/* -- Customer item list ------------------------------------------------------
   A bordered list of disclosure rows, one per item: name, then a muted line of whatever tells it
   apart from its namesakes, with a caret that turns when the row is open. Not links - an account
   can hold a dozen-plus items, and a dozen blue underlines reads as a page of links rather than
   as an inventory. Same hairline-separated, brand-tint-on-hover grammar as the job tables.

   Rows are <button>s, so !important throughout: see the file header on the global blue-slab rule. */

.ChItemList {
    border: 1px solid var(--totm-border);
    border-radius: 4px;
    overflow: hidden;
}

.ChItemRow {
    display: flex !important;
    align-items: center;
    gap: 12px;
    width: 100%;
    text-align: left;
    background-color: #fff !important;
    color: var(--totm-text) !important;
    border: 0 !important;
    border-bottom: 1px solid var(--totm-border) !important;
    border-radius: 0 !important;
    font-family: inherit;
    font-weight: normal !important;
    padding: 9px 12px !important;
    margin: 0 !important;
    cursor: pointer;
}

.ChItemList .ChItemRow:last-of-type {
    border-bottom: 0 !important;
}

.ChItemRow:hover {
    background-color: var(--totm-brand-tint, #E8F1FB) !important;
}

/* The name and facts stack; the badge and caret stay on the right of the row. */
.ChItemRowMain {
    flex: 1 1 auto;
    min-width: 0;
}

.ChItemName {
    display: block;
    font-weight: 600;
    color: var(--totm-text);
}

.ChItemFacts {
    display: block;
    margin-top: 1px;
    font-size: var(--totm-fs-xs, 12px);
    color: var(--totm-text-muted);
}

/* Not the amber/red row states: an inactive item is a fact about it, not a problem with it. */
.ChItemBadge {
    flex: 0 0 auto;
    padding: 1px 8px;
    border: 1px solid var(--totm-border-strong);
    border-radius: 12px;
    font-size: var(--totm-fs-2xs, 11px);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--totm-text-muted);
    background: #fff;
}

.ChItemCaret {
    flex: 0 0 auto;
    color: var(--totm-text-muted);
    font-size: var(--totm-fs-lg, 16px);
    line-height: 1;
    transition: transform var(--totm-motion, 0.15s ease);
}

.ChItemRowOpen .ChItemCaret {
    transform: rotate(90deg);
}

/* The open row's panel. Inset, not another card: it belongs to the row above it, and the ChForm
   inside brings its own border - which would otherwise double up against this one. */
.ChItemDetail {
    padding: 12px;
    background: #FAFBFC;
    border-bottom: 1px solid var(--totm-border);
}

.ChItemList > .ChItemDetail:last-child {
    border-bottom: 0;
}

.ChItemDetail .ChForm {
    border: none;
    background: transparent;
    padding: 0;
    max-width: none;
}

.ChImageGrid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 8px 0;
}

.ChImageThumb {
    width: 100px;
    height: 100px;
    object-fit: cover;
    border: 1px solid var(--totm-border);
    border-radius: 4px;
}

.ChCoverageNote {
    color: var(--totm-text-muted);
    font-size: var(--totm-fs-sm, 13px);
    padding: 4px 0 12px 0;
}

/* -- Buttons ---------------------------------------------------------------- */

.ChButton {
    padding: 7px 16px !important;
    border: 1px solid var(--totm-border-strong) !important;
    background-color: #fff !important;
    color: var(--totm-text) !important;
    font-weight: 500 !important;
    font-size: var(--totm-fs-sm, 13px);
    font-family: inherit;
    cursor: pointer;
    margin: 4px 6px 4px 0 !important;
}

.ChButton:hover {
    background-color: #F3F4F6 !important;
}

.ChButton:disabled {
    color: var(--totm-text-muted) !important;
    cursor: default;
}

.ChButton:disabled:hover {
    background-color: #fff !important;
}

/* The one action a screen is actually for - "Open History", "Add line", "New template". At most
   one per row, the same way the booking dialog's footer pairs one Create against one Cancel. */
.ChButtonPrimary {
    background-color: var(--totm-brand, #1976D2) !important;
    color: #fff !important;
    border-color: var(--totm-brand, #1976D2) !important;
}

.ChButtonPrimary:hover {
    background-color: var(--totm-brand-ink, #0C447C) !important;
    border-color: var(--totm-brand-ink, #0C447C) !important;
}

.ChButtonPrimary:disabled,
.ChButtonPrimary:disabled:hover {
    background-color: var(--totm-brand, #1976D2) !important;
    color: #fff !important;
    opacity: 0.55;
}

/* -- Inputs ----------------------------------------------------------------- */

.ChSearchWrap {
    display: block;
    width: 100%;
    max-width: 360px;
    margin-bottom: 12px;
}

/* input.X, not a bare .X: .ModalDialog's own "input, select, textarea" rule (border: 0, padding: 5px)
   scores (0,1,1), so a lone class loses to it however late this file loads - the same specificity
   trap Scheduler.css documents on input.CreateBookingPrimaryButton. Matching (0,1,1) and relying
   on source order is what actually puts the border back. */
input.ChSearchInput,
.ChSiTable input,
input.ChSiInput,
input.ChSiQuantity,
.ChSiTemplatePicker input,
.ChSiCopyPanel .ChFormRow input,
.ChSiAssignPanel .ChFormRow input {
    border: 1px solid var(--totm-border-strong);
    background: #fff;
    color: var(--totm-text);
    font-family: inherit;
    font-size: var(--totm-fs-sm, 13px);
    padding: 6px 8px;
    height: 32px;
    box-sizing: border-box;
}

input.ChSearchInput {
    width: 100%;
}

input.ChSearchInput:focus,
.ChSiTable input:focus,
input.ChSiInput:focus,
input.ChSiQuantity:focus,
.ChSiTemplatePicker input:focus,
.ChSiCopyPanel .ChFormRow input:focus,
.ChSiAssignPanel .ChFormRow input:focus {
    outline: none;
    border-color: var(--totm-brand);
    box-shadow: 0 0 0 2px var(--totm-brand-tint, #E8F1FB);
}

/* -- Job Info pane's Customer Item link (View.JobDetailsPane.js) --------------
   Section 2.4: the plain <label> becomes clickable when the source supports item history. */
.JobInfoCustomerItemLink {
    color: var(--totm-brand);
    text-decoration: underline;
    cursor: pointer;
}

/* The item's Service Items under that link - a collapsed-by-default toggle and a muted list.
   Token colours only, so it follows the dark theme with no rules of its own. */
.JobInfoServiceItems {
    margin-top: 6px;
}

.JobInfoServiceItemsToggle {
    display: inline-block;
    cursor: pointer;
    user-select: none;
    font-size: var(--totm-fs-sm);
    font-weight: 600;
    color: var(--totm-brand);
}

    .JobInfoServiceItemsToggle .fa {
        width: 12px;
        font-size: var(--totm-fs-2xs);
    }

.JobInfoServiceItemsList {
    margin: 4px 0 0 0;
    padding-left: 18px;
    font-size: var(--totm-fs-sm);
    color: var(--totm-text-muted);
}

    .JobInfoServiceItemsList li {
        margin: 2px 0;
    }

    .JobInfoServiceItemsList li.JobInfoServiceItemMissing {
        font-style: italic;
    }

    .JobInfoServiceItemsList li.JobInfoServiceItemText {
        color: var(--totm-text);
        white-space: pre-line;
    }

    .JobInfoServiceItemsList .JobInfoServiceItemStamp,
    .CpoNotes .CpoNoteStamp,
    .ChSiTextStamp {
        font-style: italic;
        font-size: var(--totm-fs-xs);
        color: var(--totm-text-muted);
    }

    /* Ordered Service Items (CustomerItem-ServiceItems-Design.md section 7d): a list line that's
       been ordered reads in full text colour, with a cart (purchase order) and/or boxes (stock)
       icon after it. The two differ by shape first; colour is only a second cue. */
    .JobInfoServiceItemsList li.JobInfoServiceItemOrdered {
        color: var(--totm-text);
    }

    .JobInfoServiceItemsList .JobInfoOrderedIcon {
        margin-left: 6px;
        font-size: var(--totm-fs-sm);
        cursor: help;
    }

    .JobInfoServiceItemsList .JobInfoOrderedPo {
        color: var(--totm-brand);
    }

    .JobInfoServiceItemsList .JobInfoOrderedStock {
        color: var(--totm-text);
    }

    .JobInfoServiceItemsList li.JobInfoOrderedSection {
        list-style: none;
        margin: 8px 0 0 -18px;
        padding-top: 6px;
        border-top: 1px solid var(--totm-border);
    }

    .JobInfoServiceItemsList .JobInfoOrderedTitle {
        font-weight: 600;
        color: var(--totm-text);
    }

    .JobInfoServiceItemsList .JobInfoOrderedList {
        margin: 2px 0 0 0;
        padding-left: 0;
    }

        .JobInfoServiceItemsList .JobInfoOrderedList li {
            list-style: none;
            color: var(--totm-text);
        }

        /* The icon leads here, rather than trailing as on the list lines above. */
        .JobInfoServiceItemsList .JobInfoOrderedList .JobInfoOrderedIcon {
            width: 16px;
            margin: 0 4px 0 0;
            text-align: center;
        }

        .JobInfoServiceItemsList .JobInfoOrderedList .JobInfoServiceItemStamp {
            margin-left: 20px;
        }

        /* Takes a stock line back off the job (section 7e). Muted until hovered/focused. */
        .JobInfoServiceItemsList .JobInfoOrderedList .JobInfoRemoveStock {
            margin-left: 6px;
            padding: 0 3px;
            border-radius: 3px;
            cursor: pointer;
            color: var(--totm-text-muted);
            font-size: var(--totm-fs-xs);
        }

            .JobInfoServiceItemsList .JobInfoOrderedList .JobInfoRemoveStock:hover,
            .JobInfoServiceItemsList .JobInfoOrderedList .JobInfoRemoveStock:focus-visible {
                color: #B3261E;
                background: var(--totm-brand-tint, #E8F1FB);
                outline: none;
            }

    .JobInfoServiceItemsList .JobInfoOrderedLegend {
        margin-top: 6px;
        font-size: var(--totm-fs-xs);
    }

        .JobInfoServiceItemsList .JobInfoOrderedLegend span {
            margin-right: 12px;
            white-space: nowrap;
        }

        .JobInfoServiceItemsList .JobInfoOrderedLegend .JobInfoOrderedIcon {
            margin: 0 4px 0 0;
            cursor: default;
        }

    .JobInfoServiceItemsList li.JobInfoServiceItemsAction {
        list-style: none;
        margin: 8px 0 0 -18px;
    }

/* -- Create Purchase Order (View.CreatePurchaseOrder.js) ---------------------
   The line grid reuses the Service Items editor's .ChSiTable rules; only the header's two-column
   field layout is its own. */

.CpoNotes {
    border: 1px solid var(--totm-border);
    border-radius: 4px;
    background: var(--totm-brand-tint, #E8F1FB);
    padding: 10px 12px;
    margin-bottom: 16px;
}

    .CpoNotes .CpoNotesTitle {
        font-size: var(--totm-fs-2xs);
        font-weight: 600;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--totm-text-muted);
        margin-bottom: 6px;
    }

    .CpoNotes .CpoNote {
        color: var(--totm-text);
        white-space: pre-line;
        margin-bottom: 6px;
    }

/* What has already been ordered or allocated for this job (design section 7g). Amber rather than
   the brand tint .CpoNotes uses: the notes panel is reference, this one is a "wait a moment". No
   --totm-warn token exists yet, so the literals ride as fallbacks the same way --totm-brand-tint
   does above, ready for the day one is defined. */
.CpoAlreadyOrdered {
    border: 1px solid var(--totm-warn-border, #F0C48A);
    border-left: 3px solid var(--totm-warn, #B26A00);
    border-radius: 4px;
    background: var(--totm-warn-tint, #FFF4E5);
    padding: 10px 12px;
    margin-bottom: 16px;
}

    .CpoAlreadyOrdered .CpoAlreadyOrderedTitle {
        font-size: var(--totm-fs-2xs);
        font-weight: 600;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--totm-warn, #B26A00);
        margin-bottom: 6px;
    }

        .CpoAlreadyOrdered .CpoAlreadyOrderedTitle .fa {
            margin-right: 6px;
        }

    .CpoAlreadyOrdered .CpoAlreadyOrderedIntro {
        color: var(--totm-text-muted);
        font-size: var(--totm-fs-xs);
        margin-bottom: 8px;
    }

    .CpoAlreadyOrdered .CpoAlreadyOrderedLine {
        color: var(--totm-text);
        margin-bottom: 4px;
    }

    .CpoAlreadyOrdered .CpoAlreadyOrderedProduct {
        font-weight: 600;
    }

    /* Held apart from the product on the same line, so a column of entries still scans. */
    .CpoAlreadyOrdered .CpoAlreadyOrderedDetail {
        color: var(--totm-text-muted);
        font-size: var(--totm-fs-xs);
        margin-left: 8px;
    }

    .CpoAlreadyOrdered .CpoOrderedIcon {
        margin-right: 6px;
        font-size: var(--totm-fs-sm);
    }

    .CpoAlreadyOrdered .CpoOrderedPo {
        color: var(--totm-brand);
    }

    .CpoAlreadyOrdered .CpoOrderedStock {
        color: var(--totm-text);
    }

/* The same warning against the line that would repeat it, under its product picker - where the
   decision is actually made. */
.CpoProductCell .CpoRowOrdered {
    margin-top: 4px;
    font-size: var(--totm-fs-xs);
    color: var(--totm-warn, #B26A00);
}

    .CpoProductCell .CpoRowOrdered .fa {
        margin-right: 4px;
    }

/* Add from the Service Items list (design section 7h): part, purchase order or stock, Add - read
   left to right in the order the screen is worked. The picker takes the slack so long product
   descriptions stay readable; the other two keep their natural width. */
.CpoAddBar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 12px;
}

    .CpoAddBar .CpoAddBarLabel {
        font-size: var(--totm-fs-2xs);
        font-weight: 600;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--totm-text-muted);
        width: 100%;
        margin-bottom: 2px;
    }

    .CpoAddBar .CpoAddBarProduct {
        flex: 1 1 260px;
        min-width: 0;
    }

        .CpoAddBar .CpoAddBarProduct input {
            width: 100%;
            box-sizing: border-box;
        }

    /* width:auto beats .ChSiInput's 100%, which would otherwise push the button onto its own row. */
    .CpoAddBar .CpoAddBarFulfilment {
        flex: 0 0 auto;
        width: auto;
    }

    .CpoAddBar .CpoAddBarButton {
        flex: 0 0 auto;
    }

.CpoFields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 16px;
}

    .CpoFields .CpoFieldWide {
        grid-column: 1 / -1;
    }

.CpoHint {
    margin: 0 0 8px 0;
    font-size: var(--totm-fs-xs);
    color: var(--totm-text-muted);
}

/* Line grid: grip | product | supplier | qty | unit | remove. The two pickers share the width. */
.CpoLinesTable {
    width: 100%;
}

    .CpoLinesTable td.CpoGripCell {
        width: 16px;
        padding-right: 0;
    }

    .CpoLinesTable td.CpoProductCell {
        width: 45%;
    }

    .CpoLinesTable td.CpoSupplierCell {
        width: 35%;
    }

    .CpoLinesTable .CpoSupplierCell input.autoCompleteInput {
        width: 100%;
        min-width: 160px;
    }

    /* Drag - same treatment as .JobStatusesTable (Scheduler.css): border on the placeholder's
       spanning cell, since .UserTable's collapsed borders drop one set on the <tr>. */
    .CpoLinesTable .ReorderListPlaceholder td {
        border: 1px dashed #9cc3e5;
        border-radius: 3px;
        background: #eef4fb;
        height: 36px;
    }

    /* One tbody per supplier (= one PO). The header row reads as a section title. */
    .CpoLinesTable tr.CpoGroupHeader td {
        padding-top: 14px;
        background: var(--totm-brand-tint, #E8F1FB);
        border-top: 2px solid var(--totm-border);
    }

    .CpoLinesTable .CpoGroupName {
        font-weight: 600;
        color: var(--totm-text);
        margin-right: 8px;
    }

    .CpoLinesTable .CpoGroupCount {
        font-size: var(--totm-fs-xs);
        color: var(--totm-text-muted);
    }

    .CpoLinesTable .CpoNoSupplierGroup .CpoGroupName {
        color: #B3261E;
    }

    /* "From stock" (section 7e) - the same boxes icon as Job Details, before the group name, and
       in the confirm/summary dialogs' lists. */
    .CpoStockIcon {
        margin-right: 6px;
        color: var(--totm-text);
    }

    /* An empty group is hidden, except while dragging - the no-supplier group is then a drop
       target for clearing a line's supplier. Its spanning cell gives the drop somewhere to land. */
    .CpoLinesTable tbody.CpoGroupEmpty {
        display: none;
    }

    .CpoLinesTable.CpoDragging tbody.CpoGroupEmpty {
        display: table-row-group;
    }

    .CpoLinesTable tr.ui-sortable-helper {
        background: #fff;
        box-shadow: 0 2px 6px rgba(0,0,0,0.2);
        display: table;
    }

    .CpoFields input.ChSiInput,
    .CpoFields input.autoCompleteInput {
        width: 100%;
        box-sizing: border-box;
    }

/* -- Service Items editor (View.CustomerItemServiceItems.js) ------------------
   CustomerItem-ServiceItems-Design.md section 4.2. The grid reuses .UserTable; these
   only cover the inputs, the two row states and the button row. */

.ChSiInput {
    width: 100%;
    min-width: 120px;
}

/* The product picker fills its column like every other field in the row. Two classes to one:
   Util.Control.SearchableDropDown's input carries .autoCompleteInput, whose fixed 330px width is a
   single-class rule in Scheduler.css - so this has to out-specify it, not merely come later. The
   min-width keeps the column wide enough for "1010 - FRIDGE FREEZER - STAINLESS STEEL LEFT DR"
   once the table stops being sized by that 330px. */
.ChSiTable input.autoCompleteInput {
    width: 100%;
    min-width: 200px;
}

.ChSiQuantity {
    width: 80px;
}

.ChSiUnit {
    color: var(--totm-text-muted);
}

/* A product that has gone from Infusion. Amber rather than red: the line is still usable
   and still saved, it just needs re-pointing at a current product. */
.ChSiMissing td {
    border-left: 3px solid #E0A030;
    background: #FDF6E8;
}

/* Set by Save when a row has no product or no description. The same red pair
   .CreateBookingPreviewError uses, so a validation failure reads the same wherever it appears. */
.ChSiInvalid td {
    border-left: 3px solid #B3261E;
    background: #FDECEA;
}

/* Import kitset panel (template mode, Infusion Elite) - code box and Import side by side. */
.ChSiKitsetControls {
    display: flex;
    gap: 8px;
    align-items: center;
}

    .ChSiKitsetControls input.ChSiInput {
        max-width: 240px;
    }

.ChSiKitsetStatus:empty {
    display: none;
}

.ChSiKitsetStatus.ChSiKitsetError {
    color: #B3261E;
}

/* Text-only (note) lines - in the editor grid and the history table. */
.ChSiTextCell {
    white-space: pre-line;
}

.ChSiTextInput {
    resize: vertical;
    font: inherit;
}

.ChSiButtons {
    padding-top: 8px;
}

.ChButton.ChSiRemove {
    padding: 4px 10px !important;
}

.ChButton.ChSiRemove:hover {
    color: #B3261E !important;
    border-color: #B3261E !important;
}

.ChSiTemplateBanner {
    padding-top: 0;
}

/* -- Service Item templates (Phase 7) ----------------------------------------
   The Copy-from and Assign panels are inline (the shared dialog can't nest), so
   they read as insets rather than as separate surfaces. */

.ChSiCopyPanel,
.ChSiAssignPanel {
    border: 1px solid var(--totm-border);
    border-radius: 4px;
    background: var(--totm-brand-tint, #E8F1FB);
    padding: 12px;
    margin: 8px 0;
}

.ChSiCopyPanel h3,
.ChSiAssignPanel h3 {
    margin-top: 0;
}

/* On the tint, the section hairline needs to be a tint of the ink rather than the neutral
   --totm-border, which all but disappears against it. */
.ChSiCopyPanel > h3,
.ChSiAssignPanel > h3 {
    border-bottom-color: rgba(12, 68, 124, 0.18);
}

/* White on the tint, so the controls still read as controls. */
.ChSiCopyPanel .ChButton:not(.ChButtonPrimary),
.ChSiAssignPanel .ChButton:not(.ChButtonPrimary) {
    background-color: #fff !important;
}

.ChSiCopyItemCell {
    margin-top: 4px;
}

.ChSiAssignItems {
    max-height: 320px;
    overflow-y: auto;
    padding-top: 4px;
}

.ChSiAssignRow {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 0;
}

/* An item that already has its own list, or is already on this template. */
.ChSiAssignState {
    color: var(--totm-text-muted);
    font-size: var(--totm-fs-sm, 13px);
}

.ChSiTemplatePicker {
    min-width: 260px;
}
