﻿/* ── Brand Design Tokens ──────────────────────────────────────────────────── */
:root {
  /* Primary — Royal Blue */
  --color-primary-50:  #EBF0FD;
  --color-primary-100: #C3D2F9;
  --color-primary-200: #8AAAF3;
  --color-primary-400: #3A6AE0;  /* table headers, soft UI */
  --color-primary:     #0548CB;  /* brand anchor */
  --color-primary-800: #033AAB;  /* hover, sub-headers */
  --color-primary-900: #022880;  /* darkest */

  /* Secondary — Amber */
  --color-secondary-50:  #FEF4E6;
  --color-secondary-100: #FBDFAB;
  --color-secondary-200: #F5C055;
  --color-secondary-400: #E8972A;  /* badges, highlights */
  --color-secondary:     #C47A18;  /* anchor */
  --color-secondary-800: #8A520A;
  --color-secondary-900: #5C3606;
  --color-secondary-50-opacity-6: color-mix(in srgb, var(--color-secondary) 6%, white);
  
  /* Type — Roboto Mono for record identifiers so IDs read as records, not prose */
  --font-mono: 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Neutral */
  --color-text-dark:   #1C2B3A;
  --color-text-title: #B4B2A9 ;
  --color-page-tint:   #F0F4FE;

  /* MudBlazor palette overrides */
  --mud-palette-success:                                   var(--color-success);

  /* Radzen component overrides */
  --rz-primary:                                            var(--color-primary);
  --rz-color-secondary:                                    var(--color-secondary);
  --rz-panel-menu-item-active-background-color:            var(--color-secondary-50);
  --rz-panel-menu-item-active-color:                       var(--color-secondary);
  --rz-panel-menu-item-2nd-level-active-background:             var(--color-secondary-50);
  --rz-panel-menu-item-2nd-level-active-background-color:       var(--color-secondary-50);
  --rz-panel-menu-item-2nd-level-active-color:                  var(--color-secondary);

  /* Semantic */
  --color-success-50:  #E8F8F3;
  --color-success:     #1D9E75;
  --color-success-800: #0F5E45;
  --color-warning: #E8972A;
  --color-error:   #E24B4A;
  --color-info:    #3A6AE0;
}

/* --- Radzen sidebar: active nav item background + text --- */
.rz-panel-menu .rz-state-active,
.rz-navigation-item.rz-state-active {
    background-color: var(--color-primary-50) !important;
}
.rz-panel-menu .rz-state-active .rz-navigation-item-text,
.rz-panel-menu .rz-state-active .rz-navigation-link,
.rz-panel-menu .rz-state-active span {
    color: var(--color-primary) !important;
}

/* --- Radzen overline text --- */
.rz-text-overline {
    font-weight: bold;
}

/* --- Radzen secondary color class override --- */
.rz-color-secondary {
    color: var(--color-secondary) !important;
}

/* --- Radzen chart tooltips: never intercept the pointer ---
   The tooltip is an overlay drawn above the plot area, so on a chart wired to SeriesClick it swallows
   the click for whichever bar or slice it happens to be covering: the bar only responds where the
   tooltip is not, and moving the mouse away and back is the only way to reach the rest of it. Letting
   the pointer pass straight through keeps the tooltip visible while the click lands on the series. */
.rz-chart-tooltip,
.rz-chart-tooltip * {
    pointer-events: none;
}

/* --- Chart value labels: Radzen fills these with the axis label grey, which disappears against a
       saturated bar it is drawn on top of. A white halo behind the glyphs keeps them legible over
       both a filled bar and the plot background. paint-order draws the stroke first so the outline
       sits behind the letterforms rather than eating into them. --- */
.rz-series-data-label {
    fill: #1f2937;
    font-weight: 600;
    paint-order: stroke;
    stroke: #ffffff;
    stroke-width: 3px;
    stroke-linejoin: round;
}

/* --- Clickable KPI cards: gentle white -> faint secondary tint on hover --- */
.kpi-card-clickable {
    cursor: pointer;
    transition: background-color 0.2s ease-in-out;
}

.kpi-card-clickable:hover {
    background-color: var(--color-secondary-50-opacity-6) !important; /* var(--color-secondary) at 6% */
}

/* --- Pulsing highlight: light secondary <-> white over one 3s cycle, 5 pulses then rest on light secondary --- */
@keyframes kpi-card-pulse {
    0%   { background-color: var(--color-secondary-50-opacity-6); }
    50%  { background-color: #ffffff; }
    100% { background-color: var(--color-secondary-50-opacity-6); }
}

.kpi-card-pulse {
    animation: kpi-card-pulse 3s ease-in-out 5 forwards;
}

/* --- Radzen basefont color class override --- */
.rz-color-title {
    color: var(--color-text-title) !important;
}

/* --- Radzen top header bar uses brand primary. Flex so the one stack inside is centred in
       the bar's height: the header has only a min-height, so a height: 100% on the stack is
       auto and its contents sat at the top once the bar grew (display size). --- */
.rz-header {
    background-color: var(--color-primary) !important;
    display: flex;
    align-items: center;
}
.rz-header > .rz-stack {
    flex: 1;
}

/* --- MudTable header cells: pale blue across the whole app. Column labels are chrome,
       not a second banner — the saturated blue stays on the panel band above them. --- */
.mud-table-head .mud-table-cell {
    background-color: var(--color-primary-50) !important;
    color: var(--color-primary-900) !important;
    font-weight: 700;
}

/* --- Conflict fix: unify the base font so Radzen & MudBlazor typography match --- */
html, body {
    font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

/* --- Conflict fix: MudBlazor's default z-index stack (popover 1200, dialog 1400, snackbar 1500)
       already sits above the Radzen shell (max z-index ~1002), so no override is needed.
       Do NOT slam .mud-overlay to a flat z-index: a MudSelect renders a transparent full-screen
       .mud-overlay (outside-click catcher) that must stay BELOW its own .mud-popover list, or
       item clicks hit the overlay, close the menu, and the value never changes. --- */

/* --- Dashboard look: light page behind white cards --- */
.rz-body {
    background-color: #f4f5fa;
}

/* --- Operational Excellence dashboard: white header band (matches the printed reference) --- */
.op-header-band {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 0.75rem 1.5rem 1rem;
    background: #ffffff;
    border-top: 1px solid #d9dee4;
    border-bottom: 2px solid #d9dee4;
    color: var(--color-text-dark);
}
/* Full title on desktop, short title on mobile (toggled in the mobile media query below). */
.op-header-title-mobile {
    display: none;
}
.op-header-titles {
    text-align: center;
}
/* --- Logo sits in the left column, in full color directly on the white band --- */
.op-header-logo img {
    display: block;
    height: 50px;
}
.op-header-title {
    font-size: 1.9rem;
    font-weight: 800;
    letter-spacing: 0.01em;
    line-height: 1.1;
    color: #44484d;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.12);  /* faint embossed look like the reference */
}
.op-header-subtitle {
    font-size: 1rem;
    font-weight: 700;
    color: #1f3a66;  /* bold navy, like the reference subtitle */
    margin-top: 2px;
}
.op-header-period {
    justify-self: end;
    text-align: center;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.25;
    color: #ffffff;
    background: linear-gradient(180deg, #9aa1a9 0%, #7d848c 100%);  /* brushed-grey badge */
    border: 1px solid #6f767e;
    border-radius: 4px;
    padding: 0.45rem 1rem;
}

/* --- Operational Excellence header: mobile layout (stacked sections, no logo, short title) --- */
@media (max-width: 768px) {
    .op-header-band {
        flex-direction: column;
        align-items: stretch;
        gap: 0.75rem;
    }
    .op-header-logo {
        display: none;   /* drop the logo on mobile */
    }
    .op-header-title-full {
        display: none;   /* hide the long title... */
    }
    .op-header-title-mobile {
        display: block;  /* ...show the short one */
        font-size: 1.3rem;
    }
    .op-header-subtitle {
        display: none;   /* drop the subtitle on mobile */
    }
    .op-header-filters {
        justify-content: center;
        flex-wrap: wrap;
    }
}

/* --- Operational Excellence: tighter, better-defined cards (scoped to this page) --- */
.op-dashboard .rz-card {
    border: 1px solid #e6e9ee;
    box-shadow: 0 1px 2px rgba(16, 24, 40, 0.06);
    padding: 1rem;
}

/* --- The filter, said once above everything and marked on each section it reaches ---
   The bar carries the chips and the Remove buttons; a section carries only a mark. Repeating the
   chips inside every card read as several filters rather than one. --- */
.op-filter-bar {
    background: #eef3ff;
    border: 1px solid #cfdcfb;
    border-radius: 6px;
    padding: 0.6rem 0.85rem;
}
.op-filter-bar__label {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-weight: 700;
    font-size: 0.82rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-primary);
}
.op-filter-bar__note {
    display: block;
    margin-top: 0.4rem;
    color: #5b6b8c;
}

/* The mark itself. Brand blue on a tint of it, so it reads as the filter rather than as a warning:
   the amber and red glyphs on these same cards mean something is wrong, and this does not. */
.op-filtered {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.35rem;
    border-radius: 50%;
    background: #dfe8fd;
    color: var(--color-primary);
    flex: none;
}
/* On a card the mark sits in the header's top-left corner, which is centred content, so it is taken
   out of the flow rather than pushing the code and name off centre. */
.op-filtered--card {
    position: absolute;
    top: 0;
    left: 0;
    margin: 4px;
}

/* --- Top KPI strip: stacked two-tier card — neutral header band (code + name) on top of a white value body --- */
.op-metric-header {
    min-height: 3.2rem;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    background: #f1f3f6;
    color: var(--color-text-dark);
    border-bottom: 1px solid #e2e6ea;
    padding: 0.45rem 0.5rem;
}
.op-metric-code {
    font-weight: 700;
    font-size: 1.05rem;
    line-height: 1.1;
    letter-spacing: 0.02em;
    color: var(--color-text-dark);
}
.op-metric-name {
    font-size: 0.68rem;
    color: #6b7280;
    line-height: 1.15;
    margin-top: 1px;
}
.op-metric-body {
    padding: 0.75rem 0.5rem;
    text-align: center;
}
.op-metric-value-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
}
.op-metric-value {
    font-size: 1.8rem;
    font-weight: 700;
    line-height: 1;
    color: var(--color-text-dark);
}
.op-metric-target {
    font-size: 0.78rem;
    color: #6b7280;
    margin-top: 0.35rem;
}

/* --- Driver section header: the pillar's score, trend and target beside the title (was a card of its own) --- */
.op-section-score {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.15rem 0.5rem;
    border-radius: 6px;
}
.op-section-score--missing {
    background: #fef2f2;
}
.op-section-score-value {
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1;
    color: var(--color-text-dark);
}
.op-section-score-target {
    font-size: 0.78rem;
    color: #6b7280;
}

/* --- Driver cards: a grid (name | current | ppt | target | weight) so every row's numbers align --- */
.op-driver-row {
    display: grid;
    grid-template-columns: 1fr 4.5rem 4.5rem 4.5rem 3.5rem 1.5rem;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0;
    border-bottom: 1px solid #eef0f3;
}
.op-driver-row:last-child {
    border-bottom: none;
}
.op-driver-head {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #6b7280;
    font-weight: 600;
    border-bottom: 1px solid #e2e6ea;
}
.op-driver-name {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--color-text-dark);
    font-size: 0.9rem;
}
.op-driver-num {
    text-align: right;
}
.op-driver-current {
    font-weight: 600;
    color: var(--color-text-dark);
}
/* Current value coloured against its target: at/above target, within 5% of it, or further off. */
.op-driver-current.op-driver-good {
    color: #16a34a;
}
.op-driver-current.op-driver-warn {
    color: #deca37;
}
.op-driver-current.op-driver-bad {
    color: #dc2626;
}
/* PPT and Target sit behind the current value: same alignment, quieter weight. */
.op-driver-sub {
    font-size: 0.82rem;
    color: #6b7280;
}
/* The between-driver rule only exists in the stacked layout; the grid uses each row's own border instead. */
.op-driver-sep {
    display: none;
}

/* --- Stacked driver rows below the Md breakpoint (960px), the way a MudTable collapses into cards on a phone.
   Six columns cannot fit a panel that is half a tablet wide, so each driver becomes a block: the name as its
   heading, then one labelled line per column, with a rule between drivers. --- */
@media screen and (max-width: 959.98px) {
    .op-driver-row {
        display: block;
        padding: 0.6rem 0;
        border-bottom: none;
    }
    /* The header keeps only its "Top N Drivers" caption: the column names now ride on each value as a data-label.
       Both classes are needed so these win over the .op-driver-row rules above. */
    .op-driver-row.op-driver-head {
        border-bottom: 1px solid #e2e6ea;
        padding-bottom: 0.4rem;
    }
    .op-driver-row.op-driver-head .op-driver-num,
    .op-driver-row.op-driver-head > span:last-child {
        display: none;
    }
    .op-driver-name {
        display: flex;
        margin-bottom: 0.35rem;
        font-weight: 600;
    }
    .op-driver-row > .op-driver-num {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 1rem;
        padding: 0.15rem 0;
    }
    .op-driver-row > .op-driver-num::before {
        content: attr(data-label);
        color: #6b7280;
        font-size: 0.72rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        font-weight: 600;
    }
    .op-driver-info {
        justify-content: flex-start;
        margin-top: 0.4rem;
    }
    .op-driver-sep {
        display: block;
        margin: 0;
    }
}
.op-driver-info {
    display: inline-flex;
    justify-content: center;
    align-items: center;
}

/* --- Site table: emphasize the GMLx Total rollup, which renders as the MudTable footer --- */
.op-site-total .mud-table-cell {
    font-weight: 700;
    background: #eef2f7 !important;
    border-top: 2px solid #d9dee4;
    color: var(--color-text-dark);
}

/* --- Site table in its grid layout. Both media queries below mirror MudBlazor's own Breakpoint.Sm boundary
       (its stacked rules live in @media(max-width: 960px)); .mud-sm-table is on the table at every width, so
       it can't be used to tell the two layouts apart.
       Eight columns have to fit the card without a horizontal scrollbar, so cells are tighter than the
       MudBlazor default: figures stay on one line and only the header labels (at their spaces, e.g.
       "Orders / day") and the site name wrap, so no word is ever broken mid-letter. --- */
@media screen and (min-width: 960.02px) {
    .op-site-table .mud-table-cell {
        padding: 4px 6px !important;
        font-size: 0.78rem;
        white-space: nowrap;
        text-align: center;
    }
    .op-site-table .mud-table-cell:first-child {
        white-space: normal;
        text-align: left;
    }
    .op-site-table .mud-table-head .mud-table-cell {
        font-size: 0.72rem;
        white-space: normal;
    }
}

/* --- Site table stacked into cards: MudBlazor hides tfoot in that layout, which would drop the GMLx Total
       from the table entirely on a phone. Show it so the rollup stacks into a final labelled card, with the
       rule above it rather than around every cell. --- */
@media screen and (max-width: 960px) {
    .op-site-table .mud-table-root .mud-table-foot {
        display: revert;
    }
    .op-site-table .op-site-total .mud-table-cell {
        border-top: none;
    }
    .op-site-table .op-site-total .mud-table-cell:first-child {
        border-top: 2px solid #d9dee4;
    }
}

/* --- Header "GMLx Central" home button: frosted-glass pill that blends into the blue bar --- */
.home-brand-btn {
    display: inline-flex;
    align-items: center;
    background: rgba(255, 255, 255, 0.15);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 8px;
    padding: 2px 14px;
    text-decoration: none !important;
    transition: background .15s ease;
}
.home-brand-btn:hover {
    background: rgba(255, 255, 255, 0.25);
}
/* Radzen puts the hover underline on a child span, not the <a>, so cover descendants too */
.home-brand-btn,
.home-brand-btn:hover,
.home-brand-btn * {
    text-decoration: none !important;
}
.home-brand-btn .rz-text-h6 {
    color: white;
}

/* --- Flat, clickable header icons --- */
.header-icon {
    cursor: pointer;
    display: inline-flex;
    color: white;
}
.header-icon:hover {
    color: grey
}
/* A header control and its MudPopover share a wrapper. The popover leaves an empty block element
   behind the control, which turns the wrapper into a text line with descender space under the
   icon and pushes it up. A flex wrapper centres the control and gives the placeholder no line. */
.header-anchor {
    position: relative;
    display: flex;
    align-items: center;
}
/* The bell's MudBadge root is inline-block, which puts the same baseline gap back under the icon. */
.header-anchor .mud-badge-root {
    display: flex;
    align-items: center;
}

/* --- Make the DataGrid grouping drag-handle (⋮) obvious: you grab THIS, not the title, to drop a column in the group panel --- */
.rz-column-drag {
    color: var(--rz-primary, #4f46e5) !important;
    opacity: 0.85;
    cursor: grab;
}
.rz-column-drag:hover {
    opacity: 1;
    background-color: var(--rz-primary-light, rgba(79, 70, 229, .12));
    border-radius: 4px;
}

a, .btn-link {
    color: #006bb7;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* --- Test-environment banner (only present when DATABASE_MODE=Test) --- */
/* Shell becomes a vertical flex box so the banner sits above the Radzen layout
   and the layout fills the remaining height. Without .test-mode this is inert,
   so production is untouched. */
.app-shell.test-mode {
    display: flex;
    flex-direction: column;
    height: 100vh;
}

.app-shell.test-mode > .rz-layout {
    height: auto;
    flex: 1 1 auto;
    min-height: 0;
}

/* --- MudDataGrid money column header (Open Orders). A header cell lays its title and its filter icon
       out with justify-content: space-between and gives the title a width:100% box, so text-align
       alone right-aligns the label against the icon rather than the column edge — leaving it a couple
       of dozen pixels adrift of the figures below. Reversing the row puts the icon first, and the
       text-align then lands the label flush right, over the numbers. Both are needed: the reversal
       moves the box, text-align moves the text inside it. --- */
.mud-table-cell.oo-money-header {
    text-align: right;
}

.oo-money-header .column-header {
    flex-direction: row-reverse;
}

/* --- MudDataGrid narrow columns (Open Orders). Aging, Open ARO $ and Division hold three digits,
       a short money figure and a two-letter code, but an auto-layout table shares the slack out
       evenly and hands each of them far more than that. width:1% collapses the column to its
       content so the width goes to Customer Name and Territory Name instead.

       nowrap keeps the title on one line: the header lays its title and its filter icon out with
       space-between and gives the title a width:100% box, so "Open ARO $" was breaking across three
       lines rather than widening its column. white-space inherits, so the title picks it up from
       the cell. --- */
.mud-table-cell.oo-tight-col {
    width: 1%;
    white-space: nowrap;
}

.test-env-banner.mud-alert {
    border-radius: 0;
    justify-content: center;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    background-color: #000;
    color: #fff;
    /* Black & white hazard-stripe top & bottom edges */
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    border-image: repeating-linear-gradient(45deg, #000 0 12px, #fff 12px 24px) 4;
}

.test-env-banner .mud-alert-message {
    width: 100%;
    text-align: center;
    color: #fff;
}

/* ── Public request form: the classes SHARED across RequestFields/ ─────────────
   Global rather than scoped because each of these is written by several components at once --
   .rq-req by the renderer, CatalogItemsField, KitFamiliesField and RequestFileField; .rq-sentinels
   by the distributor, sales rep and ship-to pickers. Blazor stamps a scoped rule with ONE
   component's attribute, so no per-component file can reach them all, and the copies that used to
   sit in PublicRequestForm.razor.css carried that page's attribute and matched nothing whatsoever.
   Anything written by exactly one component still belongs in that component's own .razor.css. */

/* The asterisk on a required question the component labels itself, rather than through a
   MudBlazor Required. */
.rq-req {
    color: var(--color-error, #E24B4A);
    margin-left: .15rem;
    font-weight: 700;
}

/* The "Request new distributor" / "Type manually" affordances under a picker. */
.rq-sentinels {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin-top: .5rem;
}

.rq-items__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

/* Catalog and lot numbers are identifiers: monospace with aligned digits, as elsewhere in the app. */
.rq-mono {
    font-family: var(--font-mono, 'Roboto Mono', ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-size: .85rem;
}

/* A wide items table must scroll inside itself rather than widening the page on a phone. */
.rq-items .mud-table-container {
    overflow-x: auto;
}

.rq-files {
    display: flex;
    flex-direction: column;
    gap: .35rem;
}