/* /Components/Layout/MainLayout.razor.rz.scp.css */
#blazor-error-ui[b-ixllurku4p] {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-ixllurku4p] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-5tlck5nvpx],
.components-reconnect-repeated-attempt-visible[b-5tlck5nvpx],
.components-reconnect-failed-visible[b-5tlck5nvpx],
.components-pause-visible[b-5tlck5nvpx],
.components-resume-failed-visible[b-5tlck5nvpx],
.components-rejoining-animation[b-5tlck5nvpx] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-5tlck5nvpx],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-5tlck5nvpx],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-5tlck5nvpx],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-5tlck5nvpx],
#components-reconnect-modal.components-reconnect-retrying[b-5tlck5nvpx],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-5tlck5nvpx],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-5tlck5nvpx],
#components-reconnect-modal.components-reconnect-failed[b-5tlck5nvpx],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-5tlck5nvpx] {
    display: block;
}


#components-reconnect-modal[b-5tlck5nvpx] {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-5tlck5nvpx 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-5tlck5nvpx 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-5tlck5nvpx 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-5tlck5nvpx]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-5tlck5nvpx 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-5tlck5nvpx {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-5tlck5nvpx {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-5tlck5nvpx {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-5tlck5nvpx] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-5tlck5nvpx] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-5tlck5nvpx] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-5tlck5nvpx] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-5tlck5nvpx] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-5tlck5nvpx] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-5tlck5nvpx] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-5tlck5nvpx 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-5tlck5nvpx] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-5tlck5nvpx {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}

/* PBI 175 — dark treatment. The reconnect dialog is chrome the user only ever sees when something
   has gone wrong, so a white card flashing over a dark app reads as a second failure rather than a
   status message. Ancestor selector works here exactly as the light rules above do: scoped CSS
   appends its [b-*] attribute to the subject, not to the ancestor. */
html[data-theme="dark"] #components-reconnect-modal[b-5tlck5nvpx] {
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.6);
}

html[data-theme="dark"] #components-reconnect-modal button[b-5tlck5nvpx] {
    background-color: var(--mud-palette-primary);
    /* The dark palette's primary is a bright cyan, so the label has to go dark to stay legible. */
    color: #0E1B21;
}

html[data-theme="dark"] #components-reconnect-modal button:hover[b-5tlck5nvpx] {
    background-color: var(--mud-palette-primary-darken);
}

html[data-theme="dark"] .components-rejoining-animation div[b-5tlck5nvpx] {
    border-color: var(--mud-palette-primary);
}
/* /Components/Layout/TabStrip.razor.rz.scp.css */
.tab-strip[b-kzdcn4h33f] {
    display: flex;
    align-items: stretch;
    width: 100%;
    background: var(--mud-palette-background-grey);
    border-bottom: 1px solid var(--mud-palette-lines-default);
    user-select: none;
}

.tab-strip-scroller[b-kzdcn4h33f] {
    display: flex;
    flex: 1 1 auto;
    align-items: flex-end;
    gap: 4px;
    padding: 6px 12px 0 12px;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: thin;
}

.tab-strip-scroller[b-kzdcn4h33f]::-webkit-scrollbar {
    height: 4px;
}

.tab-strip-scroller[b-kzdcn4h33f]::-webkit-scrollbar-thumb {
    background: var(--mud-palette-lines-default);
    border-radius: 2px;
}

.tab-strip-tab[b-kzdcn4h33f] {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    width: 220px;
    height: 52px;
    padding: 6px 8px 6px 12px;
    border-radius: 10px 10px 0 0;
    border: 1px solid var(--mud-palette-lines-default);
    border-bottom: none;
    cursor: pointer;
    background: var(--mud-palette-background);
    color: var(--mud-palette-text-secondary);
    transition: background-color 100ms ease, color 100ms ease, transform 100ms ease;
    position: relative;
    overflow: hidden;
}

.tab-strip-tab:hover[b-kzdcn4h33f] {
    background: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

.tab-strip-tab-active[b-kzdcn4h33f] {
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    margin-bottom: -1px;
    box-shadow: 0 -1px 0 var(--mud-palette-surface);
}

.tab-strip-tab-active[b-kzdcn4h33f]::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: var(--mud-palette-primary);
    border-radius: 10px 10px 0 0;
}

.tab-strip-tab-icon[b-kzdcn4h33f] {
    flex: 0 0 auto;
    margin-right: 8px;
    color: var(--mud-palette-text-secondary);
}

.tab-strip-tab-active .tab-strip-tab-icon[b-kzdcn4h33f] {
    color: var(--mud-palette-primary);
}

.tab-strip-tab-content[b-kzdcn4h33f] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    line-height: 1.2;
}

.tab-strip-tab-title[b-kzdcn4h33f] {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.85rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tab-strip-tab-active .tab-strip-tab-title[b-kzdcn4h33f] {
    font-weight: 600;
}

.tab-strip-tab-label[b-kzdcn4h33f] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1 1 auto;
    min-width: 0;
}

.tab-strip-tab-subtitle[b-kzdcn4h33f] {
    font-size: 0.7rem;
    color: var(--mud-palette-text-disabled);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-top: 2px;
}

.tab-strip-tab-active .tab-strip-tab-subtitle[b-kzdcn4h33f] {
    color: var(--mud-palette-text-secondary);
}

.tab-strip-close[b-kzdcn4h33f] {
    flex: 0 0 auto;
    margin-left: 6px;
    border: none;
    background: transparent;
    cursor: pointer;
    padding: 3px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--mud-palette-text-secondary);
    opacity: 0;
    transition: opacity 100ms ease, background-color 100ms ease;
}

.tab-strip-tab:hover .tab-strip-close[b-kzdcn4h33f],
.tab-strip-tab-active .tab-strip-close[b-kzdcn4h33f] {
    opacity: 1;
}

.tab-strip-close:hover[b-kzdcn4h33f] {
    background: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

.tab-strip-dirty-dot[b-kzdcn4h33f] {
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--mud-palette-warning);
    box-shadow: 0 0 0 2px var(--mud-palette-background);
}

.tab-strip-tab-active .tab-strip-dirty-dot[b-kzdcn4h33f] {
    box-shadow: 0 0 0 2px var(--mud-palette-surface);
}

.tab-strip-tab-dragging[b-kzdcn4h33f] {
    opacity: 0.5;
}

/* While any tab is being dragged, suppress pointer events on all descendants so dragover always
   fires on the outer .tab-strip-tab — letting OffsetX be measured against the full 220px tab
   body. Child combinator (> *) would miss grandchildren (MudIcon SVG, label spans), and
   exempting .tab-strip-close would route events to its ~24px box and break the left/right-half
   placement at the right edge of every tab. The close button can't usefully accept clicks mid-
   drag anyway, so blanket suppression is correct. */
.tab-strip-drag-in-progress *[b-kzdcn4h33f] {
    pointer-events: none;
}

.tab-strip-drop-indicator[b-kzdcn4h33f] {
    flex: 0 0 auto;
    align-self: stretch;
    width: 2px;
    margin: 6px 0 0 0;
    background: var(--mud-palette-primary);
    border-radius: 1px;
    pointer-events: none;
}

/* Bug 245 — "all open tabs" overflow control. The button and click-away overlay render inline in
   this component, so they're styled here (scoped). The dropdown popover is teleported to the page
   root via MudPopoverProvider, so its content is styled globally in wwwroot/app.css
   (.tab-strip-overflow-popover and its children). */
.tab-strip-overflow[b-kzdcn4h33f] {
    position: relative;
    flex: 0 0 auto;
    display: flex;
    align-items: flex-end;
    padding: 6px 8px 0 4px;
}

.tab-strip-overflow-btn[b-kzdcn4h33f] {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    height: 40px;
    padding: 0 8px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    background: var(--mud-palette-background);
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
    transition: background-color 100ms ease, color 100ms ease;
}

.tab-strip-overflow-btn:hover[b-kzdcn4h33f],
.tab-strip-overflow-btn-open[b-kzdcn4h33f] {
    background: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

.tab-strip-overflow-count[b-kzdcn4h33f] {
    font-size: 0.78rem;
    font-weight: 600;
    min-width: 14px;
    text-align: center;
}

/* Sits just below --mud-palette-popover z-index (--mud-zindex-popover = 1200) and above page
   content, so a click outside the popover closes it. Same idiom as StatusBadgeSelect.razor. */
.tab-strip-overflow-overlay[b-kzdcn4h33f] {
    position: fixed;
    inset: 0;
    z-index: 1199;
}

@media (max-width: 768px) {
    .tab-strip[b-kzdcn4h33f] {
        display: none;
    }
}
/* /Components/Pages/DirectLicensing/PublisherOwnershipSplits.razor.rz.scp.css */
/* PBI 464 — publisher ownership splits, rendered as a compact text list among the song's composition
   facts. The visual language here is intentionally the opposite of the PUB/MAS request-coverage bars
   sitting in the right-hand column of the same card: no bar, no fill, no side colors — just names and
   aligned figures. That contrast is what keeps an agent from reading ownership as coverage. */

.dl-ownership-splits__rows[b-rwu8c9kpaf] {
    /* Constrained so the name/percentage pairs stay a tidy adjacent column. The parent facts column is
       flex: 1 and can be very wide; without this the percentages would drift far from the publisher
       names and stop scanning as a list. */
    max-width: 320px;

    /* Subtle rule tying the rows together as one group, and setting them in from the "Composed by /
       Published by" lines above so the block reads as a nested detail of the composition. */
    border-left: 2px solid var(--mud-palette-lines-default);
    padding-left: 8px;
}

.dl-ownership-splits__row[b-rwu8c9kpaf] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    line-height: 1.5;
}

.dl-ownership-splits__pct[b-rwu8c9kpaf] {
    /* Tabular figures + fixed width + right alignment: the decimal points line up down the column, so
       66.65 / 33.35 can be eyeballed as summing to 100 without reading digit by digit. */
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
    min-width: 62px;
    text-align: right;
    flex: 0 0 auto;
    font-size: 0.75rem;
    color: var(--mud-palette-text-primary);
}

.dl-ownership-splits__total[b-rwu8c9kpaf] {
    /* Only rendered when the splits don't sum to 100%. Separated by a hairline so it reads as a
       conclusion about the rows above rather than another publisher row. */
    margin-top: 2px;
    padding-top: 2px;
    border-top: 1px solid var(--mud-palette-lines-default);
}
/* /Components/Pages/DirectLicensing/SongEditDialog.razor.rz.scp.css */
/* PBI 386 — the Recent Changes table in the song editor.

   The table has no Height of its own, so the dialog is the only thing that scrolls: a table with its own
   scrollbar nested inside the dialog's means the wheel moves whichever of the two the pointer happens to
   be over, which is never reliably the one the agent meant.

   Losing MudTable's FixedHeader would normally lose the header on the way down, so it is made sticky
   instead. sticky anchors to the nearest scrolling ancestor, which without an inner scroller is the
   dialog — so the header follows the reader without a second scrollbar. The explicit background stops the
   striped rows showing through it.

   ::deep because MudTable renders the table, and a child component's elements do not carry this
   component's CSS-isolation scope attribute. */
[b-e5hl8ulbni] .song-edit-history thead th {
    position: sticky;
    top: 0;
    z-index: 3;
    background-color: var(--mud-palette-surface);
}

/* Change values are prose (a 225-character publisher list is normal here), so they wrap rather than
   forcing the table wider than the dialog. */
[b-e5hl8ulbni] .song-edit-history td {
    white-space: normal;
    overflow-wrap: break-word;
    vertical-align: top;
}
/* /Components/Pages/DirectLicensing/SongSearchDialog.razor.rz.scp.css */
/* PBI 386 — layout for the candidate results table.

   ::deep is required throughout: the table is rendered by MudTable, a child component, so its elements do
   not carry this component's CSS-isolation scope attribute. The scope lands on the wrapping div in this
   component's own markup, and ::deep reaches through to the table inside it. */

/* table-layout: fixed is what removes the horizontal scrollbar. Without it the browser widens columns to
   fit their content, the table grows past 2000px, and the agent has to scroll sideways to reach the codes
   — which on a maximised Chrome window at 1920x1080 means the right-hand half of the row is never visible
   at rest. Fixed layout makes the th widths authoritative and scales them down proportionally when their
   sum exceeds the dialog, so the whole row always fits whatever width is available. */
.song-search-results[b-gwm1q83coy]  table {
    table-layout: fixed;
    width: 100%;
}

/* Cells WRAP. Nothing is hidden behind a hover.

   The earlier version clipped to an ellipsis to keep rows at 45px, on the reasoning that the full value
   was one hover away. That was the wrong trade for this screen: an agent comparing thirty candidates is
   reading composer and publisher strings against each other, and a comparison you can only make one
   tooltip at a time is not a comparison. Taller rows and fewer of them at once is the right price.

   break-word, NOT anywhere. The two look interchangeable and are not: `anywhere` also lets a column
   shrink below its longest word, so it broke words mid-letter even where there was room — the button read
   "Ma/tc/h", the title "Summ/ertim/e", and a link count of 831 came out as three stacked digits.
   break-word only breaks a word that cannot fit its line on its own, which is the intent: wrap at spaces,
   split a 40-character publisher name as a last resort.

   vertical-align: top so a two-line cell lines up with a ten-line one beside it. */
.song-search-results[b-gwm1q83coy]  td {
    white-space: normal;
    overflow-wrap: break-word;
    vertical-align: top;
}

/* The action button, the qualification badge and the tick columns hold controls and single characters,
   never prose. Wrapping them only ever produces the "Ma/tc/h" failure above. */
.song-search-results[b-gwm1q83coy]  td:nth-child(1),
.song-search-results[b-gwm1q83coy]  td:nth-child(2),
.song-search-results[b-gwm1q83coy]  td.mark-cell {
    white-space: nowrap;
}

/* !important is load-bearing here, not laziness. MudBlazor's own cell rule sets ~41px of horizontal
   padding per cell with a selector this file cannot outrank, and at these column widths that padding was
   eating most of the column: a 94px Composers column had 53px of content left, about seven characters, so
   every word broke mid-letter no matter which overflow-wrap keyword was used. Measured, not inferred.
   Cutting the padding returns roughly 30px of text width per column, which is what makes wrapped prose
   legible without adding a horizontal scrollbar. An earlier pass tried the same override on font-size and
   dropped it as cosmetic; it is back, just below, because the two sizes it would have reconciled turned
   out to be visibly inconsistent from column to column. */
.song-search-results[b-gwm1q83coy]  td,
.song-search-results[b-gwm1q83coy]  th {
    padding-left: 5px !important;
    padding-right: 5px !important;
}

/* One font size for every column.

   Before this, a column's size depended on how its cell happened to be built. The plain-text columns —
   Alternate Titles, Composers, Arrangers, Artists, Publishers, Catalog, the copyright years and the whole
   tick band — inherited MudBlazor's 0.875rem body-cell size. The four whose cells wrap a MudText or
   MudLink instead (SongID, Title, Links, GoThrough) rendered at Typo.caption's 0.75rem. Reading across one
   row meant reading across two type sizes, which is what it looked like.

   Unified on the smaller of the two, not the larger. This table puts 27 columns of wrapping prose inside a
   dialog, so the extra characters per line shorten both the wrap and the row; and the two columns an agent
   reads first, Title and SongID, were already at this size, so the smaller value is also the one that
   moves the fewest of the columns that matter.

   Set here rather than on each cell so this is the single place the size is decided — a stray Typo on a
   column added later cannot pull one out of line again. !important for the same reason the padding rule
   above needs it: MudBlazor sets the cell font-size with a selector this file cannot outrank.

   That last point is why the MudTable also carried an inline font-size: 0.72rem, now removed. A size set
   on the table is overridden for every cell that holds text, because MudBlazor's rule targets td directly
   and beats inheritance — so the inline value reached almost nothing while reading as though it governed
   the table, and it was a third size on top of the two it was meant to settle.

   Two things are deliberately left out. Controls keep their own sizing: the Match button, the
   qualification chip and the PD chip are not column text, and dragging them to 0.75rem would just make
   them look broken. And the header row stays at MudBlazor's 0.875rem, which is unreachable from here
   anyway (see the note below) — a slightly larger header over a smaller body is ordinary table practice,
   and every column width was measured against the header at that size. */
.song-search-results[b-gwm1q83coy]  td,
.song-search-results[b-gwm1q83coy]  td .mud-typography {
    font-size: 0.75rem !important;
}

/* Note on the header font, because it looks like an omission: MudBlazor sets font-size and white-space
   on its own header cell with a more specific selector than anything reachable from here, so trying to
   shrink or wrap the headers from this file silently does nothing — verified by reading
   getComputedStyle, which still reported 14px and nowrap after the attempt. Rather than escalate into an
   !important specificity fight with the component library, every column width in the razor is sized from
   the header's MEASURED scrollWidth at that 14px, plus a small buffer. That is why the widths look
   oddly specific (ISWC 54, ASCAP 64, GoThrough 91): each is the width its own label actually needs.
   If a label changes, re-measure rather than guess. */

/* The present/absent marks read as a column of ticks, so they are centred under their label. clip, not
   ellipsis: a tick is one character and never needs truncating, but inheriting the body's ellipsis
   rendered it as "✓…" once the surrounding markup whitespace was counted. */
.song-search-results[b-gwm1q83coy]  td.mark-cell,
.song-search-results[b-gwm1q83coy]  th.mark-col {
    text-align: center;
}

.song-search-results[b-gwm1q83coy]  td.mark-cell {
    text-overflow: clip;
}

/* The action and badge columns are sized to their measured control widths (102px for the button, 108px
   for the chip) so they need no overflow exception. An earlier version let them overflow visibly instead,
   which painted the chip straight over the SongID beside it — the ids read "18…" while the column was
   wide enough for them. Sizing the column is the fix; letting content escape its cell is not. */

/* Headers stay on one line too, so the header row matches the body's rhythm. */
.song-search-results[b-gwm1q83coy]  th {
    white-space: nowrap;
}

/* The header sticks to the top of the DIALOG's scroll area rather than to a scroll area of the table's
   own. MudTable's FixedHeader needs an explicit Height, which gives the table a second scrollbar nested
   inside the dialog's — and a nested scroll means the wheel moves whichever one the pointer is over,
   which is never reliably the one the agent meant. sticky anchors to the nearest scrolling ancestor, so
   dropping the height makes that ancestor the dialog and the header still follows the reader down.

   The explicit background is required: without it the striped rows show straight through the header as it
   passes over them. */
.song-search-results[b-gwm1q83coy]  thead th {
    position: sticky;
    top: 0;
    z-index: 3;
    background-color: var(--mud-palette-surface);
}

/* PBI 386 — the unqualified-match confirmation, drawn under the pointer.

   Fixed positioning with a very high z-index because it has to sit above the dialog it is rendered
   inside, and above the results table's own scroll container, which would otherwise clip it. The
   coordinates come from the click; the viewport clamp lives in the inline style (the browser knows the
   viewport size, the server does not).

   The backdrop is a transparent full-screen click target, so clicking anywhere else dismisses — what a
   popover is expected to do, and cheaper than wiring up an outside-click handler. */
.song-match-confirm-backdrop[b-gwm1q83coy] {
    position: fixed;
    inset: 0;
    z-index: 2400;
}

.song-match-confirm[b-gwm1q83coy] {
    position: fixed;
    z-index: 2401;
    width: 340px;
}
/* /Components/Pages/DirectLicensing/TicketReplyComposer.razor.rz.scp.css */
.tc-composer[b-oeouolylys] {
    border-top: 1px solid var(--mud-palette-lines-default);
    padding: 12px;
    background: var(--mud-palette-surface);
}

/* Internal-note tint mirrors Zendesk's yellow internal-note affordance so the agent can't
   mistake an internal note for a customer-facing reply. */
.tc-composer.tc-internal .tc-editor[b-oeouolylys] {
    background: var(--es-draft-bg);
}

.tc-toolbar[b-oeouolylys] {
    border: 1px solid var(--mud-palette-lines-default);
    border-bottom: none;
    border-radius: 6px 6px 0 0;
    padding: 2px 4px;
}

/* PBI 164.2 — closed ticket: grey the editor + toolbar so it reads as locked. Buttons disable
   themselves; this greys the contenteditable box (which has no disabled state of its own) and
   blocks stray interaction with it. The notice + disabled controls carry the "why". */
.tc-composer.tc-readonly .tc-editor[b-oeouolylys],
.tc-composer.tc-readonly .tc-toolbar[b-oeouolylys] {
    background: var(--mud-palette-action-disabled-background);
    opacity: 0.7;
}

.tc-composer.tc-readonly .tc-editor[b-oeouolylys] {
    cursor: not-allowed;
}

.tc-editor[b-oeouolylys] {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 0 0 6px 6px;
    min-height: 90px;
    max-height: 240px;
    overflow-y: auto;
    padding: 8px 10px;
    outline: none;
    font-size: 0.9rem;
    line-height: 1.4;
    word-break: break-word;
}

.tc-editor:focus[b-oeouolylys] {
    border-color: var(--mud-palette-primary);
}

/* Placeholder for the empty contenteditable — attr() reads data-placeholder off the div. */
.tc-editor:empty[b-oeouolylys]::before {
    content: attr(data-placeholder);
    color: var(--mud-palette-text-disabled);
    pointer-events: none;
}

.tc-emoji-grid[b-oeouolylys] {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 2px;
    padding: 4px;
    max-width: 240px;
}

.tc-emoji-glyph[b-oeouolylys] {
    font-size: 1.1rem;
    line-height: 1;
}
/* /Components/Pages/DirectLicensing/TicketWorkspaceView.razor.rz.scp.css */
/* Fixed viewport-relative height so the three panes scroll independently (Zendesk-style) instead
   of the whole page growing. The offset is the chrome above this component:
   64px MudAppBar + ~59px TabStrip (52px tab + 6px scroller pad + 1px border) + 16px wrapper pt-4
   + 24px wrapper pb-6 = 163px. If the app bar / tab strip height changes, update this. On narrow
   viewports (below) the layout falls back to natural page scroll. */
.tw-root[b-o1ztn54lic] {
    display: flex;
    flex-direction: column;
    height: calc(100vh - 163px);
    min-height: 0;
}

.tw-header[b-o1ztn54lic] {
    border-bottom: 1px solid var(--mud-palette-lines-default);
    flex: 0 0 auto;
}

.tw-title-wrap[b-o1ztn54lic] {
    min-width: 0;
    overflow: hidden;
    flex: 0 1 auto;
}

.tw-title[b-o1ztn54lic] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* In-place refresh indicator — a thin bar under the header while a soft refresh runs (after a
   reply submit). Fixed height so it never steals height from the three-pane body below it. */
.tw-refresh-bar[b-o1ztn54lic] {
    flex: 0 0 auto;
}

.tw-center-message[b-o1ztn54lic] {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Three-pane body. Panes scroll independently; the whole row fills the remaining height. */
.tw-body[b-o1ztn54lic] {
    flex: 1 1 auto;
    display: flex;
    min-height: 0;
    overflow: hidden;
}

.tw-pane[b-o1ztn54lic] {
    padding: 12px;
    min-width: 0;
    overflow-y: auto;
    /* Hard stop: never scroll horizontally. overflow-y:auto alone makes the browser compute
       overflow-x to auto (visible+auto is illegal), which produced a horizontal scrollbar as
       soon as a long value/tag exceeded the pane. Long content wraps (below) instead. */
    overflow-x: hidden;
}

.tw-pane-left[b-o1ztn54lic] {
    flex: 0 0 26%;
    border-right: 1px solid var(--mud-palette-lines-default);
}

.tw-pane-right[b-o1ztn54lic] {
    flex: 0 0 26%;
    border-left: 1px solid var(--mud-palette-lines-default);
}

/* Center pane holds the scrolling thread + the pinned composer, so it manages its own
   vertical layout and does NOT scroll as a whole (the thread scrolls instead). */
.tw-pane-center[b-o1ztn54lic] {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding-bottom: 0;
}

/* The scrolling conversation. Subtle grey inset so the white comment cards read as distinct
   messages (issue: cards were the same color as the pane). */
.tw-thread[b-o1ztn54lic] {
    flex: 1 1 auto;
    overflow-y: auto;
    background: var(--mud-palette-background-grey);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    padding: 8px;
}

.tw-card[b-o1ztn54lic] {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
}

/* Fields stack label-above-value so long labels (CreationSourceURL, UserNameStringEmployee, …)
   can't overlap their value the way a fixed-width label column did. */
.tw-field[b-o1ztn54lic] {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.tw-field-label[b-o1ztn54lic] {
    line-height: 1.2;
}

.tw-field-value[b-o1ztn54lic] {
    min-width: 0;
    /* overflow-wrap:anywhere breaks even an unbroken token (a long URL, a slug) so it can never
       push the field wider than the pane. word-break is the older-engine fallback. */
    overflow-wrap: anywhere;
    word-break: break-word;
}

/* URL-valued fields wrap to fit the column (multi-line is fine, and fully readable) rather than
   a single nowrap line that overflowed the pane and forced a horizontal scrollbar. */
.tw-field-link[b-o1ztn54lic] {
    display: block;
    overflow-wrap: anywhere;
    word-break: break-word;
}

.tw-tags[b-o1ztn54lic] {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

/* Outlined chip-like pill rendered as a plain span (not MudChip) so we fully control clipping:
   a tag too long for the column ellipsizes and shows its full text on hover, instead of the
   MudChip label overflowing and overlapping neighbors. */
.tw-tag[b-o1ztn54lic] {
    display: inline-block;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    box-sizing: border-box;
    height: 20px;
    line-height: 18px;
    padding: 0 8px;
    font-size: 0.65rem;
    color: var(--mud-palette-text-secondary);
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
}

.tw-tags-toggle[b-o1ztn54lic] {
    margin-top: 2px;
    text-transform: none;
    font-size: 0.72rem;
}

/* Public replies are white cards on the grey thread so each message stands out. */
.tw-comment[b-o1ztn54lic] {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    padding: 8px 10px;
    margin-bottom: 8px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

.tw-comment:last-child[b-o1ztn54lic] {
    margin-bottom: 0;
}

/* Internal notes are staff coordination — tint them apart from customer-facing replies. */
.tw-comment.tw-internal[b-o1ztn54lic] {
    background: var(--es-draft-bg);
    border-color: var(--es-draft-border);
}

/* Avatar-left, content-right message layout (Zendesk-style). */
.tw-comment-row[b-o1ztn54lic] {
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

.tw-comment-main[b-o1ztn54lic] {
    flex: 1 1 auto;
    min-width: 0;
}

/* Initials disc standing in for a profile photo. */
.tw-avatar[b-o1ztn54lic] {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1;
    user-select: none;
}

/* Staff: filled brand blue, white initials. */
.tw-avatar-agent[b-o1ztn54lic] {
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

/* End user: inverted — white disc, blue initials + brand ring. */
.tw-avatar-customer[b-o1ztn54lic] {
    background: var(--mud-palette-surface);
    color: var(--mud-palette-primary);
    border: 2px solid var(--mud-palette-primary);
}

.tw-comment-head[b-o1ztn54lic] {
    margin-bottom: 4px;
}

.tw-comment-body[b-o1ztn54lic] {
    white-space: pre-wrap;
    word-break: break-word;
    font-size: 0.9rem;
    line-height: 1.45;
}

/* PBI 164.2 — comment rendered from sanitized html_body. Block elements handle spacing, so drop
   pre-wrap (which would double up the HTML's own whitespace). ::deep is required because the
   sanitized markup is injected via MarkupString and does NOT receive this component's CSS-isolation
   scope attribute — a plain `.tw-html p` selector would never match it. */
.tw-comment-body.tw-html[b-o1ztn54lic] {
    white-space: normal;
}

/* PBI 164.3 — give paragraphs a real TOP margin (browser/Gmail default is ~1em), not just a
   bottom one. Zendesk wraps an agent's signature in <div class="signature"><p>…</p></div> and
   leans on that <p>'s top margin for the blank line between the message and the signature. We
   strip the class for safety, so without a top margin here the signature butted directly against
   the last body line. Adjacent paragraphs collapse to a single 0.75em gap, so body spacing stays
   tight. */
.tw-comment-body.tw-html[b-o1ztn54lic]  p {
    margin: 0.75em 0;
}

/* NB: no p:first-child reset — Zendesk's signature <p> is the first (only) child of its wrapper
   <div>, so zeroing first-child top margins would kill the very gap this fixes. A leading <p> at
   the top of a comment just gets a harmless 0.75em of lead-in space (comments open with text, not
   a <p>, so this is rare). */
.tw-comment-body.tw-html[b-o1ztn54lic]  p:last-child {
    margin-bottom: 0;
}

.tw-comment-body.tw-html[b-o1ztn54lic]  ul,
.tw-comment-body.tw-html[b-o1ztn54lic]  ol {
    margin: 0 0 8px;
    padding-left: 20px;
}

.tw-comment-body.tw-html[b-o1ztn54lic]  img {
    max-width: 100%;
    height: auto;
}

.tw-comment-body.tw-html[b-o1ztn54lic]  a {
    color: var(--es-link);
    text-decoration: underline;
    word-break: break-all;
}

.tw-comment-body.tw-html[b-o1ztn54lic]  blockquote {
    margin: 0 0 8px;
    padding-left: 10px;
    border-left: 3px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-secondary);
}

.tw-comment-body.tw-html[b-o1ztn54lic]  pre {
    white-space: pre-wrap;
    word-break: break-word;
    background: rgba(0, 0, 0, 0.04);
    padding: 6px 8px;
    border-radius: 4px;
}

.tw-comment-body.tw-html[b-o1ztn54lic]  code {
    background: rgba(0, 0, 0, 0.04);
    padding: 1px 4px;
    border-radius: 3px;
    font-size: 0.85em;
}

.tw-comment-body.tw-html[b-o1ztn54lic]  table {
    border-collapse: collapse;
    max-width: 100%;
}

.tw-comment-body.tw-html[b-o1ztn54lic]  td,
.tw-comment-body.tw-html[b-o1ztn54lic]  th {
    border: 1px solid var(--mud-palette-lines-default);
    padding: 4px 8px;
}

/* Stack the panes on narrow viewports so nothing is clipped (AC-friendly graceful degrade).
   The fixed viewport height + independent-scroll model is desktop-only; below this, fall back
   to natural page scroll so the panes aren't crammed into a short fixed box. */
@media (max-width: 960px) {
    .tw-root[b-o1ztn54lic] {
        height: auto;
    }

    .tw-body[b-o1ztn54lic] {
        flex-direction: column;
        overflow-y: auto;
    }

    .tw-pane-left[b-o1ztn54lic],
    .tw-pane-right[b-o1ztn54lic] {
        flex: 0 0 auto;
        border: none;
        border-bottom: 1px solid var(--mud-palette-lines-default);
    }

    .tw-pane-center[b-o1ztn54lic] {
        flex: 0 0 auto;
        overflow: visible;
        min-height: 420px;
    }
}
/* /Components/Pages/Home.razor.rz.scp.css */
/* UI/UX review (chore/2026-07-16): scoped styles for the Home hub. All colours come from MudBlazor
   palette CSS variables so the page follows the light/dark toggle automatically. */

.home-hero-title[b-9g4pfp6o81] {
    font-weight: 700;
}

.home-hero-subtitle[b-9g4pfp6o81] {
    color: var(--mud-palette-text-secondary);
    max-width: 62ch;
}

/* Auto-fill grid: cards flow into as many columns as the viewport allows and collapse to one on
   narrow screens — no manual breakpoints needed. */
.home-grid[b-9g4pfp6o81] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 16px;
}

.home-card[b-9g4pfp6o81] {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 20px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    text-decoration: none;
    transition: border-color 120ms ease, box-shadow 120ms ease, transform 120ms ease;
}

.home-card:hover[b-9g4pfp6o81] {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10);
    transform: translateY(-2px);
}

.home-card:focus-visible[b-9g4pfp6o81] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.home-card-icon[b-9g4pfp6o81] {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 12px;
    /* Fallback for engines without color-mix; the tinted version wins where supported. */
    background: rgba(62, 176, 213, 0.12);
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
}

.home-card-body[b-9g4pfp6o81] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.home-card-title[b-9g4pfp6o81] {
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.2;
}

.home-card-desc[b-9g4pfp6o81] {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary);
    line-height: 1.35;
}

/* Wrapper span (not the MudIcon itself) so the icon inherits currentColor and this scoped rule can
   drive it — scoped-CSS attributes aren't applied to child-component roots. */
.home-card-arrow[b-9g4pfp6o81] {
    flex: 0 0 auto;
    display: inline-flex;
    color: var(--mud-palette-text-disabled);
    transition: transform 120ms ease, color 120ms ease;
}

.home-card:hover .home-card-arrow[b-9g4pfp6o81] {
    color: var(--mud-palette-primary);
    transform: translateX(3px);
}
/* /Components/Pages/Sales/CustomerDetail.razor.rz.scp.css */
/* Customer detail page layout. Full-height flex column so the PAGE never scrolls — each section pane
   scrolls on its own (no nested page + section scrollbars). Offset = the chrome above this component:
   64px MudAppBar + ~59px TabStrip (52px tab + 6px scroller pad + 1px border) + 16px wrapper pt-4 +
   24px wrapper pb-6 = 163px (same value as TicketWorkspaceView.razor.css — update both if the app
   bar / tab strip height changes). Below 960px the fixed-height/independent-scroll model is dropped
   in favour of natural page scroll so nothing is crammed into a short box. */
.cd-root[b-cexsg4m73f] {
    display: flex;
    flex-direction: column;
    height: calc(100vh - 163px);
    min-height: 0;
    overflow: hidden;
}

.cd-header[b-cexsg4m73f] {
    flex: 0 0 auto;
    background: var(--mud-palette-surface);
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* Three-column body; the columns fill the height under the banner and never scroll as a whole. */
.cd-body[b-cexsg4m73f] {
    flex: 1 1 auto;
    display: flex;
    min-height: 0;
    overflow: hidden;
    gap: 16px;
    padding-top: 12px;
}

/* A column is a vertical flex stack of panes. Ratios 3:5:4 mirror the old MudGrid xs=3/5/4. */
.cd-col[b-cexsg4m73f] {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
    gap: 12px;
}

.cd-col-left[b-cexsg4m73f] { flex: 3 1 0; }
.cd-col-center[b-cexsg4m73f] { flex: 5 1 0; }
.cd-col-right[b-cexsg4m73f] { flex: 4 1 0; }

/* A scrolling section pane: vertical scroll only. overflow-y:auto alone makes the browser compute
   overflow-x to auto, which showed a phantom horizontal scrollbar whenever content exceeded the
   pane width — pin it hidden (matches the .tw-pane rule). */
.cd-pane[b-cexsg4m73f] {
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0;
}

.cd-pane-fill[b-cexsg4m73f] { flex: 1 1 auto; }
.cd-pane-42[b-cexsg4m73f] { flex: 1 1 42%; }
.cd-pane-58[b-cexsg4m73f] { flex: 1 1 58%; }
.cd-pane-50[b-cexsg4m73f] { flex: 1 1 50%; }
.cd-pane-natural[b-cexsg4m73f] { flex: 0 0 auto; }

/* Panes are plain <div>s (not MudPaper) so the scoped scroll rules above actually apply — Blazor's
   CSS-isolation attribute is not added to MudBlazor component roots, which silently dropped the
   overflow rules when these were MudPaper. Restyle them as the Outlined cards they replace. */
.cd-pane[b-cexsg4m73f],
.cd-pane-natural[b-cexsg4m73f] {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius);
    background: var(--mud-palette-surface);
    box-sizing: border-box;
}

.cd-section-body[b-cexsg4m73f] {
    padding: 8px 16px 16px;
}

/* Frozen section header inside a scrolling pane; surface background so content passes underneath it
   rather than through it. */
.cd-sticky-header[b-cexsg4m73f] {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--mud-palette-surface);
    padding: 12px 16px 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* Narrow viewports: drop the fixed-height, independent-scroll model and let the page scroll,
   stacking the columns so nothing is crammed into a short fixed box. */
@media (max-width: 960px) {
    .cd-root[b-cexsg4m73f] {
        height: auto;
        overflow: visible;
    }

    .cd-body[b-cexsg4m73f] {
        flex-direction: column;
        overflow: visible;
    }

    .cd-col[b-cexsg4m73f] {
        flex: 0 0 auto;
    }

    .cd-pane[b-cexsg4m73f],
    .cd-pane-fill[b-cexsg4m73f],
    .cd-pane-42[b-cexsg4m73f],
    .cd-pane-58[b-cexsg4m73f],
    .cd-pane-50[b-cexsg4m73f] {
        flex: 0 0 auto;
        overflow: visible;
    }
}
/* /Components/Shared/SortableLookupTable.razor.rz.scp.css */
.sortable-lookup-table[b-29d5iuf636] {
    width: 100%;
    user-select: none;
}

.sortable-lookup-grid[b-29d5iuf636] {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    overflow: hidden;
    font-size: 0.875rem;
}

/* The ::deep combinator is required because the consumer renders <th> / <td> elements
   via the Headers and RowTemplate RenderFragments. Blazor's scoped CSS only marks
   elements that this component renders directly, so without ::deep the th/td styling
   falls back to browser defaults (centered headers, no padding, etc.). */
.sortable-lookup-grid[b-29d5iuf636]  thead th {
    text-align: left;
    padding: 8px 10px;
    background: var(--mud-palette-background-grey);
    color: var(--mud-palette-text-secondary);
    border-bottom: 1px solid var(--mud-palette-lines-default);
    font-weight: 500;
}

.sortable-lookup-grid[b-29d5iuf636]  tbody td {
    padding: 6px 10px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    vertical-align: middle;
    background: var(--mud-palette-surface);
}

.sortable-lookup-grid[b-29d5iuf636]  tbody tr:last-child td {
    border-bottom: none;
}

.sortable-lookup-row:hover[b-29d5iuf636]  td {
    background: var(--mud-palette-action-default-hover);
}

.sortable-lookup-handle-col[b-29d5iuf636],
.sortable-lookup-handle-cell[b-29d5iuf636] {
    width: 32px;
    padding: 0 4px;
    text-align: center;
}

.sortable-lookup-handle[b-29d5iuf636] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: grab;
    color: var(--mud-palette-text-secondary);
    padding: 4px;
    border-radius: 4px;
}

.sortable-lookup-handle:hover[b-29d5iuf636] {
    color: var(--mud-palette-text-primary);
    background: var(--mud-palette-action-default-hover);
}

/* Active drag: switch the cursor on the handle itself (only the handle is draggable
   in this component, unlike TabStrip where the whole tab is). */
.sortable-lookup-table.is-dragging .sortable-lookup-handle[b-29d5iuf636] {
    cursor: grabbing;
}

.sortable-lookup-handle.is-disabled[b-29d5iuf636] {
    cursor: not-allowed;
    color: var(--mud-palette-text-disabled);
    opacity: 0.5;
}

.sortable-lookup-handle.is-disabled:hover[b-29d5iuf636] {
    background: transparent;
    color: var(--mud-palette-text-disabled);
}

/* The row currently being dragged is dimmed so the user tracks where it will land
   rather than where it's leaving from. ::deep so the opacity reaches consumer cells. */
.sortable-lookup-row.is-row-dragging[b-29d5iuf636]  td {
    opacity: 0.4;
}

/* Drop indicator: a 2px primary-color rule along the top/bottom edge of the row where
   the dragged item will land. Using inset box-shadow avoids the cross-browser position:
   relative-on-tr quirk and keeps the row from shifting layout when the indicator
   appears. ::deep so the shadow paints on consumer-owned cells too. */
.sortable-lookup-row.drop-above[b-29d5iuf636]  td {
    box-shadow: inset 0 2px 0 0 var(--mud-palette-primary);
}

.sortable-lookup-row.drop-below[b-29d5iuf636]  td {
    box-shadow: inset 0 -2px 0 0 var(--mud-palette-primary);
}
