/* ─── Design System: base-theme.css ───��──────────────────────────────
   Overrides MudBlazor defaults to match the BrandedMark design system.
   Tokens: Teal brand, warm-slate neutrals, Geist type, outline-first surfaces.
   ───────────────��─────────────────────��────────────────────────────── */

:root {
    /* Mono family for IDs, dates, numeric counts, codes. Pair with
       --mud-typography-*-size for sizing. */
    --bm-mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
}

/* ─── Page gutters follow the theme's spacing scale ───────────────
   MudContainer's gutters are MudBlazor's own 16px / 24px (≥600px). They are re-pointed so page
   content stays aligned with the app bar and context bar, whose gutters read the same rungs. */
.mud-container--gutters {
    padding-left: var(--bm-spacing-lg);
    padding-right: var(--bm-spacing-lg);
}

@media (min-width: 600px) {
    .mud-container--gutters {
        padding-left: var(--bm-spacing-xl);
        padding-right: var(--bm-spacing-xl);
    }
}

.mud-button-outlined-default {
    border-color: var(--mud-palette-gray-light) !important;
}

/* Disable upper case for tabs. */
.mud-tab {
    text-transform: none !important;
}

/* ─── Chips: pill-shaped, unified status system ───────────────── */
.mud-chip {
    border-radius: 999px !important;
    letter-spacing: -0.005em;
}

.mud-chip.mud-chip-size-small {
    height: 22px;
    font-size: 12px;
    font-weight: 500;
}

.mud-chip.mud-chip-size-medium {
    height: 26px;
    font-size: 12.5px;
    font-weight: 500;
}

/* Status pill that is not a MudChip: a bordered, tinted badge that sits inline inside a table
   cell, a drawer header or a document row without MudChip's margins and ripple. Global rather
   than scoped because three unrelated surfaces render it and a scoped copy is reachable from
   none of the others. */
.bm-chip {
    display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 8px;
    border-radius: 999px; font-size: 11.5px; font-weight: 600; width: fit-content;
    white-space: nowrap;
    background: var(--mud-palette-background-gray); color: var(--mud-palette-text-primary);
    border: 1px solid var(--mud-palette-lines-default);
}

.bm-chip-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--mud-palette-text-secondary); flex-shrink: 0; }
.bm-chip .mud-icon-root { font-size: 13px; }

.bm-chip-success { background: rgba(var(--mud-palette-success-rgb), .14); color: var(--mud-palette-success-darken); border-color: rgba(var(--mud-palette-success-rgb), .30); }
.bm-chip-success .bm-chip-dot { background: var(--mud-palette-success); }
.bm-chip-warning { background: rgba(var(--mud-palette-warning-rgb), .14); color: var(--mud-palette-warning-darken); border-color: rgba(var(--mud-palette-warning-rgb), .30); }
.bm-chip-warning .bm-chip-dot { background: var(--mud-palette-warning); }
.bm-chip-danger { background: rgba(var(--mud-palette-error-rgb), .14); color: var(--mud-palette-error-darken); border-color: rgba(var(--mud-palette-error-rgb), .30); }
.bm-chip-danger .bm-chip-dot { background: var(--mud-palette-error); }
.bm-chip-info { background: rgba(var(--mud-palette-info-rgb), .14); color: var(--mud-palette-info-darken); border-color: rgba(var(--mud-palette-info-rgb), .30); }
.bm-chip-info .bm-chip-dot { background: var(--mud-palette-info); }
.bm-chip-brand { background: rgba(var(--mud-palette-primary-rgb), .12); color: var(--mud-palette-primary-darken); border-color: rgba(var(--mud-palette-primary-rgb), .28); }
.bm-chip-brand .bm-chip-dot { background: var(--mud-palette-primary); }

/* Tooltip: repoint off the inverted gray-darker onto the Dark/DarkContrastText pair (dark mode contrast). */
.mud-tooltip.mud-tooltip-default {
    background-color: var(--mud-palette-dark);
    color: var(--mud-palette-dark-text);
}

.mud-tooltip.mud-tooltip-default.mud-tooltip-arrow::after {
    border-color: var(--mud-palette-dark) rgba(0, 0, 0, 0) rgba(0, 0, 0, 0) rgba(0, 0, 0, 0);
}

/* ─── Cards: outline-first, reduced shadow noise ─────────────── */
.mud-paper.mud-elevation-1 {
    box-shadow: 0 1px 2px rgba(16,17,28,.04), 0 0 0 1px rgba(16,17,28,.06) !important;
}

.mud-paper-outlined {
    border-color: var(--mud-palette-lines-default, #E2E2E8) !important;
}

/* ─── Global search bar ──────────────────────────────────────── */
/* Topbar trigger that opens the unified search/command palette (GlobalSearchComponent).
   Colors derive from the appbar palette slots — the "App bar background/text" tokens the
   theme editor exposes — NOT the gray ramp or body-text slots: the gray ramp isn't
   tokenized, so tenant themes saved without BrandedMark's gray overrides carry MudBlazor's
   light-mode grays in their dark palette, which made the trigger glow against a dark appbar. */
.bm-search-trigger {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    max-width: 520px;
    height: 38px;
    padding: 0 10px 0 12px;
    background: color-mix(in srgb, var(--mud-palette-appbar-text) 12%, var(--mud-palette-appbar-background));
    border: 1px solid color-mix(in srgb, var(--mud-palette-appbar-text) 18%, transparent);
    border-radius: var(--mud-default-borderradius);
    color: color-mix(in srgb, var(--mud-palette-appbar-text) 62%, transparent);
    cursor: pointer;
    font-family: inherit;
    font-size: 0.8125rem;
    transition: border-color .12s, background-color .12s;
}

.bm-search-trigger:hover {
    border-color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-appbar-text) 18%, var(--mud-palette-appbar-background));
}

.bm-search-trigger-icon {
    color: color-mix(in srgb, var(--mud-palette-appbar-text) 78%, transparent);
    flex-shrink: 0;
}

.bm-search-trigger-text {
    flex: 1;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bm-search-trigger-kbd {
    flex-shrink: 0;
    font-family: var(--mud-typography-monospace-family, monospace);
    font-size: 0.6875rem;
    color: color-mix(in srgb, var(--mud-palette-appbar-text) 78%, transparent);
    border: 1px solid color-mix(in srgb, var(--mud-palette-appbar-text) 22%, transparent);
    border-radius: 5px;
    padding: 1px 6px;
    background: color-mix(in srgb, var(--mud-palette-appbar-text) 8%, var(--mud-palette-appbar-background));
}

/* The app bar's narrowest tier (see .bm-appbar-inner in AppLayout.razor.css): the trigger folds to
   its icon rather than pushing the profile chip under a docked help rail. Its wrapper follows only
   while it holds the trigger — the unsaved-changes bar takes the same slot and keeps its width. */
@container bm-appbar (max-width: 559.98px) {
    .bm-appbar-inner .bm-appbar-search:has(> .bm-search-trigger) {
        flex: 0 0 auto;
        min-width: 0;
        max-width: none;
        margin-right: 0;
    }

    .bm-search-trigger {
        width: 38px;
        padding: 0;
        justify-content: center;
    }

    .bm-search-trigger-text,
    .bm-search-trigger-kbd {
        display: none;
    }
}

/* UnifiedSearchPalette dialog container overrides. These size MudDialog's own element, which lives
   outside the palette component's CSS-isolation scope (and is an ancestor of the scoped content, so
   ::deep can't reach it), so they're global. The rest of the palette's styling is scoped in
   UnifiedSearchPalette.razor.css. */
.usp-dialog .mud-dialog {
    max-width: 640px;
    width: 640px;
    margin-top: 72px !important;
    border-radius: 16px !important;
}

.usp-dialog .mud-dialog-content {
    padding: 0 !important;
}

.app-search-bar .mud-input {
    height: 42px;
}

.app-search-bar.mud-input-control {
    background-color: var(--mud-palette-gray-lighter);
    margin-bottom: 5px;
    height: 42px;
    border-radius: var(--mud-default-borderradius);
}

.app-search-bar .mud-input.mud-input-outlined .mud-input-outlined-border {
    border: none;
    border-radius: var(--mud-default-borderradius);
}

.search-item-text-container {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* ─── Select Components ──────────────────────────────────���───── */
.bm-select {
    gap: 10px;
}

.bm-select > a {
    height: 45px;
    width: 80px;
    margin: 32px 0 0 0;
}

.bm-blob-img-td {
    width: 100%;
    display: inline-flex;
    justify-content: center;
}

.edit-content-drawer {
    width: 600px !important;
}

/* ─── Focus ring: brand teal ─────────────────────────────���───── */
.mud-input-outlined:focus-within .mud-input-outlined-border {
    border-color: var(--mud-palette-primary) !important;
}

/* ─── Notification bell badge ─────────────────────────────────────
   MudBadge's default overlap offset (top/right: -8px) sits the count on the
   icon-button's outer corner — floating above the appbar, detached from the
   bell glyph. Pull it in to hug the glyph's top-right corner (the glyph sits
   ~12px inside the 48px button), matching a conventional notification badge. */
.bm-appbar-actions .mud-badge.mud-badge-overlap {
    top: 3px !important;
    right: 3px !important;
}

/* ─── Sidebar / Drawer ──────────────────────────────────────────── */
.mud-drawer {
    border-right: 1px solid var(--mud-palette-lines-default) !important;
    box-shadow: none !important;
}

.bm-sidebar.mud-drawer {
    overflow-y: hidden !important;
}

/* Lock background scroll while the drawer is shown as a temporary overlay.
   .bm-layout-overlay is applied to .mud-layout by AppLayout when the drawer
   is open in temporary mode; :has() lets us lock the html/body scroll
   without touching JS. */
html:has(.bm-layout-overlay),
html:has(.bm-layout-overlay) body {
    overflow: hidden;
    touch-action: none;
}

/* ─── App bar: flat, border-separated ───────────────────────────── */
.mud-appbar {
    box-shadow: none !important;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* ─── Focused editor (Label Designer): full-bleed app bar ───────────
   AppLayout adds .bm-focused-editor to the MudLayout root for focused-editor
   routes, where the nav drawer is hidden. Reclaim the full viewport width and
   strip the left insets MudBlazor leaves on the app bar — the drawer-width
   margin and the toolbar gutter — plus the app-bar row's own left padding, so
   the exit panel sits flush in the corner like the settings sidebar header.
   These live here (global) rather than in AppLayout.razor.css because they
   target child-component elements that don't carry the scoped isolation
   attribute. */
.bm-focused-editor .mud-appbar {
    margin-left: 0 !important;
    width: 100% !important;
}

.bm-focused-editor .bm-appbar > .mud-toolbar {
    padding-left: 0 !important;
}

.bm-focused-editor .bm-appbar-inner {
    padding-left: 0 !important;
}

/* ─── List search in context bar ─────────────────────────────────── */
.bm-list-search {
    width: 420px;
    min-width: 280px;
}

/* ─── Profile menu dropdown: rounded, elevated ──────────────────── */
.mud-menu .mud-popover .mud-paper {
    border-radius: 12px;
    overflow: hidden;
}

/* ─── Drop-zone file input: hidden visually, kept in DOM so the
       wrapper paper acts as a click+drop target. Replaces the
       MudFileUpload InputStyle="opacity:0" usage deprecated in
       MudBlazor 9.x. ──────────────────────────────────────────────── */
.bm-input-hidden {
    opacity: 0;
}

/* ─── Presentation utilities ─────────────────────────────────────
       Lift inline `Style="cursor:…"` / `Style="opacity:…"` onto
       reusable classes so hover/focus pseudo-states stay reachable and
       MudBlazor theming is respected. Toggle via `Class="..."` rather
       than inline `Style`. Enforced by the
       blazor.inline-style-presentation semantic-review invariant. */
.bm-clickable {
    cursor: pointer;
}

/* De-emphasised text / icons (captions, secondary metadata). */
.bm-muted {
    opacity: 0.6;
}

/* Decorative / watermark icons sitting behind content. */
.bm-faint {
    opacity: 0.2;
}

/* Elements only meaningful on touch devices (phones/tablets) — e.g. "Take photo"
   camera-capture buttons, where desktop browsers ignore the `capture` attribute and the
   button would just duplicate the file picker. Hidden when the primary pointer is a
   mouse/trackpad (fine) or absent (none). */
@media (pointer: fine), (pointer: none) {
    .bm-touch-only {
        display: none !important;
    }
}

/* Inverse of bm-touch-only: elements replaced by a touch-specific variant on phones/tablets
   (e.g. the picker-only button a camera-primary layout supersedes). */
@media (pointer: coarse) {
    .bm-pointer-only {
        display: none !important;
    }
}

/* Keyboard-navigated list-row highlight (↑/↓/j/k on list pages). Applied to the row via
   MudDataGrid's RowClassFunc — theme-aware so it reads in light and dark, and an inset
   left-edge bar marks the active row. Overrides striped-row cell backgrounds. */
.bm-row-highlighted td {
    background-color: var(--mud-palette-primary-hover) !important;
}

.bm-row-highlighted td:first-child {
    box-shadow: inset 3px 0 0 0 var(--mud-palette-primary);
}

/* Selected-row highlight for picker tables (person/company search panels). Applied to the
   row via MudTable's RowClassFunc; overrides striped/hover cell backgrounds. */
.bm-row-selected td {
    background-color: var(--mud-palette-primary-lighten) !important;
}

/* ─── Reusable application banner (AppBanner) ───────────────────────
   A full-width bar pinned to the very top of the viewport. The app shell is pushed below it by the
   `:has()` rules further down (Stripe-style — the banner is never overlaid, content always sits
   below it). Reusable for any persistent app-wide notice; the sandbox/test-environment notice and
   the staff second-factor notice are the consumers. */
:root {
    --bm-banner-height: 40px;
    /* How far the shell is pushed down. Its own variable because two banners can be live at once —
       the sandbox notice and the staff second-factor notice are independent facts — and the offset
       then doubles while each banner keeps its height. */
    --bm-banner-offset: var(--bm-banner-height);
}

.bm-app-banner ~ .bm-app-banner {
    top: var(--bm-banner-height);
}

body:has(.bm-app-banner ~ .bm-app-banner) {
    --bm-banner-offset: calc(var(--bm-banner-height) * 2);
}

.bm-app-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--bm-banner-height);
    z-index: 1401; /* above MudAppBar + drawer so it stays visible */
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 var(--bm-spacing-lg);
    color: #fff;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.4;
}

.bm-app-banner-content {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bm-app-banner-actions {
    flex: 0 0 auto;
}

.bm-app-banner-icon,
.bm-app-banner-btn {
    color: #fff;
}

.bm-app-banner--warning { background-color: #b45309; }
.bm-app-banner--info    { background-color: #1f3a4f; }
.bm-app-banner--error   { background-color: #b00020; }
.bm-app-banner--success { background-color: #1f8a3a; }

/* Push the whole shell below the banner whenever one is present (the banner is rendered above every
   layout, so `:has()` — already used for the drawer overlay above — drives the offset rather than a
   per-layout class). `!important` beats MudBlazor's `.mud-appbar-fixed-top { top: 0 }`. The rules are
   scoped per layout so the standard shell (.mud-layout) and the full-screen designer
   (.designer-fullscreen, its own fixed root) each shift correctly and never double-offset. */
body:has(.bm-app-banner) .mud-layout .mud-appbar {
    top: var(--bm-banner-offset) !important;
}

body:has(.bm-app-banner) .mud-layout .mud-drawer {
    top: var(--bm-banner-offset) !important;
    height: calc(100% - var(--bm-banner-offset)) !important;
}

body:has(.bm-app-banner) .mud-layout .mud-main-content {
    margin-top: var(--bm-banner-offset);
}

/* Experience designer: a bespoke fixed full-screen root (DesignerLayout), no MudLayout shell. Its own
   app bar lives inside this root, so shifting the whole root down (and trimming its height) is enough. */
body:has(.bm-app-banner) .designer-fullscreen {
    top: var(--bm-banner-offset) !important;
    height: calc(100vh - var(--bm-banner-offset)) !important;
}

/* Elements pinned BELOW the standard MudAppBar via `top: app-bar height` — the sticky Tier-2 context
   bar (normal pages) and the label designer's fixed shell. The app bar is itself shifted down by the
   banner, so their top must clear both. */
body:has(.bm-app-banner) .bm-context-bar,
body:has(.bm-app-banner) .label-designer-shell,
body:has(.bm-app-banner) .label-designer-loading {
    top: calc(var(--mud-appbar-height, 60px) + var(--bm-banner-offset)) !important;
}

/* ─── Detail page layout: main column + sticky "on this page" / readiness rail ─────────
   Shared by the product editor (ProductDetailComponent) and Recalls (RecallDetailPage).
   The rail pins below BOTH the fixed app bar AND the sticky context bar, plus a 16px gap;
   without clearing the context bar the rail's header slides underneath it. Rail width is
   per-page via --bm-detail-rail-width (236px scrollspy default; Recalls sets 320px).

   --bm-context-bar-height is the single source for PageContextBar's rendered height
   (Shared/PageContextBar.razor[.css], itself `position: sticky; top: var(--mud-appbar-height)`):
   the h5 title + body2 subtitle (53px) plus its --bm-spacing-md padding above and below, at the
   ≥lg widths where the rail shows. If PageContextBar's typography/padding changes, update this
   one token — both the rail's sticky top and the section scroll-margin-top derive from it via
   --bm-detail-rail-top. Declared here because scoped CSS cannot write to :root. */
:root {
    --bm-context-bar-height: calc(53px + 2 * var(--bm-spacing-md));
    --bm-detail-rail-top: calc(var(--mud-appbar-height, 64px) + var(--bm-context-bar-height) + 16px);
}

body:has(.bm-app-banner) {
    /* The app bar is shifted down by the banner, so the rail must clear it too. */
    --bm-detail-rail-top: calc(var(--mud-appbar-height, 64px) + var(--bm-banner-offset) + var(--bm-context-bar-height) + 16px);
}

.bm-detail-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--bm-detail-rail-width, 236px);
    gap: var(--bm-spacing-xl);
    align-items: start;
}

.bm-detail-main {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--bm-spacing-lg);
}

.bm-detail-rail {
    position: sticky;
    top: var(--bm-detail-rail-top);
}

/* Anchor jumps land below the app bar + context bar, not tucked under them. */
.bm-detail-section {
    scroll-margin-top: var(--bm-detail-rail-top);
}

@media (max-width: 1279px) {
    .bm-detail-grid {
        grid-template-columns: 1fr;
    }

    .bm-detail-rail {
        position: static;
    }
}

/* Semibold weight for section headings / table cell titles (replaces inline
   Style="font-weight:600"). */
.bm-semibold {
    font-weight: 600;
}

/* Monospace for IDs, serials, codes, dates (pair with Typo.caption). */
.bm-mono {
    font-family: var(--bm-mono);
}

/* An input's Class lands on the whole control, so bm-mono would set its helper text and counter
   in mono too; this sets only what is typed. */
.bm-mono-input input,
.bm-mono-input textarea {
    font-family: var(--bm-mono);
}

/* MudBlazor's own asterisk on a required input's label, without its Required, which refuses a blank
   answer on blur: a passport answer left blank is reported, never refused. On any wrapper, since a
   picker's Class lands outside the input it draws. */
.bm-required .mud-input-label::after {
    content: "*";
}

/* MudBlazor puts an input's counter beside its helper text with nothing stopping it shrinking, so
   a helper of more than a line breaks "0 / 30" over two. */
.mud-input-helper-text > .ms-auto {
    flex-shrink: 0;
    white-space: nowrap;
    padding-inline-start: 8px;
}

/* Tonal surface (tenant cards, summary panels): soft gray fill with rounded
   corners. Pair with MudPaper Elevation="0". */
.bm-tonal {
    background-color: var(--mud-palette-background-gray);
    border-radius: 8px;
}

/* Rounder bm-tonal variant for footer / hero cards. */
.bm-tonal-lg {
    border-radius: var(--bm-radius-lg);
}

/* Fixed-width inline filter inputs in list/grid toolbars. */
.bm-search-field {
    min-width: 200px;
    max-width: 320px;
}

.bm-filter-select {
    min-width: 180px;
    max-width: 280px;
}

.bm-filter-select-sm {
    max-width: 140px;
}

/* Preserve newlines/whitespace in rendered text (e.g. AI answer suggestions). */
.bm-prewrap {
    white-space: pre-wrap;
}

/* Wrap an unbroken string (an API key, a URL) rather than let it widen its container. Global
   because it lands on MudBlazor components, which a scoped rule cannot reach. */
.bm-breakable {
    overflow-wrap: anywhere;
}

/* Container for MarkdownRenderer output (e.g. the Knowledge answer preview). */
.bm-markdown-preview {
    font-size: 0.88rem;
    line-height: 1.6;
}
