/* ============================================================
   GSM Industrial — Bill of Materials Module
   Recursive Assembly/Part tree table.
   Depends on steelpulse-base.css for design tokens.
   ============================================================ */

:root {
    /* Item-Level Details' whole band (header tiers + checked cells) is tinted
       with this one hue so it reads as its own category next to the primary-
       blue Operations band and the neutral Item Information band — matching
       the owner's mockup, which used a pink/red. Deliberately NOT
       --mud-palette-error (MudBlazor's fully-saturated alarm red) — reusing
       the app's actual error color here would make a routine "this item gets
       a Weld Standard" flag read as "something's wrong". This is a muted,
       desaturated dusty rose instead: enough pink/red to match the mockup,
       dark enough for the white checkmark icon to stay readable on top
       (~5.9:1 contrast), but low-saturation enough to not double as a
       warning color. Static across both themes, same convention as this
       app's other --gsm-* tokens (steelpulse-base.css) — the color-mix()
       rules below are what actually adapt it to light/dark, same pattern
       used throughout this file for the neutral header/sticky tints. */
    --gsm-bom-detail: #9c4a5c;
}

/* The tab strip used to sit in its own card (MudTabs' Elevation/Rounded
   paper) inside this wrap's own second card (shadow+radius) — two nested
   cards whose seams didn't quite line up read as a stray band of
   background color between the tabs and the table. Each fabricated item/
   mobilization's whole tree now lives inside a MudExpansionPanel (see
   BomNodeTree.razor, .app-accordion in site.css) — that panel is the one
   visible card, so this wrap stays a plain scroll container and MudTabs'
   own paper is flattened below. */
.bom-wrap {
    max-width: 100%;
    overflow-x: auto;
}

.bom-tabs.mud-paper {
    box-shadow: none !important;
    background: transparent;
}

.bom-table {
    border-collapse: separate;
    border-spacing: 0;
    width: max-content;
    min-width: 100%;
    background: var(--mud-palette-surface);
    font-size: var(--gsm-text-base);
}

.bom-table th,
.bom-table td {
    box-sizing: border-box;
    padding: 4px 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    white-space: nowrap;
}

/* The whole <thead> sticks vertically as ONE unit — not each <th> individually.
   A single cell trying to be sticky on BOTH axes at once (top for vertical
   scroll, left/right for horizontal — needed on Mark/Toggle/Select/Actions)
   is the classic "sticky corner" problem: unreliable across browsers even
   though single-axis sticky (all the body cells need) works fine. Splitting
   the two jobs onto different elements — thead handles top, individual
   header cells only ever handle left/right — sidesteps it entirely. */
.bom-table thead {
    position: sticky;
    top: 0;
    z-index: 5;
}

/* Navy (--gsm-brand-navy) is used elsewhere only as a small accent (a single
   corner legend cell) — applying it to a whole header row read as "way too
   dark" in light mode, and every hover/overlay below was tuned assuming that
   dark backdrop (white text, white lighten-on-hover), which is unreadable
   once the base is light. Matches the theme-adaptive treatment this app
   already uses for other table headers (e.g. .gsm-permissions-table). */
/* --mud-palette-background-gray rendered too close to --mud-palette-surface
   (the plain body/row background) to read as a separate tier at all, in
   either theme — confirmed against a real screenshot, not assumed. A flat
   rgba(0,0,0,..)/rgba(255,255,255,..) overlay technically fixed the contrast
   (one direction per theme, via a body.sp-dark override) but the achromatic
   result read as dated "OS chrome" gray, not part of this app's palette.
   color-mix() with --mud-palette-secondary (this app's cool slate accent,
   #4a5568 light / #64748b dark) instead of plain black/white gives a
   header that's tinted toward the app's own color language — and since
   Secondary sits at a "middle" lightness in both palettes, mixing it into
   background-gray automatically darkens in light mode and lightens in dark
   mode from the SAME rule, no body.sp-dark override needed at all. */
.bom-table thead th {
    background: color-mix(in srgb, var(--mud-palette-secondary) 20%, var(--mud-palette-background-gray));
    color: var(--mud-palette-text-secondary);
    font-size: var(--gsm-text-sm);
    font-weight: 600;
    text-align: left;
}

/* Vertical labels for the routing columns — keeps 20+ operation/resource
   columns from making the table absurdly wide. The rotation lives on the
   inner .bom-op-vlabel span, not on the <th> itself (unlike an earlier
   version of this rule) — .bom-col-bulk-btn below is absolutely positioned
   against the <th>, and an absolutely-positioned descendant of a rotated
   element renders through that same rotation (its own counter-transform
   would have to fight the parent's), so the <th> needs to stay unrotated to
   be a sane containing block for it. */
/* Needs the ".bom-table thead th" prefix for the same specificity reason
   documented on .bom-detail-hdr further down this file: the plain ".bom-table
   thead th" rule up top sets text-align:left with two type selectors, which
   otherwise beats a bare ".bom-op-hdr" (one class) and silently re-lefts the
   label on any column wide enough for the difference to show. */
.bom-table thead th.bom-op-hdr {
    position: relative;
    text-align: center;
    /* Table cells are stretched to the full row height regardless of their
       own content, and vertical-align controls where the content sits inside
       that full-height box — "bottom" is what used to keep every label
       flush against the row's bottom edge (previously an incidental side
       effect of rotating the <th> itself). Without it, a short label just
       centers in the row and can drift up into .bom-col-bulk-btn's reserved
       top strip once any other column in the row is taller (e.g. expanded). */
    vertical-align: bottom;
    cursor: pointer;
}
.bom-op-hdr:hover {
    background: rgba(0, 0, 0, 0.06);
}
/* Tapped/clicked open to show the untruncated label — the row grows to fit,
   other (still-truncated) headers just get extra empty space, which is fine
   since it's a temporary, one-at-a-time state. */
.bom-op-hdr.expanded {
    background: rgba(0, 0, 0, 0.09);
}
.bom-op-vlabel {
    display: inline-block;
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    text-align: left;
    max-height: 140px;
    /* rotate(180deg) is a point-reflection through the element's own center —
       it swaps top<->bottom (and left<->right) of whatever was laid out
       BEFORE the transform. So a gap that needs to land at the visual TOP
       (clearing .bom-col-bulk-btn, which sits at the true top of the <th>'s
       full-row-height box) has to be reserved as padding-BOTTOM here, not
       padding-top — padding-top would end up rendering at the visual bottom
       instead, doing nothing for the overlap. Keeping this on the label
       itself (not the <th>) means the gap travels with the bottom-anchored
       content regardless of which column in the row ends up tallest. */
    padding-bottom: 20px;
}
.bom-op-hdr.expanded .bom-op-vlabel {
    max-height: 320px;
}

/* ⋯ bulk-mark button — auto-assign/clear checks for this whole column, see
   BomColumnBulkDialog. Sits in the unrotated top strip .bom-op-hdr's
   padding-top reserves, centered above the (separately rotated) label. Kept
   in horizontal-tb explicitly since writing-mode is inherited — without
   this it would pick up vertical-rl from .bom-op-hdr's ancestors and lay its
   icon out sideways. */
.bom-col-bulk-btn {
    position: absolute;
    top: 2px;
    left: 50%;
    transform: translateX(-50%);
    width: 20px;
    height: 15px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    writing-mode: horizontal-tb;
    color: var(--mud-palette-text-secondary);
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 3px;
    cursor: pointer;
    z-index: 2;
}
.bom-col-bulk-btn:hover {
    background: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

/* Row-3 leaf column header for an Operations/Resources column (includes the
   Field On Site column — see BomVisibleColumn.IsFieldInstall — which shares
   this same MegaGroup) — tinted with the app's existing primary-blue accent
   so the band has a header identity of its own, matching the rose treatment
   .bom-detail-hdr gets below. Needs the ".bom-table thead th" prefix for the
   same specificity reason documented on .bom-detail-hdr; deliberately placed
   BEFORE that rule in the file so a leaf column with .bom-detail-hdr as well
   (there isn't one today, but if that ever changes) resolves to rose, not
   blue, via source order. Lower percentage than the rose treatment — primary
   blue is more saturated to begin with, so the same 14-34% range read as too
   heavy next to the deliberately muted Details tint. */
.bom-table thead th.bom-op-hdr {
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface));
}
.bom-table thead th.bom-op-hdr:hover {
    background: color-mix(in srgb, var(--mud-palette-primary) 20%, var(--mud-palette-surface));
}
.bom-table thead th.bom-op-hdr.expanded {
    background: color-mix(in srgb, var(--mud-palette-primary) 28%, var(--mud-palette-surface));
}

/* Row-3 leaf column header for an Item-Level-Detail column — same shape as
   the plain .bom-op-hdr above (vertical label, click-to-expand), tinted with
   the dusty-rose detail accent. Every rule here needs the ".bom-table thead
   th" prefix: that rule (further up this file) sets background too, and its
   one-class-plus-two-type-selectors specificity otherwise beats a bare
   ".bom-detail-hdr" (one class only) — the tint would be silently overridden
   and never render. The prefix has to carry through :hover/.expanded too,
   not just the base rule, or THEY end up losing to the now-boosted base
   instead (same class count once boosted; ties go to whichever also has the
   :hover/.expanded class on top, which needs the same th-qualified base to
   compare against). */
.bom-table thead th.bom-detail-hdr {
    background: color-mix(in srgb, var(--gsm-bom-detail) 14%, var(--mud-palette-surface));
}
.bom-table thead th.bom-detail-hdr:hover {
    background: color-mix(in srgb, var(--gsm-bom-detail) 26%, var(--mud-palette-surface));
}
.bom-table thead th.bom-detail-hdr.expanded {
    background: color-mix(in srgb, var(--gsm-bom-detail) 34%, var(--mud-palette-surface));
}

/* Identity columns pin to the left and Actions pins to the right — with up
   to 29 routing columns in between, these would otherwise scroll off-screen
   and become undiscoverable (they did, in practice).
   Needs an explicit OPAQUE background, not "inherit" — background isn't an
   inherited CSS property by default, and forcing inheritance only actually
   worked for rows that happen to set their own background (tinted assembly
   rows); plain part rows have no background on the <tr> at all, so "inherit"
   resolved to transparent and let horizontally-scrolling cells show through
   underneath the sticky Mark/Actions columns as they scrolled past.
   Same color-mix() approach as thead th above, at a lighter strength, so the
   tiers read as header (20%) > frozen column (10%) > plain content (0%) —
   self-adjusting per theme, no body.sp-dark override needed. Always fully
   opaque (color-mix of two opaque colors stays opaque), which is what
   actually guarantees no bleed-through, not the "opaque-ness" of the base
   token alone. */
.bom-sticky {
    position: sticky;
    z-index: 2;
    background: color-mix(in srgb, var(--mud-palette-secondary) 10%, var(--mud-palette-surface));
}
/* --mud-palette-primary-hover LAYERED on top of an opaque base, not used
   bare — hover tokens are translucent overlays meant to sit ON an existing
   opaque background, not serve as one themselves. Used directly as a sticky
   cell's only background, the translucency let horizontally-scrolling column
   content show/bleed through underneath during scroll (the exact bug the
   comment above this rule already warns about). Tried the solid
   -lighten/-darken variants instead — -lighten alone read as barely-there
   pale/washed-out, -darken as too saturated/heavy for a whole row. Layering
   -hover (the strength MudBlazor actually calibrated for "a row is tinted
   but still readable") over an opaque surface base gets the intended
   intensity back while staying fully opaque. */
.bom-row.bom-tier-assembly .bom-sticky {
    background: linear-gradient(var(--mud-palette-primary-hover), var(--mud-palette-primary-hover)), var(--mud-palette-surface);
}
thead .bom-sticky {
    z-index: 7;
}

/* Fixed, deliberately narrow padding — the shared 4px/8px padding above was
   being added on TOP of these widths (box-sizing:border-box now folds it in,
   but 8px a side left almost no room for a 24px-wide caret column), and every
   later "left" offset in this chain assumed a width that padding was quietly
   inflating past. That's the actual reason the sticky columns drifted out of
   alignment instead of stacking cleanly. */
.bom-toggle-cell {
    left: 0;
    width: 24px;
    min-width: 24px;
    padding-left: 4px;
    padding-right: 4px;
    text-align: center;
    cursor: pointer;
    user-select: none;
}
.bom-caret {
    color: var(--mud-palette-text-secondary);
}

.bom-select-cell {
    left: 24px;
    width: 32px;
    min-width: 32px;
    padding-left: 2px;
    padding-right: 2px;
}

.bom-mark-cell {
    left: 56px;
    width: 150px;
    min-width: 150px;
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    font-family: 'Roboto Mono', monospace;
    font-weight: 600;
    border-right: 1px solid var(--mud-palette-lines-default);
}

/* Toggle/Select/Mark (row 1) have no sub-header beneath them in row 2 —
   unlike Operations · Resources/Item-Level Details, which use that line to
   separate their mega-band from their own sub-band. Without this, the
   header's plain per-row border-bottom leaves a stray line directly under
   "Mark" (and the blank toggle/select cells to its left). */
.bom-table thead tr:first-child .bom-toggle-cell,
.bom-table thead tr:first-child .bom-select-cell,
.bom-table thead tr:first-child .bom-mark-cell {
    border-bottom: none;
}

.bom-tier-icon {
    vertical-align: middle;
    margin-right: 4px;
    color: var(--mud-palette-text-secondary);
}

/* Tier tinting carries the hierarchy signal instead of deep proportional
   indentation — assemblies are tinted, parts are plain, and the (capped)
   indent from BomNodeRow just adds a light nesting cue on top.
   Deliberately NOT --mud-palette-background-gray — that's the column
   header's own background (.bom-table thead th below), and reusing it here
   made Assembly rows (which act as row headers/section groupings for their
   Part children) visually indistinguishable from the column headers
   themselves, in both light and dark mode. A primary-tinted overlay keeps
   the "this row groups others" signal while staying clearly a row, not a
   header — and ties visually to the primary-blue routing checkmarks
   elsewhere in this same table. Layered the same way as
   .bom-row.bom-tier-assembly .bom-sticky above (bare -hover is translucent;
   -lighten alone is too pale) so the whole row — sticky and scrolling cells
   alike — reads as one uniform tint instead of two subtly different ones. */
.bom-row.bom-tier-assembly {
    background: linear-gradient(var(--mud-palette-primary-hover), var(--mud-palette-primary-hover)), var(--mud-palette-surface);
    font-weight: 600;
}
/* color-mix() with --mud-palette-text-secondary (a mid-gray in both
   palettes) instead of a flat rgba(0,0,0,..)/rgba(255,255,255,..) stripe —
   mixing a "middle" gray into either a near-white or near-black surface
   reliably nudges it toward middle-gray in the right direction for whichever
   theme is active, so one rule covers both (same reasoning as thead th
   above, no separate body.sp-dark override needed). Kept a low percentage
   and a neutral gray rather than the secondary-slate tint used for
   header/sticky — this is meant to read as a faint stripe, not its own tier. */
.bom-row.bom-tier-part.bom-depth-alt {
    background: color-mix(in srgb, var(--mud-palette-text-secondary) 8%, var(--mud-palette-surface));
}

/* "padding:0" needs to match/exceed .bom-table td's specificity (0,1,1) to
   actually win — .bom-op-cell alone (0,1,0) would lose and silently keep the
   base 4px/8px padding, leaving almost no room in a 22px-wide cell. */
.bom-table td.bom-op-cell {
    width: 22px;
    min-width: 22px;
    max-width: 22px;
    padding: 0;
    text-align: center;
    cursor: pointer;
    border-left: 1px solid var(--mud-palette-lines-default);
}
/* First leaf column of a new Operation/Detail sub-group (see BomNodeTree.
   ColumnGroupStarts) — a heavier divider than the plain 1px border every
   cell already gets above, so a long run of resource/detail columns visibly
   breaks at each new category without making someone glance up at the row-2
   sub-header label to find the boundary. Two rules: row-3 header <th>s have
   no existing border-left to compete with (plain class is enough), but body
   <td>s need the ".bom-table td.bom-op-cell" prefix to outrank that rule's
   own border-left immediately above, same specificity story as the header
   tint fixes elsewhere in this file. */
.bom-col-group-start {
    border-left-width: 2px;
    border-left-color: var(--mud-palette-text-secondary);
}
.bom-table td.bom-op-cell.bom-col-group-start {
    border-left-width: 2px;
    border-left-color: var(--mud-palette-text-secondary);
}
.bom-op-cell.checked {
    background: var(--mud-palette-primary);
}
.bom-op-cell.checked:hover {
    background: var(--mud-palette-primary-darken);
}
.bom-op-cell:not(.checked):hover {
    background: rgba(0, 0, 0, 0.04);
}
/* Not applicable at this tier (marking matrix) — no hover, not clickable
   (no @onclick is even attached — see BomNodeRow). A flat tint here was too
   subtle to actually notice at a 22px cell; a diagonal hatch reads clearly as
   "not available" at a glance, the way a disabled spreadsheet cell would.
   Uses "transparent" between stripes rather than a solid base so the row's
   own tint (assembly tier tinting, alt-row striping) still shows through.
   A flat rgba(0,0,0,0.12) stripe (the original approach) all but disappears
   against a dark-mode surface — same reasoning as the color-mix() rules
   elsewhere in this file: mixing text-secondary (a mid-gray in both
   palettes) toward transparent keeps the stripe visible against either a
   near-white or near-black background, from the same rule. */
.bom-op-cell.na {
    cursor: default;
    background: repeating-linear-gradient(
        45deg, transparent, transparent 4px,
        color-mix(in srgb, var(--mud-palette-text-secondary) 40%, transparent) 4px,
        color-mix(in srgb, var(--mud-palette-text-secondary) 40%, transparent) 8px);
}
/* Marked cells get a checkmark on top of the shaded background — color
   alone (especially a subtle tint at this cell size) isn't a reliable enough
   signal on its own. */
.bom-check-icon {
    width: 16px;
    height: 16px;
    color: white;
}

/* Item Type / Ship List / Stock chips need to stay compact even under
   site.css's @media(max-width:1024px) tablet override, which forces every
   MudChip to padding:11px/font-size:0.8rem !important for touch targets
   elsewhere in the app — fine for a standalone chip, but it would blow out
   row height across the entire (already dense) BOM table. !important here
   is the only way to win that fight, matching this file's existing
   specificity battles (see .bom-table td.bom-op-cell above). */
.bom-table .mud-chip.bom-type-chip,
.bom-table .mud-chip.bom-flag-chip {
    height: 18px !important;
    padding: 0 8px !important;
    font-size: 10px !important;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.bom-table .mud-chip.bom-type-chip .mud-chip-content,
.bom-table .mud-chip.bom-flag-chip .mud-chip-content {
    font-size: 10px !important;
    padding: 0;
}

/* Item-Level-Detail columns (Project-Plan-sourced) use the dusty-rose accent
   (--gsm-bom-detail, defined at the top of this file) instead of primary
   blue, so routing and item-detail bands read as two visually distinct kinds
   of flag, not one undifferentiated grid. */
.bom-detail-cell.checked {
    background: var(--gsm-bom-detail);
}
.bom-detail-cell.checked:hover {
    background: color-mix(in srgb, black 18%, var(--gsm-bom-detail));
}
/* Unmarked Detail cells also get a faint rose wash — otherwise the column
   band only reads as "Details" where something happens to be checked, and
   looks identical to a plain Operations column everywhere else in the body.
   "transparent" as the color-mix() target (not --mud-palette-surface) so the
   row's own tinting (assembly tier, alt-row stripe) still shows through
   underneath, same reasoning as .bom-op-cell.na's hatch above. Overrides
   .bom-op-cell:not(.checked):hover on hover — same specificity (three
   pseudo/class selectors each), so it has to come after that rule in this
   file to win by source order. */
.bom-detail-cell:not(.checked) {
    background: color-mix(in srgb, var(--gsm-bom-detail) 8%, transparent);
}
.bom-detail-cell:not(.checked):hover {
    background: color-mix(in srgb, var(--gsm-bom-detail) 18%, transparent);
}

/* Collapsed group placeholder — a single neutral filler column standing in
   for however many leaf columns the group actually has, in both header and
   body, so the table stays narrow until someone actually expands it. */
.bom-col-placeholder {
    cursor: pointer;
    background: rgba(0, 0, 0, 0.03) !important;
}
.bom-col-placeholder:hover {
    background: rgba(0, 0, 0, 0.07) !important;
}
/* Item-Level-Details variant — rose-tinted so even the "nothing shown yet"
   filler column reads as belonging to the Details band. Needs !important to
   match .bom-col-placeholder's own !important; wins on source order (defined
   after it here) since both are single-class selectors of equal specificity. */
.bom-col-placeholder-detail {
    background: color-mix(in srgb, var(--gsm-bom-detail) 10%, var(--mud-palette-surface)) !important;
}
.bom-col-placeholder-detail:hover {
    background: color-mix(in srgb, var(--gsm-bom-detail) 20%, var(--mud-palette-surface)) !important;
}

/* Group-band row (row 1 of the header) — one cell per Operation/Detail
   category, spanning its visible leaf columns. */
.bom-group-hdr {
    writing-mode: horizontal-tb;
    text-align: center;
    border-left: 1px solid var(--mud-palette-lines-default);
    overflow: hidden;
    text-overflow: ellipsis;
    /* Item Information spans rows 1-2 (rowspan) while Operations · Resources
       and Item-Level Details occupy row 1 alone — without an explicit
       top-align, the browser centers Item Information's label across its
       taller two-row height, so it sits visibly lower than the other two. */
    vertical-align: top;
}
.bom-group-collapsible {
    cursor: pointer;
}
.bom-group-collapsible:hover {
    background: rgba(0, 0, 0, 0.06);
}
/* Operations · Resources mega-band — same idea as the Details tint below,
   using the app's existing primary-blue accent instead of a new hue (this
   band already owns blue everywhere else — checked cells, Assembly row
   tinting), at a lower percentage than the Details tint since primary blue
   is more saturated to start with. Needs the ".bom-table thead th" prefix
   for the same specificity reason as .bom-detail-hdr/.bom-group-hdr-detail. */
.bom-table thead th.bom-group-hdr-ops {
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, var(--mud-palette-background-gray));
}
.bom-table thead th.bom-group-hdr-ops.bom-group-collapsible:hover {
    background: color-mix(in srgb, var(--mud-palette-primary) 22%, var(--mud-palette-background-gray));
}
/* Item-Level-Details mega-band — rose-tinted the same way .bom-table thead th
   tints toward --mud-palette-secondary, so it self-adjusts for light/dark
   instead of needing a separate dark-mode override. Needs the same
   ".bom-table thead th" prefix as .bom-detail-hdr above, for the same
   specificity reason — a bare ".bom-group-hdr-detail" loses to
   ".bom-table thead th" further up this file and never actually paints. */
.bom-table thead th.bom-group-hdr-detail {
    background: color-mix(in srgb, var(--gsm-bom-detail) 22%, var(--mud-palette-background-gray));
}
.bom-group-hdr-detail.bom-group-collapsible:hover {
    background: color-mix(in srgb, var(--gsm-bom-detail) 34%, var(--mud-palette-background-gray));
}
/* Row 2 of the header — one cell per Operation (Cut, Weld, ...) or Detail
   category (Weld Standards, Testing, ...), spanning its own visible columns.
   Slightly smaller/lighter than the row-1 mega-band so the two tiers read as
   parent/child, not two equally-weighted headers. Purely a label — clicking
   the mega-band above it (row 1) is what opens the visibility picker. */
.bom-subgroup-hdr {
    writing-mode: horizontal-tb;
    text-align: center;
    font-size: 11px;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    border-left: 1px solid var(--mud-palette-lines-default);
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Operations · Resources sub-header row — same lighter-echo idea as
   .bom-subgroup-hdr-detail below, primary-blue instead of rose. */
.bom-table thead th.bom-subgroup-hdr-ops {
    color: color-mix(in srgb, var(--mud-palette-primary) 55%, var(--mud-palette-text-secondary));
    background: color-mix(in srgb, var(--mud-palette-primary) 6%, var(--mud-palette-background-gray));
}
/* Item-Level-Details sub-header row — a lighter echo of .bom-group-hdr-detail
   above it (this row is the "child" tier, see the comment on .bom-subgroup-hdr
   itself), tinting both text and background so the rose thread carries all
   the way down through the header before reaching the leaf columns. Both
   properties need the ".bom-table thead th" prefix — that rule sets BOTH
   background and color, so a bare ".bom-subgroup-hdr-detail" loses on both
   to the same specificity gap as .bom-group-hdr-detail/.bom-detail-hdr above. */
.bom-table thead th.bom-subgroup-hdr-detail {
    color: color-mix(in srgb, var(--gsm-bom-detail) 65%, var(--mud-palette-text-secondary));
    background: color-mix(in srgb, var(--gsm-bom-detail) 10%, var(--mud-palette-background-gray));
}

/* Visible affordance that the band opens something — clicking a table
   header with no other cue tested as undiscoverable in practice. */
.bom-group-hdr-icon {
    vertical-align: middle;
    margin-left: 6px;
    opacity: 0.75;
}

/* Nested checklist inside BomColumnVisibilityDialog. */
.bom-vis-group-label {
    font-weight: 600;
    font-size: var(--gsm-text-sm);
    color: var(--mud-palette-text-secondary);
    margin-top: 8px;
}

.bom-actions-cell {
    right: 0;
    white-space: nowrap;
    text-align: right;
    padding-left: 12px;
    border-left: 1px solid var(--mud-palette-lines-default);
    box-shadow: -2px 0 3px rgba(0, 0, 0, 0.06);
}
/* Edit / Add / Delete as a tight, evenly-aligned row. Flex lives on an inner
   wrapper, not the <td> itself — display:flex directly on a sticky table
   cell is a known-flaky combination in some browsers. */
.bom-actions-row {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 2px;
}

/* Numeric columns (Qty, Length, Weight) — right-justified so values of
   different magnitudes stay column-aligned, like a spreadsheet. */
.bom-col-right {
    text-align: right;
}

/* Parts tab's plain MudTable was using .gsm-table's default header as-is,
   which reads flat next to the Assemblies tab's taller, tinted .bom-table
   thead th right above it in the same tab strip. Same color-mix() tint and
   comfortable row height as that header, so the two tabs feel like one
   table module rather than two different table styles. */
.bom-parts-table.mud-table .mud-table-head th {
    background: color-mix(in srgb, var(--mud-palette-secondary) 20%, var(--mud-palette-background-gray)) !important;
    padding-top: 10px;
    padding-bottom: 10px;
}

.bom-empty {
    text-align: center;
    padding: 24px !important;
    color: var(--mud-palette-text-secondary);
}

/* Notes cell — the one column in .bom-table td's blanket white-space:nowrap
   rule that actually needs to wrap; a note can be a full sentence, and
   forcing it onto one line would blow the column out to the table's full
   scrollable width instead of growing the row's height. The cell itself
   isn't a click target — each note line and the "Add note" row below it are
   their own independent targets (clicking a note edits just that one;
   clicking "Add note" opens with a fresh blank one), so the interaction
   weight matches what's actually about to happen, not "click anywhere for
   anything". */
.bom-notes-cell {
    white-space: normal;
    max-width: 220px;
    min-width: 160px;
    vertical-align: top;
}
.bom-notes-line {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-bottom: 2px;
    cursor: pointer;
    border-radius: 3px;
    padding: 1px 3px;
    margin-left: -3px;
}
.bom-notes-line:hover {
    background: rgba(0, 0, 0, 0.06);
}
/* Always visible, not just on hover — hover-only affordances don't work for
   tablet users (see steelpulse-bom.css tooltip history elsewhere in this
   app), and a bare icon with no label isn't self-explanatory either, so this
   carries its own visible text rather than relying on a title tooltip. */
.bom-notes-add-row {
    display: flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
    color: var(--mud-palette-text-secondary);
    font-size: var(--gsm-text-sm);
    border-radius: 3px;
    padding: 1px 3px;
    margin-left: -3px;
    margin-top: 2px;
}
.bom-notes-add-row:hover {
    background: rgba(0, 0, 0, 0.06);
    color: var(--mud-palette-text-primary);
}
.bom-notes-add-icon {
    width: 16px;
    height: 16px;
}
/* Tag chip — a specific-operation tag is tinted with the same primary blue
   the Operations band already uses elsewhere in this table; "All" is neutral
   since it isn't scoped to any one operation. */
.bom-notes-tag {
    flex: 0 0 auto;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    padding: 1px 5px;
    border-radius: 3px;
    background: color-mix(in srgb, var(--mud-palette-primary) 16%, var(--mud-palette-background-gray));
    color: color-mix(in srgb, var(--mud-palette-primary) 70%, var(--mud-palette-text-secondary));
    white-space: nowrap;
}
.bom-notes-tag.all {
    background: var(--mud-palette-background-gray);
    color: var(--mud-palette-text-secondary);
}
.bom-notes-text {
    font-size: var(--gsm-text-sm);
}
