/* /Components/Global/Components/IconSelect.razor.rz.scp.css */
.icon-select[b-ejk5pdcen7] {

    .mud-input-adornment {
        display: none;
    }

    .mud-input-slot[b-ejk5pdcen7] {
        padding: 0 !important;
        height: 100% !important;
        width: 100% !important;
    }

    .mud-icon-root[b-ejk5pdcen7] {
        align-items: end;
        vertical-align: bottom;
    }

    .mud-select-filler[b-ejk5pdcen7] {
        max-width: 1.65vw;
        margin-left: 0;
        margin-right: 0;
    }
}

.icon-select-popover[b-ejk5pdcen7] {
    width: fit-content !important;

    .mud-list > .mud-list-item {
        padding-left:8px;
        padding-right:8px;
    }
}
/* /Components/Global/Components/MiscItemsPanel.razor.rz.scp.css */
/* .c-num / .c-amount are global
   (wwwroot/CSS/quote-ui.css) — only what's specific to this row layout lives here. */

.misc-body[b-7689pmtrqb] {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 14px;
}

.misc-row[b-7689pmtrqb] {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.misc-row:last-of-type[b-7689pmtrqb] {
    border-bottom: none;
    padding-bottom: 0;
}

/* Six inputs don't fit on one line inside a half-width card — the description gets its own row
   (it's the field most likely to need the space), everything else shares a second, wrapping row. */
.misc-row-fields[b-7689pmtrqb] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

.misc-field-qty[b-7689pmtrqb] {
    width: 72px;
    flex: 0 0 auto;
}

.misc-field-price[b-7689pmtrqb],
.misc-field-weight[b-7689pmtrqb] {
    width: 128px;
    flex: 0 0 auto;
}

.misc-field-taxable[b-7689pmtrqb] {
    flex: 0 0 auto;
}

.misc-amount[b-7689pmtrqb] {
    flex: 1 1 auto;
    font-size: 16px;
}

.misc-taxable-locked[b-7689pmtrqb] {
    font-size: 14px;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.misc-add[b-7689pmtrqb] {
    align-self: flex-start;
}

/* Same treatment as BuildQuote.razor.css's .meta-error — duplicated because Blazor scopes each
   component's CSS to that component; there is no way to share a scoped rule across two files. */
.meta-error[b-7689pmtrqb] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--mud-palette-warning-darken, var(--mud-palette-warning));
}

.meta-error[b-7689pmtrqb]  .mud-icon-root {
    font-size: 16px;
    color: var(--mud-palette-warning);
}
/* /Components/Global/Components/MudToolWindow.razor.rz.scp.css */
:root[b-xo4aigke6w] {
    --theme-primary: #1e499e;
    --theme-primary-overlay: #112a90cc;
    --DarkHighlight: #00000078;
}

.tool-window[b-xo4aigke6w] {
    
}

.tool-window-container[b-xo4aigke6w] {
    padding-bottom: 1rem;
    
}

.tool-window-footer[b-xo4aigke6w] {
    position: absolute;
    background-color:var(--DarkHighlight);
    top: 95%;
    left: 1px;
    padding: 0.25vh;
    width: 101%;
    
    h6 {
        font-size: 1.2rem;
    }
}
/* /Components/Global/Dialogs/CsvImportDialog.razor.rz.scp.css */
.cid-dropzone[b-l33ye8w586] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 32px 16px;
    text-align: center;
    border-style: dashed;
    border-color: var(--mud-palette-lines-inputs);
    border-radius: 8px;
}

.cid-dropzone-active[b-l33ye8w586] {
    border-color: var(--mud-palette-primary);
    background-color: var(--mud-palette-primary-hover);
}

.cid-map-row[b-l33ye8w586] {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 8px 16px;
    align-items: start;
    padding: 10px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.cid-map-row:last-child[b-l33ye8w586] {
    border-bottom: none;
}

.cid-map-label[b-l33ye8w586] {
    font-weight: 500;
}

.cid-required[b-l33ye8w586] {
    color: var(--mud-palette-error);
    margin-left: 2px;
}

.cid-map-warning[b-l33ye8w586] {
    color: var(--mud-palette-warning-darken);
    display: block;
    margin-top: 2px;
}

.cid-preview[b-l33ye8w586] {
    margin-top: 20px;
}

.cid-preview-scroll[b-l33ye8w586] {
    overflow-x: auto;
}

.cid-preview-table[b-l33ye8w586] {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8rem;
}

.cid-preview-table th[b-l33ye8w586],
.cid-preview-table td[b-l33ye8w586] {
    text-align: left;
    padding: 4px 10px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    white-space: nowrap;
    max-width: 160px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cid-issues-head[b-l33ye8w586] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 8px;
}

.cid-issues[b-l33ye8w586] {
    max-height: 240px;
    overflow-y: auto;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    padding: 8px 12px;
}

.cid-issue[b-l33ye8w586] {
    font-size: 0.85rem;
    padding: 3px 0;
}

/* iPad/iPhone: the two-column mapping row has no room to sit side by side. */
@media (max-width: 600px) {
    .cid-map-row[b-l33ye8w586] {
        grid-template-columns: 1fr;
    }
}
/* /Components/Global/Dialogs/CustomerDialog.razor.rz.scp.css */
/* Same "two switches side by side" shape as BuildQuote.razor.css's .switch-row — not shared
   because Blazor scopes each component's CSS to that component. */
.cd-switches[b-mzx66r9eue] {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 28px;
}
/* /Components/Global/Dialogs/DuplicateCustomerDialog.razor.rz.scp.css */
.dc-list[b-fr8do5k9nt] {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.dc-row[b-fr8do5k9nt] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 14px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    background-color: var(--mud-palette-surface);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.dc-row:hover[b-fr8do5k9nt],
.dc-row:focus-visible[b-fr8do5k9nt] {
    border-color: var(--mud-palette-primary);
    background-color: var(--mud-palette-action-default-hover, var(--mud-palette-surface));
}

.dc-name[b-fr8do5k9nt] {
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.dc-meta[b-fr8do5k9nt] {
    font-size: 13px;
    color: var(--mud-palette-text-secondary);
}
/* /Components/Global/Dialogs/LineItemDialog.razor.rz.scp.css */
/* Live price readout at the bottom of the mobile line editor. Mirrors the derived-values strip
   on the desktop grid so both surfaces show board feet and weight, not just the final amount. */

.ld-preview[b-mu0l306s0v] {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    padding: 12px 14px;
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
}

.ld-preview-grid[b-mu0l306s0v] {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 16px;
}

.ld-preview-grid > div[b-mu0l306s0v] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.ld-preview-grid span[b-mu0l306s0v] {
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.ld-preview-grid strong[b-mu0l306s0v] {
    font-size: 15px;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

.ld-preview-total[b-mu0l306s0v] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 2px solid var(--mud-palette-lines-default);
}

.ld-preview-total span[b-mu0l306s0v] {
    font-size: 13px;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
}

.ld-preview-total strong[b-mu0l306s0v] {
    font-size: 22px;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}
/* /Components/Global/Dialogs/PdfViewerDialog.razor.rz.scp.css */
/*
    Chrome for the PDF viewer dialog. The pages themselves are canvases painted by PDF.js —
    the PDF's own white paper, identical in every theme — so the theme work here is only the
    frame around them: everything is var(--mud-palette-*) because three switchable themes mean
    a literal hex only looks right in one of them.

    The backdrop/sheet relationship is the same one QuotePreviewDialog.razor.css establishes:
    `background-gray` desk under `surface`-adjacent paper, so the pages read as sheets on a
    desk rather than floating in nothing.
*/

.pdfv-title[b-2pozdzowul] {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
}

.pdfv-title-text[b-2pozdzowul] {
    display: flex;
    flex-direction: column;
    gap: 1px;
    margin-right: auto;
}

/* Color comes from the .mud-secondary-text class on the MudText itself — same reasoning as the
   preview dialog's eyebrow (see QuotePreviewDialog.razor's comment block). */
.pdfv-eyebrow[b-2pozdzowul] {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

.pdfv-title-text h2[b-2pozdzowul] {
    margin: 0;
    font-family: "Roboto Slab", serif;
    font-size: 20px;
    font-weight: 500;
    line-height: 1.15;
}

/* ------------------------------------------------------------------ toolbar */

.pdfv-toolbar[b-2pozdzowul] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.pdfv-pageno[b-2pozdzowul] {
    font-size: 12px;
    font-variant-numeric: tabular-nums; /* "Page 2 / 3" must not wiggle as the numbers change */
    margin-right: auto;
}

/* Icon-only on purpose: this row has to fit an iPhone in portrait without wrapping. */
.pdfv-zoom[b-2pozdzowul] {
    display: flex;
    align-items: center;
    gap: 2px;
}

/* ------------------------------------------------------------------ pages */

/* Positioning context for the loading overlay, nothing else. */
.pdfv-body[b-2pozdzowul] {
    position: relative;
}

/* The scroll container PDF.js fills. A fixed-ish height (not max-height) so that "Fit whole
   page" has a real height to fit into; both axes scroll because zooming in makes a page wider
   than the dialog. */
.pdfv-scroll[b-2pozdzowul] {
    height: min(72vh, 860px);
    overflow: auto;
    padding: 16px;
    background-color: var(--mud-palette-background-gray);
}

.pdfv-loading[b-2pozdzowul] {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.pdfv-alert[b-2pozdzowul] {
    margin: 16px;
}

/* ::deep because PDF.js creates these elements at runtime — Blazor's scope attribute is only
   stamped on elements written in this file, so bare selectors would silently never match
   (same trap as the .ql-table wrapper note in QuoteList.razor). */

/* width: fit-content + auto margins rather than flex centering: a flex-centered child wider
   than the scroll container gets its left edge clipped unreachably, this way it scrolls. */
.pdfv-scroll[b-2pozdzowul]  .pdfv-page {
    width: fit-content;
    margin: 0 auto 16px;
}

.pdfv-scroll[b-2pozdzowul]  .pdfv-page:last-child {
    margin-bottom: 0;
}

.pdfv-scroll[b-2pozdzowul]  .pdfv-page canvas {
    display: block;
    box-shadow: var(--mud-elevation-2);
}
/* /Components/Global/Dialogs/ProductDialog.razor.rz.scp.css */
/* Four section cards (Basics/Dimensions/Pricing/Metadata) in ProductDialog.razor's MudGrid.
   MudBlazor palette variables only — the app ships three switchable themes. */

.pd-section[b-j79wi5wwb2] {
    height: 100%;
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
}

.pd-section-title[b-j79wi5wwb2] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 8px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--mud-palette-divider);
    color: var(--mud-palette-text-secondary);
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.pd-section-title[b-j79wi5wwb2]  .mud-icon-root {
    color: var(--mud-palette-primary);
}
/* /Components/Global/Dialogs/QuotePreviewDialog.razor.rz.scp.css */
/*
    The "document" half of the preview is a paper metaphor rendered honestly: a sheet with a real
    margin, hairline rules, and tabular figures. It is NOT a pixel copy of the QuestPDF output —
    that would look wrong on a phone. Both read from the same QuotePdfModel, so the content
    agrees; the presentation is native to the screen it is on.

    Everything is var(--mud-palette-*): three switchable themes, so a literal hex only looks
    right in one of them.
*/

.qpv-title[b-25oglh36l7] {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
}

.qpv-title-text[b-25oglh36l7] {
    display: flex;
    flex-direction: column;
    gap: 1px;
    margin-right: auto;
}

/* Color comes from the .mud-text-secondary class on the MudText itself, not from here — see
   Components/Global/Dialogs/QuotePreviewDialog.razor. */
.qpv-eyebrow[b-25oglh36l7] {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

/* Color comes from Color="Color.Inherit" on the MudText itself (inherits body's
   var(--mud-palette-text-primary)) — this rule is layout/type only. */
.qpv-title-text h2[b-25oglh36l7] {
    margin: 0;
    font-family: "Roboto Slab", serif;
    font-size: 20px;
    font-weight: 500;
    line-height: 1.15;
}

/* The dialog body is the scroll container, not the page: a long quote scrolls inside a frame
   that keeps the tab strip and the action bar in view. */
/* The backdrop must differ from `.sheet` below (which is `surface`) or the "sheet of paper"
   reads as nothing at all — both were `surface`, i.e. the same color. `background-gray` is the
   recessed step below `surface` in MudBlazor's own elevation order, which is exactly the
   paper-on-a-desk relationship wanted here. It is safe to use now that every theme sets it
   explicitly: Lumber used to fall through to MudBlazor's cool #F5F5F5, which is why a neutral
   grey backdrop looked wrong against that theme's warm palette. */
.qpv-scroll[b-25oglh36l7] {
    max-height: min(66vh, 720px);
    overflow-y: auto;
    overflow-x: hidden;
    padding: 16px;
    background-color: var(--mud-palette-background-gray);
}

/* ---------------------------------------------------------------- the sheet */

.sheet[b-25oglh36l7] {
    max-width: 860px;
    margin: 0 auto;
    padding: 28px 30px 30px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background-color: var(--mud-palette-surface);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 8px 28px rgba(0, 0, 0, 0.07);
    color: var(--mud-palette-text-primary);
}

.sheet-head[b-25oglh36l7] {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: start;
    gap: 18px;
    padding-bottom: 16px;
    /* Brand walnut is the printed document's only non-grey ink; the same rule anchors the
       header here. */
    border-bottom: 2px solid var(--mud-palette-primary);
}

.sheet-logo[b-25oglh36l7] {
    width: 92px;
    height: auto;
    object-fit: contain;
}

.sheet-co[b-25oglh36l7] {
    display: flex;
    flex-direction: column;
    gap: 1px;
    font-size: 12px;
    line-height: 1.45;
}

.sheet-co strong[b-25oglh36l7] {
    font-family: "Roboto Slab", serif;
    font-size: 15px;
    font-weight: 600;
    color: var(--mud-palette-primary);
}

.sheet-meta[b-25oglh36l7] {
    text-align: right;
}

.sheet-doctype[b-25oglh36l7] {
    font-family: "Roboto Slab", serif;
    font-size: 22px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--mud-palette-primary);
}

.sheet-meta dl[b-25oglh36l7] {
    display: grid;
    grid-template-columns: auto auto;
    justify-content: end;
    gap: 2px 12px;
    margin: 8px 0 0;
    font-size: 12px;
}

.sheet-meta dt[b-25oglh36l7] {
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: 10px;
    align-self: center;
    color: var(--mud-palette-text-secondary);
}

.sheet-meta dd[b-25oglh36l7] {
    margin: 0;
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- parties */

.sheet-parties[b-25oglh36l7] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    padding: 18px 0;
}

.party[b-25oglh36l7] {
    display: flex;
    flex-direction: column;
    gap: 1px;
    font-size: 13px;
    line-height: 1.5;
}

.party h3[b-25oglh36l7] {
    margin: 0 0 4px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* ---------------------------------------------------------------- line items */

.sheet-lines[b-25oglh36l7] {
    overflow-x: auto;
}

.sheet-lines table[b-25oglh36l7] {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.sheet-lines th[b-25oglh36l7] {
    padding: 7px 8px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    text-align: left;
    white-space: nowrap;
    color: var(--mud-palette-text-secondary);
    background-color: var(--mud-palette-background-gray);
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.sheet-lines td[b-25oglh36l7] {
    padding: 9px 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    vertical-align: top;
}

/* A line with a note suppresses its own rule so .note-row's cell can draw it instead — the rule
   belongs under the line+note pair, not between a line and its own annotation. Mirrors
   QuoteDocument.cs's BodyCell(bottomBorder:) and the desktop grid's row-main/row-meta split. */
.sheet-lines tr.no-rule td[b-25oglh36l7] {
    border-bottom: none;
}

.c-note[b-25oglh36l7] {
    padding-top: 0;
    padding-bottom: 9px;
    font-size: 12px;
    font-style: italic;
    color: var(--mud-palette-text-secondary);
}

.note-label[b-25oglh36l7] {
    font-weight: 600;
    font-style: normal;
}

/* .c-num / .c-amount are global — wwwroot/CSS/quote-ui.css. This sheet's table takes them as-is. */

.c-unit[b-25oglh36l7] {
    white-space: nowrap;
    font-size: 11px;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-secondary);
}

.c-activity[b-25oglh36l7] {
    white-space: nowrap;
    font-size: 12px;
    color: var(--mud-palette-primary);
}

.c-desc[b-25oglh36l7] {
    min-width: 220px;
}

/* ---------------------------------------------------------------- footer */

.sheet-foot[b-25oglh36l7] {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 28px;
    padding-top: 18px;
}

.sheet-notes[b-25oglh36l7] {
    font-size: 13px;
    line-height: 1.55;
    color: var(--mud-palette-text-secondary);
}

.sheet-notes h3[b-25oglh36l7] {
    margin: 12px 0 4px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.sheet-notes p[b-25oglh36l7] {
    margin: 0 0 12px;
    white-space: pre-wrap;
}

.sheet-right[b-25oglh36l7] {
    min-width: 268px;
}

.sheet-bf[b-25oglh36l7] {
    display: flex;
    justify-content: space-between;
    width: fit-content;
    min-width: 190px;
    margin-bottom: 6px;
    align-items: baseline;
    gap: 8px;
    padding: 6px 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.sheet-bf strong[b-25oglh36l7] {
    font-size: 15px;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

/* Even rhythm is the acceptance criterion Larry's QuickBooks complaint set: every row is the
   same height, and emphasis is carried by weight and a rule, never by extra padding. */
.sheet-totals[b-25oglh36l7] {
    min-width: 268px;
    margin: 0;
}

.tot[b-25oglh36l7] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    height: 30px;
    font-size: 13px;
}

.tot dt[b-25oglh36l7] {
    color: var(--mud-palette-text-secondary);
}

.tot dd[b-25oglh36l7] {
    margin: 0;
    font-variant-numeric: tabular-nums;
}

.tot-strong[b-25oglh36l7] {
    border-top: 1px solid var(--mud-palette-lines-default);
    font-weight: 600;
}

.tot-strong dt[b-25oglh36l7],
.tot-strong dd[b-25oglh36l7] {
    color: var(--mud-palette-text-primary);
}

.tot-strongest[b-25oglh36l7] {
    border-top: 2px solid var(--mud-palette-primary);
    font-size: 15px;
    font-weight: 700;
}

.tot-strongest dt[b-25oglh36l7],
.tot-strongest dd[b-25oglh36l7] {
    color: var(--mud-palette-primary);
}

/* ---------------------------------------------------------------- dialog actions */

.qpv-actions[b-25oglh36l7] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
}

.qpv-actions-group[b-25oglh36l7] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
}

/* ---------------------------------------------------------------- narrow screens */

@media (max-width: 700px) {
    .qpv-scroll[b-25oglh36l7] {
        padding: 8px;
    }

    /* Five buttons (Close, Download, View, Email, Edit — Print is desktop-only) in one
       non-wrapping row (MudDialog's own `.mud-dialog-actions` sets no flex-wrap) forced icons and
       labels to clip at phone width. Stacking them into full-width rows reads as a proper action
       list instead of a shrinking strip of clipped buttons. */
    .qpv-actions[b-25oglh36l7],
    .qpv-actions-group[b-25oglh36l7] {
        flex-direction: column;
        align-items: stretch;
        width: 100%;
    }

    /* MudButton's own root carries no scope attribute (it's rendered by the component, not
       written literally in this file — DesignContext.md §4), hence ::deep. Left-aligned rather
       than MudButton's default centered content, so the icon+label reads like a list row. */
    .qpv-actions[b-25oglh36l7]  .mud-button-root {
        width: 100%;
        justify-content: flex-start;
    }

    .sheet[b-25oglh36l7] {
        padding: 18px 16px 20px;
    }

    /* The three header blocks stop being columns and become a stack; a 92px logo beside two
       text blocks has nowhere to go at phone width. */
    .sheet-head[b-25oglh36l7] {
        grid-template-columns: 1fr;
        gap: 10px;
    }

    .sheet-meta[b-25oglh36l7] {
        text-align: left;
    }

    .sheet-meta dl[b-25oglh36l7] {
        justify-content: start;
    }

    .sheet-parties[b-25oglh36l7],
    .sheet-foot[b-25oglh36l7] {
        grid-template-columns: 1fr;
        gap: 16px;
    }

    .sheet-totals[b-25oglh36l7],
    .sheet-right[b-25oglh36l7] {
        min-width: 0;
    }
}
/* /Components/Global/Dialogs/UserManagementDialog.razor.rz.scp.css */
/* Colors come from MudBlazor palette variables / the shared StatusBadge component only — this
   app has three switchable themes and a literal hex only looks right in one of them. */

.umd-toolbar[b-8vp6es3d3x] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 12px;
}

/* The wrapper is load-bearing, not decorative — same footgun as every other MudTable in this app
   (DesignContext.md §4): Blazor only stamps its scope attribute onto elements written literally
   in this file, so a rule targeting MudTable's own root via Class="…" would land outside the
   scope and silently match nothing. This dialog doesn't currently need such a rule, but the next
   edit that adds one needs this div to reach through. */
.umd-table[b-8vp6es3d3x] {
    overflow-x: auto;
}

.umd-username[b-8vp6es3d3x] {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.umd-status[b-8vp6es3d3x] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
/* /Components/Global/PageComponents/QuoteBreakdownView.razor.rz.scp.css */
/*
    Breakdown tab layout. The chart panels are MudCards and reuse the global .stat primitive
    (wwwroot/CSS/quote-ui.css); only the arrangement around them lives here.
*/

.bd[b-69i81jcrkr] {
    display: flex;
    flex-direction: column;
    gap: 14px;
    max-width: 980px;
    margin: 0 auto;
}

.bd-kpis[b-69i81jcrkr] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
    gap: 10px;
}

/* Two charts side by side on a wide dialog, stacked below it. Both are horizontal bar charts
   whose height is driven by their row count, so they don't need to match. */
.bd-pair[b-69i81jcrkr] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
    align-items: start;
}

.bd-panel[b-69i81jcrkr] {
    min-width: 0;
}

.bd-body[b-69i81jcrkr] {
    padding: 10px 12px 4px;
}

/* ---------------------------------------------------------------- table view */

.bd-table[b-69i81jcrkr] {
    overflow-x: auto;
}

.bd-table table[b-69i81jcrkr] {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.bd-table th[b-69i81jcrkr] {
    padding: 8px 12px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    text-align: left;
    white-space: nowrap;
    color: var(--mud-palette-text-secondary);
    background-color: var(--mud-palette-background-gray);
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.bd-table td[b-69i81jcrkr] {
    padding: 9px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-primary);
}

.bd-table tbody tr:last-child td[b-69i81jcrkr] {
    border-bottom: none;
}

/* .c-num / .c-amount are global — wwwroot/CSS/quote-ui.css. This table takes them as-is. */

@media (max-width: 820px) {
    .bd-pair[b-69i81jcrkr] {
        grid-template-columns: 1fr;
    }
}
/* /Components/Layout/MainLayout.razor.rz.scp.css */
/* Layout shell styling. All of this used to be inline style attributes (the appbar flex
   row, the hardcoded cream icon colors) or missing entirely — this file is the shell's
   CSS-isolation home. Colors come from the live palette vars only; the shell has to look
   right in all three themes.

   Scope-attribute gotcha (see AppContext.md): a Class= passed to a MudBlazor component
   lands on an element WITHOUT this file's scope attribute, so those are reached with
   `.owned-wrapper ::deep .class` — never bare `.class`. */

.appbar-row[b-tso5dieh0f] {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    min-width: 0;
}

.appbar-brand[b-tso5dieh0f] {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

.appbar-brand[b-tso5dieh0f]  .appbar-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.appbar-actions[b-tso5dieh0f] {
    display: flex;
    align-items: center;
}

/* Responsive branding, CSS-only so the first paint is already correct:
   below 600px (MudBlazor's Xs) the title goes and the nav hamburger appears;
   at 600px+ the drawer is a persistent mini rail, so the hamburger goes. */
@media (max-width: 599.98px) {
    .appbar-brand[b-tso5dieh0f]  .appbar-title {
        display: none;
    }
}

@media (min-width: 600px) {
    .appbar-brand[b-tso5dieh0f]  .appbar-nav-toggle {
        display: none;
    }
}

/* Drawer footer: the desktop collapse/expand chevron, separated from the nav by a
   hairline in the theme's divider color and inked with the drawer's own icon slot. */
.drawer-foot[b-tso5dieh0f] {
    border-top: 1px solid var(--mud-palette-divider);
    padding: 6px;
    display: flex;
    justify-content: flex-end;
}

.drawer-foot[b-tso5dieh0f]  .mud-icon-button {
    color: var(--mud-palette-drawer-icon);
}

/* Account menu (appbar). The menu panel is MudBlazor's own popover, so these rules reach it
   through ::deep from the wrapper this component owns — a Class= on MudMenu would land outside
   the scope attribute (DesignContext.md §4). Palette variables only, as everywhere else: this
   surface has to read correctly in Light, Dark and Lumber. */
.appbar-account-head[b-tso5dieh0f] {
    padding: 8px 16px 6px;
    min-width: 200px;
}

/* The sign-out control is a real <form> POST (a circuit cannot write a Set-Cookie header), so it
   needs to be talked out of looking like a form and into looking like the menu item above it. */
.appbar-signout form[b-tso5dieh0f] {
    margin: 0;
}

.appbar-signout[b-tso5dieh0f]  .mud-button-root {
    justify-content: flex-start;
    padding: 6px 16px;
    font-weight: 400;
    text-transform: none;
}
/* /Components/Layout/NavMenu.razor.rz.scp.css */
/* Theme-aware nav styling. Every color here resolves from the active palette's
   drawer-* slots (white drawer in Light, warm near-black in Dark, brand walnut in
   Lumber), so all three themes restyle the nav without a single literal hex.

   The tinted hover/active fills are derived from the drawer's own text ink via
   color-mix rather than a fixed grey: drawer-text is guaranteed to contrast with
   drawer-background in every theme (ThemeContrastTests asserts it), so a 10-16%
   tint of it always reads as "slightly raised" on that drawer. The plain rgba()
   line before each color-mix is the fallback for anything too old to know
   color-mix — the modern line wins whenever it parses. */

.nav-menu[b-ikuxkdbv4j] {
    padding: 12px 8px;
}

.nav-menu[b-ikuxkdbv4j]  .mud-nav-link {
    border-radius: 8px;
    margin: 2px 0;
    color: var(--mud-palette-drawer-text);
    transition: background-color 120ms ease;
}

.nav-menu[b-ikuxkdbv4j]  .mud-nav-link .mud-icon-root {
    color: var(--mud-palette-drawer-icon);
}

.nav-menu[b-ikuxkdbv4j]  .mud-nav-link:hover:not(.active) {
    background-color: rgba(128, 128, 128, 0.14);
    background-color: color-mix(in srgb, var(--mud-palette-drawer-text) 10%, transparent);
}

/* Active = tinted fill + a rail on the leading edge in the drawer's icon accent,
   + heavier text. The rail is an inset box-shadow rather than a border so it adds
   no width and survives the mini (icon-only) collapsed state, where it is the
   main "you are here" signal since the label is hidden. */
.nav-menu[b-ikuxkdbv4j]  .mud-nav-link.active:not(.mud-nav-link-disabled) {
    background-color: rgba(128, 128, 128, 0.18);
    background-color: color-mix(in srgb, var(--mud-palette-drawer-text) 16%, transparent);
    box-shadow: inset 3px 0 0 0 var(--mud-palette-drawer-icon);
}

.nav-menu[b-ikuxkdbv4j]  .mud-nav-link.active:not(.mud-nav-link-disabled) .mud-nav-link-text {
    font-weight: 600;
}
/* /Components/Pages/BuildQuote.razor.rz.scp.css */
/* Quote builder.

   Everything here is expressed in MudBlazor palette variables rather than literal colours,
   because the app ships three themes (Light / Dark / the cream "Lumber" theme) and the user can
   switch between them at any time from the appbar. Hard-coded hexes would look correct in
   exactly one of the three. */

.qp[b-pftf6gk5rh] {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

/* ---------------------------------------------------------------- page header */

.qp-head[b-pftf6gk5rh] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
}

.qp-eyebrow[b-pftf6gk5rh] {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.qp-title[b-pftf6gk5rh] {
    margin: 2px 0 0;
    font-family: "Roboto Slab", serif;
    font-size: 30px;
    font-weight: 500;
    line-height: 1.15;
    color: var(--mud-palette-text-primary);
}

/* The finalized badge sits under the title, not beside it — the title is the quote number and
   needs to stay the thing you read first. */
.qp-head-title .badge[b-pftf6gk5rh] {
    margin-top: 8px;
}

/* Groups the stat tiles with the "New Quote" button so they sit together at the header's trailing
   edge — .qp-head's own space-between only has two flex children (this and .qp-head-title), so
   the button rides along with the stats rather than landing in the middle of the row. */
.qp-head-actions[b-pftf6gk5rh] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
}

.qp-stats[b-pftf6gk5rh] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

/* Live running figures. Board feet and weight are up here rather than buried in the table
   because the spec asks for the board-foot calculation to be *shown*, and freight weight is
   what the yard quotes on. */



.stat strong small[b-pftf6gk5rh] {
    margin-left: 3px;
    font-size: 11px;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
}

.stat-due[b-pftf6gk5rh] {
    border-color: var(--mud-palette-primary);
    box-shadow: inset 0 0 0 1px var(--mud-palette-primary);
}

.stat-due strong[b-pftf6gk5rh] {
    color: var(--mud-palette-primary);
}

/* ---------------------------------------------------------------- panels */

.qp-body[b-pftf6gk5rh] {
    display: flex;
    flex-direction: column;
    gap: 20px;
}







.totals-wrap[b-pftf6gk5rh] {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 16px;
}

.totals-card[b-pftf6gk5rh] {
    width: 100%;
    max-width: 460px;
}

/* At a mid desktop width (~900-1150px) both cards no longer fit on one row at a readable size —
   this lets Miscellaneous drop to its own line above Totals rather than squeezing both. */
.misc-wrap[b-pftf6gk5rh] {
    flex: 1 1 520px;
    min-width: 320px;
}

/* ---------------------------------------------------------------- details form */

.form-stack[b-pftf6gk5rh] {
    display: flex;
    flex-direction: column;
    gap: 22px;
}

.form-section-head[b-pftf6gk5rh] {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--mud-palette-divider);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.form-section-head[b-pftf6gk5rh]  .mud-icon-root {
    font-size: 17px;
    color: var(--mud-palette-text-secondary);
}

/* Primary rather than the `dark` palette slot: primary is the brand walnut and is set
   explicitly on all three themes, whereas `dark` falls through to a MudBlazor default. */

/* ---------------------------------------------------------------- finalized (read-only) state

   A finalized quote is a record to read, not a form that happens to be broken, so this does the
   opposite of fading the page out: values stay at full contrast and it is the *input chrome*
   that goes away — borders, fill, dropdown carets, clear buttons. What is left reads as a
   printed document.

   `fieldset[disabled]` (set in the markup) is what actually enforces the lock: it removes every
   control inside from the tab order natively, so it cannot be defeated with a keyboard. The
   rules below only handle presentation, plus the MudBlazor widgets whose click target is a div
   rather than a real form control — `disabled` has no effect on those. */

.lockable[b-pftf6gk5rh] {
    /* Neutralise the fieldset's own UA styling; min-width:0 stops its default min-content
       sizing from blowing out the flex/grid layouts it now wraps. */
    border: 0;
    margin: 0;
    padding: 0;
    min-width: 0;
}

/* Scoped to the widgets rather than the whole subtree on purpose: a blanket
   `pointer-events: none` would also kill the line-item grid's horizontal scroll, and a wide
   finalized quote still has to be readable out to the Amount column. */
.lockable[disabled][b-pftf6gk5rh]  .mud-input-control,
.lockable[disabled][b-pftf6gk5rh]  .mud-toggle-group,
.lockable[disabled][b-pftf6gk5rh]  .mud-switch {
    pointer-events: none;
}

/* MudBlazor greys disabled controls out; undo that, then restore the text colour. Safari needs
   -webkit-text-fill-color specifically — it paints disabled input text with that rather than
   `color`, and this app targets iMac/iPad/iPhone. */
.lockable[disabled][b-pftf6gk5rh]  .mud-disabled {
    opacity: 1 !important;
}

.lockable[disabled][b-pftf6gk5rh]  input,
.lockable[disabled][b-pftf6gk5rh]  textarea,
.lockable[disabled][b-pftf6gk5rh]  .mud-input-slot,
.lockable[disabled][b-pftf6gk5rh]  .mud-select-input .mud-input-slot {
    color: var(--mud-palette-text-primary) !important;
    -webkit-text-fill-color: var(--mud-palette-text-primary) !important;
}

.lockable[disabled][b-pftf6gk5rh]  .mud-input-label,
.lockable[disabled][b-pftf6gk5rh]  .mud-switch .mud-typography {
    color: var(--mud-palette-text-secondary) !important;
}

/* Drop the box around each value — this is the change that turns fields into text. */
.lockable[disabled][b-pftf6gk5rh]  .mud-input-outlined-border {
    border-color: transparent !important;
}

.lockable[disabled][b-pftf6gk5rh]  .mud-input.mud-input-outlined {
    background-color: transparent !important;
}

/* Trailing affordances (clear ✕, dropdown caret, date-picker icon) promise an interaction that
   is no longer on offer. Leading adornments — the "$" on money fields — are part of the value
   and stay.

   The clear button needs naming separately: MudBlazor renders it as a direct child of
   .mud-input rather than inside the end adornment, so hiding the adornment misses it. */
.lockable[disabled][b-pftf6gk5rh]  .mud-input-adornment-end,
.lockable[disabled][b-pftf6gk5rh]  .mud-input-clear-button {
    display: none;
}

/* A value that has no input to sit in — currently the fulfillment choice, whose meaning is
   carried by which half of a toggle is filled rather than by any text. Styled to sit on the
   same baseline as the read-only fields around it. */
.locked-value[b-pftf6gk5rh] {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 4px 0;
    font-size: 16px;
    color: var(--mud-palette-text-primary);
}

.locked-value[b-pftf6gk5rh]  .mud-icon-root {
    font-size: 19px;
    color: var(--mud-palette-text-secondary);
}

.switch-row[b-pftf6gk5rh] {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 28px;
}

.fulfil-toggle[b-pftf6gk5rh] {
    max-width: 320px;
}

/* ---------------------------------------------------------------- line item grid */

.table-scroll[b-pftf6gk5rh] {
    overflow-x: auto;
}

.line-table[b-pftf6gk5rh] {
    width: 100%;
    /* Raised from 1180px with the action column (1 icon → 2), so the fluid Description column
       doesn't give up those 36px at the narrowest desktop width. */
    min-width: 1300px;
    border-collapse: collapse;
    /* Spec: noticeably larger than the QuickBooks output this replaces — read at a shop
       counter, and sometimes off paper. */
    font-size: 15px;
}

.line-table th[b-pftf6gk5rh] {
    padding: 10px 8px;
    border-bottom: 1px solid var(--mud-palette-divider);
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
    text-align: left;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.line-table td[b-pftf6gk5rh] {
    padding: 8px;
    vertical-align: middle;
}

.row-main > td[b-pftf6gk5rh] {
    padding-top: 12px;
    padding-bottom: 4px;
}

/* Spec calls for a full, visible horizontal rule under every line item — explicitly not
   subtle zebra striping. The primary row and its derived-values row are one logical item, so
   the rule goes under the pair. */
.row-meta > td[b-pftf6gk5rh] {
    padding-top: 0;
    padding-bottom: 12px;
    border-bottom: 2px solid var(--mud-palette-lines-default);
}

.row-main:hover > td[b-pftf6gk5rh],
.row-main:hover + .row-meta > td[b-pftf6gk5rh] {
    background-color: var(--mud-palette-table-hover);
}

.row-flagged > td:first-child[b-pftf6gk5rh] {
    box-shadow: inset 3px 0 0 var(--mud-palette-warning);
}

.c-idx[b-pftf6gk5rh] { width: 40px; }
.c-qty[b-pftf6gk5rh] { width: 84px; }
.c-item[b-pftf6gk5rh] { width: 330px; }
.c-size[b-pftf6gk5rh] { width: 150px; }
.c-opt[b-pftf6gk5rh] { width: 300px; }
/* Two small icon buttons (note, delete) — was 48px when delete was the only one. */
.c-act[b-pftf6gk5rh] { width: 84px; }

/* Keeps the pair on one line and right-aligned, so the column reads the same whether it holds one
   button or two (a finalized quote drops delete; a blank row drops the note button). */
.act-cell[b-pftf6gk5rh] {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 2px;
}

/* .c-num / .c-amount themselves are global (wwwroot/CSS/quote-ui.css). What stays here is only
   what belongs to *this* table: the desktop entry grid is a fixed-width layout (see the sibling
   .c-* widths above and .line-table's min-width), so Rate/Amount get a column width the other
   two tables — which are fluid — must not inherit. Scoped selectors carry the Blazor scope
   attribute, so these out-specify the global rule regardless of link order. */
.c-num[b-pftf6gk5rh] { width: 108px; }

/* Larger and at full contrast because this grid is the data-entry surface: the Amount figure
   has to stay readable at a shop counter against 14px inputs. */
.c-amount[b-pftf6gk5rh] {
    font-size: 16px;
    color: var(--mud-palette-text-primary);
}

.idx[b-pftf6gk5rh] {
    display: inline-grid;
    place-items: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
    border: 1px solid var(--mud-palette-lines-default);
    font-size: 12px;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

.item-cell[b-pftf6gk5rh],
.size-cell[b-pftf6gk5rh],
.opt-cell[b-pftf6gk5rh] {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* Options sit in a tidy two-column grid instead of a free-wrapping flow, so selects line up
   row over row across every line item. */
.opt-cell[b-pftf6gk5rh] {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    flex-direction: initial;
    gap: 6px;
    align-items: center;
}

.opt-cell > *[b-pftf6gk5rh] {
    min-width: 0;
}

/* Every control has a fixed slot, so choosing E/P (which adds Type + Thickness) never shifts the
   others, and the fixed-unit label ("BF") always sits in the same place instead of wherever the
   auto-flow leaves a gap. ::deep because a MudBlazor root carries no scope attribute (§4). */
.opt-cell[b-pftf6gk5rh]  > .opt-surf  { grid-column: 1; grid-row: 1; }
.opt-cell[b-pftf6gk5rh]  > .opt-moist { grid-column: 2; grid-row: 1; }
.opt-cell[b-pftf6gk5rh]  > .opt-ptype { grid-column: 1; grid-row: 2; }
.opt-cell[b-pftf6gk5rh]  > .opt-thick { grid-column: 2; grid-row: 2; }
.opt-cell[b-pftf6gk5rh]  > .opt-uom   { grid-column: 1; grid-row: 3; }
.opt-cell[b-pftf6gk5rh]  > .opt-unit  { grid-column: 2; grid-row: 3; }
/* The reset icon sits beside the description field, not below it — the field is already the
   widest control in the row and has room. flex-shrink:0 on the icon keeps it from being squeezed
   as the field grows/shrinks with the column. */
.desc-cell[b-pftf6gk5rh] {
    display: flex;
    align-items: flex-start;
    gap: 2px;
}

/* ::deep required — MudTextField/MudIconButton's own root carries no scope attribute
   (DesignContext.md §4), so an unscoped rule on the right of ::deep is what reaches them. */
.desc-cell[b-pftf6gk5rh]  > .mud-input-control {
    flex: 1 1 auto;
}

.desc-cell[b-pftf6gk5rh]  > .mud-icon-button {
    flex-shrink: 0;
    margin-top: 4px;
}

.size-fixed[b-pftf6gk5rh],
.uom-fixed[b-pftf6gk5rh] {
    display: inline-flex;
    align-items: center;
    font-size: 13px;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* Product picker rows: SKU is the audit key, the description is what people actually read. */
.ac-item[b-pftf6gk5rh] {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
}

.ac-sku[b-pftf6gk5rh] {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-secondary);
}

.ac-desc[b-pftf6gk5rh] {
    font-size: 14px;
}

/* Derived values live on a second line so the primary row stays scannable, but they are always
   on screen — the notes ask for the board-foot figure to be shown, not just used internally. */
.meta[b-pftf6gk5rh] {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.tag[b-pftf6gk5rh] {
    display: inline-flex;
    align-items: center;
    padding: 2px 9px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.tag-num[b-pftf6gk5rh] {
    font-variant-numeric: tabular-nums;
}

.meta-error[b-pftf6gk5rh] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--mud-palette-warning-darken, var(--mud-palette-warning));
}

.meta-error[b-pftf6gk5rh]  .mud-icon-root {
    font-size: 16px;
    color: var(--mud-palette-warning);
}

.meta-hint[b-pftf6gk5rh] {
    font-size: 13px;
    font-style: italic;
    color: var(--mud-palette-text-disabled);
}

/* Tighten MudBlazor's default input chrome inside the grid — at default spacing the rows get
   tall enough that only three or four line items fit on screen at once. */
.line-table[b-pftf6gk5rh]  .mud-input-control {
    margin-top: 0 !important;
}

.line-table[b-pftf6gk5rh]  .mud-input.mud-input-outlined .mud-input-slot {
    font-size: 14px;
}

/* ---------------------------------------------------------------- empty state */

/* ---------------------------------------------------------------- add-row footer */

/* The "Add Line Item" row: a genuine <tfoot> row spanning every column, so it reads as the
   next row in the grid rather than a control stuck on below it. Same reasoning MiscItemsPanel
   has for its own "Add item" affordance, adapted to a table instead of a stack of cards. */
.line-table tfoot .row-add td[b-pftf6gk5rh] {
    padding: 0;
    border-top: 1px dashed var(--mud-palette-lines-default);
}

.add-row[b-pftf6gk5rh] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 44px;
    border: none;
    background: none;
    cursor: pointer;
    font: inherit;
    font-weight: 700;
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mud-palette-primary);
    transition: background-color 0.15s ease;
}

/* Plain rgba() fallback for anything too old to know color-mix, same convention as
   NavMenu.razor.css's hover tint — the modern line wins whenever it parses. */
.add-row:hover[b-pftf6gk5rh],
.add-row:focus-visible[b-pftf6gk5rh] {
    background-color: rgba(128, 128, 128, 0.08);
    background-color: color-mix(in srgb, var(--mud-palette-primary) 8%, transparent);
}

.add-row:focus-visible[b-pftf6gk5rh] {
    outline: none;
    box-shadow: inset 0 0 0 2px var(--mud-palette-primary);
}

.add-row[b-pftf6gk5rh]  .mud-icon-root {
    font-size: 18px;
}

/* ---------------------------------------------------------------- totals */

.totals[b-pftf6gk5rh] {
    display: flex;
    flex-direction: column;
}

/* Spec: even vertical spacing between Subtotal / Tax / Shipping / Total. The rows that hold an
   input and the rows that hold a plain figure are given the same min-height so the column of
   numbers on the right stays on a steady rhythm instead of jumping around the input boxes. */
.tot-row[b-pftf6gk5rh] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    min-height: 46px;
    padding: 2px 0;
}

.tot-label[b-pftf6gk5rh] {
    font-size: 15px;
    color: var(--mud-palette-text-secondary);
}

.tot-label-wrap[b-pftf6gk5rh] {
    max-width: 62%;
    line-height: 1.25;
}

.tot-value[b-pftf6gk5rh] {
    font-size: 16px;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

.tot-field[b-pftf6gk5rh] {
    width: 132px;
    flex: 0 0 132px;
}

.tot-field[b-pftf6gk5rh]  .mud-input-control {
    margin-top: 0 !important;
}

.tot-field[b-pftf6gk5rh]  input {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.tot-row-total[b-pftf6gk5rh] {
    margin-top: 6px;
    border-top: 2px solid var(--mud-palette-lines-default);
}

.tot-row-total .tot-label[b-pftf6gk5rh] {
    font-size: 16px;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.tot-row-total .tot-value[b-pftf6gk5rh] {
    font-size: 20px;
    font-weight: 600;
}

.tot-row-due[b-pftf6gk5rh] {
    margin-top: 2px;
    padding: 10px 12px;
    border-radius: 10px;
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
    border: 1px solid var(--mud-palette-primary);
}

.tot-row-due .tot-label[b-pftf6gk5rh] {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--mud-palette-text-primary);
}

.tot-row-due .tot-value[b-pftf6gk5rh] {
    font-size: 24px;
    font-weight: 700;
    color: var(--mud-palette-primary);
}

/* ---------------------------------------------------------------- mobile wizard */

.wiz[b-pftf6gk5rh] {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background-color: var(--mud-palette-surface);
    overflow: hidden;
}

.wiz-rail[b-pftf6gk5rh] {
    display: flex;
    margin: 0;
    padding: 6px 4px 4px;
    list-style: none;
    border-bottom: 1px solid var(--mud-palette-divider);
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
}

.wiz-step[b-pftf6gk5rh] {
    position: relative;
    flex: 1;
}

/* Connector between the step dots. Drawn from each step back toward the previous one so it
   never overhangs the first or last dot. */
.wiz-step + .wiz-step[b-pftf6gk5rh]::before {
    content: "";
    position: absolute;
    top: 25px;
    right: 50%;
    left: -50%;
    height: 2px;
    background-color: var(--mud-palette-lines-default);
}

.wiz-step.is-active[b-pftf6gk5rh]::before,
.wiz-step.is-done[b-pftf6gk5rh]::before {
    background-color: var(--mud-palette-primary);
}

.wiz-step button[b-pftf6gk5rh] {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: 8px 2px;
    border: 0;
    background: none;
    cursor: pointer;
    color: var(--mud-palette-text-secondary);
    font: inherit;
}

.wiz-dot[b-pftf6gk5rh] {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 2px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
    font-size: 14px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.wiz-dot[b-pftf6gk5rh]  .mud-icon-root {
    font-size: 18px;
    color: inherit;
}

.is-active .wiz-dot[b-pftf6gk5rh] {
    border-color: var(--mud-palette-primary);
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

.is-done .wiz-dot[b-pftf6gk5rh] {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

.wiz-label[b-pftf6gk5rh] {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
}

.is-active .wiz-label[b-pftf6gk5rh] {
    color: var(--mud-palette-primary);
}

.wiz-body[b-pftf6gk5rh] {
    padding: 18px 14px;
}

/* Kept in reach of a thumb, and always showing the number the customer is about to be told. */
.wiz-actions[b-pftf6gk5rh] {
    position: sticky;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 12px;
    border-top: 1px solid var(--mud-palette-divider);
    background-color: var(--mud-palette-surface);
}

.wiz-actions-due[b-pftf6gk5rh] {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1.15;
}

.wiz-actions-due span[b-pftf6gk5rh] {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.wiz-actions-due strong[b-pftf6gk5rh] {
    font-size: 17px;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

/* ---------------------------------------------------------------- mobile line cards */

.cards[b-pftf6gk5rh] {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.card[b-pftf6gk5rh] {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 4px 4px 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background-color: var(--mud-palette-surface);
}

.card-flagged[b-pftf6gk5rh] {
    border-color: var(--mud-palette-warning);
    box-shadow: inset 3px 0 0 var(--mud-palette-warning);
}

.card-tap[b-pftf6gk5rh] {
    flex: 1;
    min-width: 0;
    padding: 8px 0;
    cursor: pointer;
}

.card-top[b-pftf6gk5rh] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

.card-desc[b-pftf6gk5rh] {
    flex: 1;
    min-width: 0;
    font-size: 15px;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.card-amt[b-pftf6gk5rh] {
    font-size: 16px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    color: var(--mud-palette-text-primary);
}

.card-meta[b-pftf6gk5rh] {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 7px;
}

.card-error[b-pftf6gk5rh] {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 7px;
    font-size: 13px;
    color: var(--mud-palette-warning-darken, var(--mud-palette-warning));
}

.card-error[b-pftf6gk5rh]  .mud-icon-root {
    font-size: 16px;
    color: var(--mud-palette-warning);
}

/* ---------------------------------------------------------------- narrow screens */

@media (max-width: 600px) {
    .qp-title[b-pftf6gk5rh] {
        font-size: 24px;
    }

    .qp-stats[b-pftf6gk5rh] {
        width: 100%;
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .stat[b-pftf6gk5rh] {
        min-width: 0;
    }
}
/* /Components/Pages/CustomerList.razor.rz.scp.css */
/* Customer list.

   Same rules as the quote pages: MudBlazor palette variables only, never literal colours — the
   app ships three switchable themes and a hard-coded hex only looks right in one of them.

   The table-chrome block below (header band, row rules, hover, pager) is a SECOND copy of what
   QuoteList.razor.css already has — permitted under the app's rule of three (see quote-ui.css's
   own header comment), but this makes two. If a third table-heavy page shows up, promote this
   block to quote-ui.css instead of copying it again.

   .stat / .badge / .empty / .c-num are NOT duplicated here — they're global, in
   wwwroot/CSS/quote-ui.css. */

.cl[b-kqmzd1mjcl] {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

/* ---------------------------------------------------------------- page header */

.cl-head[b-kqmzd1mjcl] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
}

.cl-eyebrow[b-kqmzd1mjcl] {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.cl-title[b-kqmzd1mjcl] {
    margin: 2px 0 0;
    font-family: "Roboto Slab", serif;
    font-size: 30px;
    font-weight: 500;
    line-height: 1.15;
    color: var(--mud-palette-text-primary);
}

.cl-stats[b-kqmzd1mjcl] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

/* ---------------------------------------------------------------- filter toolbar */

/* Sits on the same gray band the table headers use, so the filters read as part of the table
   chrome rather than as free-floating form fields on the page. */
.cl-toolbar[b-kqmzd1mjcl] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--mud-palette-divider);
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
}

.cl-search[b-kqmzd1mjcl] {
    flex: 1 1 260px;
    max-width: 380px;
}

.cl-flag-filter[b-kqmzd1mjcl] {
    flex: 0 0 160px;
}

.cl-toolbar[b-kqmzd1mjcl]  .mud-input-control {
    margin-top: 0 !important;
}

/* ---------------------------------------------------------------- table */

.cl-table[b-kqmzd1mjcl]  .mud-table {
    background-color: transparent;
}

.cl-table[b-kqmzd1mjcl]  .mud-table-sort-label {
    color: inherit;
}

.cl-table[b-kqmzd1mjcl]  .mud-table-sort-label-icon {
    font-size: 15px;
}

.cl-table[b-kqmzd1mjcl]  .mud-table-head .mud-table-cell {
    padding: 10px 12px;
    border-bottom: 1px solid var(--mud-palette-divider);
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.cl-table[b-kqmzd1mjcl]  .mud-table-body .mud-table-cell {
    padding: 12px;
    border-bottom: 2px solid var(--mud-palette-lines-default);
    font-size: 15px;
}

.cl-table[b-kqmzd1mjcl]  .mud-table-body .mud-table-row {
    cursor: pointer;
}

.cl-table[b-kqmzd1mjcl]  .mud-table-body .mud-table-row:hover .mud-table-cell {
    background-color: var(--mud-palette-table-hover);
}

.cl-table[b-kqmzd1mjcl]  .mud-table-body .mud-table-row:last-child .mud-table-cell {
    border-bottom: 0;
}

.cl-table[b-kqmzd1mjcl]  .mud-table-pagination {
    border-top: 0;
}

/* Quotes count (6th column) is the one right-aligned column, so its header has to follow the
   figures. Addressed positionally because MudTh renders its own <th> — a class passed to it
   lands outside this component's scope and cannot be selected directly. Re-check this if columns
   are added or reordered. */
.cl-table[b-kqmzd1mjcl]  .mud-table-head .mud-table-cell:nth-child(6) {
    text-align: right;
}

.cl-table[b-kqmzd1mjcl]  .mud-table-head .mud-table-cell:nth-child(6) .mud-table-sort-label {
    justify-content: flex-end;
}

.cell-customer[b-kqmzd1mjcl] {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
}

.cell-company[b-kqmzd1mjcl] {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}

.cell-flags[b-kqmzd1mjcl] {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* .empty (quote-ui.css) is a flex column, so this wraps the two buttons as one row within it —
   Import from CSV is the one action worth surfacing here beyond QuoteList's single-button empty
   state, since an empty customer list is the single most likely moment for a bulk import. */
.empty-actions[b-kqmzd1mjcl] {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
}

/* ---------------------------------------------------------------- narrow screens */

@media (max-width: 600px) {
    .cl-title[b-kqmzd1mjcl] {
        font-size: 24px;
    }

    .cl-stats[b-kqmzd1mjcl] {
        width: 100%;
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .stat[b-kqmzd1mjcl] {
        min-width: 0;
        padding: 8px 10px;
    }

    .stat strong[b-kqmzd1mjcl] {
        font-size: 16px;
    }

    .cl-search[b-kqmzd1mjcl],
    .cl-flag-filter[b-kqmzd1mjcl] {
        flex-basis: 100%;
        max-width: none;
    }
}
/* /Components/Pages/Home.razor.rz.scp.css */
/* Home page: dock launcher + statistics dashboard.

   Every colour resolves from the live palette vars so all three themes restyle the page
   without a literal hex (the charts' baked hexes live in Theming/ChartPalette.cs, the one
   documented exception). Tinted fills derive from the theme's own inks via color-mix, with
   a plain rgba() fallback line before each — same pattern as NavMenu.razor.css. */

.home[b-o6u6q7t5s2] {
    max-width: 1200px;
    margin: 0 auto;
}

/* ---------------------------------------------------------------- dock */

/* A macOS-dock-style launcher: one floating, frosted, rounded bar holding a tile per page.
   fit-content + auto margins keep it centred at any width. */
.dock[b-o6u6q7t5s2] {
    display: flex;
    justify-content: center;
    gap: 8px;
    width: fit-content;
    max-width: 100%;
    margin: 4px auto 24px;
    padding: 10px 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 22px;
    background-color: var(--mud-palette-surface);
    background-color: color-mix(in srgb, var(--mud-palette-surface) 78%, transparent);
    -webkit-backdrop-filter: blur(14px); /* target devices are iMac/iPad/iPhone — Safari needs the prefix */
    backdrop-filter: blur(14px);
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.10);
}

.dock-item[b-o6u6q7t5s2] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    min-width: 148px;
    padding: 12px 18px 10px;
    border-radius: 16px;
    text-decoration: none;
    transition: transform 140ms ease, background-color 140ms ease;
}

/* The dock lift: the whole tile rises and its icon plate brightens. Transform only — no
   width/layout change, so neighbours don't shuffle. */
.dock-item:hover[b-o6u6q7t5s2],
.dock-item:focus-visible[b-o6u6q7t5s2] {
    transform: translateY(-4px);
    background-color: rgba(128, 128, 128, 0.10);
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 7%, transparent);
}

.dock-item:focus-visible[b-o6u6q7t5s2] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* The iOS-style icon plate: a rounded square tinted from Primary, ink in Primary itself. */
.dock-icon[b-o6u6q7t5s2] {
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    border-radius: 13px;
    margin-bottom: 3px;
    background-color: rgba(128, 128, 128, 0.14);
    background-color: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
    transition: transform 140ms ease;
}

.dock-item:hover .dock-icon[b-o6u6q7t5s2],
.dock-item:focus-visible .dock-icon[b-o6u6q7t5s2] {
    transform: scale(1.08);
}

/* MudIcon / MudText roots carry no scope attribute (Class= lands on the component's own
   element), so they're reached through the owned wrappers above via ::deep. */
.dock-icon[b-o6u6q7t5s2]  .mud-icon-root {
    color: var(--mud-palette-primary);
}

.dock-item[b-o6u6q7t5s2]  .dock-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.dock-item[b-o6u6q7t5s2]  .dock-desc {
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* ---------------------------------------------------------------- dashboard layout */

.home-stats[b-o6u6q7t5s2] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 16px;
}

.home-stats .stat[b-o6u6q7t5s2] {
    flex: 1 1 150px;
}

.home-grid[b-o6u6q7t5s2] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}

.span-2[b-o6u6q7t5s2] {
    grid-column: 1 / -1;
}

.hd-body[b-o6u6q7t5s2] {
    padding: 12px 14px 8px;
}

.home-loading[b-o6u6q7t5s2] {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* Blend MudTabs into the panel: hairline under the tab row, panels padded by .hd-body. */
.home-tabs[b-o6u6q7t5s2]  .mud-tabs-tabbar {
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background-color: transparent;
}

/* The two ranking panels stack below tablet width — side-by-side charts under ~880px
   squeeze their label gutters to nothing. */
@media (max-width: 880px) {
    .home-grid[b-o6u6q7t5s2] {
        grid-template-columns: 1fr;
    }

    .dock-item[b-o6u6q7t5s2] {
        min-width: 120px;
        padding: 10px 12px 8px;
    }

    .dock-item[b-o6u6q7t5s2]  .dock-desc {
        white-space: normal;
        text-align: center;
    }
}
/* /Components/Pages/ProductList.razor.rz.scp.css */
/* Product list. Same rules as CustomerList.razor.css: MudBlazor palette variables only, no
   literal colours, and the table-chrome block below is a permitted third copy of the block
   CustomerList/QuoteList already carry (see quote-ui.css's rule-of-three note) — if a fourth
   table-heavy page shows up, promote it to quote-ui.css instead of copying it again.

   .stat / .badge / .empty / .c-num are NOT duplicated here — they're global, in
   wwwroot/CSS/quote-ui.css. */

.pl[b-yz0pj2q4xy] {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

/* ---------------------------------------------------------------- page header */

.pl-head[b-yz0pj2q4xy] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
}

.pl-eyebrow[b-yz0pj2q4xy] {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.pl-title[b-yz0pj2q4xy] {
    margin: 2px 0 0;
    font-family: "Roboto Slab", serif;
    font-size: 30px;
    font-weight: 500;
    line-height: 1.15;
    color: var(--mud-palette-text-primary);
}

.pl-stats[b-yz0pj2q4xy] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

/* ---------------------------------------------------------------- filter toolbar */

.pl-toolbar[b-yz0pj2q4xy] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--mud-palette-divider);
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
}

.pl-search[b-yz0pj2q4xy] {
    flex: 1 1 260px;
    max-width: 380px;
}

.pl-category-filter[b-yz0pj2q4xy] {
    flex: 0 0 200px;
}

.pl-active-filter[b-yz0pj2q4xy] {
    flex: 0 0 140px;
}

.pl-toolbar[b-yz0pj2q4xy]  .mud-input-control {
    margin-top: 0 !important;
}

/* ---------------------------------------------------------------- table */

.pl-table[b-yz0pj2q4xy]  .mud-table {
    background-color: transparent;
}

.pl-table[b-yz0pj2q4xy]  .mud-table-sort-label {
    color: inherit;
}

.pl-table[b-yz0pj2q4xy]  .mud-table-sort-label-icon {
    font-size: 15px;
}

.pl-table[b-yz0pj2q4xy]  .mud-table-head .mud-table-cell {
    padding: 10px 12px;
    border-bottom: 1px solid var(--mud-palette-divider);
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.pl-table[b-yz0pj2q4xy]  .mud-table-body .mud-table-cell {
    padding: 12px;
    border-bottom: 2px solid var(--mud-palette-lines-default);
    font-size: 15px;
}

.pl-table[b-yz0pj2q4xy]  .mud-table-body .mud-table-row {
    cursor: pointer;
}

.pl-table[b-yz0pj2q4xy]  .mud-table-body .mud-table-row:hover .mud-table-cell {
    background-color: var(--mud-palette-table-hover);
}

.pl-table[b-yz0pj2q4xy]  .mud-table-body .mud-table-row:last-child .mud-table-cell {
    border-bottom: 0;
}

.pl-table[b-yz0pj2q4xy]  .mud-table-pagination {
    border-top: 0;
}

.cell-sku[b-yz0pj2q4xy] {
    font-family: "Roboto Mono", monospace;
    font-size: 13px;
    color: var(--mud-palette-text-secondary);
}

.cell-description[b-yz0pj2q4xy] {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
}

.cell-muted[b-yz0pj2q4xy] {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}

/* ---------------------------------------------------------------- narrow screens */

@media (max-width: 600px) {
    .pl-title[b-yz0pj2q4xy] {
        font-size: 24px;
    }

    .pl-stats[b-yz0pj2q4xy] {
        width: 100%;
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .stat[b-yz0pj2q4xy] {
        min-width: 0;
        padding: 8px 10px;
    }

    .stat strong[b-yz0pj2q4xy] {
        font-size: 16px;
    }

    .pl-search[b-yz0pj2q4xy],
    .pl-category-filter[b-yz0pj2q4xy],
    .pl-active-filter[b-yz0pj2q4xy] {
        flex-basis: 100%;
        max-width: none;
    }
}
/* /Components/Pages/QuoteList.razor.rz.scp.css */
/* Saved quotes list.

   Same rules as the quote builder: MudBlazor palette variables only, never literal colours —
   the app ships three switchable themes (Light / Dark / the cream "Lumber" theme) and a
   hard-coded hex only looks right in one of them.

   The primitives in the first section (.stat / .badge / .empty) intentionally mirror
   BuildQuote.razor.css so the two pages read as one product. They are duplicated rather than
   shared because Blazor scopes each component's CSS to that component — a rule in
   BuildQuote.razor.css cannot reach this page. If a third page needs them, promote the block to
   a global stylesheet instead of copying it again. */

.ql[b-ol6f34jg0u] {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

/* ---------------------------------------------------------------- page header */

.ql-head[b-ol6f34jg0u] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
}

.ql-eyebrow[b-ol6f34jg0u] {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.ql-title[b-ol6f34jg0u] {
    margin: 2px 0 0;
    font-family: "Roboto Slab", serif;
    font-size: 30px;
    font-weight: 500;
    line-height: 1.15;
    color: var(--mud-palette-text-primary);
}

.ql-stats[b-ol6f34jg0u] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}




/* The money figure gets the same emphasis treatment the builder gives Amount Due, so the one
   number an operator scans for reads the same on both screens. */


/* ---------------------------------------------------------------- panel */







/* ---------------------------------------------------------------- filter toolbar */

/* Sits on the same gray band the table headers use, so the filters read as part of the table
   chrome rather than as free-floating form fields on the page. */
.ql-toolbar[b-ol6f34jg0u] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--mud-palette-divider);
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
}

.ql-search[b-ol6f34jg0u] {
    flex: 1 1 240px;
    max-width: 340px;
}

.ql-status-filter[b-ol6f34jg0u] {
    flex: 0 0 200px;
}

.ql-toolbar[b-ol6f34jg0u]  .mud-input-control {
    margin-top: 0 !important;
}

/* ---------------------------------------------------------------- table */

/* The table sits inside a MudCard, which already provides the surface and the border. */
.ql-table[b-ol6f34jg0u]  .mud-table {
    background-color: transparent;
}

.ql-table[b-ol6f34jg0u]  .mud-table-sort-label {
    color: inherit;
}

.ql-table[b-ol6f34jg0u]  .mud-table-sort-label-icon {
    font-size: 15px;
}

.ql-table[b-ol6f34jg0u]  .mud-table-head .mud-table-cell {
    padding: 10px 12px;
    border-bottom: 1px solid var(--mud-palette-divider);
    background-color: var(--mud-palette-background-gray, var(--mud-palette-background));
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.ql-table[b-ol6f34jg0u]  .mud-table-body .mud-table-cell {
    padding: 12px;
    /* Spec calls for a full visible rule under each row rather than zebra striping — matching
       the line-item grid in the builder. */
    border-bottom: 2px solid var(--mud-palette-lines-default);
    font-size: 15px;
}

/* Every body row opens its quote (OnRowClick), so the pointer is the affordance for that.
   Reached through the .ql-table wrapper above rather than MudTable's RowStyle: presentation
   belongs in the stylesheet, and an inline style is invisible to the theme review. */
.ql-table[b-ol6f34jg0u]  .mud-table-body .mud-table-row {
    cursor: pointer;
}

.ql-table[b-ol6f34jg0u]  .mud-table-body .mud-table-row:hover .mud-table-cell {
    background-color: var(--mud-palette-table-hover);
}

/* The card edge already closes the list off; a rule under the final row doubles it up. */
.ql-table[b-ol6f34jg0u]  .mud-table-body .mud-table-row:last-child .mud-table-cell {
    border-bottom: 0;
}

/* A finalized quote is settled: flag it the way the builder flags a row needing attention,
   but in the brand colour rather than the warning colour. */
.ql-table[b-ol6f34jg0u]  .mud-table-body .row-finalized .mud-table-cell:first-child {
    box-shadow: inset 3px 0 0 var(--mud-palette-primary);
}

.ql-table[b-ol6f34jg0u]  .mud-table-pagination {
    border-top: 0;
}

/* Quote number is the audit key — same treatment the builder gives a product SKU. */
.cell-number[b-ol6f34jg0u] {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.cell-customer[b-ol6f34jg0u] {
    display: flex;
    flex-direction: column;
    line-height: 1.3;
}

.cell-company[b-ol6f34jg0u] {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}

.cell-amount[b-ol6f34jg0u] {
    display: block;
    text-align: right;
    font-size: 16px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    color: var(--mud-palette-text-primary);
}

/* Amount Due (6th column) is the one right-aligned column, so its header has to follow the
   figures. Addressed positionally because MudTh renders the <th> itself — a class passed to it
   lands outside this component's scope and cannot be selected directly. */
.ql-table[b-ol6f34jg0u]  .mud-table-head .mud-table-cell:nth-child(6) {
    text-align: right;
}

.ql-table[b-ol6f34jg0u]  .mud-table-head .mud-table-cell:nth-child(6) .mud-table-sort-label {
    justify-content: flex-end;
}

/* ---------------------------------------------------------------- badges */



/* Status reads as a progression rather than three unrelated colours:
   Draft is provisional (outline only, no fill), Sent is live and awaiting an answer (the
   brand's teal, its "active" colour), Accepted is resolved (success). */




/* ---------------------------------------------------------------- empty state */




/* ---------------------------------------------------------------- narrow screens */

@media (max-width: 600px) {
    .ql-title[b-ol6f34jg0u] {
        font-size: 24px;
    }

    .ql-stats[b-ol6f34jg0u] {
        width: 100%;
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .stat[b-ol6f34jg0u] {
        min-width: 0;
        padding: 8px 10px;
    }

    .stat strong[b-ol6f34jg0u] {
        font-size: 16px;
    }

    .ql-search[b-ol6f34jg0u],
    .ql-status-filter[b-ol6f34jg0u] {
        flex-basis: 100%;
        max-width: none;
    }
}
