﻿
:root {
    --table-header-bg: rgb(243, 244, 246);
    --table-header-text: rgb(115, 115, 115);
    --table-border-color: rgb(229, 231, 235);
    --row-bg: rgb(249, 250, 251);
    --alt-row-bg: white;
    --item-name-text: rgb(17, 24, 39);
    --item-name-text-hover: rgb(220 38 38);
    --item-sub-name-text: rgb(107 114 128);
    --table-data-green: rgb(22 163 74);
}

.mud-table-head {
    background-color: var(--table-header-bg);
    position: sticky;
    z-index: 3;
    top: 0;
    box-shadow: inset 0 0px black, inset -1px -1px var(--mud-palette-table-lines);
}

    .mud-table-head th {
        color: var(--table-header-text) !important;
        border-bottom: none;
        /* Wrap long header labels at word boundaries. Never split mid-word.
           Static columns size naturally to their content; only cost-type
           columns get a min-width so headers like "Ocean Freight
           (Container) Fee-Base" wrap to two lines instead of wrapping after
           every word when the column is crunched. */
        white-space: normal;
        overflow-wrap: normal;
        word-break: normal;
        line-height: 1.2;
        vertical-align: bottom;
    }

        .mud-table-head th.cost-type-header {
            min-width: 120px;
        }

.sticky-left-header {
    position: sticky;
    background-color: var(--table-header-bg);
    box-shadow: inset 0 0px black, inset -1px -1px var(--mud-palette-table-lines);
    left: 0;
}

/* The expand/collapse toggle lives in an auto-generated first column that
   spans the header, group-header and data rows. With table-layout: fixed it
   otherwise grabs a large width share, leaving a big empty gap in front of the
   Item No (data rows) and the group toggle (group-header rows). Pin it narrow
   and hug its contents to the left. */
.grouped-table th:first-child,
.grouped-table td:first-child {
    width: 36px;
    min-width: 36px;
    max-width: 36px;
    border-right: none !important;
    padding-left: 0;
    padding-right: 0;
}

    .grouped-table td:first-child .d-flex {
        justify-content: center;
    }

    .grouped-table td:first-child svg {
        fill: rgb(17, 24, 39)
    }

    .grouped-table td:first-child:not(:where(.white-row > *, .grey-row > *)) {
        background-color: var(--table-header-bg);
        border-top: 1px solid var(--mud-palette-table-lines);
    }

    .grouped-table td:first-child button {
        padding: 4px;
    }

.grouped-table .mud-table-cell button {
    padding: 12px;
}

.group-header {
    background-color: var(--table-header-bg);
    border-top: 1px solid var(--mud-palette-table-lines);
    padding: 0 !important;
}

.sticky-group-header {
    padding: 16px;
    position: sticky;
    left: 0;
    color: var(--item-name-text);
    font-weight: 600;
}

.sticky-column {
    min-width: 300px;
    position: sticky;
    left: -1px;
    border-right: none !important;
    box-shadow: inset 0 0px black, inset -1px 0 var(--mud-palette-table-lines);
    z-index: 2;
}

/* A locked identity column: item number, brand or name, held against the left edge while the cost
   types scroll past. These grids run to dozens of cost columns and three screens to the right there
   is nothing on the row saying which product you are reading.

   The offset and width come from the markup, because each column's offset is the sum of the widths
   before it and only the page knows what order they are in. Everything else -- how it sits, its
   backgrounds, its divider -- is here so a locked column looks the same on every grid.

   Only a run starting at the left is locked: a sticky column must sit against the edge or against
   another sticky column, and one with a scrolling column in between has that content slide
   underneath it. */
.locked-column {
    position: sticky;
    z-index: 2;
    border-right: none !important;
    box-shadow: inset -1px 0 var(--mud-palette-table-lines);

    /* A locked column is a fixed width, so anything wider has to be contained rather than allowed
       to spill: the cost columns scroll underneath it and overflowing content would sit on top of
       them. No white-space rule here -- the name cell is several lines by design (name, chips, a
       show-children button) and forcing it onto one pushed the row menu out past the column edge. */
    overflow: hidden;
}

/* The name cell is a row: the name block, then the row's three-dot menu. Flex items refuse to
   shrink below their content by default, so without this the block holds its full width and shoves
   the menu outside the column. min-width: 0 lets it give way and wrap instead. */
.locked-column > .flex {
    min-width: 0;
}

.locked-column .item-name {
    overflow-wrap: anywhere;
}

.grey-row .locked-column {
    background-color: var(--row-bg);
}

.white-row .locked-column {
    background-color: var(--alt-row-bg);
}

/* The header has its own background; without it the cost-type headers show through as they pass. */
.locked-header {
    position: sticky;
    z-index: 3;
    background-color: var(--table-header-bg);
    box-shadow: inset -1px -1px var(--mud-palette-table-lines);

    /* Headers are short labels, so they may stay on one line, but they are contained for the same
       reason the cells are: a header wider than its column would sit over the cost-type headers
       scrolling past it. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.expand-button {
    padding: 8px;
    margin-left: -8px;
    margin-right: 8px;
}

.grey-row {
    background-color: var(--row-bg);
}

    .grey-row .sticky-column {
        background-color: var(--row-bg);
    }

.white-row {
    background-color: var(--alt-row-bg);
}

    .white-row .sticky-column {
        background-color: var(--alt-row-bg);
    }

.mud-table-root > .mud-table-body:last-child > .mud-table-row:last-child > .mud-table-cell {
    border-bottom: 1px solid var(--mud-palette-table-lines);
}


/* Right-click flag zone (FF + PD cost cells): stretch over the td's own 6px/16px padding so a
   right-click anywhere in the cell -- not just on the number -- opens the color-coding menu, and
   the flag shading fills the whole cell. The context-menu cursor plus a faint inset ring on hover
   signal that the cell is color-codable. */
.flag-zone {
    display: block;
    margin: -6px -16px;
    padding: 6px 16px;
    min-height: calc(100% + 12px);
    box-sizing: border-box;
    cursor: context-menu;
}

    .flag-zone:hover {
        box-shadow: inset 0 0 0 1px var(--mud-palette-lines-default, rgba(0, 0, 0, 0.25));
    }

.mud-table-cell {
    padding: 6px 16px;
    border-bottom: none;
}

    .mud-table-cell button {
        padding: 4px;
    }

/* One scrollport for both axes.
   Previously .mud-table (the outer paper) was the VERTICAL scroller -- bounded height plus
   overflow-y:auto -- while .mud-table-container kept MudBlazor's overflow-x:auto and had its own
   vertical overflow unset. Splitting the axes across two elements caused both grid complaints:
     * The horizontal scrollbar belongs to the container, whose height is its full content height.
       The outer element clipped that, so the scrollbar sat far below the visible area and only a
       sliver of it was reachable.
     * position:sticky resolves per axis against the nearest scrolling ancestor. The sticky Name
       column (left) resolved against the container while vertical clipping happened on the wrapper,
       so it painted over whatever sat at the bottom edge instead of being clipped with the rows.
   Bounding the container and letting it scroll both ways puts the sticky header, the sticky column,
   the rows and the scrollbars in one coordinate space. The pager is a sibling of the container, so it
   stays below the scroll area rather than floating over it. */
.mud-table {
    table-layout: fixed;
    width: 100%
}

/* A full-page grid fills the window whether it holds six rows or six hundred, which is what these
   two lines are for. They are not scoped to the grids, though, so every table in the app inherits
   them: a BOM card with two components got 724px of empty box and pushed its own totals off the
   bottom of the screen, and the Edit BOM Children dialog grew past the viewport and took Cancel and
   Save with it. Relaxed below wherever a table is plainly not a page. */
/* MEASURED, NOT GUESSED.
   These grids used to be sized with a viewport calculation -- 100vh minus an estimate of the page
   chrome. That can only ever be right for one arrangement of the page, and these pages have two:
   General Costs and Product Development both carry a filters panel that opens and closes. Opened, it
   adds height the calculation knew nothing about, the container overflowed the h-screen wrapper, and
   the horizontal scrollbar -- which lives at the container's bottom edge -- was pushed out of sight.
   That is the "wonky on PD and General Costs" case, and no constant fixes it.

   So the page wrapper becomes a flex column and the grid takes the space that is actually left.
   min-height: 0 on every link in the chain is what allows a flex item to shrink below its content
   size; without it the container refuses to give the scrollbar room and the whole thing overflows
   again. The wrapper is MainLayout's, so this is expressed from .mud-main-content down rather than
   in any one page's scoped css. Dialogs and the timeline sit outside this chain and keep their own
   heights. */
.mud-main-content > div.h-screen {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

    /* the last block a page renders is its content; everything above it is header and filters.

       overflow-y: auto is for the pages that are NOT a grid. The wrapper above is h-screen with
       overflow-hidden -- that is what lets a grid own its scrolling -- so a page that is simply
       taller than the window (Summary, Sales, most of the setup pages) was sized to the window here
       and had everything below the fold cut off with no scrollbar at all. It now scrolls inside this
       block instead. A grid page fills this block exactly (every link below is min-height: 0), so it
       never overflows and never shows a second scrollbar, and its sticky header and locked columns
       still stick to the table container, which stays the nearest scroller. */
    .mud-main-content > div.h-screen > div:last-child {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow-y: auto;
    }

    /* ...but not when the last block is a status indicator rather than content.

       A page still loading renders a progress bar, and one with nothing to show renders an alert.
       Both are divs, so both match the rule above and get stretched to fill the window. An
       indeterminate MudProgressLinear draws a solid bar on a lighter track, and at full height that
       is a floor-to-ceiling block of colour over the whole page -- it reads as a crash rather than
       as loading, which is exactly how it was reported on Workflow Setup.

       These size to their content instead. Naming the class alongside :last-child is what makes it
       win: the same selector plus one more class, so it beats the stretch without !important. */
    .mud-main-content > div.h-screen > div:last-child.mud-progress-linear,
    .mud-main-content > div.h-screen > div:last-child.mud-progress-circular,
    .mud-main-content > div.h-screen > div:last-child.mud-alert {
        flex: 0 0 auto;
    }

    .mud-main-content > div.h-screen > div:last-child .mud-table:not(.table-with-header) {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        flex-direction: column;
    }

        /* the scroller fills what is left, and the pager keeps its natural height below it */
        .mud-main-content > div.h-screen > div:last-child .mud-table:not(.table-with-header) > .mud-table-container {
            flex: 1 1 auto;
            min-height: 0;
            max-height: none;
        }

        .mud-main-content > div.h-screen > div:last-child .mud-table:not(.table-with-header) > .mud-table-pagination {
            flex: 0 0 auto;
        }

/* Fallback for anything rendered outside that chain. Kept because a grid in a dialog or a nested
   view still needs a bound; pages under the layout have it overridden above. */
.mud-table-container {
    max-height: calc(100vh - 156px);
    overflow: auto;
    /* Firefox: the default thin scrollbar is hard to grab on these wide grids. */
    scrollbar-width: auto;
}

    /* Chunkier scrollbars on the grid scrollport -- the horizontal bar is the main way across the
       cost columns and the browser default is too slim a click target. WebKit/Chromium only; the
       scrollbar-width above covers Firefox. */
    .mud-table-container::-webkit-scrollbar {
        height: 14px;
        width: 14px;
    }

    .mud-table-container::-webkit-scrollbar-thumb {
        background-color: rgba(0, 0, 0, 0.35);
        border-radius: 7px;
        /* A transparent border keeps a gutter so the thumb reads as grabbable. */
        border: 3px solid transparent;
        background-clip: content-box;
    }

    .mud-table-container::-webkit-scrollbar-thumb:hover {
        background-color: rgba(0, 0, 0, 0.55);
    }

    .mud-table-container::-webkit-scrollbar-track {
        background-color: rgba(0, 0, 0, 0.06);
    }

    /* The class lands on the outer .mud-table, so match the container as its descendant; the
       direct form is kept in case it is applied to the container too. */
    .mud-table.table-with-header > .mud-table-container,
    .mud-table-container.table-with-header {
        max-height: calc(100vh - 191px);
        min-height: calc(100vh - 191px);
    }

.item-name {
    color: var(--item-name-text);
    font-weight: 500;
}

    .item-name.selectable:hover {
        color: var(--item-name-text-hover);
        text-decoration: underline;
        cursor: pointer;
        font-weight: 500;
    }

.item-sub-name {
    color: var(--item-sub-name-text);
}

.subitem-row {
    background-color: var(--table-header-bg);
    border-top: 1px solid var(--table-border-color);
    border-bottom: 1px solid var(--table-border-color);
}

    .subitem-row td {
        border: 1px solid var(--table-border-color);
    }

.sticky-pager {
    z-index: 3;
    background-color: var(--alt-row-bg);
    position: sticky;
    bottom: 0;
    left: 0;
    right: 0;
}

.mud-table-pagination {
    max-height: 50px;
    z-index: 3;
}

.filters-row {

    display: flex;
    flex-direction: row;
    gap: 10px;
    flex-wrap: wrap;
    padding: 10px 0px;
}

.filter-outline {
    display: flex;
    flex-direction: row;
    gap: 8px;
    padding: 8px;
    background-color: var(--table-header-bg);
    border: 1px solid rgb(229, 229, 229);
    height: 50px;
    border-radius: 0.5rem;
    align-items: center;
}

.filter-name {
    color: rgb(55 65 81);
    white-space: nowrap;
    font-size: .75rem;
    font-weight: 500;
}

.filter-chip {
    margin: 0;
    padding: 0.5rem 0.75rem;
    font-size: .75rem;
    line-height: 1rem;
    background-color: white;
    border-radius: calc(0.5rem - 2px);
}

.table-header-controls {
    display: flex;
    flex-direction: row;
    gap: 15px;
    max-height: 36.5px;
    margin-bottom: 13.5px;
}

    .table-header-controls .mud-input-control {
        margin-top: 0;
        margin-bottom: 0;
    }

    .table-header-controls input {
        padding: 0.5rem 0.75rem !important;
    }

/* A table inside a dialog, or on the BOM card, is as tall as the rows it holds. Neither is a page,
   and neither should be stretched to the height of one. */
.mud-dialog .mud-table-container,
.bom-card .mud-table-container {
    min-height: 0;
    max-height: none;
}
