/* Portal stylesheet. Contents:
     - --arc-orange tokens, .btn-outline-orange/purple/pink, .text-bg-orange,
       disabled-gray, .arc-navbar, #userInfo.authenticated
     - uniform modal height (.modal-dialog/.modal-content/.modal-body pinned to 75vh)
     - navbar customization: side modes, icon rail, widget drag, sticky footer,
       .palette-sw, customize-modal grip/icon grid
     - form pages (.arc-form/.arc-form-section) + .arc-req required-field marker
     - "THE UI SYSTEM" below: wizard step rail, the quick-add/discard swap lane, ArcPicker's
       "+ new" label link, rich picker rows (.arc-pk-part)
     - ArcListView: stacked/clamped/ellipsised list cells, card + compact view modes,
       whole-row open, drag-resizable columns, the filter-panel + columns-chooser scroll
       areas, by-action dropdown tints, the shared-scope globe, the preset view-state
       chip, the loading/busy indicators, and the two-row toolbar with its pinning +
       z-index ladder
     - check-row groups, one-line address, .arc-doc-cards document header, .arc-doc-key,
       .arc-field-row / .arc-group-row, .arc-acc* accordions */

:root {
    --arc-orange: #e8590c;
    --arc-orange-dark: #c44a05;
}

/* Orange accent for the primary button across themes. */
.btn-primary {
    --bs-btn-bg: var(--arc-orange);
    --bs-btn-border-color: var(--arc-orange);
    --bs-btn-hover-bg: var(--arc-orange-dark);
    --bs-btn-hover-border-color: var(--arc-orange-dark);
    --bs-btn-active-bg: var(--arc-orange-dark);
    --bs-btn-active-border-color: var(--arc-orange-dark);
}

/* ---- Action-based button colors (site-wide scheme) ------------------------------------------
   Bootstrap ships success/warning/danger/primary; these add the orange/purple/pink OUTLINE
   variants (built on Bootstrap 5.3's --bs-btn-* vars so they behave like any .btn / .btn-sm:
   colored icon + border, fill on hover). Action → color used across the app:
     View = orange · Edit = purple · History = pink · Submit = blue (btn-outline-primary) ·
     Approve / Save = green · Reject = yellow · Delete / Cancel = red.
   Apply these classes to new action buttons so the whole site stays consistent. */
.btn-outline-orange {
    --bs-btn-color: #e8590c; --bs-btn-border-color: #e8590c;
    --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #e8590c; --bs-btn-hover-border-color: #e8590c;
    --bs-btn-active-color: #fff; --bs-btn-active-bg: #e8590c; --bs-btn-active-border-color: #e8590c;
    --bs-btn-focus-shadow-rgb: 232, 89, 12;
    --bs-gradient: none;
}
.btn-outline-purple {
    --bs-btn-color: #6f42c1; --bs-btn-border-color: #6f42c1;
    --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #6f42c1; --bs-btn-hover-border-color: #6f42c1;
    --bs-btn-active-color: #fff; --bs-btn-active-bg: #6f42c1; --bs-btn-active-border-color: #6f42c1;
    --bs-btn-focus-shadow-rgb: 111, 66, 193;
    --bs-gradient: none;
}
.btn-outline-pink {
    --bs-btn-color: #d63384; --bs-btn-border-color: #d63384;
    --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #d63384; --bs-btn-hover-border-color: #d63384;
    --bs-btn-active-color: #fff; --bs-btn-active-bg: #d63384; --bs-btn-active-border-color: #d63384;
    --bs-btn-focus-shadow-rgb: 214, 51, 132;
    --bs-gradient: none;
}

/* Brand-orange badge (Bootstrap's text-bg-* pattern — e.g. the FMSOP basis indicator). */
.text-bg-orange {
    color: #fff !important;
    background-color: var(--arc-orange) !important;
}

/* Every button renders gray when disabled (overrides each variant's own disabled color). */
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
    --bs-btn-disabled-color: #6c757d;
    --bs-btn-disabled-bg: #e9ecef;
    --bs-btn-disabled-border-color: #ced4da;
    --bs-btn-disabled-opacity: 1;
}
[data-bs-theme="dark"] .btn:disabled,
[data-bs-theme="dark"] .btn.disabled,
[data-bs-theme="dark"] fieldset:disabled .btn {
    --bs-btn-disabled-color: #adb5bd;
    --bs-btn-disabled-bg: #343a40;
    --bs-btn-disabled-border-color: #495057;
}

.arc-navbar {
    background-color: var(--arc-orange);
}

.arc-navbar .navbar-brand,
.arc-navbar .nav-link,
.arc-navbar .navbar-text {
    color: #fff;
}

.arc-navbar .nav-link:hover {
    color: #ffe9d6;
}

[data-bs-theme="dark"] .arc-navbar {
    background-color: var(--arc-orange-dark);
}

/* Signed-in user name acts as a button (profile modal / right-click menu). */
#userInfo.authenticated {
    cursor: pointer;
    padding: 2px 8px;
    border-radius: 4px;
    transition: background-color .15s ease-in-out;
    user-select: none;
}

#userInfo.authenticated:hover {
    background-color: rgba(255, 255, 255, .18);
}

/* ── Uniform modal height (owner: every modal is a fixed ~75vh box) ──────────────────────────
   Multi-step flows — the parts editor wizard #ptModal especially — must never resize between
   steps, so the modal-content is pinned at 75vh and the body is the only scroller (header/footer
   stay put). Applied to ALL modals (plain confirm dialogs, centered, scrollable, and any future
   modal) via the base classes rather than a per-markup .modal-dialog-scrollable opt-in — see the
   Decision in docs/architecture/ui/guidelines.md. Overrides Bootstrap's own scrollable/centered
   height rules (same specificity, later in the cascade). */
.modal-dialog,
.modal-dialog-scrollable,
.modal-dialog-centered {
    height: 75vh;
    min-height: 75vh;
}
.modal-content {
    height: 100%;
    max-height: 100%;
    overflow: hidden;
}
.modal-body {
    overflow-y: auto;
}
/* Modals wrap header/body/footer in a <form>, which breaks the flex scroll (it relies on those
   being direct flex children of .modal-content). display:contents drops the form's layout box so
   the sections become direct flex children again — body scrolls, header/footer pin. (Form
   submission is unaffected; it's a DOM relationship, not a layout one.) */
.modal-content > form {
    display: contents;
}

/* ---------- Navbar customization (Employee Portal) ---------- */

/* User-removed nav items: a class of its own so it can never fight the RBAC d-none toggles
   (portal-auth.js owns d-none; nav-customize.js owns this). */
.arc-nav-removed { display: none !important; }

/* Side navbar modes (user preference). Below the lg navbar-expand breakpoint the familiar top
   bar + hamburger always wins — the position preference is a desktop concern (and prefs are
   device-scoped, so a phone profile never stores a side position anyway). */
@media (min-width: 992px) {
    body.arc-nav-left .arc-navbar,
    body.arc-nav-right .arc-navbar {
        position: fixed;
        top: 0;
        bottom: 0;
        width: 250px;
        align-items: flex-start;
        z-index: 1030; /* above content, below modals (1055) and the context menus (1080+) */
    }
    body.arc-nav-left .arc-navbar { left: 0; right: auto; }
    body.arc-nav-right .arc-navbar { right: 0; left: auto; }
    body.arc-nav-left { padding-left: 250px; }
    body.arc-nav-right { padding-right: 250px; }

    body.arc-nav-left .arc-navbar > .container-fluid,
    body.arc-nav-right .arc-navbar > .container-fluid {
        flex-direction: column;
        align-items: stretch;
        height: 100%;
    }
    body.arc-nav-left .arc-navbar .navbar-collapse,
    body.arc-nav-right .arc-navbar .navbar-collapse {
        flex-direction: column;
        align-items: stretch;
        flex-grow: 1;
        width: 100%;
        /* The sidebar scrolls when the item list outgrows a short viewport (low resolution or
           high display scaling), so bottom items and the utility cluster stay reachable. Safe
           for the flyout menus: nav-customize.js re-anchors every open menu position:fixed
           (viewport-clamped), and fixed elements aren't clipped by ancestor overflow. */
        min-height: 0;
        overflow-y: auto;
        overflow-x: hidden;
    }
    body.arc-nav-left .arc-navbar .navbar-nav,
    body.arc-nav-right .arc-navbar .navbar-nav {
        flex-direction: column;
        width: 100%;
        margin-right: 0 !important; /* neutralize me-auto in column flow */
    }
    /* Anchor for the dropend/dropstart flyout menus (nav-customize.js swaps the classes). */
    body.arc-nav-left .arc-navbar .navbar-nav .nav-item,
    body.arc-nav-right .arc-navbar .navbar-nav .nav-item {
        position: relative;
    }
    /* Utility cluster (site docs / theme / user / language) sits at the sidebar bottom. */
    body.arc-nav-left .arc-navbar .navbar-collapse > .d-flex,
    body.arc-nav-right .arc-navbar .navbar-collapse > .d-flex {
        margin-top: auto;
        flex-wrap: wrap;
        padding-top: .75rem;
    }
}

/* ---------- Sidebar icons + collapsible icon rail (Employee Portal) ---------- */

/* Top-level link icons exist in the markup but show only in the side modes, so the
   top bar (and the mobile hamburger menu) keeps today's text-only look. */
.arc-nav-icon { display: none; }

/* The sidebar collapse toggle only exists visually in the side modes at desktop width. */
.arc-nav-collapse-btn { display: none; }

@media (min-width: 992px) {
    body.arc-nav-left .arc-nav-icon,
    body.arc-nav-right .arc-nav-icon {
        display: inline-block;
        width: 1.4rem;
        text-align: center;
    }
    body.arc-nav-left .arc-nav-collapse-btn,
    body.arc-nav-right .arc-nav-collapse-btn {
        display: inline-flex;
        align-self: flex-start;
        margin: .25rem 0 .25rem;
    }

    /* Collapsed: a 64px icon-only rail. Labels/carets hide; flyout menus still show full text. */
    body.arc-nav-collapsed.arc-nav-left .arc-navbar,
    body.arc-nav-collapsed.arc-nav-right .arc-navbar { width: 64px; }
    body.arc-nav-collapsed.arc-nav-left { padding-left: 64px; }
    body.arc-nav-collapsed.arc-nav-right { padding-right: 64px; }

    body.arc-nav-collapsed.arc-nav-left .arc-nav-label,
    body.arc-nav-collapsed.arc-nav-right .arc-nav-label { display: none; }
    body.arc-nav-collapsed.arc-nav-left .arc-navbar .navbar-nav .dropdown-toggle::after,
    body.arc-nav-collapsed.arc-nav-right .arc-navbar .navbar-nav .dropdown-toggle::after { display: none; }
    body.arc-nav-collapsed.arc-nav-left .arc-navbar .navbar-nav .nav-link,
    body.arc-nav-collapsed.arc-nav-right .arc-navbar .navbar-nav .nav-link {
        text-align: center;
        padding-left: .25rem;
        padding-right: .25rem;
    }
    body.arc-nav-collapsed.arc-nav-left .arc-navbar .navbar-brand,
    body.arc-nav-collapsed.arc-nav-right .arc-navbar .navbar-brand { margin-right: 0; }

    /* Utility cluster in the collapsed rail: EVERYTHING stays reachable, icon-only — sign
       in/out and the user's name (the My Profile popup) shed their .arc-nav-label text, the
       language switcher sheds its code + caret, and the cluster stacks vertically centered. */
    body.arc-nav-collapsed.arc-nav-left .arc-navbar .navbar-collapse > .d-flex,
    body.arc-nav-collapsed.arc-nav-right .arc-navbar .navbar-collapse > .d-flex {
        flex-direction: column;
        align-items: center;
    }
    body.arc-nav-collapsed.arc-nav-left .arc-navbar #langCurrent,
    body.arc-nav-collapsed.arc-nav-right .arc-navbar #langCurrent { display: none; }
    body.arc-nav-collapsed.arc-nav-left .arc-navbar .navbar-collapse > .d-flex .dropdown-toggle::after,
    body.arc-nav-collapsed.arc-nav-right .arc-navbar .navbar-collapse > .d-flex .dropdown-toggle::after { display: none; }
}

/* ---------- Widget drag-to-reorder (Employee Portal edit mode) ---------- */
/* touch-action:none on the GRIP ONLY: dragging starts from the handle while normal page
   scrolling elsewhere on a touch screen keeps working. */
.pw-grip { cursor: grab; touch-action: none; }
.pw-grip:active { cursor: grabbing; }
.pw-dragging { opacity: .55; }
.pw-dragging .card { border-color: var(--arc-orange); border-style: dashed; }
body.pw-no-select { user-select: none; }

/* Navbar dropdown placement note: Bootstrap skips Popper for any dropdown inside a .navbar
   (data-bs-popper="static"), so its CSS-only placement has zero viewport awareness. All the
   fit-to-viewport work (side-mode flyouts re-anchored position:fixed and clamped on-screen,
   height caps + internal scrolling everywhere, horizontal nudge in top mode) lives in
   nav-customize.js (fitNavMenu, on shown.bs.dropdown) — don't add per-menu CSS position
   hacks here; they'd fight the JS. */

/* Sticky footer (user preference, default ON): needs a solid background so page content doesn't
   show through while it overlays the scroll, and a z-index under the navbar/menus. */
.arc-footer.sticky-bottom {
    background-color: var(--bs-body-bg);
    z-index: 1019;
}

/* Site-theme (design palette) picker: the small two-color swatch on each menu item. The themes
   themselves live in arc-themes.css. */
.palette-sw {
    display: inline-block;
    width: 1.05rem;
    height: 1.05rem;
    border-radius: 4px;
    border: 1px solid var(--bs-border-color);
    flex: none;
}

/* Customize-navigation modal: drag grip + icon-picker grid */
.nav-cst-grip { cursor: grab; touch-action: none; }
.nav-cst-grip:active { cursor: grabbing; }
#navIconGrid .nav-icon-opt { width: 2.4rem; height: 2.15rem; padding: .2rem; }


/* ---------- Form pages ----------
   Two conventions live here (docs/architecture/ui/guidelines.md → "Form pages"):

   1. Simple stacked forms — one continuous single column of <fieldset class="arc-form-section">
      sections with a <legend> heading, so DOM order = visual order = tab order (no side-by-side
      cards, no positive tabindex). Header-field sections cap their width (.arc-form); wide sections
      (a lines table, say) opt into full width (.arc-form-wide).
   2. Document editors — a compact header over a full-width lines table with
      collapsed .arc-acc accordions below, so the whole document fits a 1080p screen without scrolling.
      Every one of them is VIEW-ONLY: a .arc-doc-cards row whose cards each carry a ✎ pencil into that
      document's shared header WIZARD modal, plus the notes cards above the lines. .arc-field-row / .arc-group-row
      are in-modal form rows. All classes are theme-aware via Bootstrap CSS vars. */
.arc-form { max-width: 56rem; }
.arc-form-wide { max-width: none; }
.arc-form-section {
    border: 0;
    margin: 0 0 1.5rem;
    padding: 0;
    min-width: 0; /* let the fieldset shrink inside flex/grid instead of forcing min-content width */
}
.arc-form-section > legend {
    float: none;             /* Reboot floats <legend>; we want it in normal flow as a heading */
    margin-bottom: .75rem;
    padding-bottom: .35rem;
    font-size: 1.05rem;
    font-weight: 600;
    border-bottom: 1px solid var(--bs-border-color);
}

/* Required-field marker (site-wide): a red asterisk inside the <label> (span aria-hidden) and a
   small "* … required" key line placed before the fields. Uses Bootstrap's danger var so both
   themes track. */
.arc-req { color: var(--bs-danger); margin-left: .15rem; font-weight: 600; }
.arc-req-key { color: var(--bs-secondary-color); font-size: .8rem; }

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   THE UI SYSTEM — the shared component rules (see docs/architecture/ui/guidelines.md).

   Every rule here must be INERT on a page that does not use it.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── Wizard shell: sticky step rail, the quick-add/discard swap lane, the picker's "+ new" ───────*/
/* Sticky wizard step rail (parts + vendor staged wizards). The rail and its pane share the single
   scrolling .modal-body, so without this the rail scrolls away with the pane. `position: sticky`
   pins the rail column to the top of the modal-body scroller; `align-self: flex-start` stops the
   Bootstrap-row flex item from stretching to full height (a stretched item has no room to stick),
   so it holds its natural height and stays visible while the pane scrolls. */
.arc-wiz-rail-col {
    position: sticky;
    top: 0;
    align-self: flex-start;
    z-index: 1;
}

/* Quick-add CONTENT SWAP (inside a wizard): the
   step panes hide and this compact create form takes the pane's place — ONE modal layer only, never a
   stacked dialog. Its own Save/Cancel live in the block, so the wizard footer hides while it's up. */
.arc-wiz-swap {
    padding: .25rem .25rem 0;
}
.arc-wiz-swap-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .25rem .6rem;
    padding-bottom: .35rem;
    margin-bottom: .5rem;
    border-bottom: 1px solid var(--bs-border-color);
}
/* Discard pane (ArcDiscardPane) — the same swap lane, rendering the host's unsaved changes as a
   READONLY three-column table (field · saved · your change) instead of a native confirm(). */
.arc-discard-table th,
.arc-discard-table td {
    vertical-align: top;
    font-size: .875rem;
}
.arc-discard-table thead th {
    font-weight: 600;
    white-space: nowrap;
}

/* The "＋ new" affordance ArcPicker adds to a quick-add-enabled field's <label> (the mouse path; the
   pinned "＋ New …" dropdown row is the keyboard one). */
.arc-pk-addnew {
    font-size: .8rem;
    text-decoration: none;
    vertical-align: baseline;
}


/* ── Rich picker rows ───────────────────────────────────────────────────────────────────── */
/* Rich full-width part-picker rows: a ~48px thumbnail beside a
   three-line part summary (number + description / on-hand + UoM + department / preferred vendor +
   manufacturer). The ArcPicker panel spans the modal width (createAsync fitTo); the shared
   `.arc-pk-sub` (arc-picker.js) styles the muted lines 2–3, `.arc-thumb` the thumbnail chrome. */
.arc-pk-part { display: flex; gap: .5rem; align-items: flex-start; text-align: start; }
.arc-pk-part-lines { min-width: 0; flex: 1 1 auto; }

/* ══ ArcListView — list cells, the three view modes, the toolbar and its pinning ══════════════*/
/* Stacked "part" cell (number bold on line 1, description muted + 2-line clamp below). The number never
   wraps; a min-width gives the 2-line-clamped description meaningfully more room (freed by the column
   removals/merges). Compact view renders the plain number instead (compactRender), so the description
   sub-line never exists there; the min-width is reset so the number column stays narrow.
   TWO FLOORS: the shared `.arc-part-col` is the modest 14rem every runtime list uses for its
   first-line part cell, and `.arc-part-col-lg` is the 20rem used where the part IS
   the row's subject. A min-width is a HARD floor for table-layout:auto, so keeping the runtime lists on
   the smaller one is part of the §C0 no-default-scrollbar budget. */
.arc-part-num { font-weight: 600; white-space: nowrap; }
.arc-part-col { min-width: 14rem; }
.arc-part-col-lg { min-width: 20rem; }
.arc-table-compact .arc-part-col,
.arc-table-compact .arc-part-col-lg { min-width: 0; }
.arc-part-src { white-space: nowrap; }
/* Compact-mode column sizing. Tight: the column shrinks to its content (identity/number
   cells) instead of soaking up leftover width. Grow: the column absorbs whatever width
   the other columns leave over, and its inner ellipsis span fills that width instead of
   clipping at its own rem cap — so a wide window shows more text, not more whitespace.
   max-width: 0 keeps the grow column's content out of the auto-layout math (a long title
   can never force a horizontal scrollbar); min-width is its readable floor. */
.arc-table-compact .arc-col-tight { width: 1%; white-space: nowrap; }
.arc-table-compact .arc-col-grow { width: 100%; max-width: 0; min-width: 12rem; }
.arc-table-compact .arc-col-grow .arc-ellipsis,
.arc-table-compact .arc-col-grow .arc-clamp-2 { max-width: 100%; }
/* The shared 2-LINE CLAMP for any long free text in a list cell (a part description, a location's notes,
   a manufacturer's notes). It is used instead of the `text-truncate d-inline-block; max-width:NNrem` idiom:
   `text-truncate` bakes `white-space: nowrap` INTO the cell markup, which followed the same
   renderer into card view and pushed content past the card's border (§C0b). A clamp wraps, so the row (or
   card) grows the second line and then stops. `overflow-wrap: anywhere` handles an unbroken token — a
   pasted URL, a long part number. */
.arc-clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
    overflow-wrap: anywhere;
}
/* A stacked cell's muted second line (vendor → ship-to, status → "N open", total → line count). Kept
   generic because five runtime lists render one; wraps like any card content (§C0b). */
.arc-cell-sub { overflow-wrap: anywhere; word-break: break-word; }
/* The shared SINGLE-LINE ELLIPSIS for a list cell's own text — the one-line sibling of
   `.arc-clamp-2` above, for a field whose value is a title rather than a paragraph: a maintenance order's
   title, a PM schedule's. One line, capped, "…", and THE RENDERER PUTS THE FULL TEXT IN A `title`
   ATTRIBUTE, which is what makes truncating safe (no hover, no ellipsis — that is the rule, not a style
   choice). Deliberately generic: it is a site-wide utility, not a maintenance class.
   Use `.arc-clamp-2` instead where the value really is free text that deserves two wrapped lines. */
.arc-ellipsis {
    display: inline-block;
    max-width: 20rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}
/* CARD VIEW has nothing to scroll into, so an ellipsis there would push past the card's border (§C0b, the
   same reason `.arc-card-val .text-nowrap` un-nowraps below): in a card the text simply wraps. */
.arc-card-val .arc-ellipsis,
.arc-card-identity .arc-ellipsis {
    display: inline;
    max-width: 100%;
    overflow: visible;
    white-space: normal;
}
/* Description list cell: preserve newlines + wrap long/multi-line descriptions in the paginated table. */
.pt-desc-cell { white-space: pre-wrap; word-break: break-word; }
/* Staged-for-removal source row in the parts wizard: deleting a source crosses it out and
   offers Undo instead of dropping it, so the row must READ as gone without leaving the table. The
   line-through is on the cells (a <tr> is not a text box), and the Undo button is excluded so it stays
   legible and clickable. */
.pt-src-removed > td { text-decoration: line-through; color: var(--bs-secondary-color); opacity: .75; }
.pt-src-removed > td .btn { text-decoration: none; opacity: 1; }

/* ArcListView CARD view — content wraps inside the card, never past its border (the list
   rework's §C0b rule). Cards reuse each column's `render()`, so a long unbroken token — a part number, a
   vendor part #, a pasted URL, a file name — would otherwise push the card body wider than its own box
   and make the card grid scroll sideways. `overflow-wrap: anywhere` lets the browser break mid-token as a
   LAST resort (normal words still break at spaces) and `word-break` is the older-engine twin. The card
   grows taller instead. Renderers keep `text-nowrap` on their `tdClass` (table-only), never inside the
   returned markup, so nothing nowrap leaks in here. */
.arc-card-val,
.arc-card-identity {
    overflow-wrap: anywhere;
    word-break: break-word;
    min-width: 0;
}
/* A cell renderer that legitimately nowraps in the TABLE (money, quantities, dates) must still wrap in a
   card — the card is the one place where a nowrap span has nothing to scroll into. */
.arc-card-val .text-nowrap,
.arc-card-identity .text-nowrap { white-space: normal !important; }

/* ArcListView WHOLE-ROW OPEN (spec.rowOpen — the contract is the arc-list-view.js header).
   A row/card whose single open action resolved gets `.arc-row-open`, so the affordance is the same on
   every list and in all three view modes. The table's row highlight is already Bootstrap's own
   `.table-hover`, so the only thing needed there is the cursor; a card has no hover state of its own, so
   it gets the same tinted border the other clickable surfaces use (.arc-thumb-clickable, a.arc-part-link).
   The two EXCLUDED cells reset the cursor, so "this bit is not the row" reads before the click: the
   row-actions cell and the media cell (whose own thumbnail re-asserts pointer for the lightbox). */
tr.arc-row-open,
.card.arc-row-open { cursor: pointer; }
.card.arc-row-open:hover { border-color: var(--bs-primary); }
tr.arc-row-open > td.arc-row-actions,
tr.arc-row-open > td.arc-thumb-col,
.card.arc-row-open > .arc-row-actions { cursor: default; }

/* ArcListView compact view mode (spec.compactView) — a dense, small-type table for admin scanning
   (e.g. Internal Parts with the audit columns showing). Reuses the same <table> DOM; only the type
   size / cell padding / thumbnail shrink. No colors are set, so the Bootstrap table CSS vars keep
   light + dark mode correct. Matches Bootstrap's own `.table > :not(caption) > * > *` cell selector. */
.arc-table-compact { font-size: .78rem; line-height: 1.2; }
/* Minimal vertical padding — the driver of compact-row height. */
.arc-table-compact > :not(caption) > * > * { padding: .05rem .4rem; }
/* The row-action buttons default to btn-group-sm, whose height otherwise sets the row height —
   shrink them (Bootstrap 5.3 --bs-btn-* vars) so a data-grid row is as short as its text. */
.arc-table-compact .btn {
    --bs-btn-padding-y: 0rem;
    --bs-btn-padding-x: .3rem;
    --bs-btn-font-size: .72rem;
    --bs-btn-line-height: 1.2;
}
.arc-table-compact .badge { padding: .18em .4em; font-weight: 500; }
/* Every compact row stays on ONE line — no cell wraps, and any long free text (a description, a note)
   collapses to a single ellipsised line instead of bleeding down the row. The normal table + card views
   keep the wrapping `.pt-desc-cell` / 2-line `.arc-clamp-2` rules above. */
.arc-table-compact td,
.arc-table-compact th { white-space: nowrap; }
.arc-table-compact .pt-desc-cell,
.arc-table-compact .arc-clamp-2 {
    display: inline-block;
    max-width: 24rem;
    -webkit-line-clamp: none;
    line-clamp: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

/* ArcListView DRAG-RESIZABLE COLUMNS — an 8px grab strip on every header cell's right edge.
   Table and compact share the same <table>, so one rule set covers both; cards have no columns. The
   handle is absolutely positioned inside its `.arc-col-th`, so it never disturbs the header label, the
   sort icon or the `text-end` Actions header. Widths live device-local per list
   (`arc:<resource>-col-widths`, the same tier as the filter panel's width — never in a preset) and are
   applied as INLINE width/min-width/max-width on the <th> AND every matching <td>: the inline min-width
   is what lets a resize go under a tdClass floor (`.arc-part-col`'s 14rem) and the max-width is what
   pairs with `overflow: hidden` below so a NARROWED column clips instead of pushing `.table-responsive`
   wider. In the normal table view a narrowed cell simply wraps and grows taller; in compact, where
   `white-space: nowrap` is global, the same rule ellipsises it. */
.arc-col-th { position: relative; }
.arc-col-resizer {
    position: absolute; top: 0; right: 0; bottom: 0; z-index: 2;
    width: 8px;
    cursor: col-resize; touch-action: none; user-select: none;
}
.arc-col-resizer:hover { background-color: var(--bs-primary); opacity: .3; }
.arc-col-resized { overflow: hidden; text-overflow: ellipsis; }
/* A cell renderer's own inner box (the 2-line clamp, compact's 24rem ellipsis span, a chip list) must
   give way to the width the user chose — otherwise its own max-width is the floor the column can't go
   under, and the drag appears to do nothing. */
.arc-col-resized > * { max-width: 100%; }
/* ...and the reach must extend past a wrapper: the sub-line shape is
   td > .arc-cell-sub > .arc-ellipsis, and the direct-child rule above stops at the
   wrapper div, leaving the span's own rem cap in force no matter how far the column
   is dragged. */
.arc-col-resized .arc-ellipsis,
.arc-col-resized .arc-clamp-2 { max-width: 100%; }

/* ArcListView filter-panel facet scroll area. Horizontal padding + a stable scrollbar gutter keep
   the option checkboxes' left edge and the trailing count numbers from being clipped by the
   scroll container (the labels are plain flex, not .form-check, so no negative checkbox margin). */
.panel-items {
    max-height: 16rem;
    overflow-y: auto;
    padding-inline: .25rem;
    scrollbar-gutter: stable;
}

/* ArcListView Columns-chooser scroll area. A page with a long column list (every
   audit-six-carrying list, easily 20+ entries) grew the `#…ColumnMenu` dropdown
   unbounded and ran it off the bottom of the viewport. Caps just the checkbox rows — the "Show
   columns" header and the trailing divider + "All" button stay outside this element as ordinary
   `.dropdown-menu` `<li>`s, so they never scroll out of reach. Rows are also compacted (tighter
   than the default `.dropdown-item` padding/line-height) so more fit before scrolling kicks in. */
.arc-col-menu-items {
    max-height: min(60vh, 24rem);
    overflow-y: auto;
    padding-inline: .25rem;
    scrollbar-gutter: stable;
}
.arc-col-menu-items .dropdown-item {
    padding-top: .15rem;
    padding-bottom: .15rem;
    line-height: 1.3;
}

/* By-action icon tints for DROPDOWN-MENU items. Whenever an action folds out of an inline
   icon button and into a ⋯ kebab / caret menu, its icon keeps the by-action color the button carried
   (see "Action-based button colors" at the top of this file) — the menu item's own text stays the
   default color, except Delete, whose whole row goes .text-danger. Shared by ArcFiles' image-card kebab
   and ArcListView's preset-row kebab + "Reset to page default" item; the Bootstrap vars keep them
   themeable, and the two purple/orange values are the same ones .btn-outline-purple / --arc-orange use
   (these replaced the files-only `.arc-file-menu-purple` / `-orange` pair). */
.arc-menu-icon-purple { color: #6f42c1; }
.arc-menu-icon-orange { color: var(--arc-orange); }
.arc-menu-icon-green { color: var(--bs-success); }
.arc-menu-icon-primary { color: var(--bs-primary); }
/* Shared scope: the globe on ArcListView's shared-preset rows and its menu header. The
   emphasis token, not raw --bs-info — cyan on a white menu is unreadable. */
.arc-menu-icon-info { color: var(--bs-info-text-emphasis); }

/* The Presets button's view-state chip. One glance answer to "what am I looking at?":
   the page default, a saved preset (`✓ name`), or an edited view that is neither (`● Modified`). It is
   computed from the view-state fingerprint in arc-list-view.js, not from the one-way active-preset flag,
   so a page-size / view / search edit registers too. Subtle tinted pills — this rides INSIDE a toolbar
   button, so it must not out-shout the button's own label or the by-action palette. */
.arc-view-chip {
    display: inline-block;
    margin-left: .15rem;
    padding: .05rem .4rem;
    border: 1px solid transparent;
    border-radius: .75rem;
    font-size: .72rem;
    font-weight: 600;
    line-height: 1.4;
    vertical-align: middle;
    white-space: nowrap;
}
.arc-view-chip:empty { display: none; }
.arc-view-chip-default {
    background: var(--bs-secondary-bg);
    color: var(--bs-secondary-color);
    border-color: var(--bs-border-color);
}
.arc-view-chip-preset {
    background: color-mix(in srgb, var(--bs-primary) 14%, var(--bs-body-bg));
    color: var(--bs-primary-text-emphasis);
    border-color: var(--bs-primary-border-subtle);
}
.arc-view-chip-modified {
    background: color-mix(in srgb, var(--bs-warning) 22%, var(--bs-body-bg));
    color: var(--bs-warning-text-emphasis);
    border-color: var(--bs-warning-border-subtle);
}

/* ArcListView loading indication (decisions: docs/architecture/ui/guidelines.md; the
   contract is the LOADING STATES block in arc-list-view.js). A refetch keeps the old rows on screen
   (stale-while-revalidate), so the busy signal is deliberately subtle: past the 250 ms delayed-show the
   VISIBLE results container (#…TableWrap for table + compact, its sibling #…Cards) dims and takes
   aria-busy="true". Nothing else changes — the dimmed rows stay fully interactive, which is the whole
   point of keeping them. A fetch that resolves inside the delay never gets here at all. */
.arc-list-busy {
    opacity: .55;
    transition: opacity .15s linear;
}
/* The reserved-space indicator (the fetch-info line under the search box). It is ALWAYS in the layout
   and toggled with visibility, never display, so lighting it can never shift the line it sits on. */
.arc-list-busy-ind {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    visibility: hidden;
}
.arc-list-busy-ind.arc-busy-on { visibility: visible; }
/* The reduced-motion twin of a spinner glyph: hidden by default, shown in place of it below. */
.arc-busy-label {
    display: none;
    font-size: .8rem;
}
/* prefers-reduced-motion: reduce — the INFORMATION stays, the motion goes (the opacity dim above is
   not motion, so it is untouched; only its transition is dropped). Every `.arc-busy-spin` glyph is
   replaced by static "Updating…" text: the standalone indicator swaps in its `.arc-busy-label`, and
   the Refresh button's own label has already been swapped to the same word by setRefreshBusy(). */
@media (prefers-reduced-motion: reduce) {
    .arc-list-busy { transition: none; }
    .arc-busy-spin.spinner-border { display: none; }
    .arc-busy-label { display: inline; }
}

/* ---------- ArcListView TOOLBAR ----------
   The two-row toolbar and its pinning — the standard toolbar every ArcListView page renders, so these
   class names are on every list page in the app. The behavioural contract is THE TOOLBAR block in
   wwwroot/js/arc-list-view.js; the measurement lives in measurePins() / syncPinStuck(), which set the
   two custom properties below on the list HOST.

   Z-INDEX BUDGET (the site-wide ladder is documented at `.arc-src-pop` below: navbar 1020, side-nav
   1030, modals 1055, list context menus 1080+). The two pinned layers slot in UNDER the navbar and
   under the sticky footer (1019) — they are page content that floats, not chrome:

       1014  pinned <thead> cells (opaque — the rows scroll UNDER them)
       1016  pinned row 1         (opaque — it must cover the header it is pinned above)
       1017  ANY toolbar dropdown, from either row — over both pinned layers and over the table
       1019  sticky footer            (existing)
       1020  navbar                   (existing, Bootstrap .sticky-top)

   Row 1 pins at `--arc-pin-top` (0 when the navbar isn't sticky or is a full-height side nav) and the
   header at `--arc-pin-head` (that offset PLUS row 1's measured height — row 1 wraps on narrow screens,
   so it is re-measured on resize, on every render and on a column drag). Row 2 and the pager never pin.

   PINNED HEADER: the pinned band must not hard-code `background-color: var(--bs-body-bg)`, which is
   the PAGE background, not the table header's — see `.arc-thead-pin` below — and the toolbar
   menus must paint above it (Bootstrap's `$zindex-dropdown: 1000` — see the 1017 rule below). */
.arc-tb-row1 {
    position: sticky;
    top: var(--arc-pin-top, 0px);
    z-index: 1016;
    /* Opaque: rows scroll UNDER this band. `--bs-body-bg` is CORRECT here and is not a hard-coded
       colour — the toolbar sits directly on the page background, which is exactly what Bootstrap's
       `body { background-color: var(--bs-body-bg) }` paints, and every arc-themes.css palette redefines
       `--bs-body-bg` to its own `--arc-t-bg`. (The <thead> band is the one that had this wrong: a table
       header is NOT painted with the page background — see `.arc-thead-pin` below.) */
    background-color: var(--bs-body-bg);
    padding-block: .35rem;
}
/* The shadow belongs to the STUCK state only — a permanent band would read as chrome. */
.arc-tb-row1.arc-tb-pinned { box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .1); }
/* EVERY toolbar dropdown, from BOTH rows. Bootstrap's own `$zindex-dropdown` is 1000,
   which is under the pinned <thead> (1014) and the pinned row-1 band (1016) — so a Presets / Columns /
   view-chooser menu opened from row 2 would be painted over as soon as it reached either (the presets
   menu rendering half behind the table). A menu is a transient overlay: it belongs above the
   band it was opened near, and below the navbar. The descendant selector also covers the per-preset ⋯
   kebab submenus nested inside #{P}PresetMenu. This rule is what makes the header pin survivable. */
.arc-tb-row1 .dropdown-menu,
.arc-tb-row2 .dropdown-menu { z-index: 1017; }
/* `clip` does NOT create a scroll container, so a sticky <thead> inside it resolves against PAGE
   scroll; measurePins() adds this only while the table FITS and hands the wrapper back to Bootstrap's
   `overflow-x: auto` (and drops the header pin outright) the moment it genuinely overflows sideways. */
.table-responsive.arc-tb-clip { overflow-x: clip; }
/* Sticky header cells need `border-collapse: separate`: with collapsed borders the rules between rows
   belong to the TABLE box, so they scroll out from under the stuck cells. With separate borders each
   cell owns its own, so the theme's `thead th` border-bottom travels with the pinned cell and is
   deliberately NOT overridden here (replacing it with `inset 0 -2px 0
   var(--bs-border-color)` would silently recolour it in the four palettes that set `--arc-t-th-bb`). Applied only while the pin is live. */
.arc-thead-pin .table-responsive > table {
    border-collapse: separate;
    border-spacing: 0;
}
.arc-thead-pin .table-responsive > table > thead > tr > th {
    position: sticky;
    top: var(--arc-pin-head, 0px);
    z-index: 1014;
    /* THE PINNED HEADER MUST NOT CHANGE COLOUR (`background-color: var(--bs-body-bg)` would be wrong:
       it is the PAGE background, and in arc-themes.css a table
       header is nothing of the kind: `html[data-arc-theme] .table thead th` paints `--arc-t-th-bg` over
       the `.table-responsive` surface `--arc-t-surface`. Measured by screenshot pixel, that swap shifted
       the header's colour in 13 of the 18 palette×mode combinations — worst of all in Signal, where it
       flipped the header between near-black and cream (Δ225/255). It only looked innocent in OG and
       Blueprint, where the page and table-header colours happen to coincide.)
       So instead of substituting ONE colour, rebuild the exact stack the browser composites when the
       header is in flow, bottom to top:
         background-color   the page background — an OPAQUE floor, so rows can never ghost through
         layer 2 (--under)  the wrapper's own table-card surface, which may itself be translucent
                            (Aurora is rgba(255,255,255,.045) in dark mode)
         layer 1 (--face)   the <thead>'s own background — `transparent` in Nordic Steel and Aurora,
                            which is precisely why layer 2 has to be painted too
       In the OG theme none of the `--arc-t-*` tokens exist: --face falls back to Bootstrap's own
       `--bs-table-bg` (inherited from `.table`, itself `var(--bs-body-bg)`), --under to transparent, and
       the result is the colour Bootstrap paints unpinned. Verified pixel-identical to an unpinned header
       in 16 of the 18 palette×mode combinations; Aurora (both modes) is the one accepted limitation — it
       also tints `body` with two decorative fixed radial gradients, which an opaque band cannot reproduce.
       The gap depends on where you sample: up to ~15/255 light / ~33/255 dark at the table's left edge
       (nearest the gradient centred at -70px 32%), decaying to 0 by mid-table. That is the same trade the
       row-1 band above has always made. */
    --arc-th-pin-face: var(--arc-t-th-bg, var(--bs-table-bg, transparent));
    --arc-th-pin-under: var(--arc-t-surface, transparent);
    background-color: var(--bs-body-bg, #fff);
    background-image:
        linear-gradient(var(--arc-th-pin-face), var(--arc-th-pin-face)),
        linear-gradient(var(--arc-th-pin-under), var(--arc-th-pin-under));
}


/* ══ Check-row groups, one-line address, document header cards, field rows, accordions ═══════*/

/* Check-row group (site-wide multi-select convention — docs/architecture/ui/guidelines.md → "Check-row
   groups (`.arc-checkgroup` / `.arc-checkrow`)"): each choice is a ROW carrying a real checkbox, the option name, and a muted one-line
   description of what picking it does. Ticked state is a SHAPE (the checkbox glyph) first, with a border
   + tint second — it replaced the vendor-contact role chips (btn-check + btn-outline-secondary), whose
   only signal was a background color that several site themes render unreadably. Every color is a
   Bootstrap var or --arc-orange (re-pointed to each theme's primary by arc-themes.css), so all eight
   themes and both light/dark track for free. Shared by ArcContactBlocks (contact roles) and
   ArcQuickAdd's `checkgroup` field type. Rows keep Bootstrap's .form-check float mechanics — the extra
   left padding just insets the box the checkbox is pulled into. */
.arc-checkgroup { display: grid; gap: .3rem; }
.arc-checkrow {
    margin: 0;
    padding: .3rem .55rem .35rem 2rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .375rem;
    background: var(--bs-body-bg);
}
.arc-checkrow:has(.form-check-input:checked) {
    border-color: var(--arc-orange);
    background: color-mix(in srgb, var(--arc-orange) 8%, var(--bs-body-bg));
}
.arc-checkrow:has(.form-check-input:focus-visible) { border-color: var(--arc-orange); }
.arc-checkrow .form-check-label { display: block; cursor: pointer; }
.arc-checkrow-name { display: block; font-size: .85rem; line-height: 1.3; }
.arc-checkrow:has(.form-check-input:checked) .arc-checkrow-name { font-weight: 600; }
/* The description is muted by FADING THE BODY INK (not each theme's fixed --bs-secondary-color), so its
   contrast is computed against whatever the row is actually sitting on and clears WCAG AA in all eight
   themes × both modes. Using --bs-secondary-color measured 4.02–4.42 on the light themes' tinted checked
   rows — muted enough to look right, too muted to read at .75rem. */
.arc-checkrow-desc {
    display: block;
    font-size: .75rem;
    line-height: 1.3;
    color: color-mix(in srgb, var(--bs-body-color) 78%, transparent);
}

/* One-line address summary (D2): line1/line2/city/region/postal joined onto one wrapping line,
   shown read-only inside the header card that drives it. Replaces the retired multi-line
   .arc-addr-panel block. Out of the tab order (no focusable elements). */
.arc-addr-line { font-size: .8rem; color: var(--bs-secondary-color); }

/* Read-only header CARDS (D1) — THE site-wide document-page header standard: each zone is its own
   Bootstrap card in a wrapping row. card-header = zone icon + plain-case title + that zone's ✎ pushed
   right (ms-auto); card-body = the zone content (name/badges, one-line address, contacts, fact pairs).
   Consumers: the purchasing document editors (PO / REQ / RFQ) and /Feedback/Item. */
.arc-doc-cards {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: .75rem;
    margin-bottom: 1rem;
}
.arc-doc-card { flex: 1 1 15rem; min-width: 0; display: flex; flex-direction: column; }
.arc-doc-card > .card-header {
    display: flex;
    align-items: center;
    gap: .4rem;
    font-size: .85rem;
    font-weight: 600;
    padding: .4rem .75rem;
}
.arc-doc-card > .card-header > .bi { color: var(--bs-secondary-color); }
.arc-doc-card > .card-body { flex: 1 1 auto; padding: .6rem .75rem; }
.arc-doc-card .arc-addr-line { margin: .1rem 0; }

/* Note body text inside a notes card (Printed notes / Internal notes — see .arc-doc-cards above). */
.arc-doc-note-text { font-size: .85rem; white-space: normal; }

/* A compact inline action row (e.g. the "now: {vendor}" line carrying the generic Update-to-current
   pin action) — text and small buttons on ONE wrapping line. */
.arc-inline-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem .5rem;
    margin: .1rem 0;
}

/* Card/column key line + compact inline fact-pairs. `.arc-doc-key` is also the PO/RFQ wizards' in-modal
   key line, and /Feedback/Item's "Recent errors" sub-heading inside the context card. */
.arc-doc-key {
    font-size: .68rem; text-transform: uppercase; letter-spacing: .04em;
    font-weight: 600; color: var(--bs-secondary-color);
    display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .4rem; margin-bottom: .2rem;
}
.arc-doc-name { font-weight: 600; color: var(--bs-body-color); }
.arc-doc-line { font-size: .8rem; color: var(--bs-secondary-color); }
.arc-doc-facts { display: flex; flex-wrap: wrap; gap: .05rem .9rem; font-size: .8rem; }
.arc-doc-facts > span { color: var(--bs-body-color); white-space: nowrap; }
.arc-doc-facts .arc-fact-k { color: var(--bs-secondary-color); }
.arc-doc-facts .arc-fact-total { font-weight: 700; }

/* Compact label-beside-field row (D6): a ~90px label column beside a small control; multi-input
   groups (dates, charges) drop to a label-above flex row instead. */
.arc-field-row {
    display: grid; grid-template-columns: 5.5rem 1fr; align-items: center;
    gap: .15rem .5rem; margin-bottom: .45rem;
}
.arc-field-row > label { margin-bottom: 0; font-size: .8rem; text-align: right; color: var(--bs-secondary-color); }
.arc-field-row > .arc-field-wide { grid-column: 1 / -1; }
.arc-group-row { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: .45rem; }
.arc-group-row > div { flex: 1 1 6rem; min-width: 0; }
.arc-group-row label { display: block; font-size: .72rem; margin-bottom: .1rem; color: var(--bs-secondary-color); }

/* Collapsed ACCORDION (D3) — Notes / Attachments / summary below the lines: a one-line header row
   (chevron + title + muted subtitle) over a Bootstrap collapse. Chevron rotates on expand; nothing
   is remembered between loads (fresh-collapsed). */
.arc-acc { border-top: 1px solid var(--bs-border-color); }
.arc-acc:last-of-type { border-bottom: 1px solid var(--bs-border-color); }
.arc-acc-head {
    display: flex; align-items: center; gap: .5rem; width: 100%;
    padding: .5rem .35rem; background: none; border: 0; color: inherit; text-align: left;
}
.arc-acc-head:hover { background: var(--bs-tertiary-bg); }
.arc-acc-chevron { transition: transform .15s ease; color: var(--bs-secondary-color); }
.arc-acc-head[aria-expanded="true"] .arc-acc-chevron { transform: rotate(90deg); }
.arc-acc-title { font-weight: 600; }
.arc-acc-sub { font-size: .8rem; color: var(--bs-secondary-color); }
.arc-acc-body { padding: .35rem .5rem 1rem; }

/* ---------- Site Info */
/* The definition grid behind /Portal/Admin/SiteInfo's build/runtime/database card: one grid for
   all three groups, each group introduced by a small uppercase label spanning the full width, and
   each fact a 45/55 label-over-value cell that wraps rather than overflows. The marketing bundle must
   not ship portal-only CSS, so these rules live here. */
.si-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
    gap: .3rem 1.75rem;
    font-size: .875rem;
}

.si-glabel {
    grid-column: 1 / -1;
    margin: .9rem 0 .15rem;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}

.si-glabel:first-child {
    margin-top: 0;
}

.si-cell {
    display: grid;
    grid-template-columns: 45% 55%;
    align-items: baseline;
}

.si-cell .si-v {
    overflow-wrap: anywhere;
}
