/* ================================================================
   MUDBLAZOR OVERRIDES - design-system bridge
   ----------------------------------------------------------------
   Single source of truth: branding.css (--lw-* tokens), which is
   kept in sync with ledgerwise-ui globals.css. This file wires
   MudBlazor's palette and key component surfaces to those tokens
   so that changing a --lw-* variable cascades through the whole
   app - no value is duplicated in C# that can silently drift.

   Brand role mapping (matches ledgerwise-ui post-restructure,
   commit c20e822 "restructure color token system"):

     * Semantic primary = NAVY (#020B2B = --lw-primary-dark
       = globals --primary). Drives filled primary action
       BUTTONS only - same as ledgerwise-ui's default <Button>
       (bg-primary).

     * Brand accent = BLUE (#3980A5 = --lw-primary-blue
       = globals --brand-accent). Mapped to MudBlazor
       Color.Primary, so it drives links, focus rings,
       checkboxes, switches, radios, progress, selected-state
       tints, and text/outline buttons - everywhere ledgerwise-ui
       uses --brand-accent.

   The C# theme (LedgerwiseTheme.cs) still sets Color.Primary to
   the same blue as a fallback for MudBlazor's contrast/ripple
   math; the variables below are what actually render, so the
   design system stays driven by branding.css.
   ================================================================ */

/* 1. Bridge MudBlazor's brand palette to the --lw-* design tokens.
      :root:root out-specifies MudThemeProvider's own :root block,
      so these win regardless of stylesheet injection order. */
:root:root {
    /* Color.Primary == brand accent (blue) */
    --mud-palette-primary: var(--lw-primary-blue);
    --mud-palette-primary-darken: var(--lw-primary-blue-dark);
    --mud-palette-primary-lighten: var(--lw-primary-blue-light);
    --mud-palette-primary-text: var(--lw-primary-blue-fg);

    /* Color.Secondary == brand gold */
    --mud-palette-secondary: var(--lw-primary-gold);
    --mud-palette-secondary-text: var(--lw-primary-gold-fg);

    /* Input outlines use the stronger --input alpha (0.4) from the June 2026
       restructure, distinct from the lighter hairline divider (--border, 0.2).
       Mirrors ledgerwise-ui globals --input. */
    --mud-palette-lines-inputs: var(--lw-input-border);

    /* Corner radius bridge. MudBlazor derives EVERY component's corner
       (buttons, chips, cards, inputs, menus, alerts) from this one var; it is
       NOT read from our --lw-* tokens unless wired here. Drive it from the
       design token so the 8px control radius cascades app-wide, matching
       ledgerwise-ui's rounded controls. The C# DefaultBorderRadius is only a
       fallback for MudBlazor's own injected :root and is kept matching. */
    --mud-default-borderradius: var(--lw-radius-control);

    /* Card shadow bridge. Resting elevation (1) is what MudCard and MudPaper
       use by default; mapping it to --lw-shadow-card makes every card/panel
       carry ledgerwise-ui's soft navy-tinted card shadow (its universal
       `bg-card shadow-card` treatment). The C# Shadows.Elevation[1] is the
       matching fallback. Higher elevations (menus/dialogs at 8) are unchanged. */
    --mud-elevation-1: var(--lw-shadow-card);
}

/* 2. Filled primary action buttons use the SEMANTIC primary (navy),
      matching ledgerwise-ui's default <Button> (bg-primary = navy).
      Everything else on Color.Primary keeps the blue accent from the
      palette bridge above. Scoped to MudButton's filled-primary class
      so accent chips/badges are unaffected. */
.mud-button-filled.mud-button-filled-primary {
    background-color: var(--lw-primary-dark);
    color: var(--lw-primary-dark-fg);
}

.mud-button-filled.mud-button-filled-primary:hover,
.mud-button-filled.mud-button-filled-primary:focus-visible {
    background-color: var(--lw-primary-dark-hover);
    color: var(--lw-primary-dark-fg);
}

/* 3. Global keyboard focus-visible ring (teal brand accent), mirroring
      ledgerwise-ui globals.css. Keyboard-only (not mouse). Mirrors the source's
      selector list rather than a universal `*` to avoid double-outlining
      MudBlazor inputs that draw their own focus treatment. Component-scoped
      rules (e.g. auth.css .auth-*:focus-visible) win by specificity. */
button:focus-visible,
[role="button"]:focus-visible,
a:focus-visible,
summary:focus-visible {
    outline: 2px solid var(--lw-primary-blue);
    outline-offset: 2px;
}

/* Sidebar sits on dark navy; use a light ring so it stays visible. */
.lw-nav-menu button:focus-visible,
.lw-nav-menu a:focus-visible,
[data-sidebar] button:focus-visible,
[data-sidebar] a:focus-visible {
    outline-color: rgba(255, 255, 255, 0.6);
}

/* -------------------------------------------------------------------------
   MudText / MudIcon Color.Secondary == muted GRAY body text, not gold.
   MudBlazor's `Color` enum names brand palette SLOTS; Color.Secondary is the
   gold brand accent (--mud-palette-secondary). Hundreds of call sites used it
   intending "secondary/muted text", which MudBlazor exposes only via the
   .mud-text-secondary utility (--mud-palette-text-secondary), not the enum.
   Remap the text/icon secondary-color class to the gray content token so
   captions, hints, and neutral icons read correctly. Gold brand accents on
   chips/buttons use their own classes (.mud-chip-color-secondary, button
   classes) and are intentionally unaffected -- keep using Color.Secondary
   there for a deliberate gold accent. Specificity (0,2,0) + !important beats
   MudBlazor's .mud-secondary-text (0,1,0) !important.
   ------------------------------------------------------------------------- */
.mud-typography.mud-secondary-text,
.mud-icon-root.mud-secondary-text {
    color: var(--lw-gray-graphite) !important;
    --mud-ripple-color: var(--lw-gray-graphite) !important;
}

/* -------------------------------------------------------------------------
   Form-surface dialog bodies. ledgerwise-ui gives modal/drawer bodies the
   subtle cool surface (--form-surface, #fcfdfe) while the dialog frame, the
   title row, and the actions footer stay on the white card. MudBlazor renders
   <DialogContent> as .mud-dialog-content, with .mud-dialog-title and
   .mud-dialog-actions as siblings on the white paper, so tinting only the
   content reproduces that two-tone form look across every dialog from one
   token-driven rule. Individual dialogs that need a pure-white or custom body
   (e.g. media viewers) can override .mud-dialog-content in their scoped CSS.
   ------------------------------------------------------------------------- */
.mud-dialog .mud-dialog-content {
    background-color: var(--lw-form-surface);
}

/* -------------------------------------------------------------------------
   Dialog / bottom-sheet scrim. MudBlazor's default overlay is a flat
   rgba(33,33,33,.5) with no blur; ledgerwise-app renders the SAME backdrop
   for both dialog.tsx and drawer.tsx ("bg-foreground/40 backdrop-blur-[2px]").
   Drive it from the shared tokens so every MudDialog overlay matches the
   hand-rolled sheet backdrops (.vim-backdrop, .cod-backdrop, ...) exactly.
   The scrim is what makes a bottom sheet read as a layer above the page --
   sheets only reveal a 48px strip of it, so a weak/absent dim is obvious.
   ------------------------------------------------------------------------- */
.mud-overlay .mud-overlay-scrim.mud-overlay-dark {
    background-color: var(--lw-scrim);
    border-color: var(--lw-scrim);
    backdrop-filter: var(--lw-scrim-blur);
    -webkit-backdrop-filter: var(--lw-scrim-blur);
}

/* -------------------------------------------------------------------------
   Review dialogs (ProposalReviewModal): let the dialog use nearly the full
   viewport so the tall PDF preview fits without the dialog body scrolling.
   The column and preview heights themselves are set inline in the markup (a
   viewport calc), which avoids scoped-CSS / cache pitfalls and
   percentage-height chains through MudGrid/MudItem that do not resolve.
   ------------------------------------------------------------------------- */
.mud-dialog.irm-review-dialog {
    max-height: calc(100vh - 32px);
}

/* Confirm-invoice / confirm-proposal bottom sheets (InvoiceReviewModal +
   ProposalReviewModal). Reference: ledgerwise ui-app drawer.tsx side="sheet"
   -- inset-x-0 bottom-0, height 100dvh - 48px, 12px top radius, muted shell,
   slide-in-from-bottom. The header/footer bands inside stay on the white
   card so they read as elevated. */
.mud-dialog.lw-modal.irm-sheet,
.mud-dialog.lw-modal.prm-sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100vw;
    max-width: 100vw !important;
    height: calc(100dvh - 48px);
    max-height: calc(100dvh - 48px);
    margin: 0;
    border-radius: 12px 12px 0 0;
    background: var(--lw-bg-muted);
    overflow: hidden;
    animation: lw-sheet-up 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes lw-sheet-up {
    from { transform: translateY(100%); }
    to { transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .mud-dialog.lw-modal.irm-sheet,
    .mud-dialog.lw-modal.prm-sheet { animation: none; }
}

/* The sheet header band (.irm-take-head / .prm-take-head) owns its own
   padding/border. */
.mud-dialog.lw-modal.irm-sheet .mud-dialog-title,
.mud-dialog.lw-modal.prm-sheet .mud-dialog-title {
    padding: 0;
}

/* The body is the 58/42 split over bg-muted; no dialog padding, and the
   column must be able to flex-fill the sheet height. */
.mud-dialog.lw-modal.irm-sheet .mud-dialog-content,
.mud-dialog.lw-modal.prm-sheet .mud-dialog-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    padding: 0;
    max-height: none;
    background-color: var(--lw-bg-muted);
}

/* Generic bottom-sheet dialog (lw-modal--sheet): the reference drawer.tsx
   side="sheet" geometry (inset-x-0 bottom-0, 100dvh - 48px, 12px top radius,
   slide-in-from-bottom) applied to a STANDARD lw-modal -- the panel keeps its
   form-surface tint and the LwModalHeader/Body/Footer chrome, unlike the
   bespoke irm/prm takeover shells above. Pair with lw-modal--scroll so the
   footer stays pinned and the body's inner region scrolls (give it the
   dlg-fields recipe: flex 1 1 auto / min-height 0 / overflow-y auto). */
.mud-dialog.lw-modal.lw-modal--sheet {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100vw;
    max-width: 100vw !important;
    height: calc(100dvh - 48px);
    max-height: calc(100dvh - 48px);
    margin: 0;
    border-radius: 12px 12px 0 0;
    overflow: hidden;
    animation: lw-sheet-up 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}

@media (prefers-reduced-motion: reduce) {
    .mud-dialog.lw-modal.lw-modal--sheet { animation: none; }
}

/* Full-screen takeover dialog (lw-modal--takeover): a true edge-to-edge
   workspace (reference gc-allocation-wizard.tsx) -- fills the viewport with no
   radius; header (title), content, and actions (footer) stack as a flex column
   and the content region owns the internal scroll. Used by
   AssignInvoiceToDrawRequestModal's fullscreen allocation editor. */
.mud-dialog.lw-modal.lw-modal--takeover {
    position: fixed;
    inset: 0;
    width: 100vw;
    max-width: 100vw !important;
    height: 100dvh;
    max-height: 100dvh !important;
    margin: 0;
    border-radius: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    background: #fff;
}

.mud-dialog.lw-modal.lw-modal--takeover .mud-dialog-title {
    padding: 0;
    flex: 0 0 auto;
}

.mud-dialog.lw-modal.lw-modal--takeover .mud-dialog-content {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    padding: 0;
    max-height: none;
    overflow: hidden;
    background: #fff;
}

.mud-dialog.lw-modal.lw-modal--takeover .mud-dialog-actions {
    flex: 0 0 auto;
    margin: 0;
    padding: 0;
}

/* Add-invoice review: a true full-page takeover (reference AddInvoiceDrawer
   is a fixed inset-0 portal, not a floating dialog). MudDialog snapshots its
   Class at open, so the step is detected structurally: the takeover markup
   (.aim-take) only exists during the Review step. */
.mud-dialog.aim-dialog:has(.aim-take),
.mud-dialog.asim-dialog:has(.asim-take) {
    width: 100vw;
    max-width: 100vw !important;
    height: 100vh;
    max-height: 100vh;
    margin: 0;
    border-radius: 0;
}

.mud-dialog.irm-review-dialog .mud-dialog-content {
    max-height: none;
}

/* The add-invoice review takeover owns its inset (58/42 split over bg-muted);
   the LwModalBody wrapper must not add the standard 24px dialog padding. */
.mud-dialog.aim-dialog:has(.aim-take) .lw-modal-body,
.mud-dialog.asim-dialog:has(.asim-take) .lw-modal-body {
    padding: 0;
    gap: 0;
}

/* Document search autocomplete popover: widen results beyond the input width.
   Replaces the unsupported MudAutocomplete PopoverStyle attribute (MUD0002). */
.documents-search-popover {
    width: max-content;
    min-width: 500px;
    max-width: 800px;
}

/* Inline visibility "Visible To" menu (Documents tab): the menu provides its
   own padding via .lw-vis-menu, so strip the default MudList vertical padding. */
.lw-visibility-popover .mud-list {
    padding-top: 0;
    padding-bottom: 0;
}

/* Canonical select menu chrome (.lw-select-menu) -- set by the LwSelect atom
   via PopoverClass. Source: ledgerwise-app create-fields.tsx PickerField menu
   (measured 2026-07-24): card 4px below the field, 8px radius, hairline
   border, white, card shadow, 4px vertical padding; options px-12 py-8,
   14px/20px, accent hover; selected row = accent fill. Global because
   MudPopover teleports to the provider, out of scoped-CSS reach. */
.lw-select-menu.mud-popover {
    margin-top: 4px;
    border-radius: var(--lw-radius-card);
    border: 1px solid var(--lw-border);
    background: var(--lw-white);
    box-shadow: var(--lw-shadow-card);
}

.lw-select-menu .mud-list {
    padding: 4px 0;
}

.lw-select-menu .mud-list-item {
    min-height: 0;
    height: auto;
    padding: 8px 12px;
    color: var(--lw-text-primary);
    font-family: var(--lw-font-family);
    font-size: 14px;
    line-height: 20px;
}

.lw-select-menu .mud-list-item:hover,
.lw-select-menu .mud-list-item:focus-visible,
.lw-select-menu .mud-list-item.mud-selected-item {
    background: var(--lw-accent) !important;
}

.lw-select-menu .mud-list-item .mud-typography {
    font-family: var(--lw-font-family);
    font-size: 14px;
    line-height: 20px;
}

/* Pinned action row ("+ Add New ...") -- reference PickerField footerAction:
   accent 14px/500 over a top hairline. Pass Class="lw-select-item--action"
   on the MudSelectItem. */
.lw-select-menu .mud-list-item.lw-select-item--action {
    border-top: 1px solid var(--lw-border);
    color: var(--lw-primary-blue);
    font-weight: 500;
}

.lw-select-menu .mud-list-item.lw-select-item--action .mud-typography {
    font-weight: 500;
}

/* Shared dropdown menu chrome (.lw-menu) -- pass PopoverClass="lw-menu" on a
   MudMenu. Source: ledgerwise-app ui/dropdown-menu.tsx + the project-header
   item overrides (gap-2 px-2.5 py-2, min-w-[180px]): popup rounded-lg
   (reference --radius = 4px) white surface, p-1, shadow-md + 1px
   foreground/10 ring; items 14px rounded-md (8px) with 16px
   content-secondary icons, accent hover; destructive items red with a
   destructive/10 hover. Global because MudPopover teleports to the provider,
   out of scoped-CSS reach. */
.lw-menu.mud-popover {
    border-radius: var(--lw-radius-sm);
    background: var(--lw-white);
    color: var(--lw-text-primary);
    box-shadow:
        0 0 0 1px color-mix(in srgb, var(--lw-text-primary) 10%, transparent),
        0 4px 6px -1px rgba(0, 0, 0, 0.1),
        0 2px 4px -2px rgba(0, 0, 0, 0.1);
}

.lw-menu .mud-list {
    min-width: 180px;
    padding: 4px;
}

/* MudMenu renders items as .mud-menu-item (not .mud-list-item) -- both
   aliases carry the same chrome (caught 2026-07-23: kebab menus were
   rendering raw Material despite PopoverClass="lw-menu"). */
.lw-menu .mud-list-item,
.lw-menu .mud-menu-item {
    min-height: 0;
    height: auto; /* Mud pins 44px on dense menu items */
    padding: 8px 10px;
    border-radius: var(--lw-radius-control);
    color: var(--lw-text-primary);
    font-family: var(--lw-font-family);
    font-size: 14px;
    line-height: 20px;
}

.lw-menu .mud-list-item:hover,
.lw-menu .mud-list-item:focus-visible,
.lw-menu .mud-menu-item:hover,
.lw-menu .mud-menu-item:focus-visible {
    background: var(--lw-accent);
}

.lw-menu .mud-list-item .mud-list-item-icon,
.lw-menu .mud-menu-item .mud-list-item-icon {
    min-width: 0;
    margin-inline-end: 8px;
    color: var(--lw-gray-graphite);
}

.lw-menu .mud-list-item .mud-list-item-icon .mud-icon-root,
.lw-menu .mud-list-item svg.mud-icon-root,
.lw-menu .mud-menu-item svg.mud-icon-root {
    font-size: 16px;
    width: 16px;
    height: 16px;
    color: var(--lw-gray-graphite);
}

.lw-menu .mud-list-item-text {
    margin: 0;
}

.lw-menu .mud-menu-item .mud-typography {
    font-family: var(--lw-font-family);
    font-size: 14px;
    line-height: 20px;
}

.lw-menu .mud-menu-item .mud-ripple {
    display: none;
}

.lw-menu .mud-list-item-text .mud-typography {
    font-size: 14px;
    line-height: 20px;
    letter-spacing: normal;
}

.lw-menu .mud-divider {
    margin: 4px 0;
    border-color: var(--lw-border);
}

/* Destructive item -- MudMenuItem Class="lw-menu-item--destructive". */
.lw-menu .lw-menu-item--destructive,
.lw-menu .lw-menu-item--destructive .mud-list-item-icon,
.lw-menu .lw-menu-item--destructive .mud-icon-root {
    color: var(--lw-destructive);
}

.lw-menu .lw-menu-item--destructive:hover,
.lw-menu .lw-menu-item--destructive:focus-visible {
    background: color-mix(in srgb, var(--lw-destructive) 10%, transparent);
}

/* -- Main content height chain (project detail sticky footers) ------------
   These MUST live in a global sheet: MainLayout.razor.css ::deep rules for
   .lw-main-content/.lw-content-shell never match -- MainLayout has no plain
   ancestor element above MudMainContent to carry the scope attribute, so its
   ::deep block is dead code (verified via live DOM, 2026-07-12).
   Flex column + 100vh lets pages stretch to the viewport bottom; the
   :has() clause stretches the MudContainer only on the project detail page
   (its shell pins a sticky bulk-action footer), leaving every other page's
   block layout untouched. */
.mud-main-content.lw-main-content {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.lw-content-shell:has(> .lw-project-detail-shell) {
    display: flex;
    flex-direction: column;
    flex: 1;
    width: 100%;
}
