/* /Components/Features/DevelopmentRunsTab.razor.rz.scp.css */
/* Scoped styles of DevelopmentRunsTab.razor. Uses MudBlazor's own theme
   palette variables (--mud-palette-*) instead of hardcoded hex values, like
   QaTab.razor.css, so the cards stay readable in both themes. */

.bk-devrun-card + .bk-devrun-card[b-hfh2n2v7a3] {
    margin-top: 0;
}

.bk-devrun-head[b-hfh2n2v7a3] {
    gap: 8px;
}

.bk-devrun-details-link[b-hfh2n2v7a3] {
    display: inline-flex;
    align-items: center;
    padding: 0 8px;
    font-size: 0.8125rem;
    color: var(--mud-palette-primary);
    text-decoration: none;
    border-bottom: 1px solid transparent;
}

.bk-devrun-details-link:hover[b-hfh2n2v7a3],
.bk-devrun-details-link:focus-visible[b-hfh2n2v7a3] {
    border-bottom-color: currentColor;
}

.bk-devrun-reason[b-hfh2n2v7a3] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--mud-palette-text-primary);
}

/* The agent's own account of a run the pipeline refused, set apart from the
   verdict above it so the two are never read as one statement: the reason is
   what the pipeline decided, this is what the agent says about it. */
.bk-devrun-account[b-hfh2n2v7a3] {
    padding-left: 10px;
    border-left: 2px solid var(--mud-palette-lines-default);
}

/* Area/commit/file-count chips: same rounded-pill shape as
   .bk-qa-filter (QaTab.razor.css), but read-only - no hover/click affordance,
   since these summarize rather than filter anything. */
.bk-devrun-chip[b-hfh2n2v7a3],
.bk-devrun-area-chip[b-hfh2n2v7a3] {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    padding: 3px 10px;
    font-size: 12.5px;
    line-height: 1.5;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-pill);
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.bk-devrun-area-chip[b-hfh2n2v7a3] {
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* At most one short line (an acceptance criterion of "Developer run ends
   with a very short summary"): no wrapping onto a second row, chips that do
   not fit scroll horizontally instead - each chip keeps flex-shrink: 0 above
   so it is never squeezed unreadable. */
.bk-devrun-areas[b-hfh2n2v7a3] {
    gap: 6px;
    margin-top: 10px;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
}

/* Below phone width (360px), an area chip's own max-width above already keeps
   a single chip from forcing excess horizontal scroll. */
@media (max-width: 400px) {
    .bk-devrun-area-chip[b-hfh2n2v7a3] {
        max-width: 160px;
    }
}

/* The QA findings this run fixed, each with the developer's own response -
   set apart the same way .bk-devrun-account already sets the agent's account
   apart from the pipeline's own verdict above it. */
.bk-devrun-qa[b-hfh2n2v7a3] {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed var(--mud-palette-lines-default);
}

.bk-devrun-qa-title[b-hfh2n2v7a3] {
    display: block;
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.bk-devrun-qa-row[b-hfh2n2v7a3] {
    display: grid;
    grid-template-columns: 18px 1fr;
    column-gap: 8px;
    row-gap: 2px;
    padding: 6px 0;
}

.bk-devrun-qa-row + .bk-devrun-qa-row[b-hfh2n2v7a3] {
    border-top: 1px solid var(--mud-palette-lines-default);
}

.bk-devrun-qa-icon[b-hfh2n2v7a3] {
    align-self: start;
    margin-top: 2px;
}
/* /Components/Features/PhaseRunsList.razor.rz.scp.css */
/* Scoped styles of PhaseRunsList.razor. Uses MudBlazor's own theme palette
   variables (--mud-palette-*) instead of hardcoded hex values, so the list
   stays readable in both themes - same convention as QaTab.razor.css and
   DevelopmentRunsTab.razor.css. */

.bk-phase-runs[b-7fc6kiqzbf] {
    display: flex;
    flex-direction: column;
}

.bk-phase-run + .bk-phase-run[b-7fc6kiqzbf] {
    margin-top: 0;
}

.bk-phase-run-head[b-7fc6kiqzbf] {
    gap: 8px;
}

.bk-phase-run-details-link[b-7fc6kiqzbf] {
    display: inline-flex;
    align-items: center;
    padding: 0 8px;
    font-size: 0.8125rem;
    color: var(--mud-palette-primary);
    text-decoration: none;
    border-bottom: 1px solid transparent;
}

.bk-phase-run-details-link:hover[b-7fc6kiqzbf],
.bk-phase-run-details-link:focus-visible[b-7fc6kiqzbf] {
    border-bottom-color: currentColor;
}

.bk-phase-run-reason[b-7fc6kiqzbf] {
    font-size: 13px;
    line-height: 1.5;
    color: var(--mud-palette-text-primary);
    white-space: pre-wrap;
    word-break: break-word;
}
/* /Components/Features/QaTab.razor.rz.scp.css */
/* Scoped styles of QaTab.razor. All tones use MudBlazor's own theme palette
   variables (--mud-palette-*, updated globally by MudThemeProvider on a
   dark-mode toggle) instead of hardcoded hex values - the report must stay
   readable in both themes. */

/* One verdict line instead of a second copy of the version and status the
   switcher and the phase-section head above already carry. */
.bk-qa-verdict[b-srnxobgl3q] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
}

.bk-qa-verdict-text[b-srnxobgl3q] {
    font-size: 13px;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
}

.bk-qa-bar[b-srnxobgl3q] {
    display: flex;
    height: 5px;
    border-radius: var(--bk-radius-xs);
    overflow: hidden;
    background: var(--mud-palette-lines-default);
}

.bk-qa-bar-pass[b-srnxobgl3q] {
    background: var(--mud-palette-success);
}

.bk-qa-bar-fail[b-srnxobgl3q] {
    background: var(--mud-palette-error);
}

.bk-qa-bar-skip[b-srnxobgl3q] {
    background: var(--mud-palette-lines-default);
}

/* A test set left out by the stop rule (concept "Fast test sets first, e2e
   tests last in QA") gets its own warning tone, distinct from the neutral
   grey of a plain skipped check - it is never allowed to read as the same
   thing. */
.bk-qa-bar-notrun[b-srnxobgl3q] {
    background: var(--mud-palette-warning);
}

/* The counts as filter buttons: in a twenty-criterion report the numbers are
   the only practical way to the rows that matter, so they are clickable
   rather than a static legend. Icon plus word plus count travel together -
   the slice a chip selects is never carried by its color alone. */
.bk-qa-filters[b-srnxobgl3q] {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.bk-qa-filter[b-srnxobgl3q] {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px 3px 7px;
    font-size: 12.5px;
    font-family: inherit;
    line-height: 1.5;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-pill);
    background: transparent;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

.bk-qa-filter:hover[b-srnxobgl3q] {
    background: var(--mud-palette-action-default-hover);
}

.bk-qa-filter-fail[b-srnxobgl3q] {
    color: var(--mud-palette-error);
    border-color: color-mix(in srgb, var(--mud-palette-error) 40%, transparent);
}

.bk-qa-filter-pass[b-srnxobgl3q] {
    color: var(--mud-palette-success);
    border-color: color-mix(in srgb, var(--mud-palette-success) 40%, transparent);
}

/* Not run's own warning tone (see .bk-qa-bar-notrun above) - kept apart from
   übersprungen's neutral, tone-less chip so the two categories never blend
   together visually either. */
.bk-qa-filter-notrun[b-srnxobgl3q] {
    color: var(--mud-palette-warning-darken, var(--mud-palette-warning));
    border-color: color-mix(in srgb, var(--mud-palette-warning) 40%, transparent);
}

/* The active slice is marked by weight and a filled ground on top of its own
   tone, so which chip is on never depends on hue alone either. */
.bk-qa-filter-on[b-srnxobgl3q] {
    font-weight: 600;
    border-color: currentColor;
    background: color-mix(in srgb, currentColor 12%, transparent);
}

.bk-qa-group[b-srnxobgl3q] {
    margin-top: 18px;
}

.bk-qa-group-header[b-srnxobgl3q] {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 6px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.bk-qa-group-title[b-srnxobgl3q] {
    font-size: 13px;
    font-weight: 600;
}

.bk-qa-group-count[b-srnxobgl3q] {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}

/* The mockup the comparison judged against, above the screens it was compared
   with: a verdict on how something looks is unreviewable while the reader
   cannot see the reference. */
.bk-qa-mockup-reference[b-srnxobgl3q] {
    margin-bottom: 10px;
}

.bk-qa-rows[b-srnxobgl3q] {
    gap: 8px;
}

/* A failed entry keeps its own outlined box (fail-first order and the default
   failure filter already put it first; the box makes it recognizable even
   while scanning past it) - a translucent tint of the error color rather than
   a fixed light-red hex, so the outline still reads against a dark surface. */
.bk-qa-row-fail[b-srnxobgl3q] {
    border: 1px solid color-mix(in srgb, var(--mud-palette-error) 45%, transparent);
    border-radius: var(--bk-radius-sm);
    padding: 2px 8px;
}

.bk-qa-row-head[b-srnxobgl3q] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 2px;
    cursor: pointer;
    border-radius: var(--bk-radius-sm);
}

.bk-qa-row-head:hover[b-srnxobgl3q] {
    background: var(--mud-palette-action-default-hover);
}

/* Clamped to two lines while collapsed - a criterion's wording can run past
   1000 characters, and one runaway line would break the "20 criteria at a
   glance" overview. The full, unclamped wording reappears inside the expanded
   body (see RowBody in QaTab.razor). */
.bk-qa-row-headline[b-srnxobgl3q] {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.875rem;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

/* An open row shows its criterion in full: the clamp exists so twenty
   collapsed rows stay scannable, not to hide the wording of the one row the
   reader deliberately opened. */
.bk-qa-row-open .bk-qa-row-headline[b-srnxobgl3q] {
    -webkit-line-clamp: none;
    font-weight: 500;
}

.bk-qa-row-evidence-count[b-srnxobgl3q] {
    display: flex;
    align-items: center;
    gap: 3px;
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
    flex-shrink: 0;
}

.bk-qa-row-body[b-srnxobgl3q] {
    margin-left: 28px;
    margin-top: 4px;
    padding-bottom: 6px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.bk-qa-tech-toggle[b-srnxobgl3q] {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-top: 6px;
    cursor: pointer;
    width: fit-content;
}

.bk-qa-tech-body[b-srnxobgl3q] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 4px;
}

.bk-qa-evidence-text[b-srnxobgl3q] {
    background: var(--mud-palette-background-gray);
    border-radius: var(--bk-radius-sm);
    padding: 8px 10px;
    font-family: monospace;
    font-size: 12px;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.bk-qa-icon-wrap[b-srnxobgl3q] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

/* The result word next to its icon - visible on screen at all times, not only
   reachable via a tooltip/aria-label. Inherits the icon's own result color via
   the wrapper, so pass/fail/skip stay distinguishable by more than color
   alone while still matching it. */
.bk-qa-result-label[b-srnxobgl3q] {
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}

/* Provenance footer: which run and which commits were tested. Quiet by
   design - it answers "what was tested", not "what is the result", so it sits
   below the findings instead of between them and the verdict. */
.bk-qa-provenance[b-srnxobgl3q] {
    margin-top: 18px;
    padding-top: 10px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.bk-qa-provenance-head[b-srnxobgl3q] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    cursor: pointer;
}

.bk-qa-provenance-body[b-srnxobgl3q] {
    margin-left: 26px;
    margin-top: 4px;
}

.bk-qa-sha[b-srnxobgl3q] {
    font-family: monospace;
    font-size: 12px;
}

.bk-qa-sha-icon[b-srnxobgl3q] {
    font-size: 11px;
    vertical-align: -1px;
    margin-left: 2px;
}

/* The always-visible screenshot inventory (concept "Screenshot-Belege des
   QA-Agents ... Einsehbarkeit"): a marker class so a test or a future rule can
   target this one section, distinct from the three question groups above it -
   its gallery deliberately keeps the shared VisualizationGallery's own,
   unreduced size, unlike a row's own evidence (see .bk-qa-evidence below). */
.bk-qa-screenshots[b-srnxobgl3q] {
    margin-top: 24px;
}

/* Same look as .bk-qa-group-header/-title, but its own class names so this
   section's heading is never mistaken for one of the three question groups
   above it (a shared selector like ".bk-qa-group-title" must resolve to
   exactly those three headings, not four). */
.bk-qa-screenshots-header[b-srnxobgl3q] {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 6px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.bk-qa-screenshots-title[b-srnxobgl3q] {
    font-size: 13px;
    font-weight: 600;
}

/* A captured screenshot inside a check is EVIDENCE, not the subject of the
   page: the shared gallery's own 560px ceiling turns one expanded failure into
   a full screen of picture and pushes every other finding out of sight. Capped
   lower here only - the thumbnail is still one click from the gallery's own
   full-screen view, which keeps the unreduced 560px/dialog behaviour everywhere
   else (Diagnose, Architektur). */
.bk-qa-evidence[b-srnxobgl3q]  .bk-run-visual-image {
    max-height: 240px;
    width: auto;
    margin: 0;
}

/* VisualizationGallery's tab strip (one tab per screenshot) can overflow a
   360px viewport once a criterion has several belege; scrolling it
   horizontally keeps the report itself free of horizontal scroll. ::deep
   reaches into the child component's own markup, per the project convention -
   see ChatTranscript.razor.css for the same rule. */
.bk-qa-evidence[b-srnxobgl3q]  .mud-tabs-toolbar-wrapper {
    overflow-x: auto;
}

/* Below phone width, the evidence-count badge and the headline stack instead
   of competing for one row's width (360px viewport). */
@media (max-width: 400px) {
    .bk-qa-row-head[b-srnxobgl3q] {
        flex-wrap: wrap;
    }

    .bk-qa-row-headline[b-srnxobgl3q] {
        flex-basis: 100%;
        order: 2;
    }

    /* An open row shows its criterion in full: the clamp exists so twenty
   collapsed rows stay scannable, not to hide the wording of the one row the
   reader deliberately opened. */
.bk-qa-row-open .bk-qa-row-headline[b-srnxobgl3q] {
    -webkit-line-clamp: none;
    font-weight: 500;
}

.bk-qa-row-evidence-count[b-srnxobgl3q] {
        order: 3;
    }
}

/* /Components/Layout/LoginLayout.razor.rz.scp.css */
/* Signed-out backdrop in the app's neumorphic design (app.css .bk-soft): one
   flat tone, everything on it shaped by a light and a dark shadow.

   The login page renders outside MudThemeProvider (see LoginLayout.razor),
   so --mud-palette-* does not exist here. The active color theme instead
   arrives as inline --bk-login-*-l (light) and --bk-login-*-d (dark)
   variables, and the bk-login-* custom properties below pick one set -
   Login.razor.css and LanguageSwitchForm.razor.css consume them through
   normal CSS inheritance (custom properties are not affected by CSS
   isolation). The literal fallbacks are the Classic theme.

   Mode order: light is the base, prefers-color-scheme switches it, and
   html[data-bk-theme] (App.razor, from the app's own toggle) overrides both -
   it outranks the media query on specificity, not on order. The shadow mix
   ratios differ per mode for the same reason as in app.css: a dark tone
   needs a much deeper shade and only a faint highlight. */
.bk-login-shell[b-09ez2ywbg6] {
    --bk-login-tone: var(--bk-login-tone-l, #ECEBF2);
    --bk-login-fg: var(--bk-login-text-l, #35314D);
    --bk-login-fg-muted: var(--bk-login-muted-l, #5A5676);
    --bk-login-accent: var(--bk-login-accent-l, #594AE2);
    --bk-login-on-accent: var(--bk-login-on-accent-l, #FFFFFF);
    --bk-soft-hi: color-mix(in srgb, var(--bk-login-tone) 25%, #FFFFFF);
    --bk-soft-lo: color-mix(in srgb, var(--bk-login-tone) 80%, #000000);
    --bk-login-error-fg: #B3261E;
    /* The shared depth tokens (app.css) cover this page too; only the focus
       ring needs the login accent, as there is no MudBlazor palette here. */
    --bk-ring: 0 0 0 2px color-mix(in srgb, var(--bk-login-accent) 40%, transparent);

    position: relative;
    isolation: isolate;
    overflow: hidden;
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    /* Type for the whole page: the card and its inputs inherit from here (see
       App.razor for where the two faces are loaded). MudBlazor's Roboto never
       reaches this page, and the browser default serif looked accidental. */
    font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    color: var(--bk-login-fg);
    background: var(--bk-login-tone);
}

@media (prefers-color-scheme: dark) {
    .bk-login-shell[b-09ez2ywbg6] {
        --bk-login-tone: var(--bk-login-tone-d, #262631);
        --bk-login-fg: var(--bk-login-text-d, #E4E1F5);
        --bk-login-fg-muted: var(--bk-login-muted-d, #A9A4C6);
        --bk-login-accent: var(--bk-login-accent-d, #7B6CFF);
        --bk-login-on-accent: var(--bk-login-on-accent-d, #FFFFFF);
        --bk-soft-hi: color-mix(in srgb, var(--bk-login-tone) 90%, #FFFFFF);
        --bk-soft-lo: color-mix(in srgb, var(--bk-login-tone) 45%, #000000);
        --bk-login-error-fg: #FFB4AB;
    }
}

html[data-bk-theme="light"] .bk-login-shell[b-09ez2ywbg6] {
    --bk-login-tone: var(--bk-login-tone-l, #ECEBF2);
    --bk-login-fg: var(--bk-login-text-l, #35314D);
    --bk-login-fg-muted: var(--bk-login-muted-l, #5A5676);
    --bk-login-accent: var(--bk-login-accent-l, #594AE2);
    --bk-login-on-accent: var(--bk-login-on-accent-l, #FFFFFF);
    --bk-soft-hi: color-mix(in srgb, var(--bk-login-tone) 25%, #FFFFFF);
    --bk-soft-lo: color-mix(in srgb, var(--bk-login-tone) 80%, #000000);
    --bk-login-error-fg: #B3261E;
}

html[data-bk-theme="dark"] .bk-login-shell[b-09ez2ywbg6] {
    --bk-login-tone: var(--bk-login-tone-d, #262631);
    --bk-login-fg: var(--bk-login-text-d, #E4E1F5);
    --bk-login-fg-muted: var(--bk-login-muted-d, #A9A4C6);
    --bk-login-accent: var(--bk-login-accent-d, #7B6CFF);
    --bk-login-on-accent: var(--bk-login-on-accent-d, #FFFFFF);
    --bk-soft-hi: color-mix(in srgb, var(--bk-login-tone) 90%, #FFFFFF);
    --bk-soft-lo: color-mix(in srgb, var(--bk-login-tone) 45%, #000000);
    --bk-login-error-fg: #FFB4AB;
}

/* The bit field behind the card (LoginLayout.razor): raised tiles on a 64px
   pitch, faded out around the card by a radial mask so the form stays calm,
   and shifted a few pixels against the pointer (--bk-login-px/-py, set by the
   layout's parallax script; 0 without it). The negative inset leaves room
   for that shift without exposing an edge. Its own compositing layer, so the
   shift never repaints the tiles. */
.bk-login-bits[b-09ez2ywbg6] {
    position: absolute;
    inset: -40px;
    z-index: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, 36px);
    grid-auto-rows: 36px;
    gap: 28px;
    justify-content: center;
    align-content: center;
    overflow: hidden;
    pointer-events: none;
    -webkit-mask-image: radial-gradient(circle at 50% 50%, transparent 0 300px, rgba(0, 0, 0, 0.3) 430px, #000 720px);
    mask-image: radial-gradient(circle at 50% 50%, transparent 0 300px, rgba(0, 0, 0, 0.3) 430px, #000 720px);
    transform: translate3d(calc(var(--bk-login-px, 0) * -18px), calc(var(--bk-login-py, 0) * -18px), 0);
    transition: transform var(--bk-dur-slow) var(--bk-ease-out);
    will-change: transform;
}

/* Three shadows in every state, so the pulse below can interpolate: the
   raised pair, then a spare glow slot the glow themes fill. */
.bk-login-bits span[b-09ez2ywbg6] {
    border-radius: var(--bk-radius-md);
    background: var(--bk-login-tone);
    box-shadow: var(--bk-depth-raised-sm), 0 0 0 transparent;
}

/* Now and then a bit is pressed in and lights up in the accent, like a key
   being typed - scattered by four different nth-child strides and delays,
   so the field never pulses in rows or all at once. */
.bk-login-bits span:nth-child(37n + 7)[b-09ez2ywbg6] { animation: bk-login-bit-press-b-09ez2ywbg6 8s ease-in-out infinite; }
.bk-login-bits span:nth-child(41n + 3)[b-09ez2ywbg6] { animation: bk-login-bit-press-b-09ez2ywbg6 8s ease-in-out 2.1s infinite; }
.bk-login-bits span:nth-child(43n + 13)[b-09ez2ywbg6] { animation: bk-login-bit-press-b-09ez2ywbg6 8s ease-in-out 4.3s infinite; }
.bk-login-bits span:nth-child(47n + 22)[b-09ez2ywbg6] { animation: bk-login-bit-press-b-09ez2ywbg6 8s ease-in-out 6.2s infinite; }

/* Raised -> flat -> pressed in and lit -> back. The shadows flip between
   outer and inset only at zero size (66%/67%, 90%/91%), since an outer and an
   inset shadow cannot interpolate into each other. */
@keyframes bk-login-bit-press-b-09ez2ywbg6 {
    0%, 60%, 100% {
        background: var(--bk-login-tone);
        box-shadow: var(--bk-depth-raised-sm), 0 0 0 transparent;
    }
    66% {
        box-shadow: 0 0 0 var(--bk-soft-lo), 0 0 0 var(--bk-soft-hi), 0 0 0 transparent;
    }
    67% {
        box-shadow: inset 0 0 0 var(--bk-soft-lo), inset 0 0 0 var(--bk-soft-hi), 0 0 0 transparent;
    }
    74%, 84% {
        background: color-mix(in srgb, var(--bk-login-tone) 55%, var(--bk-login-accent));
        box-shadow: var(--bk-depth-inset), 0 0 0 transparent;
    }
    90% {
        box-shadow: inset 0 0 0 var(--bk-soft-lo), inset 0 0 0 var(--bk-soft-hi), 0 0 0 transparent;
    }
    91% {
        box-shadow: 0 0 0 var(--bk-soft-lo), 0 0 0 var(--bk-soft-hi), 0 0 0 transparent;
    }
}

/* Glow themes in dark mode: the lit bit also glows. */
@keyframes bk-login-bit-press-glow-b-09ez2ywbg6 {
    0%, 60%, 100% {
        background: var(--bk-login-tone);
        box-shadow: var(--bk-depth-raised-sm), 0 0 0 transparent;
    }
    66% {
        box-shadow: 0 0 0 var(--bk-soft-lo), 0 0 0 var(--bk-soft-hi), 0 0 0 transparent;
    }
    67% {
        box-shadow: inset 0 0 0 var(--bk-soft-lo), inset 0 0 0 var(--bk-soft-hi), 0 0 0 transparent;
    }
    74%, 84% {
        background: color-mix(in srgb, var(--bk-login-tone) 35%, var(--bk-login-accent));
        box-shadow: var(--bk-depth-inset),
            0 0 20px 2px color-mix(in srgb, var(--bk-login-accent) 55%, transparent);
    }
    90% {
        box-shadow: inset 0 0 0 var(--bk-soft-lo), inset 0 0 0 var(--bk-soft-hi), 0 0 0 transparent;
    }
    91% {
        box-shadow: 0 0 0 var(--bk-soft-lo), 0 0 0 var(--bk-soft-hi), 0 0 0 transparent;
    }
}

/* Only the pulsing bits (the same four strides as above) swap animations. */
html[data-bk-theme="dark"] .bk-login-glow .bk-login-bits span:nth-child(37n + 7)[b-09ez2ywbg6],
html[data-bk-theme="dark"] .bk-login-glow .bk-login-bits span:nth-child(41n + 3)[b-09ez2ywbg6],
html[data-bk-theme="dark"] .bk-login-glow .bk-login-bits span:nth-child(43n + 13)[b-09ez2ywbg6],
html[data-bk-theme="dark"] .bk-login-glow .bk-login-bits span:nth-child(47n + 22)[b-09ez2ywbg6] {
    animation-name: bk-login-bit-press-glow-b-09ez2ywbg6;
}

@media (prefers-color-scheme: dark) {
    html:not([data-bk-theme]) .bk-login-glow .bk-login-bits span:nth-child(37n + 7)[b-09ez2ywbg6],
    html:not([data-bk-theme]) .bk-login-glow .bk-login-bits span:nth-child(41n + 3)[b-09ez2ywbg6],
    html:not([data-bk-theme]) .bk-login-glow .bk-login-bits span:nth-child(43n + 13)[b-09ez2ywbg6],
    html:not([data-bk-theme]) .bk-login-glow .bk-login-bits span:nth-child(47n + 22)[b-09ez2ywbg6] {
        animation-name: bk-login-bit-press-glow-b-09ez2ywbg6;
    }
}

@media (prefers-reduced-motion: reduce) {
    .bk-login-bits[b-09ez2ywbg6] {
        transform: none;
        transition: none;
    }

    .bk-login-bits span[b-09ez2ywbg6] {
        animation: none !important;
    }
}

/* Reachable from the very first page an unauthenticated visitor sees (concept
   "Oberflaeche in Deutsch und Englisch umschaltbar"): top-right, matching
   MainLayout's own placement next to the dark-mode toggle. The pill is a
   groove pressed into the page; LanguageSwitchForm raises the active
   language out of it. */
.bk-login-language[b-09ez2ywbg6] {
    position: absolute;
    top: 20px;
    right: 20px;
    z-index: 1;
    border-radius: var(--bk-radius-pill);
    background: var(--bk-login-tone);
    box-shadow: var(--bk-depth-inset-sm);
}
/* /Components/Layout/MainLayout.razor.rz.scp.css */
/* Account tile at the foot of the drawer: avatar, signed-in admin, logout.
   The element is the logout form itself (see MainLayout.razor), so the layout
   lives on a <form> rather than a wrapper div. */
.bk-account[b-8pn62cp0dq] {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 4px 12px 6px;
    padding: 7px 8px 7px 9px;
    border-radius: var(--bk-radius-sm);
    border-top: 1px solid var(--mud-palette-lines-default);
    border-top-left-radius: 0;
    border-top-right-radius: 0;
    min-width: 0;
}

.bk-account-avatar[b-8pn62cp0dq] {
    flex: none;
    width: 28px;
    height: 28px;
    display: grid;
    place-items: center;
    border-radius: var(--bk-radius-round);
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1;
}

.bk-account-text[b-8pn62cp0dq] {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1;
}

.bk-account-role[b-8pn62cp0dq] {
    font-size: 0.62rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    line-height: 1.3;
}

.bk-account-name[b-8pn62cp0dq] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* MudTooltip wraps the button in its own span, which would otherwise stretch
   as a flex item; ::deep because that span is rendered by MudBlazor, not here. */
.bk-account[b-8pn62cp0dq]  .mud-tooltip-root {
    flex: none;
    display: inline-grid;
}

.bk-account-logout[b-8pn62cp0dq] {
    flex: none;
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: none;
    border-radius: var(--bk-radius-round);
    background: none;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
    transition: color var(--bk-dur-fast) var(--bk-ease-out), background-color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-account-logout:hover[b-8pn62cp0dq],
.bk-account-logout:focus-visible[b-8pn62cp0dq] {
    color: var(--mud-palette-primary);
    background: var(--mud-palette-action-default-hover);
}

/* Agents/Statistics/Settings as one icon-only row instead of three stacked
   MudNavLink rows - saves the vertical space a text label needs on each of
   the three, next to the project-scoped links above (which keep their text,
   since those change per project and are not yet familiar by icon alone). */
.bk-nav-icon-row[b-8pn62cp0dq] {
    display: flex;
    justify-content: center;
    gap: 4px;
    padding: 4px 8px;
}

/* MudTooltip wraps the button in its own span, same quirk bk-account already
   works around above; ::deep because that span is rendered by MudBlazor. */
.bk-nav-icon-row[b-8pn62cp0dq]  .mud-tooltip-root {
    flex: none;
}

[b-8pn62cp0dq] .bk-nav-icon-btn {
    color: var(--mud-palette-text-secondary);
}

/* Drawer header: brand plus three knobs (color theme, language, mode) in a
   230px drawer, which loses another ~11px to bk-drawer-scroll's own
   scrollbar once the "waiting for you" list gets long (see bk-drawer-scroll
   below - only that area scrolls, the header itself never does). Tighter
   side padding and gaps than the old pa-4/gap-2 so the brand name never runs
   under the first knob, and the brand itself never shrinks. */
.bk-drawer-head[b-8pn62cp0dq] {
    gap: 5px;
    padding: 16px 10px 8px 12px;
}

/* Sidebar split into three parts (feature "Desktop sidebar looks like the
   agreed design"): bk-drawer-fixed (brand, project selection, links) and
   bk-drawer-foot (icon row, user tile, version) each size to their own
   content and never grow or shrink; bk-drawer-scroll is the only one that
   does, taking whatever height is left between them and scrolling its own
   content - including its section headings - once that runs out. The
   drawer's own default overflow (MudBlazor's ".mud-drawer { overflow-y:
   auto }") is turned off in app.css so only this inner area ever grows a
   scrollbar. min-height: 0 overrides the flex item default of "at least as
   tall as my content", which would otherwise defeat the scrolling entirely. */
.bk-drawer-fixed[b-8pn62cp0dq],
.bk-drawer-foot[b-8pn62cp0dq] {
    flex: 0 0 auto;
}

/* The version line (a Typo.caption MudText, i.e. a plain inline <span>) used
   to sit directly in bk-drawer-nav, a MudBlazor flex column that auto-
   blockifies an inline flex item - which is what let its own Align.Center
   take effect. Now that it sits inside bk-drawer-foot, an ordinary block div,
   it stays genuinely inline and Align.Center has no block-level box to center
   within, so it hugs the left edge instead. text-align: center here restores
   the same visual result without touching the markup that keeps the footer
   pinned. */
.bk-drawer-foot[b-8pn62cp0dq] {
    text-align: center;
}

.bk-drawer-scroll[b-8pn62cp0dq] {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.bk-drawer-head[b-8pn62cp0dq]  .bk-brand {
    flex-shrink: 0;
}

/* The project selector under it: room above and below, so the raised
   control stands clear of both the header knobs and the first nav link
   (the old px-3/pb-1 left it touching the link below). */
.bk-drawer-project[b-8pn62cp0dq] {
    padding: 8px 12px 14px;
}

/* Neumorphic design (app.css .bk-soft): three free-standing keys, rounded
   squares rather than discs - each a convex cap, a faint light-to-shade
   gradient under the raised shadow. The current page's key is pushed down
   and takes the accent; any key sinks in while pressed (app.css's :active
   rule). The specificity here (.bk-soft plus this component's scope
   attribute) is what lets these outrank app.css's generic drawer knob and
   pressed-state rules. */
.bk-soft .bk-nav-icon-row[b-8pn62cp0dq] {
    gap: 14px;
    padding: 8px 8px 12px;
}

.bk-soft .bk-nav-icon-row[b-8pn62cp0dq]  .bk-nav-icon-btn {
    width: 40px;
    height: 40px;
    border-radius: var(--bk-radius-md);
    background: linear-gradient(145deg,
        color-mix(in srgb, var(--mud-palette-surface) 92%, #FFFFFF),
        color-mix(in srgb, var(--mud-palette-surface) 94%, #000000));
    box-shadow: var(--bk-depth-raised-sm);
}

.bk-soft .bk-nav-icon-row[b-8pn62cp0dq]  .bk-nav-icon-btn-active {
    background: var(--mud-palette-surface);
    color: var(--mud-palette-primary);
    box-shadow: var(--bk-depth-inset);
}

/* Glow presets: the pressed-in key glows from inside. */
.bk-glow .bk-nav-icon-row[b-8pn62cp0dq]  .bk-nav-icon-btn-active {
    box-shadow: var(--bk-depth-inset),
        inset 0 0 12px rgba(var(--mud-palette-primary-rgb), 0.3);
    filter: drop-shadow(0 0 5px rgba(var(--mud-palette-primary-rgb), 0.35));
}

/* The logout button: the same knob, sized to the account tile. */
.bk-soft .bk-account-logout[b-8pn62cp0dq] {
    width: 34px;
    height: 34px;
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
    transition: box-shadow var(--bk-dur-fast) var(--bk-ease-out), transform var(--bk-dur-fast) var(--bk-ease-out), color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-soft .bk-account-logout:hover[b-8pn62cp0dq],
.bk-soft .bk-account-logout:focus-visible[b-8pn62cp0dq] {
    background: var(--mud-palette-surface);
}

.bk-soft .bk-account-logout:active[b-8pn62cp0dq] {
    box-shadow: var(--bk-depth-inset-sm);
    transform: translateY(1px) scale(0.96);
}

[b-8pn62cp0dq] .bk-nav-icon-btn:hover {
    color: var(--mud-palette-primary);
}

[b-8pn62cp0dq] .bk-nav-icon-btn-active {
    color: var(--mud-palette-primary);
    background: var(--mud-palette-primary-hover);
}
/* /Components/Pages/AgentRunDetail.razor.rz.scp.css */
/* Marker classes distinguishing the Eingabe and Ergebnis blocks for
   unambiguous test locators: both can independently render
   StructuredTextView's prose branch with its own "Rohtext anzeigen" toggle,
   so a locator keyed only on the toggle button would match twice. Purely a
   locator hook otherwise - min-width: 0 only makes sure their text content
   is free to wrap instead of being constrained by a parent's shrink-to-fit
   width, it carries no layout role of its own.

   Deliberately NOT bk-run-result (see AgentRunRow.razor's use of that name
   in app.css): that class truncates a one-line list label to a single line
   via white-space: nowrap/overflow: hidden/text-overflow: ellipsis, which
   is exactly wrong for this multi-line, fully readable block. */
.bk-run-detail-input[b-mjciqjkvbr],
.bk-run-detail-result[b-mjciqjkvbr] {
    min-width: 0;
}

/* Locator hook for the unreadable-answer section (see the raw-answer/repair
   link markup below) - no layout role of its own, min-width: 0 for the same
   reason as the two rules above: this block can carry a very long raw answer
   and must stay free to wrap rather than be constrained by a parent's
   shrink-to-fit width. */
.bk-run-detail-unreadable-answer[b-mjciqjkvbr] {
    min-width: 0;
}
/* /Components/Pages/ArtifactView.razor.rz.scp.css */
/* The artifact's own page - what a phone gets, and what a direct link opens.
   Deliberately no card and no max-width: the point of giving an artifact its
   own surface is that it gets the whole width, and SandboxedHtml's frame is
   already a bordered, rounded block of its own. */
.bk-artifact-page[b-wffcp19gk2] {
    margin-top: 12px;
}

/* Way back: one wide, obvious target at the TOP, not a text button under a
   frame that can be a screen and a half tall. Reads as a row rather than a
   button so it does not compete with whatever the artifact itself offers. */
.bk-artifact-back[b-wffcp19gk2] {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    margin-bottom: 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-md);
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    text-decoration: none;
    transition: border-color var(--bk-dur-fast) var(--bk-ease-out), background-color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-artifact-back:hover[b-wffcp19gk2] {
    border-color: var(--mud-palette-primary);
    background: var(--mud-palette-background-gray);
}

/* min-width: 0 so a long session title ellipsizes instead of pushing the row
   wider than the page */
.bk-artifact-back-text[b-wffcp19gk2] {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.bk-artifact-back-label[b-wffcp19gk2] {
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.3;
}

.bk-artifact-back-session[b-wffcp19gk2] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-artifact-caption[b-wffcp19gk2] {
    color: var(--mud-palette-text-secondary);
    margin-bottom: 10px;
}

/* Provenance below the frame - the one thing that genuinely belongs after the
   artifact rather than before it. */
.bk-artifact-foot[b-wffcp19gk2] {
    display: block;
    margin-top: 12px;
    color: var(--mud-palette-text-secondary);
}
/* /Components/Pages/FeatureDetail.razor.rz.scp.css */
/* Pause banner: the link to the full failure detail sits inside the callout,
   so it takes the callout's own foreground colour instead of the theme
   primary, which would fight the red/amber background in both schemes. */
.bk-pause-details[b-z27ka1htyg] {
    display: inline-block;
    margin-top: 2px;
    color: inherit;
    opacity: 0.85;
}

.bk-pause-details:hover[b-z27ka1htyg] {
    opacity: 1;
}

/* The full failure text: container output that has to keep its line
   structure, so it stays preformatted, wraps long lines instead of forcing a
   horizontal scrollbar, and scrolls vertically inside the dialog. */
.bk-pause-detail-text[b-z27ka1htyg] {
    margin: 0;
    max-height: 60vh;
    overflow-y: auto;
    padding: 10px 12px;
    border-radius: var(--bk-radius-sm);
    background: var(--mud-palette-background-gray);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75rem;
    line-height: 1.45;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* Merge history rows. A two-column grid instead of one wrapping flex line:
   the timestamp keeps its own column so the outcomes line up under each
   other, and the right column may grow as tall as it needs (a meaning
   sentence, a wrapped file list, a sha range) without pushing the time out
   of alignment. Hairlines between rows, not cards - these are entries of one
   list, not separate objects. */
.bk-mh[b-z27ka1htyg] {
    display: flex;
    flex-direction: column;
}

.bk-mh-row[b-z27ka1htyg] {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 4px 12px;
    padding: 10px 0;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.bk-mh-row:first-child[b-z27ka1htyg] {
    border-top: 0;
    padding-top: 2px;
}

.bk-mh-when[b-z27ka1htyg] {
    font-size: 0.71875rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
    text-align: right;
    min-width: 74px;
    padding-top: 2px;
}

.bk-mh-main[b-z27ka1htyg] {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
}

.bk-mh-line[b-z27ka1htyg] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.bk-mh-meaning[b-z27ka1htyg] {
    font-size: 0.8125rem;
    color: var(--mud-palette-text-primary);
}

.bk-mh-files[b-z27ka1htyg] {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

/* One conflicting path per chip: the joined single line this replaces ran
   out of the section as soon as a conflict touched more than one file. */
.bk-mh-file[b-z27ka1htyg] {
    max-width: 100%;
    padding: 1px 6px;
    border-radius: var(--bk-radius-xs);
    background: var(--mud-palette-background-gray);
    color: var(--mud-palette-text-secondary);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.6875rem;
    line-height: 1.6;
    overflow-wrap: anywhere;
}

.bk-mh-run[b-z27ka1htyg] {
    font-size: 0.71875rem;
    color: var(--mud-palette-primary);
    text-decoration: none;
    border-bottom: 1px solid transparent;
}

.bk-mh-run:hover[b-z27ka1htyg],
.bk-mh-run:focus-visible[b-z27ka1htyg] {
    border-bottom-color: currentColor;
}

.bk-mh-sub[b-z27ka1htyg] {
    font-size: 0.6875rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}
/* /Components/Pages/ForYou.razor.rz.scp.css */
/* Phone-only bottom-anchored layout (architecture "For you anchored to the
   bottom bar"): "Waiting for you" becomes the section right on the bottom
   bar, its most urgent (currently first-listed) entry closest to it, with
   "Agents active" above it - built entirely with CSS `order` and
   `column-reverse` over ProjectAttentionLists' own UNCHANGED markup (see its
   bk-attn-* hook classes), so the same component keeps its ordinary top-down
   order wherever else it renders (MainLayout's desktop/tablet drawer).
   Untouched at 600px and up - ForYou.razor's wrapping divs render there as
   plain, unstyled blocks, which is exactly today's top-down, top-aligned
   page. See for-you-scroll-interop.js for the scroll-position half of this
   (opens, and stays, at the bottom). */
@media (max-width: 599.98px) {
    .bk-foryou-page[b-9qfs3yjevh] {
        display: flex;
        flex-direction: column;
        /* Floor, not a cap: fills at least the viewport left after .bk-page's
           own phone padding - 12px top, and (for THIS page specifically,
           see app.css's own ".bk-page:has(.bk-foryou-page)" override) just
           the bar's height at the bottom, no extra breathing room - so
           bk-foryou-fill below has room to push the lists flush against the
           bar when they are short, with no gap (criterion "no empty space
           between the last entry and the bottom bar"). Content taller than
           this simply grows past it and the page scrolls. */
        min-height: calc(100dvh - var(--bk-phone-bar-h) - 12px);
    }

    .bk-foryou-fill[b-9qfs3yjevh] {
        flex: 1 0 auto;
    }

    .bk-foryou-lists[b-9qfs3yjevh] {
        display: flex;
        flex-direction: column;
    }

    /* Section order: Agents active above, Waiting for you last (closest to
       the bar). `order` only reshuffles how these flex children PAINT - it
       never touches their real DOM position, which is what keeps
       ProjectAttentionLists' own markup (and the drawer that also renders it)
       untouched. */
    .bk-foryou-lists[b-9qfs3yjevh]  .bk-attn-agent-head {
        order: 1;
    }

    .bk-foryou-lists[b-9qfs3yjevh]  .bk-attn-agent-empty,
    .bk-foryou-lists[b-9qfs3yjevh]  .bk-attn-agent-list {
        order: 2;
    }

    .bk-foryou-lists[b-9qfs3yjevh]  .bk-attn-wait-head {
        order: 3;
    }

    .bk-foryou-lists[b-9qfs3yjevh]  .bk-attn-wait-empty,
    .bk-foryou-lists[b-9qfs3yjevh]  .bk-attn-wait-list {
        order: 4;
    }

    /* Within each section: the entries render in an auto-height flex column,
       reversed - the first DOM child (today's most urgent entry) lands at the
       main-start, which column-reverse places at the BOTTOM, i.e. closest to
       whatever comes right after this block (the bar itself, for the
       Waiting list). The rest keep today's order, just stacked upward from
       there - no markup change, only how this one element paints its
       existing children. */
    .bk-foryou-lists[b-9qfs3yjevh]  .bk-attn-wait-list,
    .bk-foryou-lists[b-9qfs3yjevh]  .bk-attn-agent-list {
        display: flex;
        flex-direction: column-reverse;
    }
}
/* /Components/Pages/Login.razor.rz.scp.css */
/* Login card in the app's neumorphic design. The bk-login-* custom properties
   (the active color theme, both modes, plus the two shadow colors mixed from
   its tone) are defined on .bk-login-shell in LoginLayout.razor.css and
   inherit down here - CSS isolation scopes selectors, not custom property
   inheritance. Raised: the card, the logo and the button. Pressed in: the
   fields, and the button while it is held down. */

.bk-login-card[b-uabmxabema] {
    position: relative;
    /* Above LoginLayout's bit field. */
    z-index: 1;
    width: 100%;
    max-width: 396px;
    padding: 40px 34px 34px;
    border-radius: var(--bk-radius-xl);
    background: var(--bk-login-tone);
    box-shadow: var(--bk-depth-floating);
    text-align: center;
    color: var(--bk-login-fg);
    animation: bk-login-rise-b-uabmxabema 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes bk-login-rise-b-uabmxabema {
    from { opacity: 0; transform: translateY(14px); }
    to { opacity: 1; transform: none; }
}

/* Contents arrive just behind the card itself, top to bottom. */
.bk-login-card > *[b-uabmxabema] {
    animation: bk-login-fade-b-uabmxabema 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.bk-login-card > *:nth-child(1)[b-uabmxabema] { animation-delay: 0.08s; }
.bk-login-card > *:nth-child(2)[b-uabmxabema] { animation-delay: 0.14s; }
.bk-login-card > *:nth-child(3)[b-uabmxabema] { animation-delay: 0.2s; }
.bk-login-card > *:nth-child(4)[b-uabmxabema] { animation-delay: 0.26s; }
.bk-login-card > *:nth-child(5)[b-uabmxabema] { animation-delay: 0.32s; }

@keyframes bk-login-fade-b-uabmxabema {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: none; }
}

/* The inline BrandLogo, tile in the theme's logo color (--bk-logo on the
   shell), raised off the card. */
.bk-login-logo[b-uabmxabema] {
    display: inline-block;
    line-height: 0;
    filter: drop-shadow(4px 4px 6px var(--bk-soft-lo)) drop-shadow(-4px -4px 6px var(--bk-soft-hi));
}

/* The logo builds itself, bit by bit: its bits drop in from the bottom row
   up (BrandLogo's markup order is top to bottom, hence the delays run
   backwards), and the solid accent bit - the next increment - lands last
   with a little press. */
.bk-login-logo[b-uabmxabema]  .bk-brand-logo g rect,
.bk-login-logo[b-uabmxabema]  .bk-brand-logo > rect:last-child {
    transform-box: fill-box;
    transform-origin: center;
    animation: bk-login-bit-in-b-uabmxabema 0.42s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.bk-login-logo[b-uabmxabema]  .bk-brand-logo g rect:nth-child(6) { animation-delay: 0.45s; }
.bk-login-logo[b-uabmxabema]  .bk-brand-logo g rect:nth-child(7) { animation-delay: 0.52s; }
.bk-login-logo[b-uabmxabema]  .bk-brand-logo g rect:nth-child(8) { animation-delay: 0.59s; }
.bk-login-logo[b-uabmxabema]  .bk-brand-logo g rect:nth-child(4) { animation-delay: 0.68s; }
.bk-login-logo[b-uabmxabema]  .bk-brand-logo g rect:nth-child(5) { animation-delay: 0.75s; }
.bk-login-logo[b-uabmxabema]  .bk-brand-logo g rect:nth-child(2) { animation-delay: 0.84s; }
.bk-login-logo[b-uabmxabema]  .bk-brand-logo g rect:nth-child(3) { animation-delay: 0.91s; }
.bk-login-logo[b-uabmxabema]  .bk-brand-logo g rect:nth-child(1) { animation-delay: 1s; }

.bk-login-logo[b-uabmxabema]  .bk-brand-logo > rect:last-child {
    animation: bk-login-bit-land-b-uabmxabema 0.55s cubic-bezier(0.22, 1, 0.36, 1) 1.15s both;
}

@keyframes bk-login-bit-in-b-uabmxabema {
    from { opacity: 0; transform: translateY(-14px) scale(0.6); }
    to { opacity: 1; transform: none; }
}

@keyframes bk-login-bit-land-b-uabmxabema {
    0% { opacity: 0; transform: translateY(-24px) scale(1.35); }
    70% { opacity: 1; transform: translateY(1px) scale(0.88); }
    100% { opacity: 1; transform: none; }
}

.bk-login-title[b-uabmxabema] {
    font-family: "Space Grotesk", "Inter", system-ui, sans-serif;
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    margin: 18px 0 2px;
    color: var(--bk-login-accent);
}

.bk-login-tagline[b-uabmxabema] {
    font-size: 0.82rem;
    color: var(--bk-login-fg-muted);
    margin: 0 0 26px;
}

/* The error as a raised pad with only a faint red tint of the tone, the way
   the app draws its paused/archived callouts. */
.bk-login-error[b-uabmxabema] {
    display: flex;
    align-items: center;
    gap: 8px;
    text-align: left;
    background: color-mix(in srgb, var(--bk-login-tone) 88%, #E24B4A);
    color: var(--bk-login-error-fg);
    border-radius: var(--bk-radius-md);
    padding: 10px 14px;
    font-size: 0.83rem;
    margin: 0 0 18px;
    box-shadow: var(--bk-depth-raised-sm);
}

.bk-login-error-icon[b-uabmxabema] {
    flex: none;
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
}

.bk-login-form[b-uabmxabema] {
    display: flex;
    flex-direction: column;
    gap: 16px;
    text-align: left;
}

/* Icon, caption and reveal button all sit on top of the input. */
.bk-login-field[b-uabmxabema] {
    position: relative;
}

.bk-login-field-icon[b-uabmxabema] {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    width: 18px;
    height: 18px;
    fill: none;
    stroke: var(--bk-login-fg-muted);
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: stroke var(--bk-dur-base) var(--bk-ease-out);
    pointer-events: none;
}

/* Pressed into the card, no outline. */
.bk-login-input[b-uabmxabema] {
    width: 100%;
    font: inherit;
    color: var(--bk-login-fg);
    /* Top padding leaves room for the floated caption, inside the field. */
    padding: 23px 14px 9px 46px;
    border: none;
    border-radius: var(--bk-radius-md);
    background: var(--bk-login-tone);
    box-shadow: var(--bk-depth-inset);
    transition: box-shadow var(--bk-dur-base) var(--bk-ease-out);
}

/* Room for the reveal button on the password field. */
.bk-login-input-reveal[b-uabmxabema] {
    padding-right: 48px;
}

.bk-login-input:focus[b-uabmxabema] {
    outline: none;
    box-shadow: var(--bk-depth-inset),
        var(--bk-ring);
}

.bk-login-input:focus ~ .bk-login-field-icon[b-uabmxabema] {
    stroke: var(--bk-login-accent);
}

/* Chrome paints autofilled inputs with its own opaque fill - repaint it with
   the tone, keeping the pressed-in shadow. */
.bk-login-input:-webkit-autofill[b-uabmxabema],
.bk-login-input:-webkit-autofill:hover[b-uabmxabema],
.bk-login-input:-webkit-autofill:focus[b-uabmxabema] {
    -webkit-text-fill-color: var(--bk-login-fg);
    -webkit-box-shadow: 0 0 0 1000px var(--bk-login-tone) inset, inset 4px 4px 8px var(--bk-soft-lo);
    caret-color: var(--bk-login-fg);
}

/* Rides on :placeholder-shown, hence the placeholder=" " in the markup. It
   floats to the top edge inside the field, never out onto the card. */
.bk-login-floating[b-uabmxabema] {
    position: absolute;
    left: 46px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.9rem;
    color: var(--bk-login-fg-muted);
    pointer-events: none;
    transition: transform var(--bk-dur-fast) var(--bk-ease-out), font-size var(--bk-dur-fast) var(--bk-ease-out), color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-login-input:focus + .bk-login-floating[b-uabmxabema],
.bk-login-input:not(:placeholder-shown) + .bk-login-floating[b-uabmxabema] {
    transform: translateY(-160%);
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bk-login-accent);
}

/* A small raised knob inside the field; pressed in while held. */
.bk-login-reveal[b-uabmxabema] {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 34px;
    height: 34px;
    display: grid;
    place-items: center;
    padding: 0;
    border: none;
    border-radius: var(--bk-radius-md);
    background: var(--bk-login-tone);
    color: var(--bk-login-fg-muted);
    cursor: pointer;
    box-shadow: var(--bk-depth-raised-sm);
    transition: color var(--bk-dur-fast) var(--bk-ease-out), box-shadow var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-login-reveal svg[b-uabmxabema] {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.bk-login-reveal:hover[b-uabmxabema],
.bk-login-reveal:focus-visible[b-uabmxabema] {
    color: var(--bk-login-accent);
}

.bk-login-reveal:focus-visible[b-uabmxabema] {
    outline: 2px solid var(--bk-login-accent);
    outline-offset: 2px;
}

.bk-login-reveal:active[b-uabmxabema],
.bk-login-reveal.is-revealed[b-uabmxabema] {
    box-shadow: var(--bk-depth-inset-sm);
}

.bk-login-reveal-slash[b-uabmxabema] {
    opacity: 0;
    transition: opacity var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-login-reveal.is-revealed .bk-login-reveal-slash[b-uabmxabema] {
    opacity: 1;
}

/* The glossy accent button of the design: a faint top-left sheen and a
   shadow in its own color instead of the dark one; it sinks in physically
   while pressed. */
.bk-login-submit[b-uabmxabema] {
    position: relative;
    overflow: hidden;
    margin-top: 8px;
    padding: 13px 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    border: none;
    border-radius: var(--bk-radius-md);
    background-color: var(--bk-login-accent);
    background-image: linear-gradient(145deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0) 55%);
    color: var(--bk-login-on-accent);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 10px 20px -8px color-mix(in srgb, var(--bk-login-accent) 65%, transparent),
        -5px -5px 12px var(--bk-soft-hi);
    transition: transform var(--bk-dur-fast) var(--bk-ease-out), box-shadow var(--bk-dur-fast) var(--bk-ease-out), filter var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-login-submit:hover[b-uabmxabema] {
    filter: brightness(1.05);
}

.bk-login-submit:active[b-uabmxabema] {
    transform: translateY(1px) scale(0.98);
    box-shadow: var(--bk-depth-pressed-accent);
}

.bk-login-submit:focus-visible[b-uabmxabema] {
    outline: 2px solid var(--bk-login-accent);
    outline-offset: 3px;
}

/* Light sweeping across the button on hover. */
.bk-login-submit[b-uabmxabema]::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, 0.3), transparent 70%);
}

.bk-login-submit:hover[b-uabmxabema]::after {
    animation: bk-login-sheen-b-uabmxabema 0.7s ease;
}

@keyframes bk-login-sheen-b-uabmxabema {
    to { transform: translateX(100%); }
}

.bk-login-submit-icon[b-uabmxabema] {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.9;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: transform var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-login-submit:hover .bk-login-submit-icon[b-uabmxabema] {
    transform: translateX(3px);
}

/* Pending state while the POST is in flight (set by the script in Login.razor):
   the arrow is swapped for a spinner so a slow sign-in is visibly working. */
.bk-login-submit.is-busy[b-uabmxabema] {
    pointer-events: none;
    filter: saturate(0.85);
}

.bk-login-submit.is-busy .bk-login-submit-icon[b-uabmxabema] {
    display: none;
}

.bk-login-submit.is-busy[b-uabmxabema]::before {
    content: "";
    width: 15px;
    height: 15px;
    border-radius: var(--bk-radius-round);
    border: 2px solid color-mix(in srgb, var(--bk-login-on-accent) 45%, transparent);
    border-top-color: var(--bk-login-on-accent);
    animation: bk-login-spin-b-uabmxabema 0.7s linear infinite;
}

@keyframes bk-login-spin-b-uabmxabema {
    to { transform: rotate(360deg); }
}

/* Sci-fi glow of the glow themes (LoginLayout's bk-login-glow), in dark mode
   only - the same rule as the app's .bk-glow: explicit dark via
   data-bk-theme, or the OS setting when the app never set a mode. */
html[data-bk-theme="dark"] .bk-login-glow .bk-login-title[b-uabmxabema] {
    text-shadow: 0 0 14px color-mix(in srgb, var(--bk-login-accent) 60%, transparent);
}

html[data-bk-theme="dark"] .bk-login-glow .bk-login-logo[b-uabmxabema] {
    filter: drop-shadow(0 0 8px color-mix(in srgb, var(--bk-login-accent) 55%, transparent));
}

html[data-bk-theme="dark"] .bk-login-glow .bk-login-submit[b-uabmxabema] {
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--bk-login-accent) 55%, transparent),
        0 0 22px -2px color-mix(in srgb, var(--bk-login-accent) 60%, transparent),
        -5px -5px 12px var(--bk-soft-hi);
}

@media (prefers-color-scheme: dark) {
    html:not([data-bk-theme]) .bk-login-glow .bk-login-title[b-uabmxabema] {
        text-shadow: 0 0 14px color-mix(in srgb, var(--bk-login-accent) 60%, transparent);
    }

    html:not([data-bk-theme]) .bk-login-glow .bk-login-logo[b-uabmxabema] {
        filter: drop-shadow(0 0 8px color-mix(in srgb, var(--bk-login-accent) 55%, transparent));
    }

    html:not([data-bk-theme]) .bk-login-glow .bk-login-submit[b-uabmxabema] {
        box-shadow: 0 0 0 1px color-mix(in srgb, var(--bk-login-accent) 55%, transparent),
            0 0 22px -2px color-mix(in srgb, var(--bk-login-accent) 60%, transparent),
            -5px -5px 12px var(--bk-soft-hi);
    }
}

@media (prefers-reduced-motion: reduce) {
    .bk-login-card[b-uabmxabema],
    .bk-login-card > *[b-uabmxabema],
    .bk-login-logo[b-uabmxabema]  .bk-brand-logo g rect,
    .bk-login-logo[b-uabmxabema]  .bk-brand-logo > rect:last-child {
        animation: none;
    }

    .bk-login-submit:active[b-uabmxabema] {
        transform: none;
    }

    .bk-login-submit:hover[b-uabmxabema]::after {
        animation: none;
    }

    .bk-login-submit:hover .bk-login-submit-icon[b-uabmxabema] {
        transform: none;
    }
}

@media (max-width: 420px) {
    .bk-login-card[b-uabmxabema] {
        padding: 32px 22px 26px;
        border-radius: var(--bk-radius-xl);
    }
}
/* /Components/Pages/ProjectAudit.razor.rz.scp.css */
/* Inspector layout: finding list on the left, the selected finding at full
   width on the right (VisualizationGallery needs the room, not the indented
   remainder of an expanded list card). Below 959.98px (Breakpoint.Md, the
   same threshold ProjectAudit.razor's IBrowserViewportService subscription
   uses to decide push-vs-replace navigation) the grid collapses to one
   column, and .bk-audit-detail turns into a full-screen overlay instead of a
   second stacked block - see .bk-audit-detail-open below.

   Both columns are capped at the same viewport-relative height, so list and
   detail scroll inside themselves instead of growing the page: a long finding
   used to push the page header and the tab bar out of view and leave the
   short list column next to a screen of dead space.

   The subtracted offset is everything this page puts around the two columns,
   not a round guess - keep it in sync when one of these changes:
     24px .bk-page padding-top (app.css)
     38px page header row (ProjectPageHeader one-line layout, button height)
     16px its margin-bottom
     16px MudTabs mt-4
     48px tab bar (.mud-tabs-tabbar-inner min-height)
     12px + 12px the grid's own py-3
     24px .bk-page padding-bottom
   dvh rather than vh so the mobile browser's collapsing address bar does not
   leave the columns overhanging the visible area. */
.bk-audit-grid[b-3nusueyhq6] {
    --bk-audit-inspector-height: calc(100dvh - 190px);
    display: grid;
    grid-template-columns: minmax(0, 340px) minmax(500px, 1fr);
    gap: 12px;
    /* Stretch, so the detail pane is as tall as the list instead of ending at
       its content and leaving the right half of the screen empty below a short
       finding - the inspector reads as two panes of equal height. */
    align-items: stretch;
}

@media (max-width: 959.98px) {
    .bk-audit-grid[b-3nusueyhq6] {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* The status filter shares the tab bar row instead of forming a third band of
   chrome under it (the page used to open with an explanatory paragraph, a tab
   row and a filter row above the first finding). MudTabs renders its Header
   fragment inside .mud-tabs-tabbar-inner, i.e. already in the tab bar's flex
   row, so it only needs to be pushed to the trailing edge. It must not shrink:
   .mud-tabs-tabbar-content claims width 100%, and with a shrinkable header the
   chips would be squeezed to nothing instead of the tab strip yielding (which
   is what MudBlazor's scroll buttons are for). The hairline under the tab bar
   replaces the MudDivider that used to sit below the in-panel filter row.

   Only on wide viewports: below the inspector breakpoint the filter is rendered
   inside the panel again (see FilterChipsRow in ProjectAudit.razor), where it
   sticks to the top of the scrolling list. */
@media (min-width: 960px) {
    .bk-audit-tabs[b-3nusueyhq6]  .mud-tabs-header-after {
        display: flex;
        align-items: center;
        flex: 0 0 auto;
        margin-left: auto;
        padding-right: 16px;
    }

    .bk-audit-tabs[b-3nusueyhq6]  .mud-tabs-tabbar {
        border-bottom: 1px solid var(--mud-palette-lines-default);
    }
}

/* Own scroll container, capped viewport-relative like .bk-components-tree:
   only this element scrolls on selection change, so its scroll position
   survives a re-render (the row @key values keep the DOM nodes themselves
   stable across selection changes). It stays mounted even while the detail
   overlay covers the screen on narrow viewports, which is exactly what keeps
   this scroll position (and the tab's status filter) alive across the mobile
   back-navigation.

   overflow-x is pinned to hidden on purpose: with only overflow-y set, the
   other axis computes from visible to auto and the list grew a stray
   horizontal scrollbar under it. */
.bk-audit-list[b-3nusueyhq6] {
    display: flex;
    flex-direction: column;
    max-height: var(--bk-audit-inspector-height);
    min-height: 220px;
    overflow-y: auto;
    overflow-x: hidden;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    background: var(--mud-palette-surface);
}

/* One card holding hairline-separated rows, instead of 72 individually
   bordered cards stacked with a gap: the same backlog reads as a single list
   and fits noticeably more findings per screen. */
.bk-audit-row[b-3nusueyhq6] {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    padding: 8px 12px;
    cursor: pointer;
    border-left: 2px solid transparent;
}

.bk-audit-row + .bk-audit-row[b-3nusueyhq6] {
    border-top: 1px solid var(--mud-palette-lines-default);
}

.bk-audit-row:hover[b-3nusueyhq6] {
    background: var(--mud-palette-action-default-hover);
}

/* The one accent color the redesign keeps: selection is the page's only
   colored channel besides the primary action buttons. */
.bk-audit-row-selected[b-3nusueyhq6],
.bk-audit-row-selected:hover[b-3nusueyhq6] {
    border-left-color: var(--mud-palette-primary);
    background: var(--mud-palette-primary-hover);
}

/* Severity, category, status and timestamp on one line above the title: two
   lines per row instead of three, and the timestamp no longer needs the word
   "bestätigt" (it is in the row's title attribute for the full phrasing). */
.bk-audit-row-meta[b-3nusueyhq6] {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.bk-audit-row-spacer[b-3nusueyhq6] {
    flex: 1 1 auto;
}

.bk-audit-row-time[b-3nusueyhq6] {
    flex: 0 0 auto;
    white-space: nowrap;
}

.bk-audit-sev[b-3nusueyhq6] {
    flex: 0 0 auto;
    white-space: nowrap;
}

/* Two-line clamp instead of a single-line ellipsis - a finding's title is the
   one thing worth reading in full even if it wraps. */
.bk-audit-row-title[b-3nusueyhq6] {
    font-size: 0.8125rem;
    line-height: 1.45;
    font-weight: 500;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Severity gutter: a fixed-width column so every row's icon sits on the same
   x-axis, letting the existing Severity-descending sort (see
   ThenByDescending(f => f.Severity) in the filtered query) read as a visible
   staircase while scrolling. The icon is decorative now - the label next to it
   carries the meaning for screen readers as well as for scanning eyes. Sits in
   a scoped stylesheet rather than app.css because it is local to this page's
   backlog rows, per the app.css convention. */
.bk-audit-severity[b-3nusueyhq6] {
    display: inline-grid;
    place-items: center;
    width: 20px;
    flex: 0 0 auto;
}

/* The two MudIcon layers (full 3-bar outline behind the stage-specific icon)
   occupy the same grid cell so they render on top of each other instead of
   side by side; reached with ::deep because MudIcon, not this component,
   owns the rendered svg element. */
.bk-audit-severity[b-3nusueyhq6]  .bk-audit-severity-empty,
.bk-audit-severity[b-3nusueyhq6]  .bk-audit-severity-filled {
    grid-area: 1 / 1;
}

/* Neutral colors in both layers (never the category's alarm/success color):
   Severity already carries meaning through bar count, and FeatureIdea must
   never render in red, see AuditSeverityDisplay. Theme variables keep both
   layers visible in light and dark mode. */
.bk-audit-severity[b-3nusueyhq6]  .bk-audit-severity-empty {
    color: var(--mud-palette-lines-default);
}

.bk-audit-severity[b-3nusueyhq6]  .bk-audit-severity-filled {
    color: var(--mud-palette-text-primary);
}

/* Category label: plain text, no per-category hue and no uppercase - it sits
   in a meta line next to sentence-case labels now. Used to carry a 4px colored
   border in five unordered MudBlazor palette hues (including
   Secondary/Tertiary, i.e. pink/turquoise) with one of them falling back to
   --mud-palette-dark, which is invisible in dark mode - moved here from
   app.css (page-local, per the CSS isolation convention) and stripped of
   color entirely, since the redesign keeps a single accent for the
   selection/primary action instead. */
.bk-audit-cat[b-3nusueyhq6] {
    flex: 0 0 auto;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
}

/* Status filter chip row: a flex row with horizontal scroll instead of a
   MudButtonGroup, which either wraps onto a second line or pushes the page
   past the viewport at 360px. Sticky only below the inspector breakpoint - on
   wide viewports the row rides in the tab bar (see the grid above) and
   .bk-audit-list keeps its own scroll area, so nothing needs to stick. */
.bk-audit-filters[b-3nusueyhq6] {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: thin;
}

.bk-audit-filters[b-3nusueyhq6]  .mud-chip {
    flex: 0 0 auto;
}

/* Inline variant (tab bar placement): no padding of its own, the tab bar row
   already provides the height. */
.bk-audit-filters-inline[b-3nusueyhq6] {
    max-width: 100%;
    scrollbar-width: none;
}

.bk-audit-filter-count[b-3nusueyhq6] {
    margin-left: 4px;
    opacity: 0.7;
    font-variant-numeric: tabular-nums;
}

@media (max-width: 959.98px) {
    .bk-audit-filters[b-3nusueyhq6] {
        position: sticky;
        top: 0;
        z-index: 5;
        background: var(--mud-palette-background);
        /* Fade hint at the trailing edge: signals there is more to scroll to
           without a visible scrollbar track on touch devices. */
        mask-image: linear-gradient(to right, black calc(100% - 24px), transparent 100%);
    }
}

/* Below 599.98px there is no mobile app bar any more to stick below (the
   phone shell drops it for the bottom bar instead, feature "Phone navigation
   at the bottom edge") - the filter row sticks to the very top of the page
   again, same as on a tablet with the same layout but the bar still present
   above 600px. */
@media (max-width: 599.98px) {
    .bk-audit-filters[b-3nusueyhq6] {
        top: 0;
    }
}

/* The auditor's remit, formerly a two-sentence paragraph above the tabs, now
   the content of the help menu next to the page title. */
.bk-audit-help-text[b-3nusueyhq6] {
    max-width: 320px;
    padding: 4px 12px;
    font-size: 0.8125rem;
    line-height: 1.55;
    color: var(--mud-palette-text-secondary);
    white-space: normal;
}

/* Detail head: one meta line and the title on the left, the actions on the
   right. On narrow viewports it stacks and the actions move to the bottom bar
   of the overlay instead (see .bk-audit-detail-actions below). */
.bk-audit-detail-head[b-3nusueyhq6] {
    display: flex;
    align-items: flex-start;
    gap: 16px;
}

.bk-audit-detail-head-main[b-3nusueyhq6] {
    flex: 1 1 auto;
    min-width: 0;
}

.bk-audit-detail-meta[b-3nusueyhq6] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.bk-audit-meta-sep[b-3nusueyhq6] {
    color: var(--mud-palette-lines-default);
}

.bk-audit-detail-title[b-3nusueyhq6] {
    margin: 5px 0 0;
    font-size: 1.125rem;
    line-height: 1.35;
    font-weight: 500;
}

/* Labeled detail sections (affected areas, visualizations): a small overline
   caption above each block, separated from the description by a hairline, so
   the page reads as a text followed by its attachments. The description itself
   carries no label - it is the first and only body text. */
.bk-audit-section[b-3nusueyhq6] {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.bk-audit-section-label[b-3nusueyhq6] {
    display: block;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 4px;
}

/* Empty state for an optional section (no affected areas / no visualization
   attached to this finding) - an icon plus a caption instead of a blank gap,
   so the reader can tell "nothing here" from "still loading". */
.bk-audit-empty[b-3nusueyhq6] {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 0;
    color: var(--mud-palette-text-secondary);
}

/* Calmer prose: the auditor writes about types and members, so nearly every
   sentence carries inline code. With app.css's grey pill plus a smaller font
   size per span (which stays global for the other pages) a description read as
   a patchwork, so inside this column inline code is monospace and nothing
   else. Fenced blocks keep their app.css treatment via the :not(pre) guard,
   and the measure is capped at 68 characters instead of the 860px that let a
   line run past 120. */
.bk-audit-detail-body[b-3nusueyhq6]  .bk-markdown {
    max-width: 68ch;
}

.bk-audit-detail-body[b-3nusueyhq6]  .bk-markdown :not(pre) > code {
    background: none;
    padding: 0;
    font-size: 0.92em;
}

/* Collapsed-by-default technical section: only rendered at all when the
   finding carries TechnicalDetails (see ProjectAudit.razor), so a
   non-technical finding shows no toggle and no empty panel here. Capped at
   the same measure as the impact text above it, so opening it does not widen
   the column. */
.bk-audit-technical[b-3nusueyhq6] {
    max-width: 68ch;
}

.bk-audit-technical[b-3nusueyhq6]  .mud-expand-panel-content {
    padding-top: 4px;
}

/* Mobile-only back bar at the top of the detail overlay: hidden on wide
   viewports (the two-column layout needs no way back, it never navigated
   anywhere), shown once .bk-audit-detail-open turns the detail into a
   full-screen overlay below. */
.bk-audit-detail-backbar[b-3nusueyhq6] {
    display: none;
}

.bk-audit-detail-actions[b-3nusueyhq6] {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
}

/* In the head the two buttons stack, so a long label does not squeeze the
   title next to them. */
.bk-audit-detail-actions-head[b-3nusueyhq6] {
    flex: 0 0 auto;
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    margin-top: 0;
}

/* Wide viewports: the detail is a card with its own scroll area, and its head
   sticks to the top of that area - the status, the title and both actions stay
   visible however long the description and the gallery grow. */
@media (min-width: 960px) {
    .bk-audit-detail[b-3nusueyhq6] {
        max-height: var(--bk-audit-inspector-height);
        overflow-y: auto;
        border: 1px solid var(--mud-palette-lines-default);
        border-radius: var(--bk-radius-sm);
        background: var(--mud-palette-surface);
    }

    .bk-audit-detail-head[b-3nusueyhq6] {
        position: sticky;
        top: 0;
        z-index: 2;
        padding: 12px 16px;
        background: var(--mud-palette-surface);
        border-bottom: 1px solid var(--mud-palette-lines-default);
    }

    .bk-audit-detail-body[b-3nusueyhq6] {
        padding: 16px;
    }
}

@media (max-width: 959.98px) {
    /* Hidden by default on narrow viewports too: only the selected finding's
       overlay (.bk-audit-detail-open) is shown, so a phone always displays
       exactly one of list or detail, never both and never neither. */
    .bk-audit-detail[b-3nusueyhq6] {
        display: none;
    }

    /* Bildschirmfuellendes Overlay ueber der weiterhin gemounteten Liste: the
       list keeps its DOM node and scroll position underneath (see the risk
       in the architecture proposal), only this layer is repositioned.
       z-index 1350 sits above MudBlazor's AppBar (1300) and Drawer (1100) so
       the overlay truly covers the whole screen including the persistent
       sidebar, but below Dialog (1400) so the convert/dismiss dialogs still
       open on top of it. */
    .bk-audit-detail.bk-audit-detail-open[b-3nusueyhq6] {
        display: flex;
        flex-direction: column;
        position: fixed;
        inset: 0;
        z-index: 1350;
        background: var(--mud-palette-background);
        overflow-y: auto;
        padding: 0 12px 12px;
    }

    .bk-audit-detail-open .bk-audit-detail-backbar[b-3nusueyhq6] {
        display: flex;
        align-items: center;
        gap: 4px;
        position: sticky;
        top: 0;
        z-index: 1;
        margin: 0 -12px;
        padding: 8px 12px;
        background: var(--mud-palette-background);
        border-bottom: 1px solid var(--mud-palette-lines-default);
    }

    .bk-audit-detail-backbar-title[b-3nusueyhq6] {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Stacked head on a phone: no room for a title and two buttons side by
       side, and the buttons are in the bottom bar there anyway. */
    .bk-audit-detail-head[b-3nusueyhq6] {
        flex-direction: column;
        gap: 4px;
        padding-top: 10px;
    }

    .bk-audit-detail-open .bk-audit-detail-body[b-3nusueyhq6] {
        flex: 1 1 auto;
    }

    /* Actions stick to the bottom of the overlay's own scroll area (not the
       page), so they stay reachable without hunting for them regardless of
       how long the description or the visualization gallery grows. */
    .bk-audit-detail-open .bk-audit-detail-actions[b-3nusueyhq6] {
        position: sticky;
        bottom: 0;
        margin: 0 -12px;
        padding: 8px 12px;
        background: var(--mud-palette-background);
        border-top: 1px solid var(--mud-palette-lines-default);
    }
}

/* No fixed mobile MudAppBar to clear on a phone any more (feature "Phone
   navigation at the bottom edge") - the overlay's own inset: 0 above already
   reaches the very top of the viewport, same as it does on a tablet. */
/* /Components/Pages/ProjectConstraints.razor.rz.scp.css */
/* Row separator for the active/archived constraint lists on this page -
   mirrors .bk-req-row on RequirementDetail.razor.css, scoped here since CSS
   isolation does not cross component files. */

.bk-constraint-row:not(:first-child)[b-fn24udijlp] {
    border-top: 1px solid var(--mud-palette-lines-default);
}
/* /Components/Pages/ProjectInventory.razor.rz.scp.css */
.bk-inventory-grid[b-g29u87zp1u] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 12px;
}
/* /Components/Pages/ProjectSettings/AgentSettings.razor.rz.scp.css */
/* Agent settings page: 12 entries in three sections, one compact line each
   until expanded (concept "Agent settings as a dense list, details on
   expand"). Scoped to AgentSettings.razor - no other component renders these
   blocks. The 599.98px breakpoint matches this project's other pages (see
   ProjectPageHeader.razor.css); everything below it additionally has to fit a
   360 px phone viewport with no horizontal scrolling (acceptance criterion),
   which the field row's own stacking rule further down is specifically for.
   The collapsed row is deliberately kept to one compact line (small padding,
   no wrapped description) so all 12 entries plus the three section headings
   fit an 900 px high desktop window without scrolling (acceptance criterion). */

.bk-agent-settings[b-4fsdzm8524] {
    max-width: 960px;
}

.bk-agent-command-bar[b-4fsdzm8524] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 4px;
}

.bk-agent-filter[b-4fsdzm8524] {
    min-width: 220px;
    max-width: 320px;
    flex: 1 1 220px;
}

.bk-agent-section[b-4fsdzm8524] {
    margin-top: 10px;
    margin-bottom: 3px;
}

.bk-agent-section-title[b-4fsdzm8524] {
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 4px;
}

.bk-agent-entry[b-4fsdzm8524] {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    margin-bottom: 3px;
    min-width: 0;
    transition: box-shadow var(--bk-dur-fast) var(--bk-ease-out), background-color var(--bk-dur-fast) var(--bk-ease-out);
}

/* A left accent bar for entries that deviate from the default, read at a
   glance in addition to the "Customized" chip already in the row (criterion
   "every deviating entry is recognizable as such without opening it"). A
   box-shadow rather than a border/padding: it paints inside the entry's
   existing border box instead of adding to it, so it cannot be the thing
   that tips the 900px collapsed-list criterion over. */
.bk-agent-entry-deviating[b-4fsdzm8524] {
    box-shadow: inset 3px 0 0 0 var(--mud-palette-primary);
}

/* Neumorphic design (app.css .bk-soft): each section (pipeline, standalone
   runs, groups) is ONE raised panel and its entries are flat rows inside it,
   parted by a hairline - raising every row on its own read as a stack of
   cramped slabs, since the entries sit only 3px apart. That margin and every
   entry's 1px border box stay exactly as they are (the border only turns
   transparent): both are part of the 900px collapsed-list criterion. The
   panel's own padding is the only height this adds. An expanded entry
   becomes a pressed-in well, keeping the deviation accent on its edge. */
.bk-soft .bk-agent-section[b-4fsdzm8524] {
    padding: 6px 8px 5px;
    border-radius: var(--bk-radius-lg);
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
}

.bk-soft .bk-agent-section-title[b-4fsdzm8524] {
    padding: 2px 4px 0;
}

.bk-soft .bk-agent-entry[b-4fsdzm8524] {
    border-color: transparent;
    border-radius: var(--bk-radius-md);
    box-shadow: none;
}

.bk-soft .bk-agent-entry:not(:last-child)[b-4fsdzm8524] {
    border-bottom-color: var(--mud-palette-lines-default);
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}

.bk-soft .bk-agent-entry-deviating[b-4fsdzm8524] {
    box-shadow: inset 3px 0 0 0 var(--mud-palette-primary);
}

.bk-soft .bk-agent-entry:has(.bk-agent-entry-body)[b-4fsdzm8524] {
    border-color: transparent;
    border-radius: var(--bk-radius-md);
    box-shadow: var(--bk-depth-inset);
}

.bk-soft .bk-agent-entry-deviating:has(.bk-agent-entry-body)[b-4fsdzm8524] {
    box-shadow: var(--bk-depth-inset), inset 3px 0 0 0 var(--mud-palette-primary);
}

/* Same reasoning for the row highlight below: background-color never
   changes an element's box size, so hovering a row to make the dense list
   easier to scan costs no extra height. */
.bk-agent-row:hover[b-4fsdzm8524] {
    background-color: var(--mud-palette-action-default-hover);
}

/* The collapsed row: name, the model in effect, its deviation marker, reset
   and the expand toggle - one line, no other setting readable without
   expanding (acceptance criterion "no further setting"). Padding alone (not
   an explicit min-height) sets the row's height, on top of the chip/icon-
   button's own content box - MudChip's default 4px margin on every side is
   overridden to 0 right below, since left at its default it alone would add
   8px per chip on top of any padding here, and a row carries up to two
   chips (the model in effect plus, when this entry deviates, its marker). */
.bk-agent-row[b-4fsdzm8524] {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 8px;
    padding: 4px 10px;
    min-width: 0;
}

.bk-agent-row[b-4fsdzm8524]  .mud-chip {
    margin: 0;
}

.bk-agent-entry-name[b-4fsdzm8524] {
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* An inset outline (box-shadow, not border-width) instead of the plain flat
   fill MudChip gives it by default: it gives the model actually in effect a
   defined edge to read against the row around it, without the chip growing
   by a single pixel. */
.bk-agent-model-chip[b-4fsdzm8524] {
    flex: none;
    font-weight: 500;
    box-shadow: inset 0 0 0 1px var(--mud-palette-lines-default);
}

.bk-agent-default-hint[b-4fsdzm8524] {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.bk-agent-entry-body[b-4fsdzm8524] {
    padding: 0 16px 12px;
    border-top: 1px solid var(--mud-palette-lines-default);
    padding-top: 10px;
    background-color: var(--mud-palette-background-grey);
    border-bottom-left-radius: var(--bk-radius-sm);
    border-bottom-right-radius: var(--bk-radius-sm);
}

.bk-agent-entry-desc[b-4fsdzm8524] {
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 8px;
}

.bk-agent-entry-fields[b-4fsdzm8524] {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 12px;
    min-width: 0;
}

.bk-agent-entry-field[b-4fsdzm8524] {
    min-width: 200px;
    flex: 1 1 200px;
}

/* Below the phone breakpoint the collapsed row wraps onto two lines (design
   "The same page on a 360 px phone": name above, model/state/controls below)
   instead of shrinking every piece until it is unreadable, and every field of
   an expanded entry stacks on its own full-width line instead of wrapping at
   a fixed min-width that could still, together with padding and borders,
   exceed a 360 px viewport and force horizontal scrolling. */
@media (max-width: 599.98px) {
    .bk-agent-filter[b-4fsdzm8524] {
        min-width: 0;
        max-width: none;
        flex: 1 1 100%;
    }

    .bk-agent-row[b-4fsdzm8524] {
        flex-wrap: wrap;
    }

    /* Forces the name onto its own full-width line so the model chip, its
       state and the reset/expand controls consistently wrap onto a second
       line below it (design "The collapsed row wraps onto two lines"),
       rather than wrapping wherever the available width happens to run out. */
    .bk-agent-entry-name[b-4fsdzm8524] {
        flex: 1 1 100%;
    }

    .bk-agent-entry-fields[b-4fsdzm8524] {
        flex-direction: column;
        align-items: stretch;
    }

    .bk-agent-entry-field[b-4fsdzm8524] {
        min-width: 0;
        width: 100%;
    }
}
/* /Components/Pages/ProjectSettings/MonitoringSettings.razor.rz.scp.css */
/* Scoped styles for MonitoringSettings.razor (concept "Log-Ueberwachungslaeufe
   im Intervall einrichten"): each monitor is one list row, and the note under
   the edit form's access field spells out that a stored secret's value is
   write-only (concept "Geheimnisse fuer die Ueberwachung sicher
   hinterlegen"). Neumorphic design (app.css .bk-soft): both become an inset
   well, the same treatment AgentSettings.razor.css already gives its own
   list rows. */

.bk-monitor-row[b-a7op3qd0w4] {
    padding: 8px 10px;
    border-radius: var(--bk-radius-md);
}

.bk-soft .bk-monitor-row[b-a7op3qd0w4] {
    box-shadow: var(--bk-depth-inset-sm);
}

.bk-monitor-lock[b-a7op3qd0w4] {
    border-radius: var(--bk-radius-md);
    background: var(--mud-palette-background-grey);
}

.bk-soft .bk-monitor-lock[b-a7op3qd0w4] {
    background: transparent;
    box-shadow: var(--bk-depth-inset-sm);
}
/* /Components/Pages/ProjectSettings/SecretsSettings.razor.rz.scp.css */
/* Scoped styles for SecretsSettings.razor (concept "Geheimnisse fuer die
   Ueberwachung sicher hinterlegen"): each stored secret is one list row,
   name and masked value only - the value itself never reaches this page,
   see ProjectSecretService's own doc comment. Neumorphic design (app.css
   .bk-soft): the row becomes an inset well, the same treatment
   AgentSettings.razor.css already gives its own list rows. */

.bk-secret-row[b-cs2csz60je] {
    padding: 8px 10px;
    border-radius: var(--bk-radius-md);
}

.bk-soft .bk-secret-row[b-cs2csz60je] {
    box-shadow: var(--bk-depth-inset-sm);
}
/* /Components/Pages/ProjectSettings/StorageSettings.razor.rz.scp.css */
/* Scoped styles for StorageSettings.razor: the stacked share bar, the
   per-category rows with their sub-item breakdown, and the ranked list of the
   largest single items. Colors come from the page's own palette (inline, one
   per category) and from the app's --mud-palette-* variables, so the page
   works in both themes. */

/* Stacked bar: one segment per category, widths are the shares of the total. */
.st-bar[b-y3osei995t] {
    display: flex;
    height: 8px;
    border-radius: var(--bk-radius-xs);
    overflow: hidden;
    background: var(--mud-palette-background-grey);
}

.st-bar-part[b-y3osei995t] {
    height: 100%;
}

/* Category color chip in front of the category name (matches its bar segment). */
.st-dot[b-y3osei995t] {
    width: 10px;
    height: 10px;
    border-radius: var(--bk-radius-xs);
    flex-shrink: 0;
    align-self: flex-start;
    margin-top: 5px;
}

/* Size plus share, right aligned so the numbers form a column. */
.st-figures[b-y3osei995t] {
    text-align: right;
    white-space: nowrap;
}

/* What occupies a category: role, content type, visualization kind, version. */
.st-subitems[b-y3osei995t] {
    padding-left: 20px;
    margin-top: 8px;
}

.st-subitem[b-y3osei995t] {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 2px 0;
}

.st-count[b-y3osei995t] {
    margin-left: 8px;
    font-size: 0.72rem;
    opacity: 0.75;
}

/* The git mirror is disk, not database - said explicitly rather than implied. */
.st-disk-pill[b-y3osei995t] {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 9px;
    border-radius: var(--bk-radius-pill);
    font-size: 0.7rem;
    background: color-mix(in srgb, var(--mud-palette-warning) 14%, transparent);
    color: var(--mud-palette-warning);
}

.st-disk-pill[b-y3osei995t]  .mud-icon-root {
    font-size: 0.85rem;
}

.st-note[b-y3osei995t] {
    margin-top: 8px;
    padding-left: 20px;
}

/* Largest items: a ranked row each, the label linking to its owning object. */
.st-items[b-y3osei995t] {
    padding: 4px 0;
}

.st-item[b-y3osei995t] {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 16px;
}

.st-item + .st-item[b-y3osei995t] {
    border-top: 1px solid var(--mud-palette-lines-default);
}

.st-rank[b-y3osei995t] {
    flex-shrink: 0;
    width: 22px;
    text-align: right;
    font-size: 0.78rem;
    color: var(--mud-palette-text-secondary);
}

/* The label is rendered by MudLink/MudText, i.e. a child component, so the
   rule has to reach into it from an element this component owns. */
.st-item[b-y3osei995t]  .st-item-label {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* /Components/Pages/ProjectSettings/WorkerImageSettings.razor.rz.scp.css */
/* Scoped styles for WorkerImageSettings.razor. Ports the Design-D look: a
   status pill, an accent scan strip, and each dependency as a compact
   clickable row (icon + name + enabled toggle only) - the details (key,
   install lines, usage note) live in the edit dialog opened on click, not
   inline, per the "just name/icon/toggle by default" design. The raw
   Dockerfile (base image, FROM/USER app) is deliberately not shown on the
   page - see the "Vollstaendigen Docker-Image-Code ansehen" dialog in the
   markup instead. CDS mockup tokens are mapped onto the app's
   --mud-palette-* variables. */

/* Active-image status pill (mockup header chip). */
.wi-status[b-h91ex6kjg4] {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 5px 12px;
    border-radius: var(--bk-radius-pill);
    font-size: 0.8rem;
    background: color-mix(in srgb, var(--mud-palette-success) 14%, transparent);
    color: var(--mud-palette-success);
    max-width: 100%;
}

.wi-status code[b-h91ex6kjg4] {
    font-family: monospace;
    word-break: break-all;
    color: inherit;
}

/* Section head for the dependency list: title left, the detect/add actions
   right - replaces the former full-width accent scan strip so the page is not
   a stack of tinted bars. */
.wi-section-head[b-h91ex6kjg4] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin: 14px 0 10px;
}

/* The dependency rows themselves, and their shared edit dialog, moved to the
   shared WorkerImageDependencyList component (component-local CSS convention)
   - this page only keeps the section head/status/suggestion chrome around it. */

/* Latest suggestion outcome as one compact status line (icon + text + time)
   instead of a MudAlert - keeps the card in the same quiet language as the
   dependency rows above it. */
.wi-sugg-status[b-h91ex6kjg4] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 2px 2px;
}

.wi-sugg-time[b-h91ex6kjg4] {
    margin-left: auto;
    font-size: 0.72rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* The last build attempt's log, shown directly on the page instead of behind
   a dialog - there is only ever the one attempt to show (see WorkerImageBuild's
   own doc comment), so a click-through no longer earns its own step. */
.wi-build-log[b-h91ex6kjg4] {
    font-family: monospace;
    font-size: 0.78rem;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 260px;
    overflow: auto;
    margin: 8px 0 0;
    background: var(--mud-palette-background-grey);
    padding: 12px;
    border-radius: var(--bk-radius-sm);
}
/* /Components/Pages/ProjectSetupChat.razor.rz.scp.css */
/* The review card's own clamp (concept "Entwurf im Projektstart-Dialog
   kompakt, Chat bleibt bedienbar"): rendered inline in .bk-chat-scroll
   (ChatPanel's ReviewPlacement="ChatReviewPlacement.InlineScroll", see
   ChatSideThreadLayer.razor's .bk-inline-review) instead of the window-height
   .bk-side-review layer every other chat kind uses, so the card sits as
   normal content next to the transcript and the docked composer below it
   never gets covered.

   max-height: 50cqh is what expresses "at most half the chat area" without
   hard-coding a viewport unit. A plain 50% does NOT work here: this card's
   immediate containing block is .bk-inline-review (ChatSideThreadLayer.razor,
   the review fragment's own wrapper), which is deliberately content-sized
   (flex: 0 0 auto, sits below .bk-thread rather than stretching to fill
   .bk-chat-scroll) and therefore has no definite height a percentage could
   resolve against - confirmed by a real-browser run of
   ProjectSetupProposalCardTests (Browser), which measured the card growing
   to its full, unclamped content height instead. cqh resolves against the
   nearest ancestor size container instead of the immediate parent -
   .bk-chat-scroll (ChatSideThreadLayer.razor.css) opts in via
   container-type: size for exactly this, so 50cqh is half of the actual chat
   area regardless of how many content-sized flex boxes sit in between.
   overflow-x: auto plus min-width: 0 is what keeps a long unbroken line (a
   URL, a code identifier) in ContextNotes from forcing the page itself to
   scroll horizontally on a narrow phone viewport instead of just this card.

   Applied to a plain wrapper <div>, authored directly in
   ProjectSetupChat.razor around the MudPaper card, not to MudPaper's own
   Class parameter: MudPaper renders its own root element internally, which
   Blazor CSS isolation never stamps with this component's scope attribute
   and which never ends up a descendant of one either (its parent in the DOM
   is ChatSideThreadLayer's own scoped .bk-inline-review) - a scoped rule
   targeting it, with or without ::deep, could never match. Confirmed against
   the actual rendered DOM: with the class on MudPaper directly, the card
   carried no scope attribute at all (only class/style), so max-height never
   applied and the card grew unclamped to its full content height - the
   failure the real-browser check caught. The wrapper div is authored
   directly here instead, so it gets the scope attribute like any other plain
   element in this file. */
.bk-proposal-card[b-w67xiyx5vs] {
    max-height: 50cqh;
    min-width: 0;
    overflow-y: auto;
    overflow-x: auto;
}

/* "Vollständig anzeigen" unclamps the card in place (not a dialog copy, see
   the architecture decision: a copy would sit outside bkAnnot's selector
   reach and lose its side-thread marking) - no max-height at all, so the
   card simply grows to its natural content height and .bk-chat-scroll's own
   scrollbar takes over instead of this card's inner one. */
.bk-proposal-card-expanded[b-w67xiyx5vs] {
    max-height: none;
}

/* ----- Two columns (concept "Projektrahmen ausserhalb des Chats gefuehrt",
   design "Rahmen als Rail") -----

   The height is duplicated from ChatPanel.razor.css's own .bk-chat-page (the
   same three breakpoints: 48px of page padding, plus the 48px mobile app bar
   below Lg, plus the tighter 12px page padding on a phone). It cannot simply
   be inherited: .bk-chat-page sits INSIDE .bk-setup-chat-col, so without a
   definite height here the row would be sized by whichever column is taller -
   and a frame panel with five expanded rows is regularly taller than the chat,
   which is exactly how the rail used to push the page into its own scrollbar
   and carry "Rahmen bestätigen" below the fold. With a definite height on the
   row, the rail gets the same viewport-height box the chat has and scrolls its
   own rows instead (ProjectFramePanel.razor.css's .bk-frame-rows). */
.bk-setup-layout[b-w67xiyx5vs] {
    display: flex;
    align-items: stretch;
    gap: 24px;
    height: calc(100dvh - 48px);
    min-height: 0;
}

@media (max-width: 1279.98px) {
    .bk-setup-layout[b-w67xiyx5vs] {
        height: calc(100dvh - 96px);
    }
}

/* The chat column takes whatever the rail leaves (the former 640px cap is
   gone - the page itself is allowed up to 1600px by app.css's .bk-page, so on
   a wide screen that cap left several hundred pixels of the content area
   empty). Readability does not come from capping this column: the transcript
   caps each text block's own measure instead (ChatTranscript.razor.css), and
   the proposal card is the one element that genuinely wanted the extra width. */
.bk-setup-chat-col[b-w67xiyx5vs] {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
}

/* The first screen of a brand new project (/projects/new): no project row
   exists yet, so no rail is rendered and this column is the row's only child.
   A welcome screen and a composer stretched across 1400px read as a form that
   lost its page, hence the cap that the two-column case no longer needs (a
   real-browser check previously measured this column's own composer at 1002px
   on a 1280px window with no frame beside it). */
.bk-setup-layout-solo .bk-setup-chat-col[b-w67xiyx5vs] {
    max-width: 720px;
}

.bk-setup-frame-col[b-w67xiyx5vs] {
    flex: 0 0 380px;
    width: 380px;
    min-height: 0;
}

/* The sheet's own grip and close action: phone-only furniture, so it claims
   no height at all while the column is a rail beside the chat. Both children
   are styled unconditionally - only whether the head is laid out at all
   depends on the breakpoint. */
.bk-setup-frame-sheet-head[b-w67xiyx5vs] {
    display: none;
    align-items: center;
    justify-content: flex-end;
    position: relative;
    flex: 0 0 auto;
    padding: 8px 8px 0 8px;
}

/* Absolutely positioned rather than a flex child, so it stays centred on the
   sheet regardless of the close button beside it. */
.bk-setup-frame-grip[b-w67xiyx5vs] {
    position: absolute;
    left: 50%;
    top: 10px;
    transform: translateX(-50%);
    width: 38px;
    height: 4px;
    border-radius: var(--bk-radius-xs);
    background: var(--mud-palette-action-disabled);
}

/* ::deep - MudIconButton renders its own root element, which this scope
   attribute does not reach. */
.bk-setup-frame-sheet-head[b-w67xiyx5vs]  .bk-setup-frame-close {
    color: var(--mud-palette-text-secondary);
}

/* The one-line summary bar is the phone's stand-in for the rail
   (ProjectFrameSummaryBar) - above the breakpoint the rail itself is on
   screen, so the bar would only repeat it. */
.bk-setup-frame-summary[b-w67xiyx5vs] {
    display: none;
}

/* The name field rides in the header's own context slot now. Text variant,
   dense, and capped so a long project name cannot push the status pills and
   Discard off the title row. */
.bk-setup-name-field[b-w67xiyx5vs] {
    max-width: 260px;
    margin-top: 0;
}

/* ----- Phone and narrow tablet -----
   Below this width two columns stop working: the rail wants 380px and the
   chat needs a readable measure of its own, so at ~900px the chat would be
   left with barely 400px minus the page padding. The rail becomes a sheet
   the summary bar opens instead - the frame stays one tap away rather than
   wrapping below an entire conversation, which is where flex-wrap used to
   put it. */
@media (max-width: 899.98px) {
    .bk-setup-layout[b-w67xiyx5vs] {
        display: block;
        height: auto;
        min-height: 0;
    }

    .bk-setup-layout-solo .bk-setup-chat-col[b-w67xiyx5vs] {
        max-width: none;
    }

    .bk-setup-frame-summary[b-w67xiyx5vs] {
        display: block;
        margin-top: 8px;
    }

    .bk-setup-frame-backdrop[b-w67xiyx5vs] {
        position: fixed;
        inset: 0;
        z-index: 1200;
        background: rgba(0, 0, 0, 0.55);
    }

    /* Above MudBlazor's own app bar (z-index 1100) so the sheet is not cut off
       by it, and translated fully out of the way - plus visibility, so a
       closed sheet is not a keyboard trap sitting just past the bottom edge. */
    .bk-setup-frame-col[b-w67xiyx5vs] {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1201;
        width: auto;
        height: min(86dvh, 720px);
        display: flex;
        flex-direction: column;
        background: var(--mud-palette-surface);
        border-top: 1px solid var(--mud-palette-lines-default);
        border-radius: var(--bk-radius-lg) var(--bk-radius-lg) 0 0;
        box-shadow: 0 -10px 34px rgba(0, 0, 0, 0.35);
        transform: translateY(101%);
        visibility: hidden;
        transition: transform var(--bk-dur-base) var(--bk-ease-out), visibility var(--bk-dur-base) var(--bk-ease-out);
    }

    .bk-setup-frame-col-open[b-w67xiyx5vs] {
        transform: translateY(0);
        visibility: visible;
    }

    .bk-setup-frame-sheet-head[b-w67xiyx5vs] {
        display: flex;
    }

    /* The panel inside is the whole sheet below the grip; its own border and
       corners would draw a second box inside the sheet's. ::deep because
       .bk-frame-panel is rendered by ProjectFramePanel, which this scope
       attribute does not reach. */
    .bk-setup-frame-col[b-w67xiyx5vs]  .bk-frame-panel {
        flex: 1 1 auto;
        min-height: 0;
        border: none;
        border-radius: 0;
        background: transparent;
    }

    /* Trimming the crumb row itself lives in ChatPanel.razor.css, which owns
       .bk-chat-head - a rule anchored there from THIS scope would compile to
       .bk-chat-head[scope-of-this-file] and never match anything. */

    .bk-setup-name-field[b-w67xiyx5vs] {
        max-width: 170px;
    }
}
/* /Components/Pages/ProjectTimeline.razor.rz.scp.css */
/* Timeline page only - the order view's entry rows and the graph view's
   canvas. Scoped to ProjectTimeline; the spine itself (bk-spine, bk-sp-*)
   stays in app.css because FeatureDetail draws one too.

   In the app's neumorphic design (app.css .bk-soft): entries and graph nodes
   are raised cards on the page tone, the implementation box a raised key and
   a state a label pressed into the card; the entry to start with, and the
   selected node, carry an accent ring on top of their shadow. */

/* The running-update chip in the header's Context slot: it carries the same
   sentence app.css's shared .bk-head-chip cuts off at 340px (who started it,
   how long ago, and that the list is the previous order), so it gets a wider
   ceiling here rather than a shortened wording - most needed for the German
   text, which runs longer than the English one. */
.bk-tl-running-chip[b-5be14rnaxs] {
    max-width: 480px;
    color: var(--mud-palette-primary);
}

/* Mode switch in the header's Actions slot: a groove pressed into the
   header, the active mode a key raised out of it. */
.bk-tl-modes[b-5be14rnaxs] {
    display: inline-flex;
    gap: 2px;
    padding: 3px;
    border-radius: var(--bk-radius-md);
    box-shadow: var(--bk-depth-inset-sm);
}

.bk-tl-mode[b-5be14rnaxs] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 13px;
    border: 0;
    border-radius: var(--bk-radius-sm);
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font-family: inherit;
    font-size: 0.75rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color var(--bk-dur-fast) var(--bk-ease-out), color var(--bk-dur-fast) var(--bk-ease-out), box-shadow var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-tl-mode:hover:not(.bk-tl-mode-on)[b-5be14rnaxs] {
    color: var(--mud-palette-text-primary);
}

.bk-tl-mode:focus-visible[b-5be14rnaxs] {
    outline: none;
    box-shadow: var(--bk-ring);
}

.bk-tl-mode-on[b-5be14rnaxs] {
    background: var(--mud-palette-surface);
    color: var(--mud-palette-primary);
    font-weight: 600;
    box-shadow: var(--bk-depth-raised-sm);
}

.bk-glow .bk-tl-mode-on[b-5be14rnaxs] {
    text-shadow: 0 0 10px rgba(var(--mud-palette-primary-rgb), 0.6);
}

/* What moved since the last visit, above the order rather than below it */
.bk-tl-strip-spacer[b-5be14rnaxs] {
    flex: 1 1 auto;
}

/* Grouping marker: the top-level requirement an entry hangs under.
   The six accents come in light/dark pairs like the bk-pill classes in
   app.css, and for the same reason: the marker carries a text label beside
   its swatch, and one tone cannot clear 4.5:1 on both surfaces. The dark
   halves below are backgrounds in light mode and would sink into the dark
   surface as text, so dark mode takes the light halves instead. */
.bk-tl-g0[b-5be14rnaxs] { --bk-tl-group: #0C447C; }
.bk-tl-g1[b-5be14rnaxs] { --bk-tl-group: #3C3489; }
.bk-tl-g2[b-5be14rnaxs] { --bk-tl-group: #633806; }
.bk-tl-g3[b-5be14rnaxs] { --bk-tl-group: #085041; }
.bk-tl-g4[b-5be14rnaxs] { --bk-tl-group: #72243E; }
.bk-tl-g5[b-5be14rnaxs] { --bk-tl-group: #27500A; }

.bk-dark .bk-tl-g0[b-5be14rnaxs] { --bk-tl-group: #B5D4F4; }
.bk-dark .bk-tl-g1[b-5be14rnaxs] { --bk-tl-group: #CECBF6; }
.bk-dark .bk-tl-g2[b-5be14rnaxs] { --bk-tl-group: #FAC775; }
.bk-dark .bk-tl-g3[b-5be14rnaxs] { --bk-tl-group: #9FE1CB; }
.bk-dark .bk-tl-g4[b-5be14rnaxs] { --bk-tl-group: #F4C0D1; }
.bk-dark .bk-tl-g5[b-5be14rnaxs] { --bk-tl-group: #C0DD97; }

.bk-tl-swatch[b-5be14rnaxs] {
    width: 9px;
    height: 9px;
    border-radius: var(--bk-radius-xs);
    flex-shrink: 0;
    background: var(--bk-tl-group, var(--mud-palette-text-disabled));
}

.bk-tl-node-group[b-5be14rnaxs],
.bk-tl-detail-group[b-5be14rnaxs] {
    color: var(--bk-tl-group, var(--mud-palette-text-secondary));
}

.bk-tl-wave-dot[b-5be14rnaxs] {
    font-size: 11px;
    font-weight: 600;
}

.bk-tl-wave-head[b-5be14rnaxs] {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    padding-bottom: 9px;
}

.bk-tl-wave-label[b-5be14rnaxs] {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-secondary);
}

.bk-tl-wave-label-now[b-5be14rnaxs] {
    color: var(--mud-palette-primary);
}

/* Just the number beside the wave name; the sentence that used to sit here
   is said once in the footnote. */
.bk-tl-wave-count[b-5be14rnaxs] {
    font-size: 0.6875rem;
    color: var(--mud-palette-text-disabled);
}

/* One timeline entry, collapsed to a single line until opened: a raised
   card, with room below for its shadow. */
.bk-tl-entry[b-5be14rnaxs] {
    background: var(--mud-palette-surface);
    border-radius: var(--bk-radius-lg);
    box-shadow: var(--bk-depth-raised-sm);
    margin-bottom: 10px;
    overflow: hidden;
}

/* The entry the page is telling the user to start with carries the same ring
   the selected node gets in the graph, so "start here" reads identically in
   both modes. */
.bk-tl-entry-lead[b-5be14rnaxs] {
    box-shadow: var(--bk-depth-raised), 0 0 0 2px color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
}

.bk-glow .bk-tl-entry-lead[b-5be14rnaxs] {
    box-shadow: var(--bk-depth-raised), 0 0 0 1px rgba(var(--mud-palette-primary-rgb), 0.6),
        0 0 18px -2px rgba(var(--mud-palette-primary-rgb), 0.45);
}

/* One row, three parts: the toggle takes the flexible left, the state (or the
   implementation it belongs to) sits next to it, the chevron closes it off.
   They are siblings rather than nested because the implementation is a link,
   and an anchor inside a button is invalid markup the button would swallow. */
.bk-tl-entry-row[b-5be14rnaxs] {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    padding-right: 6px;
}

.bk-tl-entry-head[b-5be14rnaxs] {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 auto;
    min-width: 0;
    align-self: stretch;
    box-sizing: border-box;
    padding: 10px 0 10px 12px;
    border: 0;
    background: transparent;
    color: inherit;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

.bk-tl-entry-row:hover[b-5be14rnaxs] {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 3%, transparent);
}

/* Flat until pointed at, then a small raised key that sinks in while
   pressed - the same fold key the requirement tree has. */
.bk-tl-chevron-btn[b-5be14rnaxs] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: var(--bk-radius-round);
    background: transparent;
    color: inherit;
    cursor: pointer;
    transition: box-shadow var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-tl-chevron-btn:hover[b-5be14rnaxs] {
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
}

.bk-tl-chevron-btn:active[b-5be14rnaxs] {
    box-shadow: var(--bk-depth-inset-sm);
}

.bk-tl-chevron-btn:focus-visible[b-5be14rnaxs] {
    outline: none;
    box-shadow: var(--bk-ring);
}

/* Several swatches when an entry spans several top-level requirements - a
   bundle may, and one swatch would claim a grouping that holds for only part
   of it. */
.bk-tl-swatches[b-5be14rnaxs] {
    display: inline-flex;
    gap: 2px;
    flex-shrink: 0;
}

/* The implementation and its state in one frame: the state belongs to that
   feature, and two loose chips left the reader pairing them by proximity.
   A raised key, since it is the way into the feature. */
.bk-tl-impl[b-5be14rnaxs] {
    display: inline-flex;
    align-items: stretch;
    flex-shrink: 0;
    max-width: 320px;
    border-radius: var(--bk-radius-pill);
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
    overflow: hidden;
    color: inherit;
    text-decoration: none;
    transition: box-shadow var(--bk-dur-fast) var(--bk-ease-out), transform var(--bk-dur-fast) var(--bk-ease-out);
}

/* The box is the ONLY way from the timeline to a feature's actions, so its
   hover has to be unmistakable. A grey border was not: the row underneath
   already lights up on hover in the neutral hover colour, and the box
   disappeared into it. It takes the primary colour instead - a tint and a
   ring around the lifted key, and an underlined name - which no row hover
   ever uses. */
.bk-tl-impl:hover[b-5be14rnaxs] {
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface));
    box-shadow: var(--bk-depth-lift-sm), 0 0 0 1px color-mix(in srgb, var(--mud-palette-primary) 55%, transparent);
    text-decoration: none;
}

.bk-tl-impl:active[b-5be14rnaxs] {
    transform: translateY(1px);
    box-shadow: var(--bk-depth-inset-sm);
}

.bk-tl-impl:hover .bk-tl-impl-title[b-5be14rnaxs] {
    text-decoration: underline;
}

.bk-tl-impl:hover .bk-tl-impl-name[b-5be14rnaxs] {
    color: var(--mud-palette-primary);
}

.bk-tl-impl:hover .bk-tl-impl-name[b-5be14rnaxs]  .mud-icon-root {
    color: var(--mud-palette-primary);
}

.bk-tl-impl:focus-visible[b-5be14rnaxs] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.bk-tl-impl-name[b-5be14rnaxs] {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    padding: 3px 9px 3px 12px;
    font-size: 0.75rem;
}

.bk-tl-impl-title[b-5be14rnaxs] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-tl-impl-name[b-5be14rnaxs]  .mud-icon-root {
    color: var(--mud-palette-text-secondary);
    flex-shrink: 0;
}

/* The state never truncates: it is the part that has to stay readable. */
.bk-tl-state[b-5be14rnaxs] {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex-shrink: 0;
    padding: 2px 9px;
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
}

.bk-tl-impl-state[b-5be14rnaxs] {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    padding: 2px 10px 2px 8px;
    border-left: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 70%, transparent);
}

.bk-tl-impl:hover .bk-tl-impl-state[b-5be14rnaxs] {
    border-left-color: color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
}

/* A bare state (no implementation yet): a label pressed into the card. */
.bk-tl-state[b-5be14rnaxs] {
    padding: 3px 10px;
    border-radius: var(--bk-radius-pill);
    box-shadow: var(--bk-depth-inset-sm);
}

.bk-tl-impl-state[b-5be14rnaxs]  .mud-icon-root,
.bk-tl-state[b-5be14rnaxs]  .mud-icon-root {
    flex-shrink: 0;
}

.bk-tl-entry-title[b-5be14rnaxs] {
    font-size: 0.875rem;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-tl-node-meta[b-5be14rnaxs] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.bk-tl-bundle-mark[b-5be14rnaxs] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
    font-size: 11px;
    font-weight: 500;
    color: #085041;
}

.bk-dark .bk-tl-bundle-mark[b-5be14rnaxs] {
    color: #9FE1CB;
}

/* In the order row the same mark is a MudIcon, and CSS isolation puts the
   scope attribute on the row rather than on the icon's own svg - so the rule
   above never reaches it and this one has to go through ::deep. */
.bk-tl-entry-head[b-5be14rnaxs]  .bk-tl-bundle-mark {
    color: #085041;
    flex-shrink: 0;
}

.bk-dark .bk-tl-entry-head[b-5be14rnaxs]  .bk-tl-bundle-mark {
    color: #9FE1CB;
}

/* Same reason once more for the graph node, where the mark sits in the head
   line: without ::deep it kept the inherited text colour and read as one more
   grey icon rather than as the bundle marker. */
.bk-tl-node-top[b-5be14rnaxs]  .bk-tl-bundle-mark {
    color: #085041;
    flex-shrink: 0;
}

.bk-dark .bk-tl-node-top[b-5be14rnaxs]  .bk-tl-bundle-mark {
    color: #9FE1CB;
}

/* Same ::deep reason as the bundle mark: the chevron is a MudIcon, so the
   scope attribute sits on the button around it. Without ::deep neither the
   colour nor the open-state rotation ever reached the icon. */
.bk-tl-chevron-btn[b-5be14rnaxs]  .bk-tl-chevron {
    flex-shrink: 0;
    color: var(--mud-palette-text-disabled);
    transition: transform var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-tl-chevron-btn[b-5be14rnaxs]  .bk-tl-chevron-open {
    transform: rotate(180deg);
}

.bk-tl-entry-body[b-5be14rnaxs] {
    border-top: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 60%, transparent);
    padding: 12px 14px 14px;
}

/* Members stand under the top-level requirement they belong to, each group
   with its own accent - rather than one heading above all of them, which said
   something untrue about half a bundle that spans two. */
.bk-tl-group + .bk-tl-group[b-5be14rnaxs] {
    margin-top: 12px;
}

.bk-tl-group-head[b-5be14rnaxs] {
    display: flex;
    align-items: center;
    gap: 6px;
    padding-bottom: 5px;
}

.bk-tl-group-name[b-5be14rnaxs] {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--bk-tl-group, var(--mud-palette-text-secondary));
}

.bk-tl-group-rule[b-5be14rnaxs] {
    flex: 1 1 auto;
    height: 1px;
    background: var(--mud-palette-lines-default);
}

/* The whole requirement - key, title and the chevron - is one link, so the
   pointer target matches what a reader would aim at anyway. */
.bk-tl-member-link[b-5be14rnaxs] {
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
    min-height: 34px;
    padding: 3px 6px 3px 14px;
    margin: 0 -6px;
    border-radius: var(--bk-radius-sm);
    color: inherit;
    text-decoration: none;
    transition: background-color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-tl-member-link:hover[b-5be14rnaxs] {
    background: var(--mud-palette-action-default-hover);
    text-decoration: none;
}

.bk-tl-member-link:hover .bk-tl-member-title[b-5be14rnaxs] {
    color: var(--mud-palette-primary);
}

.bk-tl-member-title[b-5be14rnaxs] {
    font-size: 0.875rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bk-tl-member-link[b-5be14rnaxs]  .bk-tl-member-go {
    color: var(--mud-palette-text-disabled);
    flex-shrink: 0;
}

.bk-tl-member-link:hover[b-5be14rnaxs]  .bk-tl-member-go {
    color: var(--mud-palette-primary);
}

/* Only a removal states what it covers in words - every other entry names
   its requirements and leaves their criteria to the requirement page. */
.bk-tl-member-note[b-5be14rnaxs] {
    font-size: 0.8125rem;
    line-height: 1.43;
    color: var(--mud-palette-text-secondary);
    margin-top: 5px;
}

.bk-tl-reason[b-5be14rnaxs] {
    font-size: 0.8125rem;
    line-height: 1.43;
    color: var(--mud-palette-text-secondary);
    margin-top: 8px;
}

.bk-tl-relations[b-5be14rnaxs] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 10px;
}

.bk-tl-relation-label[b-5be14rnaxs] {
    font-size: 0.75rem;
    font-weight: 600;
}

.bk-tl-relation-none[b-5be14rnaxs] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.bk-tl-relation-gap[b-5be14rnaxs] {
    width: 12px;
}

.bk-tl-footnote[b-5be14rnaxs] {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-top: 14px;
    font-size: 0.75rem;
    line-height: 1.66;
    color: var(--mud-palette-text-secondary);
}

.bk-tl-footnote[b-5be14rnaxs]  .mud-icon-root {
    flex-shrink: 0;
    color: var(--mud-palette-text-disabled);
}

/* Graph view. The cell size lives in the component (the SVG edge paths are
   computed from the same numbers), so only the look is here. */
.bk-tl-graph-cols[b-5be14rnaxs] {
    display: grid;
    width: max-content;
    margin-bottom: 10px;
}

.bk-tl-graph-col[b-5be14rnaxs] {
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-disabled);
}

.bk-tl-graph-col-now[b-5be14rnaxs] {
    color: var(--mud-palette-primary);
}

/* How much of the page the surface takes. The canvas itself has no height of
   its own - it fills what its host gives it - and a graph is worth a screen:
   below this it is all panning, above it the page's own content is pushed out
   of sight. */
.bk-tl-canvas[b-5be14rnaxs] {
    display: flex;
    height: 70vh;
    min-height: 420px;
    max-height: 860px;
}

/* No scrollbar of its own any more: the canvas around it is what moves. */
.bk-tl-graph[b-5be14rnaxs] {
    position: relative;
}

/* The lines are the quiet part of the drawing. There is one per stored
   dependency - an entry that waits for six others draws six - so in the accent
   colour they read as a thicket lying over the cards they connect. The neutral
   tone is what keeps them calm; being hard to SEE was a different fault, and
   most of it was the zoom: a hairline inside a layer scaled to 60% arrives as
   half a pixel. non-scaling-stroke takes the width out of the canvas' scale,
   so a line is the same weight however far away the graph is seen from.

   Three states, declared weakest first so the stronger statement wins where a
   line belongs to both: plain, the chain a hover asks about, the chain a
   selection names. */
.bk-tl-edge[b-5be14rnaxs] {
    stroke: var(--mud-palette-text-disabled);
    stroke-width: 1.2;
    /* The disabled tone is much stronger on the light surface than on the dark
       one (0.38 against 0.2 alpha), so the light theme takes it down to where
       both read as the same weight. */
    opacity: 0.6;
    vector-effect: non-scaling-stroke;
}

.bk-dark .bk-tl-edge[b-5be14rnaxs] {
    opacity: 1;
}

.bk-tl-edge-head[b-5be14rnaxs] {
    fill: var(--mud-palette-text-disabled);
    opacity: 0.6;
}

.bk-dark .bk-tl-edge-head[b-5be14rnaxs] {
    opacity: 1;
}

.bk-tl-edge-pre[b-5be14rnaxs] {
    stroke: var(--mud-palette-primary);
    stroke-width: 1.5;
    opacity: 0.8;
}

.bk-tl-edge-head-pre[b-5be14rnaxs] {
    fill: var(--mud-palette-primary);
    opacity: 0.8;
}

.bk-tl-edge-lit[b-5be14rnaxs] {
    stroke: var(--mud-palette-primary);
    stroke-width: 1.8;
}

.bk-tl-edge-head-lit[b-5be14rnaxs] {
    fill: var(--mud-palette-primary);
}

.bk-tl-graph > svg[b-5be14rnaxs] {
    position: absolute;
    left: 0;
    top: 0;
}

/* A node is a card, not a button: its foot carries a link to the feature and
   the start action, and an anchor or a button nested in a button is invalid
   markup whose click the outer one swallows. Selecting the node is its own
   control, filling the card above the foot. */
.bk-tl-node[b-5be14rnaxs] {
    position: absolute;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    /* Transparent rather than gone: the box size is fixed in the component
       (the grid pitch and the edge paths are derived from it). */
    border: 1px solid transparent;
    border-radius: var(--bk-radius-md);
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
    color: inherit;
    overflow: hidden;
    transition: opacity var(--bk-dur-fast) var(--bk-ease-out), border-color var(--bk-dur-fast) var(--bk-ease-out), box-shadow var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-tl-node-pick[b-5be14rnaxs] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 auto;
    min-height: 0;
    padding: 7px 10px 6px;
    border: 0;
    background: transparent;
    color: inherit;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

/* One row for who is on it and what can be done about it. Separated by a
   rule rather than a gap, so a card reads as "what it is" above and "where it
   stands" below. */
.bk-tl-node-foot[b-5be14rnaxs] {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    padding: 5px 10px;
    border-top: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 60%, transparent);
    background: color-mix(in srgb, var(--mud-palette-text-primary) 3%, var(--mud-palette-surface));
}

/* The foot holds either the feature link or the start button, and the card is
   as tall as the taller of the two - so the button comes down to the link's
   height instead of setting the pitch of the whole grid. */
.bk-tl-node-foot[b-5be14rnaxs]  .mud-button-root {
    min-width: 0;
    min-height: 26px;
    padding: 1px 10px;
    font-size: 0.75rem;
}

.bk-tl-node-foot .bk-tl-impl[b-5be14rnaxs] {
    max-width: 100%;
}

/* An entry that cannot start yet says what it is waiting for. The edges say
   the same thing, but only for the node the eye is already following. */
.bk-tl-node-waiting[b-5be14rnaxs] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-tl-node-waiting[b-5be14rnaxs]  .mud-icon-root {
    color: var(--mud-palette-text-disabled);
    flex-shrink: 0;
}

.bk-tl-node:hover[b-5be14rnaxs] {
    box-shadow: var(--bk-depth-lift-sm);
}

.bk-tl-node-on[b-5be14rnaxs],
.bk-tl-node-on:hover[b-5be14rnaxs] {
    box-shadow: var(--bk-depth-raised), 0 0 0 2px color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
}

.bk-glow .bk-tl-node-on[b-5be14rnaxs],
.bk-glow .bk-tl-node-on:hover[b-5be14rnaxs] {
    box-shadow: var(--bk-depth-raised), 0 0 0 1px rgba(var(--mud-palette-primary-rgb), 0.6),
        0 0 18px -2px rgba(var(--mud-palette-primary-rgb), 0.45);
}

/* Everything with no dependency path to the selection - the set that can be
   worked on in parallel with it. Kept at 0.45 rather than lower so the text
   inside still clears the contrast floor. */
.bk-tl-node-dim[b-5be14rnaxs] {
    opacity: 0.5;
}

.bk-dark .bk-tl-node-dim[b-5be14rnaxs] {
    opacity: 0.62;
}

/* The chain a hover lights: the card under the pointer and everything it
   waits for. A hover is a question asked in passing, so nothing is dimmed for
   it - only the answer brightens, and a card that a selection had dimmed comes
   back to full strength while it is part of the answer. A selection is the
   stronger statement and keeps its own ring. */
.bk-tl-node-pre[b-5be14rnaxs] {
    opacity: 1;
}

.bk-tl-node-pre:not(.bk-tl-node-on)[b-5be14rnaxs] {
    box-shadow: var(--bk-depth-raised-sm), 0 0 0 2px color-mix(in srgb, var(--mud-palette-primary) 28%, transparent);
}

.bk-tl-node-top[b-5be14rnaxs] {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
}

.bk-tl-node-group[b-5be14rnaxs] {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.02em;
    /* A flex item does not shrink below its content without this, so a long
       group name - a bundle joins every top-level requirement it touches -
       pushed itself out of the card instead of ellipsising inside it. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-tl-node-meta[b-5be14rnaxs] {
    flex-shrink: 0;
}

.bk-tl-root-dot[b-5be14rnaxs] {
    width: 6px;
    height: 6px;
    border-radius: var(--bk-radius-round);
    background: var(--mud-palette-primary);
    flex-shrink: 0;
}

.bk-tl-node-titles[b-5be14rnaxs] {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
    overflow: hidden;
}

/* The key rides in the title line, so it is set as a marker rather than as a
   pill: a pill's own padding and line-height would make every member line as
   tall as the row of pills this replaced. */
.bk-tl-node-key[b-5be14rnaxs] {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--mud-palette-text-secondary);
    /* The gap is a margin, not a space in the markup: Blazor drops
       whitespace-only text nodes, so the key would otherwise sit flush
       against the title. */
    margin-right: 5px;
}

.bk-tl-node-key-archived[b-5be14rnaxs] {
    text-decoration: line-through;
    color: var(--mud-palette-text-disabled);
}

/* A bundle lists one line per member, a single entry gets up to two. Clamped
   rather than clipped: the node box is fixed (the row pitch is derived from
   it), so an over-long title has to end in an ellipsis instead of being cut
   through the middle of a word. */
.bk-tl-node-title[b-5be14rnaxs] {
    font-size: 11px;
    line-height: 1.35;
    font-weight: 500;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

.bk-tl-node-titles .bk-tl-node-title:not(:only-child)[b-5be14rnaxs] {
    -webkit-line-clamp: 1;
    line-clamp: 1;
}

.bk-tl-detail[b-5be14rnaxs] {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 18px;
    padding: 12px 16px;
    background: var(--mud-palette-surface);
    border-radius: var(--bk-radius-lg);
    box-shadow: var(--bk-depth-raised), 0 0 0 2px color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
}

.bk-tl-detail-main[b-5be14rnaxs] {
    min-width: 0;
    flex-grow: 1;
}

.bk-tl-detail-head[b-5be14rnaxs] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.bk-tl-detail-group[b-5be14rnaxs] {
    font-size: 0.75rem;
    font-weight: 600;
}

.bk-tl-detail-sep[b-5be14rnaxs] {
    color: var(--mud-palette-text-disabled);
}

.bk-tl-detail-title[b-5be14rnaxs] {
    font-size: 0.875rem;
    font-weight: 500;
}

.bk-tl-detail-links[b-5be14rnaxs] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    align-items: flex-start;
    min-width: 0;
}

/* The order view's own markup renders even while the graph is the chosen
   view (ProjectTimeline.razor renders it unconditionally, with this class
   whenever _mode is Graph) - hidden here by default so tablet/desktop keep
   today's exact look, and turned back on by the phone breakpoint below so a
   phone always shows the order, never the graph, however the page address
   names the view. Compound with the element's own class (rather than
   ".bk-tl-order-phone-only" alone) so this reliably outweighs
   .bk-spine/.bk-tl-footnote's own base rule in app.css regardless of
   stylesheet load order. */
.bk-spine.bk-tl-order-phone-only[b-5be14rnaxs],
.bk-tl-footnote.bk-tl-order-phone-only[b-5be14rnaxs] {
    display: none;
}

/* The phone status line and its fold-out (Actions slot): hidden outside the
   phone breakpoint, where the three header chips and the "show all updates"
   link (both further above/below) already carry the same information. */
.bk-tl-phone-status-wrap[b-5be14rnaxs] {
    display: none;
}

/* Phone: the graph cannot survive a left-to-right flow at 336px of usable
   width (three cards do not fit side by side at any legible size), so the
   mode switch drops the graph and the order view - which is the same waves
   turned a quarter turn - carries the whole page. The wave number moves into
   the section head, since app.css hides the spine rail below Sm. */
@media (max-width: 599.98px) {
    .bk-tl-modes[b-5be14rnaxs] {
        display: none;
    }

    /* Its destination moves into the phone status line's own fold-out
       instead (bk-tl-phone-detail-link below). */
    .bk-tl-history-link-wrap[b-5be14rnaxs] {
        display: none;
    }

    /* The three chips give way to the single status line below - see the
       phone status rules further down. Compound with .bk-head-chip (rather
       than ".bk-tl-chip-desktop" alone) so this reliably outweighs that
       shared class's own "display: inline-flex" in app.css regardless of
       stylesheet load order. */
    .bk-head-chip.bk-tl-chip-desktop[b-5be14rnaxs] {
        display: none;
    }

    .bk-tl-order-phone-only.bk-spine[b-5be14rnaxs] {
        display: grid;
    }

    .bk-tl-order-phone-only.bk-tl-footnote[b-5be14rnaxs] {
        display: flex;
    }

    /* The graph itself (and the detail strip below it) is what the order
       view above takes over from on a phone - never drawn here, whatever
       the page address names as the view. */
    .bk-tl-graph-phone-hidden[b-5be14rnaxs] {
        display: none;
    }

    .bk-tl-wave-head[b-5be14rnaxs] {
        gap: 6px;
    }

    /* The cards keep their shape instead of bleeding to the screen edges,
       as they did while they were outlined: a raised card needs its rounded
       outline and a little tone around it to read as one. */
    .bk-tl-entry[b-5be14rnaxs] {
        border-radius: var(--bk-radius-md);
    }

    /* Tap target stays at 44px even though the row is denser than that. The
       whole title row also takes its own full-width line now rather than
       sharing one with the implementation box/state/Start button below it -
       those wrap onto a line of their own (bk-tl-entry-row's own flex-wrap
       below), which is what keeps a long implementation name from pushing
       the row wider than the screen. */
    .bk-tl-entry-head[b-5be14rnaxs] {
        min-height: 44px;
        flex-wrap: wrap;
        flex: 1 1 100%;
    }

    .bk-tl-entry-row[b-5be14rnaxs] {
        flex-wrap: wrap;
        row-gap: 4px;
    }

    .bk-tl-entry-title[b-5be14rnaxs] {
        flex-basis: 100%;
        white-space: normal;
        overflow-wrap: anywhere;
    }

    /* Closed: at most two lines, exactly like a graph node's own title
       clamp. Opened: the full title, unclamped. */
    .bk-tl-entry:not(.bk-tl-entry-open) .bk-tl-entry-title[b-5be14rnaxs] {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

    .bk-tl-entry-deps[b-5be14rnaxs] {
        white-space: normal;
    }

    /* The implementation box shrinks with the row instead of holding its
       desktop 320px floor, and its own name ellipsises within whatever
       space that leaves rather than forcing the row wider than the screen. */
    .bk-tl-impl[b-5be14rnaxs] {
        max-width: 100%;
        flex: 1 1 auto;
        min-width: 0;
    }

    .bk-tl-impl-name[b-5be14rnaxs] {
        min-width: 0;
    }

    .bk-tl-impl-title[b-5be14rnaxs] {
        min-width: 0;
    }

    .bk-tl-footnote[b-5be14rnaxs] {
        padding-left: 0;
    }

    /* The one-line status button: an inset pill spanning the row, same
       depth language as the fold-out beneath it. */
    .bk-tl-phone-status-wrap[b-5be14rnaxs] {
        display: block;
        width: 100%;
        margin: 2px 0 0;
    }

    .bk-tl-phone-status[b-5be14rnaxs] {
        display: flex;
        align-items: center;
        gap: 6px;
        width: 100%;
        box-sizing: border-box;
        border: 0;
        background: transparent;
        color: var(--mud-palette-text-secondary);
        border-radius: var(--bk-radius-pill);
        padding: 7px 14px;
        font: inherit;
        font-size: 0.75rem;
        text-align: left;
        cursor: pointer;
        box-shadow: var(--bk-depth-inset-sm);
    }

    .bk-tl-phone-status-running[b-5be14rnaxs] {
        color: var(--mud-palette-primary);
    }

    .bk-tl-phone-status-text[b-5be14rnaxs] {
        flex: 1 1 auto;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .bk-tl-phone-status[b-5be14rnaxs]  .mud-icon-root {
        flex-shrink: 0;
    }

    .bk-tl-phone-status[b-5be14rnaxs]  .bk-tl-phone-status-chev {
        transition: transform var(--bk-dur-fast) var(--bk-ease-out);
    }

    .bk-tl-phone-status[b-5be14rnaxs]  .bk-tl-phone-status-chev-open {
        transform: rotate(180deg);
    }

    /* The fold-out: last update, next update, total cost, "show all
       updates" - one row each, opened and closed by the status button
       above it (concept: the fold-out opens in place on the page itself,
       not in a dialog or bottom sheet). */
    .bk-tl-phone-details[b-5be14rnaxs] {
        margin-top: 8px;
        padding: 6px 14px 10px;
        background: var(--mud-palette-surface);
        border-radius: var(--bk-radius-lg);
        box-shadow: var(--bk-depth-raised-sm);
        font-size: 0.8125rem;
    }

    .bk-tl-phone-detail-row[b-5be14rnaxs] {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 7px 0;
        border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 60%, transparent);
    }

    .bk-tl-phone-detail-row:last-of-type[b-5be14rnaxs] {
        border-bottom: 0;
    }

    .bk-tl-phone-detail-row[b-5be14rnaxs]  .mud-icon-root {
        color: var(--mud-palette-text-secondary);
        flex-shrink: 0;
    }

    .bk-tl-phone-detail-label[b-5be14rnaxs] {
        flex: 1 1 auto;
        color: var(--mud-palette-text-secondary);
    }

    .bk-tl-phone-detail-value[b-5be14rnaxs] {
        text-align: right;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        max-width: 60%;
    }

    .bk-tl-phone-detail-link[b-5be14rnaxs] {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 6px;
        width: 100%;
        box-sizing: border-box;
        margin-top: 8px;
        padding: 7px;
        border: 1px solid var(--mud-palette-primary);
        border-radius: var(--bk-radius-md);
        color: var(--mud-palette-primary);
        text-decoration: none;
        font-size: 0.8125rem;
        font-weight: 500;
        box-shadow: var(--bk-depth-raised-sm);
    }

    .bk-tl-phone-detail-link:hover[b-5be14rnaxs] {
        text-decoration: none;
    }

    .bk-tl-phone-detail-link[b-5be14rnaxs]  .mud-icon-root {
        color: inherit;
    }
}

/* A feature that has left the list: finished, or archived before it could.
   One row, the whole row a link to it - the same shape a member row in an
   opened entry has, because it answers the same question. */
.bk-tl-closed[b-5be14rnaxs] {
    display: flex;
    align-items: center;
    gap: 9px;
    min-height: 36px;
    padding: 4px 8px;
    border-radius: var(--bk-radius-sm);
    color: inherit;
    text-decoration: none;
    transition: background-color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-tl-closed:hover[b-5be14rnaxs] {
    background: var(--mud-palette-action-default-hover);
    text-decoration: none;
}

.bk-tl-closed-main[b-5be14rnaxs] {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.bk-tl-closed-title[b-5be14rnaxs] {
    font-size: 0.875rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-tl-closed-reason[b-5be14rnaxs] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-disabled);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-tl-closed-since[b-5be14rnaxs] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    flex-shrink: 0;
}

.bk-tl-closed[b-5be14rnaxs]  .bk-tl-closed-done {
    color: var(--mud-palette-success);
    flex-shrink: 0;
}

.bk-tl-closed[b-5be14rnaxs]  .bk-tl-closed-archived {
    color: var(--mud-palette-text-disabled);
    flex-shrink: 0;
}
/* /Components/Pages/ProjectTimelineHistory.razor.rz.scp.css */
/* The update history. Same visual grammar as the panel on the implementation
   page - a run's weight readable before a word of it, its kind by colour -
   because the two answer the same question at different zoom levels. */

.bk-tlh-stats[b-a2e1lvqo68] {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 12px 16px;
    border-radius: var(--bk-radius-lg);
    background: var(--mud-palette-surface);
    /* A raised panel in the app's neumorphic design (app.css .bk-soft). */
    box-shadow: var(--bk-depth-raised);
    margin-bottom: 20px;
}

.bk-tlh-stat[b-a2e1lvqo68] {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.bk-tlh-stat-value[b-a2e1lvqo68] {
    font-size: 1.125rem;
    font-weight: 600;
}

.bk-tlh-stat-plain[b-a2e1lvqo68] {
    color: var(--mud-palette-text-primary);
}

.bk-tlh-stat-changed[b-a2e1lvqo68] {
    color: var(--mud-palette-primary);
}

.bk-tlh-stat-failed[b-a2e1lvqo68] {
    color: var(--mud-palette-error);
}

.bk-tlh-stat-manual[b-a2e1lvqo68] {
    color: #0C447C;
}

.bk-dark .bk-tlh-stat-manual[b-a2e1lvqo68] {
    color: #8FB6DF;
}

.bk-tlh-stat-label[b-a2e1lvqo68] {
    font-size: 0.6875rem;
    color: var(--mud-palette-text-secondary);
}

/* The last separator would float at the end of the row; it is cheaper to let
   it render and hide it than to special-case the loop. */
.bk-tlh-stat-sep[b-a2e1lvqo68] {
    width: 1px;
    height: 28px;
    background: var(--mud-palette-lines-default);
}

.bk-tlh-stat-sep:last-of-type[b-a2e1lvqo68] {
    display: none;
}

.bk-tlh-spark-box[b-a2e1lvqo68] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.bk-tlh-spark[b-a2e1lvqo68] {
    display: inline-flex;
    align-items: flex-end;
    gap: 3px;
    height: 26px;
}

.bk-tlh-spark-bar[b-a2e1lvqo68] {
    width: 9px;
    border-radius: var(--bk-radius-xs);
}

.bk-tlh-spark-quiet[b-a2e1lvqo68] {
    background: var(--mud-palette-lines-default);
}

.bk-tlh-spark-busy[b-a2e1lvqo68] {
    background: #BDB6F3;
}

.bk-dark .bk-tlh-spark-busy[b-a2e1lvqo68] {
    background: #4A3FA8;
}

.bk-tlh-spark-failed[b-a2e1lvqo68] {
    background: #E24B4A;
}

.bk-tlh-day[b-a2e1lvqo68] {
    margin-bottom: 14px;
}

.bk-tlh-day-head[b-a2e1lvqo68] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 6px;
}

.bk-tlh-day-label[b-a2e1lvqo68] {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-disabled);
}

.bk-tlh-day-rule[b-a2e1lvqo68] {
    flex: 1 1 auto;
    height: 1px;
    background: var(--mud-palette-lines-default);
}

.bk-tlh-day-summary[b-a2e1lvqo68] {
    font-size: 0.6875rem;
    color: var(--mud-palette-text-disabled);
}

.bk-tlh-run[b-a2e1lvqo68] {
    display: flex;
    align-items: stretch;
    margin-bottom: 4px;
}

.bk-tlh-run-when[b-a2e1lvqo68] {
    width: 84px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    padding: 9px 10px 0 0;
}

.bk-tlh-run-time[b-a2e1lvqo68] {
    font-size: 0.8125rem;
    font-weight: 500;
}

.bk-tlh-run-duration[b-a2e1lvqo68] {
    font-size: 0.6875rem;
    color: var(--mud-palette-text-disabled);
}

/* One axis down the whole day, so a run reads as a point in a sequence
   rather than as another card in a stack. */
.bk-tlh-run-axis[b-a2e1lvqo68] {
    width: 22px;
    flex-shrink: 0;
    position: relative;
    display: flex;
    justify-content: center;
}

.bk-tlh-run-line[b-a2e1lvqo68] {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--mud-palette-lines-default);
}

.bk-tlh-run-dot[b-a2e1lvqo68] {
    position: relative;
    margin-top: 12px;
    width: 11px;
    height: 11px;
    border-radius: var(--bk-radius-round);
    box-sizing: border-box;
    border: 2px solid var(--mud-palette-text-disabled);
    background: var(--mud-palette-surface);
}

.bk-tlh-run-dot-changed[b-a2e1lvqo68] {
    background: var(--mud-palette-primary);
    border-color: var(--mud-palette-primary);
}

.bk-tlh-run-dot-failed[b-a2e1lvqo68] {
    background: #E24B4A;
    border-color: #E24B4A;
}

/* Each run a raised card; a failed one keeps its warning as a ring in the
   error colour on top of the shadow instead of an outline. */
.bk-tlh-run-card[b-a2e1lvqo68] {
    flex: 1 1 auto;
    min-width: 0;
    border-radius: var(--bk-radius-md);
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
    padding: 10px 14px;
}

.bk-tlh-run-card-failed[b-a2e1lvqo68] {
    box-shadow: var(--bk-depth-raised-sm), 0 0 0 1px color-mix(in srgb, var(--mud-palette-error) 60%, transparent);
}

.bk-tlh-run-head[b-a2e1lvqo68] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 7px;
}

.bk-tlh-spacer[b-a2e1lvqo68] {
    flex: 1 1 auto;
}

.bk-tlh-run-quiet[b-a2e1lvqo68] {
    font-size: 0.8125rem;
    color: var(--mud-palette-text-disabled);
}

/* One segment per change, coloured by kind: the weight of a run before a
   word of it. */
.bk-tlh-run-bars[b-a2e1lvqo68] {
    display: inline-flex;
    align-items: center;
    gap: 2px;
}

.bk-tlh-run-bar[b-a2e1lvqo68] {
    width: 6px;
    height: 14px;
    border-radius: var(--bk-radius-xs);
}

.bk-tlh-run-bar-added[b-a2e1lvqo68] {
    background: #7FC3AC;
}

.bk-tlh-run-bar-moved[b-a2e1lvqo68] {
    background: #8FB6DF;
}

.bk-tlh-run-bar-dropped[b-a2e1lvqo68] {
    background: var(--mud-palette-lines-default);
}

.bk-tlh-run-summary[b-a2e1lvqo68] {
    font-size: 0.8125rem;
    line-height: 1.45;
    color: var(--mud-palette-text-secondary);
    margin-top: 5px;
}

.bk-tlh-run-changes[b-a2e1lvqo68] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 7px;
}

/* The pills carry an arrow, so they need the icon to sit on the text
   baseline - the shared bk-pill is a plain inline-block. */
.bk-tlh-run-changes[b-a2e1lvqo68]  .bk-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.bk-tlh-run-changes[b-a2e1lvqo68]  .mud-icon-root {
    font-size: 13px;
}

.bk-tlh-run-error[b-a2e1lvqo68] {
    font-size: 0.8125rem;
    line-height: 1.45;
    color: var(--mud-palette-error);
    margin-top: 5px;
}

.bk-tlh-footnote[b-a2e1lvqo68] {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-top: 10px;
}

.bk-tlh-footnote span[b-a2e1lvqo68] {
    font-size: 0.6875rem;
    line-height: 1.66;
    color: var(--mud-palette-text-secondary);
}

.bk-tlh-footnote[b-a2e1lvqo68]  .mud-icon-root {
    color: var(--mud-palette-text-disabled);
    flex-shrink: 0;
    margin-top: 2px;
}

/* The diff of an order: the positions before on the left, after on the
   right, one line each. Row pitch here MUST match ProjectTimeline.razor's
   DiffRowPitch - the SVG connectors are computed from it. */
.bk-tl-diff[b-a2e1lvqo68] {
    display: flex;
    align-items: flex-start;
}

.bk-tl-diff-col[b-a2e1lvqo68] {
    width: 330px;
    min-width: 0;
}

.bk-tl-diff-col-after[b-a2e1lvqo68] {
    width: 400px;
}

.bk-tl-diff-head[b-a2e1lvqo68] {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-disabled);
    padding-bottom: 8px;
}

.bk-tl-diff-head-after[b-a2e1lvqo68] {
    color: var(--mud-palette-primary);
}

.bk-tl-diff-row[b-a2e1lvqo68] {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 30px;
}

.bk-tl-diff-row-gone[b-a2e1lvqo68] {
    opacity: 0.5;
}

.bk-tl-diff-row-gone .bk-tl-diff-title[b-a2e1lvqo68] {
    text-decoration: line-through;
}

.bk-tl-diff-pos[b-a2e1lvqo68] {
    width: 16px;
    text-align: right;
    font-size: 0.75rem;
    color: var(--mud-palette-text-disabled);
    flex-shrink: 0;
}

/* A position nothing touched: present, unnamed. The ledger records only what
   changed, so naming this row would mean guessing what sits on it. */
.bk-tl-diff-tick[b-a2e1lvqo68] {
    width: 26px;
    height: 1px;
    background: var(--mud-palette-lines-default);
}

.bk-tl-diff-title[b-a2e1lvqo68] {
    font-size: 0.8125rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-tl-diff-links[b-a2e1lvqo68] {
    margin-top: 26px;
    flex-shrink: 0;
}

/* The two marks in the connector band. As classes rather than inline fills,
   because a hard-coded light chip turned into a bright blob in dark mode. */
.bk-tl-diff-mark-added[b-a2e1lvqo68] {
    fill: #E1F5EE;
}

.bk-tl-diff-glyph-added[b-a2e1lvqo68] {
    stroke: #085041;
}

.bk-tl-diff-mark-gone[b-a2e1lvqo68] {
    fill: #F1EFE8;
}

.bk-tl-diff-glyph-gone[b-a2e1lvqo68] {
    stroke: #6B6A66;
}

.bk-dark .bk-tl-diff-mark-added[b-a2e1lvqo68] {
    fill: #0C3B31;
}

.bk-dark .bk-tl-diff-glyph-added[b-a2e1lvqo68] {
    stroke: #9FE1CB;
}

.bk-dark .bk-tl-diff-mark-gone[b-a2e1lvqo68] {
    fill: #2E2D2A;
}

.bk-dark .bk-tl-diff-glyph-gone[b-a2e1lvqo68] {
    stroke: #B4B2A9;
}
/* /Components/Pages/RequirementDetail.razor.rz.scp.css */
/* Row content on the requirement detail page (acceptance criteria, obsolete-
   code-removal trail): both hold long, space-free identifiers - a fully
   qualified test name, a break commit, removed component paths - that must
   wrap within their own card instead of overflowing into the neighbouring
   bk-req-cols column. min-width: 0 lets the flex item shrink below its
   content's natural width; overflow-wrap: anywhere then lets even a single
   unbroken token break within the resulting box, so the row grows taller
   instead of wider. */
.bk-req-row-content[b-935mn99bxi] {
    flex: 1;
    min-width: 0;
    overflow-wrap: anywhere;
}
/* /Components/Pages/RequirementDraft.razor.rz.scp.css */
/* Chat-list access button (concept "Umschalter wandert in die Kopfzeile"):
   rendered as ProjectPageHeader's own TitleIcon, right before the title -
   moved out of ChatSessionsSidebar.razor.css together with the markup itself
   (see that file's own comment on the 1920px threshold below which the fixed
   list column becomes this toggle). Hidden entirely above that width, where
   the list is a real, permanently visible second column. */
.bk-chat-sessions-toggle[b-z7jfk07zyp] {
    display: none;
}

@media (max-width: 1919.98px) {
    .bk-chat-sessions-toggle[b-z7jfk07zyp] {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        padding: 3px 10px;
        border: 1px solid var(--mud-palette-lines-default);
        border-radius: var(--bk-radius-pill);
        background: var(--mud-palette-surface);
        color: var(--mud-palette-text-secondary);
        font-size: 0.8125rem;
        cursor: pointer;
        transition: border-color var(--bk-dur-fast) var(--bk-ease-out), color var(--bk-dur-fast) var(--bk-ease-out);
        /* No stacking context of its own any more: the opened list is a
           column beside the page below 1920px and a viewport-fixed drawer
           with a scrim of its own below 1280px (ChatSessionsSidebar.razor.css),
           so this button is never underneath it - it used to need z-index 22
           to stay clickable through an inset:0 overlay that spanned the page
           header as well, which is exactly what left it painting on top of
           the list's own first row. */
    }

    .bk-chat-sessions-toggle:hover[b-z7jfk07zyp] {
        border-color: var(--mud-palette-primary);
    }

    /* While the list is open the button is the marker of that state, not the
       way out of it (the list carries its own close button, scrim and
       Escape) - so it reads as pressed rather than swapping to a close icon
       it no longer performs. */
    .bk-chat-sessions-toggle-on[b-z7jfk07zyp] {
        border-color: var(--mud-palette-primary);
        color: var(--mud-palette-primary);
    }
}

/* On a phone the compact header (ChatPanel.razor.css) reorders this row down
   to an icon-only control alongside the title and Discard - the label text
   would not fit next to a truncated title otherwise. */
@media (max-width: 599.98px) {
    .bk-chat-sessions-toggle-label[b-z7jfk07zyp] {
        display: none;
    }
}

/* Neumorphic design (app.css .bk-soft): the chat list toggle is a raised
   pill, pressed in while the list is open (aria-expanded) or while held.
   Only the look - where it is shown at all stays the media query's job. */
.bk-soft .bk-chat-sessions-toggle[b-z7jfk07zyp] {
    border-color: transparent;
    box-shadow: var(--bk-depth-raised-sm);
    transition: box-shadow var(--bk-dur-fast) var(--bk-ease-out), transform var(--bk-dur-fast) var(--bk-ease-out), color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-soft .bk-chat-sessions-toggle[aria-expanded="true"][b-z7jfk07zyp],
.bk-soft .bk-chat-sessions-toggle:active[b-z7jfk07zyp] {
    box-shadow: var(--bk-depth-inset);
    color: var(--mud-palette-primary);
}

/* Diagnosis cards (feature "Accepted report links to its started diagnosis"):
   on a phone the card itself, not just its enclosing panel, must reach the
   full width the acceptance criterion asks for - the surrounding MudPaper's
   own pa-3 inset would otherwise eat 12px off both sides of it. Bleeding the
   row out by exactly that inset keeps the heading/summary text above it at
   the panel's normal inset while the cards reach its edge. */
@media (max-width: 599.98px) {
    .bk-diagnosis-cards[b-z7jfk07zyp] {
        margin-inline: calc(-1 * var(--bk-space-3));
    }
}

/* The Applied panel's own head (feature "One clear result panel after
   accepting a chat draft"): checkmark, the accepted-count heading with its
   timestamp subline, and the panel's one and only "All requirements" link -
   min-width: 0 on the text block is what lets it shrink instead of pushing
   the link off a narrow viewport (acceptance criterion: usable at 360px). */
.bk-applied-panel[b-z7jfk07zyp] {
    min-width: 0;
}

.bk-applied-head[b-z7jfk07zyp] {
    display: flex;
    align-items: center;
    gap: var(--bk-space-3);
    flex-wrap: wrap;
    margin-bottom: var(--bk-space-3);
}

.bk-applied-head-text[b-z7jfk07zyp] {
    flex: 1;
    min-width: 160px;
}

.bk-applied-head-title[b-z7jfk07zyp] {
    font-weight: 600;
}

.bk-applied-head-sub[b-z7jfk07zyp] {
    color: var(--mud-palette-text-secondary);
}

.bk-applied-all-link[b-z7jfk07zyp] {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    color: var(--mud-palette-primary);
    font-size: 0.875rem;
    cursor: pointer;
    white-space: nowrap;
}

.bk-applied-all-link:hover[b-z7jfk07zyp] {
    text-decoration: underline;
}
/* /Components/Pages/RequirementTreeView.razor.rz.scp.css */
/* Requirements overview: one filtered, expand-in-place tree instead of a
   card grid with a separate hit list and a separate archived section
   (concept "Requirement tree expands in place at any depth" / "One line per
   requirement with a quiet state mark" / "Overview filtered in place, never
   as a separate list"). Rows are plain flex lines, not MudPaper cards - the
   whole point is that a screenful holds far more of them.

   In the app's neumorphic design (app.css .bk-soft): the tree is one raised
   panel, each top-level requirement a raised strip its branch hangs from,
   the rows below it flat lines on the panel. The filter chips are soft keys,
   pressed in while their filter is on. */

.bk-rtree-tools[b-22lcb74eaf] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--bk-space-2) 10px;
    margin-bottom: var(--bk-space-4);
}

.bk-rtree-search[b-22lcb74eaf] {
    flex: 1 1 260px;
    max-width: 420px;
}

/* Filter/archived chips (acceptance criterion: which filters are active is
   visible on the page) - a plain toggle, deliberately not a MudChip, so its
   "on" state reads exactly like the approved operable design's own chips:
   raised at rest, pressed in and lit in the accent while on, the way the
   current page's key in the navigation reads. */
.bk-rtree-chip[b-22lcb74eaf] {
    display: inline-flex;
    align-items: center;
    font-size: 0.8125rem;
    font-weight: 500;
    padding: 6px 14px;
    border-radius: var(--bk-radius-pill);
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-secondary);
    box-shadow: var(--bk-depth-raised-sm);
    cursor: pointer;
    white-space: nowrap;
    user-select: none;
    transition: box-shadow var(--bk-dur-fast) var(--bk-ease-out),
        color var(--bk-dur-fast) var(--bk-ease-out),
        transform var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-rtree-chip:hover[b-22lcb74eaf] {
    color: var(--mud-palette-text-primary);
    box-shadow: var(--bk-depth-lift-sm);
}

.bk-rtree-chip:active[b-22lcb74eaf] {
    transform: translateY(1px);
    box-shadow: var(--bk-depth-inset-sm);
}

.bk-rtree-chip.bk-rtree-chip-on[b-22lcb74eaf] {
    color: var(--mud-palette-primary);
    font-weight: 600;
    box-shadow: var(--bk-depth-inset);
}

.bk-glow .bk-rtree-chip.bk-rtree-chip-on[b-22lcb74eaf] {
    text-shadow: 0 0 10px rgba(var(--mud-palette-primary-rgb), 0.6);
    box-shadow: var(--bk-depth-inset), inset 0 0 12px rgba(var(--mud-palette-primary-rgb), 0.25);
}

/* The panel. No overflow clipping: the raised top-level strips inside cast
   their shadows into the panel's own padding. */
.bk-rtree-list[b-22lcb74eaf] {
    padding: var(--bk-space-2);
    border-radius: var(--bk-radius-lg);
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised);
}

/* One requirement: its row plus the optional explain lines below it (the
   keyed unit, see the markup). A new top-level group starts a little apart
   from the branch above it. */
.bk-rtree-item.bk-rtree-item-top:not(:first-child)[b-22lcb74eaf] {
    margin-top: 10px;
}

.bk-rtree-item.bk-rtree-item-top + .bk-rtree-item:not(.bk-rtree-item-top)[b-22lcb74eaf] {
    margin-top: var(--bk-space-1);
}

.bk-rtree-row[b-22lcb74eaf] {
    display: flex;
    align-items: center;
    gap: var(--bk-space-2);
    padding: 0 var(--bk-space-3) 0 var(--bk-space-2);
    min-height: 36px;
    border-radius: var(--bk-radius-md);
    transition: background-color var(--bk-dur-fast) var(--bk-ease-out), box-shadow var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-rtree-row:hover[b-22lcb74eaf] {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 4%, transparent);
}

/* Top-level requirements read as section headers (acceptance criterion:
   "top-level requirements are set apart from the levels below them") -
   taller, bolder, raised off the panel. */
.bk-rtree-row.bk-rtree-top[b-22lcb74eaf] {
    min-height: 44px;
    font-weight: 650;
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
}

.bk-rtree-row.bk-rtree-top:hover[b-22lcb74eaf] {
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-lift-sm);
}

/* A row kept visible only because a match sits below it (acceptance
   criterion: dimmed context, not itself a match). */
.bk-rtree-row.bk-rtree-ctx[b-22lcb74eaf] {
    opacity: 0.55;
}

.bk-rtree-row.bk-rtree-arch[b-22lcb74eaf] {
    opacity: 0.6;
}

/* Nesting guides: one vertical rule per depth level, so the level a
   requirement sits on is recognizable without counting indentation
   (acceptance criterion). */
.bk-rtree-guides[b-22lcb74eaf] {
    flex: 0 0 auto;
    align-self: stretch;
    display: flex;
}

.bk-rtree-guides i[b-22lcb74eaf] {
    display: block;
    width: 16px;
    border-left: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 75%, transparent);
    font-style: normal;
}

/* The fold key: flat until pointed at, then a small raised key that sinks
   in while pressed. One chevron that turns a quarter to point down once the
   branch is open. */
.bk-rtree-caret[b-22lcb74eaf] {
    flex: 0 0 26px;
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: var(--bk-radius-sm);
    background: transparent;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
    transition: box-shadow var(--bk-dur-fast) var(--bk-ease-out), color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-rtree-caret:hover[b-22lcb74eaf] {
    color: var(--mud-palette-text-primary);
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
}

.bk-rtree-caret:active[b-22lcb74eaf] {
    box-shadow: var(--bk-depth-inset-sm);
}

.bk-rtree-caret:focus-visible[b-22lcb74eaf] {
    outline: none;
    box-shadow: var(--bk-ring);
}

.bk-rtree-caret-open[b-22lcb74eaf]  .mud-icon-root {
    rotate: 90deg;
}

@media (prefers-reduced-motion: no-preference) {
    .bk-rtree-caret[b-22lcb74eaf]  .mud-icon-root {
        transition: rotate var(--bk-dur-base) var(--bk-ease-spring);
    }
}

.bk-rtree-caret-spacer[b-22lcb74eaf] {
    flex: 0 0 26px;
}

.bk-rtree-mark[b-22lcb74eaf] {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
}

/* Met is the one mark that carries no colour at all - a screenful of fully
   met requirements should carry no colour anywhere (acceptance criterion).
   The others take the status hues (app.css --bk-hue-*) darkened for the
   light tones and lightened for the dark ones, as the status pills do. The
   legend's icons are MudIcons (a child component), hence the ::deep twin of
   each rule. */
.bk-rtree-mark-met[b-22lcb74eaf],
.bk-rtree-legend[b-22lcb74eaf]  .bk-rtree-mark-met {
    color: var(--mud-palette-text-disabled);
}

.bk-rtree-mark-open[b-22lcb74eaf],
.bk-rtree-legend[b-22lcb74eaf]  .bk-rtree-mark-open {
    color: var(--mud-palette-text-secondary);
}

.bk-rtree-mark-run[b-22lcb74eaf],
.bk-rtree-legend[b-22lcb74eaf]  .bk-rtree-mark-run {
    color: color-mix(in srgb, var(--bk-hue-development) 62%, #000000);
}

.bk-rtree-mark-fail[b-22lcb74eaf],
.bk-rtree-legend[b-22lcb74eaf]  .bk-rtree-mark-fail {
    color: color-mix(in srgb, var(--bk-hue-paused) 62%, #000000);
}

.bk-rtree-mark-defect[b-22lcb74eaf],
.bk-rtree-legend[b-22lcb74eaf]  .bk-rtree-mark-defect {
    color: color-mix(in srgb, var(--bk-hue-approval) 62%, #000000);
}

.bk-dark .bk-rtree-mark-run[b-22lcb74eaf],
.bk-dark .bk-rtree-legend[b-22lcb74eaf]  .bk-rtree-mark-run {
    color: color-mix(in srgb, var(--bk-hue-development) 55%, #FFFFFF);
}

.bk-dark .bk-rtree-mark-fail[b-22lcb74eaf],
.bk-dark .bk-rtree-legend[b-22lcb74eaf]  .bk-rtree-mark-fail {
    color: color-mix(in srgb, var(--bk-hue-paused) 55%, #FFFFFF);
}

.bk-dark .bk-rtree-mark-defect[b-22lcb74eaf],
.bk-dark .bk-rtree-legend[b-22lcb74eaf]  .bk-rtree-mark-defect {
    color: color-mix(in srgb, var(--bk-hue-approval) 55%, #FFFFFF);
}

/* The name takes the row's free width, the link inside it only its text:
   the empty rest of the row is not a link. */
.bk-rtree-name[b-22lcb74eaf] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
}

.bk-rtree-title[b-22lcb74eaf] {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: inherit;
    text-decoration: none;
    border-radius: var(--bk-radius-xs);
    transition: color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-rtree-title:hover[b-22lcb74eaf] {
    color: var(--mud-palette-primary);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}

.bk-rtree-title:focus-visible[b-22lcb74eaf] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.bk-glow .bk-rtree-title:hover[b-22lcb74eaf] {
    text-shadow: 0 0 10px rgba(var(--mud-palette-primary-rgb), 0.5);
}

.bk-rtree-title mark[b-22lcb74eaf] {
    background: color-mix(in srgb, var(--mud-palette-warning) 35%, transparent);
    color: inherit;
    padding: 0 1px;
    border-radius: var(--bk-radius-xs);
}

/* Neutral progress: a groove pressed into the row, filled from the left. */
.bk-rtree-prog[b-22lcb74eaf] {
    flex: 0 0 auto;
    width: 56px;
    height: 6px;
    border-radius: var(--bk-radius-pill);
    overflow: hidden;
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-inset-sm);
}

.bk-rtree-prog span[b-22lcb74eaf] {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: color-mix(in srgb, var(--mud-palette-text-secondary) 60%, transparent);
}

.bk-rtree-prog-spacer[b-22lcb74eaf] {
    flex: 0 0 56px;
}

/* The "matched via ..." explanation line under a row that matched through
   its description or a criterion rather than its title (acceptance
   criterion: a match found through a criterion shows which criterion text
   matched) - a second, short line, not a wider row; the row above it still
   stays exactly one line. */
.bk-rtree-explain[b-22lcb74eaf] {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 6px;
    padding: 0 var(--bk-space-3) var(--bk-space-2) 44px;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}

.bk-rtree-explain-source[b-22lcb74eaf] {
    flex: 0 0 auto;
    font-weight: 600;
}

.bk-rtree-explain mark[b-22lcb74eaf] {
    background: color-mix(in srgb, var(--mud-palette-warning) 35%, transparent);
    color: inherit;
    padding: 0 1px;
    border-radius: var(--bk-radius-xs);
}

.bk-rtree-legend[b-22lcb74eaf] {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 16px;
    margin-top: 14px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}
/* /Components/Pages/Settings.razor.rz.scp.css */
/* Settings page (/settings). Only the Anthropic credentials section lives
   here - the budget and "Weitere Konfiguration" cards compose the shared
   bk-settings-* / bk-pill building blocks from app.css and need nothing of
   their own. MudBlazor-rendered elements (MudText, MudTextField, MudIconButton)
   are reached with ::deep, since Blazor's scope attribute only lands on this
   file's own markup. */

/* No width rule anywhere in this file: all three cards on this page span the
   page container (.bk-page, capped at min(96vw, 1600px) / 2200px ultra-wide),
   so they line up on both edges instead of one being 760px and its neighbour
   full width. There used to be a .bk-cred-card { max-width } here that never
   applied - the class sits on a MudPaper, and Blazor's CSS isolation only
   stamps its scope attribute onto this component's OWN elements, never onto a
   child component's markup (that is what ::deep is for, see the rules below
   that reach MudText/MudTextField). The card being full width was therefore an
   accident of a dead rule; it is now the deliberate behaviour of all three. */

.bk-cred-head[b-cde0bjz8db] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 14px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.bk-cred-head-text[b-cde0bjz8db] {
    flex: 1;
    min-width: 0;
}

[b-cde0bjz8db] .bk-cred-title {
    font-weight: 600;
}

[b-cde0bjz8db] .bk-cred-sub {
    color: var(--mud-palette-text-secondary);
    display: block;
    line-height: 1.35;
}

.bk-cred-empty[b-cde0bjz8db] {
    padding: 14px 16px;
}

/* One credential per row, hairline-separated - the dense list this section
   replaced a stack of full cards with. */
.bk-cred-row[b-cde0bjz8db] {
    padding: 10px 16px 12px;
}

.bk-cred-row + .bk-cred-row[b-cde0bjz8db] {
    border-top: 1px solid var(--mud-palette-lines-default);
}

/* A paused credential is the one state worth tinting the whole row for: it is
   silently out of the rotation, which a pill alone reads over too easily. */
.bk-cred-row-paused[b-cde0bjz8db] {
    background: #FEF7F2;
}

.bk-dark .bk-cred-row-paused[b-cde0bjz8db] {
    background: rgba(186, 117, 23, 0.10);
}

.bk-cred-line[b-cde0bjz8db] {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    min-height: 32px;
}

.bk-cred-spacer[b-cde0bjz8db] {
    flex: 1 1 auto;
}

.bk-cred-name[b-cde0bjz8db] {
    font-size: 0.875rem;
    font-weight: 600;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 260px;
}

.bk-cred-meta[b-cde0bjz8db] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

[b-cde0bjz8db] .bk-cred-help-icon {
    font-size: 1rem;
}

/* The row's dispatch position (concept "Zugaenge in eigener Reihenfolge,
   vorderster freier zuerst"): a fixed-width badge so every row's dot and name
   line up regardless of whether the position is one or two digits. */
.bk-cred-position[b-cde0bjz8db] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 4px;
    border-radius: var(--bk-radius-xs);
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    background: var(--mud-palette-action-default-hover);
    flex: 0 0 auto;
}

/* Traffic light in front of the label: the row's state at a glance, before
   any pill is read (see Settings.razor's DotClass). */
.bk-cred-dot[b-cde0bjz8db] {
    width: 8px;
    height: 8px;
    border-radius: var(--bk-radius-round);
    flex: 0 0 auto;
}

.bk-cred-dot-ok[b-cde0bjz8db] {
    background: #1D9E75;
}

.bk-cred-dot-limited[b-cde0bjz8db] {
    background: #EF9F27;
}

.bk-cred-dot-paused[b-cde0bjz8db] {
    background: #E24B4A;
}

.bk-cred-dot-idle[b-cde0bjz8db] {
    background: #B4B2A9;
}

/* Utilization meters, one grid row per reported limit window: label, bar,
   share, reset time. Fixed side columns keep the bars of every row - and of
   every credential - aligned on the same two edges. */
.bk-cred-meters[b-cde0bjz8db] {
    display: grid;
    grid-template-columns: 52px minmax(60px, 1fr) 56px minmax(0, 190px);
    align-items: center;
    gap: 4px 10px;
    margin-top: 8px;
    /* A bar the full width of the card reads as a progress indicator for the
       whole row rather than for one limit window; capped so the share and the
       reset time stay next to it instead of an arm's length away. */
    max-width: 640px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.bk-cred-meter-label[b-cde0bjz8db] {
    white-space: nowrap;
}

.bk-cred-meter[b-cde0bjz8db] {
    display: block;
    position: relative;
    height: 5px;
    border-radius: var(--bk-radius-xs);
    background: var(--mud-palette-lines-default);
    overflow: hidden;
}

.bk-cred-meter-fill[b-cde0bjz8db] {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    border-radius: var(--bk-radius-xs);
}

.bk-cred-meter-green[b-cde0bjz8db] {
    background: #1D9E75;
}

.bk-cred-meter-amber[b-cde0bjz8db] {
    background: #EF9F27;
}

.bk-cred-meter-red[b-cde0bjz8db] {
    background: #E24B4A;
}

.bk-cred-meter-value[b-cde0bjz8db] {
    font-variant-numeric: tabular-nums;
    text-align: right;
    color: var(--mud-palette-text-primary);
}

.bk-cred-meter-reset[b-cde0bjz8db] {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* One-line explanation under a row, for the states a pill can only name */
.bk-cred-note[b-cde0bjz8db] {
    margin-top: 8px;
    font-size: 0.75rem;
    line-height: 1.4;
}

.bk-cred-note-paused[b-cde0bjz8db] {
    color: #854F0B;
}

.bk-dark .bk-cred-note-paused[b-cde0bjz8db] {
    color: #FAC775;
}

.bk-cred-note-warn[b-cde0bjz8db] {
    color: var(--mud-palette-warning-text);
}

.bk-cred-excerpt[b-cde0bjz8db] {
    display: block;
    margin-top: 4px;
    font-family: var(--mud-typography-body1-family), monospace;
    word-break: break-all;
    opacity: 0.85;
}

/* Editing surface behind the row's chevron, and the add form at the bottom of
   the card - same field widths, so the two read as one column. */
.bk-cred-detail[b-cde0bjz8db] {
    padding: 10px 0 4px;
}

.bk-cred-fields[b-cde0bjz8db],
.bk-cred-add[b-cde0bjz8db] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.bk-cred-add[b-cde0bjz8db] {
    padding: 12px 16px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

[b-cde0bjz8db] .bk-cred-label-field {
    width: 200px;
}

[b-cde0bjz8db] .bk-cred-token-field {
    width: 340px;
}

/* Phone: the four meter columns and the two fixed-width fields together are
   wider than the viewport, and a settings page that scrolls sideways hides
   its own actions. The reset time wraps onto its own line under the bar it
   belongs to, and the fields go full width. */
@media (max-width: 700px) {
    .bk-cred-meters[b-cde0bjz8db] {
        grid-template-columns: 46px minmax(0, 1fr) 52px;
    }

    .bk-cred-meter-reset[b-cde0bjz8db] {
        grid-column: 2 / -1;
        margin-bottom: 4px;
    }

    [b-cde0bjz8db] .bk-cred-label-field,
    [b-cde0bjz8db] .bk-cred-token-field {
        width: 100%;
    }
}
/* /Components/Pages/Statistics.razor.rz.scp.css */
/* Statistics page (/statistics). Only page-local layout lives here; the
   shared building blocks it composes - bk-tile-*, bk-seg-group/bk-seg,
   bk-settings-icon - stay in app.css because more than one page uses them
   (see Workers.razor.css's own note, which this page mirrors closely: same
   KPI-strip and section-card shape, just with bars instead of a run list).
   MudBlazor-rendered elements are reached with ::deep, since Blazor's scope
   attribute only lands on this file's own markup. */

.bk-stats-page[b-u7i4rb77nc] {
    max-width: 1180px;
}

.bk-stats-head[b-u7i4rb77nc] {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.bk-stats-head-text[b-u7i4rb77nc] {
    min-width: 0;
}

[b-u7i4rb77nc] .bk-stats-lead {
    color: var(--mud-palette-text-secondary);
    margin-top: 2px;
}

/* Compact sizing for the period toggle, same override Workers.razor.css
   applies to its own status filter (the shared bk-seg-group/bk-seg is sized
   for a two-way dialog switch by default). */
.bk-stats-seg-group[b-u7i4rb77nc] {
    padding: 3px;
    gap: 2px;
}

[b-u7i4rb77nc] .bk-stats-project-select {
    width: 220px;
    flex: 0 0 auto;
}

[b-u7i4rb77nc] .bk-stats-loading {
    color: var(--mud-palette-text-secondary);
    margin-top: 24px;
}

[b-u7i4rb77nc] .bk-stats-empty {
    color: var(--mud-palette-text-secondary);
    padding: 16px;
}

/* KPI strip: same auto-fit grid as the Agents page's own KPI row. */
.bk-stats-kpis[b-u7i4rb77nc] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
    gap: 12px;
    margin-top: 16px;
}

.bk-stats-kpi[b-u7i4rb77nc] {
    border-radius: var(--bk-radius-sm);
    padding: 12px 14px;
    min-width: 0;
}

[b-u7i4rb77nc] .bk-stats-kpi-sub {
    color: var(--mud-palette-text-secondary);
    display: block;
    line-height: 1.3;
}

/* Every section below the KPI strip - two two-up rows and one full-width
   card between them - shares this one flex gap, so the vertical rhythm
   between ANY two cards is the same 12px no matter which two are neighbors.
   Kept as a single mechanism on purpose: a per-section margin-top here (the
   row-2 grid and the full-width card each carrying their own) drifted out
   of sync the moment one of them changed. */
.bk-stats-sections[b-u7i4rb77nc] {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 12px;
}

/* Two cards side by side above 900px, stacked below - the same breakpoint
   MudBlazor's own grid breakpoints use for "md". */
.bk-stats-row2[b-u7i4rb77nc] {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: 12px;
}

@media (max-width: 900px) {
    .bk-stats-row2[b-u7i4rb77nc] {
        grid-template-columns: minmax(0, 1fr);
    }
}

.bk-stats-card[b-u7i4rb77nc] {
    min-width: 0;
}

/* Section header: icon tile + title/subtitle, same shape as the Agents page's
   own section cards. */
.bk-stats-sec-head[b-u7i4rb77nc] {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px;
}

.bk-stats-sec-text[b-u7i4rb77nc] {
    flex: 1;
    min-width: 0;
}

[b-u7i4rb77nc] .bk-stats-sec-title {
    font-weight: 600;
}

[b-u7i4rb77nc] .bk-stats-sec-sub {
    color: var(--mud-palette-text-secondary);
    display: block;
}

/* Cost-by-role horizontal bars: name | track | "123 $ · 45 · avg 6 $" */
.bk-stats-bars[b-u7i4rb77nc] {
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 9px;
}

.bk-stats-bar[b-u7i4rb77nc] {
    display: grid;
    grid-template-columns: 116px minmax(0, 1fr) 130px;
    align-items: center;
    gap: 10px;
    font-size: 0.8125rem;
}

.bk-stats-bar-name[b-u7i4rb77nc] {
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-stats-bar-track[b-u7i4rb77nc] {
    height: 14px;
    background: var(--mud-palette-background-gray);
    border-radius: var(--bk-radius-xs);
    overflow: hidden;
    display: block;
}

.bk-stats-bar-fill[b-u7i4rb77nc] {
    display: block;
    height: 100%;
    background: var(--mud-palette-primary);
    border-radius: var(--bk-radius-xs);
}

.bk-stats-bar-meta[b-u7i4rb77nc] {
    text-align: right;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Daily trend: a column chart in plain CSS, one flex item per day, height
   proportional to that day's cost against the period's own peak. */
.bk-stats-trend[b-u7i4rb77nc] {
    padding: 14px 16px;
}

.bk-stats-trend-cols[b-u7i4rb77nc] {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 120px;
}

.bk-stats-trend-col[b-u7i4rb77nc] {
    flex: 1 1 0;
    min-width: 2px;
    background: var(--mud-palette-primary);
    opacity: 0.55;
    border-radius: var(--bk-radius-xs) var(--bk-radius-xs) 0 0;
}

.bk-stats-trend-col:hover[b-u7i4rb77nc] {
    opacity: 0.85;
}

.bk-stats-trend-axis[b-u7i4rb77nc] {
    display: flex;
    justify-content: space-between;
    color: var(--mud-palette-text-disabled);
    font-size: 0.6875rem;
    margin-top: 6px;
}

/* Token stacked bars: one row per role, four segments (cache read / cache
   written / output / fresh input) sized by their share of that role's total.
   Fixed, non-cycling colors - not a categorical series palette, since these
   four slots always mean the same thing everywhere this bar appears. */
.bk-stats-token-rows[b-u7i4rb77nc] {
    padding: 14px 16px 4px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.bk-stats-token-row[b-u7i4rb77nc] {
    display: grid;
    grid-template-columns: 140px minmax(0, 1fr);
    align-items: center;
    gap: 10px;
}

.bk-stats-token-name[b-u7i4rb77nc] {
    color: var(--mud-palette-text-secondary);
    font-size: 0.8125rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-stats-token-track[b-u7i4rb77nc] {
    height: 15px;
    border-radius: var(--bk-radius-xs);
    overflow: hidden;
    display: flex;
    background: var(--mud-palette-background-gray);
}

.bk-stats-token-seg[b-u7i4rb77nc] {
    display: block;
    height: 100%;
}

.bk-stats-token-seg-read[b-u7i4rb77nc] {
    background: #594AE2;
}

.bk-stats-token-seg-write[b-u7i4rb77nc] {
    background: #2E7BC7;
}

.bk-stats-token-seg-output[b-u7i4rb77nc] {
    background: #0F9D71;
}

.bk-stats-token-seg-input[b-u7i4rb77nc] {
    background: #B4B2A9;
}

.bk-dark .bk-stats-token-seg-read[b-u7i4rb77nc] {
    background: #7B6CFF;
}

.bk-dark .bk-stats-token-seg-write[b-u7i4rb77nc] {
    background: #5B9FE0;
}

.bk-dark .bk-stats-token-seg-output[b-u7i4rb77nc] {
    background: #3FCB9E;
}

.bk-dark .bk-stats-token-seg-input[b-u7i4rb77nc] {
    background: #6B6860;
}

.bk-stats-token-legend[b-u7i4rb77nc] {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
    padding: 6px 16px 14px;
}

.bk-stats-token-swatch[b-u7i4rb77nc] {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: var(--bk-radius-xs);
    margin-right: 5px;
}

/* First-run vs. rework: two thin bars per role, sharing one scale (the
   larger of the two costs in the pair is always the full-width bar). */
.bk-stats-rework[b-u7i4rb77nc] {
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.bk-stats-rework-group[b-u7i4rb77nc] {
    min-width: 0;
}

.bk-stats-rework-role[b-u7i4rb77nc] {
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
    margin-bottom: 4px;
}

.bk-stats-rework-line[b-u7i4rb77nc] {
    display: grid;
    grid-template-columns: 78px minmax(0, 1fr) 92px;
    align-items: center;
    gap: 8px;
    font-size: 0.75rem;
    margin-bottom: 3px;
}

.bk-stats-rework-label[b-u7i4rb77nc] {
    color: var(--mud-palette-text-secondary);
}

.bk-stats-rework-track[b-u7i4rb77nc] {
    height: 12px;
    background: var(--mud-palette-background-gray);
    border-radius: var(--bk-radius-xs);
    overflow: hidden;
    display: block;
}

.bk-stats-rework-fill[b-u7i4rb77nc] {
    display: block;
    height: 100%;
    border-radius: var(--bk-radius-xs);
}

.bk-stats-rework-fill-first[b-u7i4rb77nc] {
    background: var(--mud-palette-primary);
}

.bk-stats-rework-fill-rework[b-u7i4rb77nc] {
    background: var(--mud-palette-primary);
    opacity: 0.5;
}

.bk-stats-rework-meta[b-u7i4rb77nc] {
    text-align: right;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Top expensive runs: a plain table (not MudTable) - five columns, fifteen
   rows at most, no sorting/paging of its own, so the lighter markup wins. */
[b-u7i4rb77nc] .bk-stats-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    font-size: 0.8125rem;
}

[b-u7i4rb77nc] .bk-stats-table th {
    text-align: left;
    font-weight: 500;
    color: var(--mud-palette-text-disabled);
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding: 0 8px 8px 16px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

[b-u7i4rb77nc] .bk-stats-table td {
    padding: 7px 8px 7px 16px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

[b-u7i4rb77nc] .bk-stats-table-role {
    color: var(--mud-palette-text-primary);
}

[b-u7i4rb77nc] .bk-stats-table-row {
    cursor: pointer;
}

[b-u7i4rb77nc] .bk-stats-table-row:hover {
    background: var(--mud-palette-action-default-hover);
}
/* /Components/Pages/Workers.razor.rz.scp.css */
/* Agents page (/workers). Only page-local layout lives here; the shared
   building blocks it composes - bk-pill, bk-tile-*, bk-settings-icon,
   bk-seg-group/bk-seg, bk-pulse-dot, bk-run-* - stay in app.css because more
   than one page uses them. MudBlazor-rendered elements (MudText, MudIcon,
   MudSelect, MudTextField) are reached with ::deep, since Blazor's scope
   attribute only lands on this file's own markup. */

.bk-agents-page[b-n5j32o2lvs] {
    max-width: 1180px;
}

.bk-agents-head[b-n5j32o2lvs] {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

/* Says the page keeps itself current, so nobody reads a stale number as a
   stuck pipeline; the exact interval and the last load are in the title. */
.bk-agents-live[b-n5j32o2lvs] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    cursor: default;
}

.bk-agents-live-dot[b-n5j32o2lvs] {
    background: #1D9E75;
}

[b-n5j32o2lvs] .bk-agents-lead {
    color: var(--mud-palette-text-secondary);
    margin-top: 2px;
}

/* KPI strip: what is happening right now, plus the trailing 24 h. Auto-fit so
   the five tiles wrap to two rows on a narrow window instead of squeezing. */
.bk-agents-kpis[b-n5j32o2lvs] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
    gap: 12px;
    margin-top: 16px;
}

.bk-agents-kpi[b-n5j32o2lvs] {
    border-radius: var(--bk-radius-sm);
    padding: 12px 14px;
    min-width: 0;
}

.bk-agents-kpi-head[b-n5j32o2lvs] {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: 20px;
}

[b-n5j32o2lvs] .bk-agents-kpi-sub {
    color: var(--mud-palette-text-secondary);
    display: block;
    line-height: 1.3;
}

/* Card section headers, same shape as the settings pages' section cards */
.bk-agents-sec-head[b-n5j32o2lvs] {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px;
}

.bk-agents-sec-text[b-n5j32o2lvs] {
    flex: 1;
    min-width: 0;
}

[b-n5j32o2lvs] .bk-agents-sec-title {
    font-weight: 600;
}

[b-n5j32o2lvs] .bk-agents-sec-sub {
    color: var(--mud-palette-text-secondary);
    display: block;
}

.bk-agents-filters[b-n5j32o2lvs] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
}

/* The shared segmented control is sized for a two-way switch in a dialog;
   as a filter bar it has to be compact and must not stretch. */
.bk-agents-seg-group[b-n5j32o2lvs] {
    padding: 3px;
    gap: 2px;
}

.bk-agents-seg-group .bk-seg[b-n5j32o2lvs] {
    flex: 0 0 auto;
    height: 30px;
    padding: 0 14px;
    font-size: 0.8125rem;
}

[b-n5j32o2lvs] .bk-agents-filter-project {
    width: 200px;
}

[b-n5j32o2lvs] .bk-agents-filter-kind {
    width: 190px;
}

[b-n5j32o2lvs] .bk-agents-filter-scope {
    width: 260px;
}

.bk-agents-loading[b-n5j32o2lvs] {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 24px 16px;
}

.bk-agents-empty[b-n5j32o2lvs] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 32px 16px;
    text-align: center;
    color: var(--mud-palette-text-disabled);
}

[b-n5j32o2lvs] .bk-agents-muted {
    color: var(--mud-palette-text-secondary);
}

.bk-agents-runs[b-n5j32o2lvs] {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 16px;
}

/* Which worker / Job is executing the run right now (queue mode: the worker
   label, Kubernetes: the Job name) */
.bk-agents-executor[b-n5j32o2lvs] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-family: var(--mud-typography-caption-family, monospace);
    font-size: 0.7rem;
}

[b-n5j32o2lvs] .bk-agents-executor-icon {
    font-size: 13px;
}

/* The access (Anthropic credential) this run used, replacing the former
   worker image display (concept "Agentenlaeufe im Ueberblick, mit lesbarer
   Zusammenfassung je Lauf") */
.bk-agents-access[b-n5j32o2lvs] {
    font-size: 0.7rem;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 260px;
}

/* Visible explanation for a row waiting on the installation-wide concurrency
   cap (concept "App-wide cap on simultaneous agent runs") - readable inline,
   not only as the pill's hover tooltip. */
.bk-agents-waiting-reason[b-n5j32o2lvs] {
    font-size: 0.7rem;
    color: var(--mud-palette-warning-darken);
}

.bk-agents-pager[b-n5j32o2lvs] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 16px;
}

/* Worker cards: identity, current job and heartbeat freshness in one tile,
   replacing the six-column table where the GUID cost a full column. */
.bk-worker-grid[b-n5j32o2lvs] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 12px;
    padding: 16px;
}

.bk-worker-card[b-n5j32o2lvs] {
    display: flex;
    flex-direction: column;
    gap: 8px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    padding: 12px 14px;
    min-width: 0;
}

.bk-worker-card-off[b-n5j32o2lvs] {
    background: var(--mud-palette-background-gray);
}

.bk-worker-top[b-n5j32o2lvs] {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.bk-worker-dot-off[b-n5j32o2lvs] {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: var(--bk-radius-round);
    background: var(--mud-palette-text-disabled);
    flex-shrink: 0;
}

.bk-worker-name[b-n5j32o2lvs] {
    font-weight: 600;
    font-size: 0.875rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.bk-worker-job[b-n5j32o2lvs] {
    min-height: 38px;
}

[b-n5j32o2lvs] .bk-worker-job-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-worker-meta[b-n5j32o2lvs] {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.bk-worker-meta > span[b-n5j32o2lvs] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

[b-n5j32o2lvs] .bk-worker-meta-icon {
    font-size: 14px;
}

.bk-worker-id[b-n5j32o2lvs] {
    font-size: 0.6875rem;
    color: var(--mud-palette-text-disabled);
    user-select: all;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-agents-token-form[b-n5j32o2lvs] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 16px;
}

[b-n5j32o2lvs] .bk-agents-token-label {
    width: 320px;
}

/* The raw token is shown exactly once - make it selectable in one click */
.bk-agents-secret[b-n5j32o2lvs] {
    user-select: all;
    overflow-wrap: anywhere;
}

@media (max-width: 599px) {
    .bk-agents-filters[b-n5j32o2lvs] {
        align-items: stretch;
    }

    [b-n5j32o2lvs] .bk-agents-filter-project,
    [b-n5j32o2lvs] .bk-agents-filter-kind,
    [b-n5j32o2lvs] .bk-agents-filter-scope {
        width: 100%;
    }
}
/* /Components/Requirements/JointImplementationDialog.razor.rz.scp.css */
.bk-joint-req-card[b-nso7kpa8kx] {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    padding: 10px 12px;
}

/* A raised pad instead of a flat bordered card, like the rest of the dialog's
   own neumorphic surroundings (app.css's shared bk-soft dialog rules) - see
   body:has(.bk-soft) at the top of app.css for why body:has() rather than a
   .bk-soft ancestor class: this dialog renders outside MudLayout, which is
   where that class lives. */
body:has(.bk-soft) .bk-joint-req-card[b-nso7kpa8kx] {
    border-color: transparent;
    box-shadow: var(--bk-depth-raised-sm);
}

.bk-joint-req-criteria[b-nso7kpa8kx] {
    margin: 6px 0 0;
    padding-left: 18px;
}

.bk-joint-req-criteria li[b-nso7kpa8kx] {
    margin-bottom: 2px;
}
/* /Components/Requirements/RequirementPicker.razor.rz.scp.css */
.bk-req-picker[b-0ysrxsl6aq] {
    display: inline-flex;
    align-items: center;
}

.bk-req-picker-blocked[b-0ysrxsl6aq] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    cursor: default;
}

.bk-req-picker-reason[b-0ysrxsl6aq] {
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* MudChip renders its own root element inside MudChip's own scope, not this
   component's - ::deep is required to reach it from here. */
.bk-req-picker[b-0ysrxsl6aq]  .bk-req-picker-removal-chip {
    margin-left: 4px;
}
/* /Components/Requirements/RequirementSelectionBar.razor.rz.scp.css */
.bk-selection-bar[b-0uydf8tgkz] {
    position: sticky;
    bottom: 0;
    z-index: 5;
    margin-top: 16px;
    padding-top: 4px;
}

.bk-selection-bar-inner[b-0uydf8tgkz] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    box-shadow: var(--mud-elevation-4);
    padding: 10px 16px;
}

/* The applied result panel's own footer (feature "One clear result panel
   after accepting a chat draft"): part of the same card, not a page-docked
   overlay - no sticky position, no border/shadow of its own, a plain divider
   against the card content above it instead. */
.bk-selection-bar-embedded[b-0uydf8tgkz] {
    position: static;
    margin-top: var(--bk-space-3);
    padding-top: 0;
}

.bk-selection-bar-embedded .bk-selection-bar-inner[b-0uydf8tgkz] {
    background: transparent;
    border: none;
    box-shadow: none;
    border-radius: 0;
    border-top: 1px solid var(--mud-palette-lines-default);
    padding: var(--bk-space-3) 0 0;
}

.bk-selection-bar-counts[b-0uydf8tgkz] {
    font-size: 13px;
    color: var(--mud-palette-text-primary);
    white-space: nowrap;
}

.bk-selection-bar-sep[b-0uydf8tgkz] {
    margin: 0 4px;
    color: var(--mud-palette-text-secondary);
}

/* 360px phones: the counts text wraps onto its own line above the actions
   rather than forcing horizontal scroll (concept requirement: the whole flow
   must work on a 360px viewport without horizontal scroll). */
@media (max-width: 599.98px) {
    .bk-selection-bar-inner[b-0uydf8tgkz] {
        padding: 8px 12px;
    }

    .bk-selection-bar-counts[b-0uydf8tgkz] {
        white-space: normal;
        flex-basis: 100%;
    }
}
/* /Components/Shared/ArchiveSection.razor.rz.scp.css */
/* Collapsed archive container. Archived content is deliberately dimmed so an
   expanded section still reads as secondary next to the active list above it. */
.bk-archive-head[b-62mkwxyou9] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    cursor: pointer;
    user-select: none;
}

/* ::deep because the chevron is rendered by MudIcon, so the scope attribute
   lands on the head div, not on the svg itself. */
.bk-archive-head[b-62mkwxyou9]  .bk-archive-chevron {
    color: var(--mud-palette-text-secondary);
}

.bk-archive-body[b-62mkwxyou9] {
    padding: 8px;
    opacity: 0.75;
}
/* /Components/Shared/ArtifactCanvas.razor.rz.scp.css */
/* One view: an artifact plus the bar that names and moves it. Its width comes
   from the frame inside (the design width), so nothing here constrains it. */
.bk-canvas-view[b-xid7bt28yn] {
    position: absolute;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-md);
    box-shadow: 0 2px 10px rgba(38, 36, 58, 0.14);
    overflow: hidden;
}

/* The one grip that moves a view: dragging the artifact itself belongs to the
   artifact (it has its own sliders and buttons), so only this bar does. */
.bk-canvas-view-head[b-xid7bt28yn] {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    padding: 8px 10px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background: var(--mud-palette-background-gray);
    cursor: move;
}

.bk-canvas-view-titles[b-xid7bt28yn] {
    flex: 1 1 auto;
    min-width: 0;
}

.bk-canvas-view-title[b-xid7bt28yn] {
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-canvas-view-caption[b-xid7bt28yn] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* /Components/Shared/BitIllustration.razor.rz.scp.css */
.bk-bit-art[b-x0qxa14mod] {
    display: block;
    overflow: visible;
}

/* Laid bits: the muted text color, faint - the lower course a touch
   stronger than the one above, as if the wall was built up over time. */
.bk-bit-art-bit[b-x0qxa14mod] {
    fill: color-mix(in srgb, var(--mud-palette-text-secondary) 30%, transparent);
}

.bk-bit-art-bit-soft[b-x0qxa14mod] {
    fill: color-mix(in srgb, var(--mud-palette-text-secondary) 18%, transparent);
}

.bk-bit-art-slot[b-x0qxa14mod] {
    fill: none;
    stroke: color-mix(in srgb, var(--mud-palette-text-secondary) 45%, transparent);
    stroke-width: 1.5;
    stroke-dasharray: 4 3;
}

.bk-bit-art-guide[b-x0qxa14mod] {
    stroke: color-mix(in srgb, var(--mud-palette-primary) 55%, transparent);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-dasharray: 2 4;
}

.bk-bit-art-lit[b-x0qxa14mod] {
    fill: var(--mud-palette-primary);
    filter: drop-shadow(0 4px 6px rgba(var(--mud-palette-primary-rgb), 0.45));
}

/* The next bit bobs gently above its slot. */
.bk-bit-art-next[b-x0qxa14mod] {
    animation: bk-bit-art-hover-b-x0qxa14mod 3.2s ease-in-out infinite;
}

@keyframes bk-bit-art-hover-b-x0qxa14mod {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(5px); }
}

@media (prefers-reduced-motion: reduce) {
    .bk-bit-art-next[b-x0qxa14mod] {
        animation: none;
    }
}
/* /Components/Shared/BitLoader.razor.rz.scp.css */
/* Four bits on a 2x2 grid; the lit color is the theme's accent unless the
   caller passes its own (--bk-bit-lit) or asks for the text color. Resting
   bits are the same color, faint, so the loader reads on every tone. */
.bk-bit-loader[b-6qn2pceni7] {
    --bk-bit-lit: var(--mud-palette-primary);
    display: inline-grid;
    grid-template-columns: repeat(2, var(--bk-bit));
    gap: var(--bk-bit-gap);
    flex-shrink: 0;
    vertical-align: middle;
}

.bk-bit-loader-inherit[b-6qn2pceni7] {
    --bk-bit-lit: currentColor;
}

.bk-bit-loader-small[b-6qn2pceni7] {
    --bk-bit: 6px;
    --bk-bit-gap: 3px;
}

.bk-bit-loader-medium[b-6qn2pceni7] {
    --bk-bit: 11px;
    --bk-bit-gap: 5px;
}

.bk-bit-loader-large[b-6qn2pceni7] {
    --bk-bit: 16px;
    --bk-bit-gap: 7px;
}

.bk-bit-loader > span[b-6qn2pceni7] {
    width: var(--bk-bit);
    height: var(--bk-bit);
    border-radius: calc(var(--bk-bit) * 0.28);
    background: color-mix(in srgb, var(--bk-bit-lit) 22%, transparent);
    animation: bk-bit-loader-step-b-6qn2pceni7 1.2s ease-in-out infinite;
}

/* Grid order is top-left, top-right, bottom-left, bottom-right; the light
   runs clockwise: TL, TR, BR, BL. */
.bk-bit-loader > span:nth-child(2)[b-6qn2pceni7] { animation-delay: 0.15s; }
.bk-bit-loader > span:nth-child(4)[b-6qn2pceni7] { animation-delay: 0.3s; }
.bk-bit-loader > span:nth-child(3)[b-6qn2pceni7] { animation-delay: 0.45s; }

@keyframes bk-bit-loader-step-b-6qn2pceni7 {
    0%, 55%, 100% {
        background: color-mix(in srgb, var(--bk-bit-lit) 22%, transparent);
        transform: scale(0.86);
        box-shadow: 0 0 0 transparent;
    }
    20% {
        background: var(--bk-bit-lit);
        transform: scale(1);
        box-shadow: 0 0 6px color-mix(in srgb, var(--bk-bit-lit) 45%, transparent);
    }
}

/* Reduced motion: the light still travels (a loader has to show it is
   working), but slower and without the bits changing size. */
@keyframes bk-bit-loader-calm-b-6qn2pceni7 {
    0%, 55%, 100% { background: color-mix(in srgb, var(--bk-bit-lit) 22%, transparent); }
    20% { background: var(--bk-bit-lit); }
}

@media (prefers-reduced-motion: reduce) {
    .bk-bit-loader > span[b-6qn2pceni7] {
        animation-name: bk-bit-loader-calm-b-6qn2pceni7;
        animation-duration: 2.4s;
    }
}
/* /Components/Shared/BrandLogo.razor.rz.scp.css */
.bk-brand-logo[b-r2ql3rkka2] {
    display: block;
    flex-shrink: 0;
    border-radius: var(--bk-radius-sm);
    transition: filter var(--bk-dur-slow) var(--bk-ease-out);
}

/* Falls back to the classic purple wherever no theme sets --bk-logo. */
.bk-brand-logo-tile[b-r2ql3rkka2] {
    fill: var(--bk-logo, #594AE2);
    transition: fill var(--bk-dur-slow) var(--bk-ease-out);
}

/* Glow presets (MainLayout's bk-glow, dark mode only): a soft halo in the
   active palette's own primary. */
.bk-glow .bk-brand-logo[b-r2ql3rkka2] {
    filter: drop-shadow(0 0 6px rgba(var(--mud-palette-primary-rgb), 0.55));
}

/* Neumorphic preset (app.css .bk-soft): a raised tile. */
.bk-soft .bk-brand-logo[b-r2ql3rkka2] {
    filter: drop-shadow(2px 2px 3px var(--bk-soft-lo)) drop-shadow(-2px -2px 3px var(--bk-soft-hi));
}
/* /Components/Shared/Chat/ChatComposer.razor.rz.scp.css */
/* Scoped styles of the docked composer (ChatComposer.razor).

   The composer SURFACE itself (.bk-composer, .bk-composer-inner,
   .bk-composer-row, .bk-composer-input, .bk-composer-send and its variants,
   .bk-composer-hint)
   is shared with ChatQuestionBox.razor, which takes over this very slot while
   a Rueckfrage is open (concept "Chat input area as one calm, full-width
   composer" - both modes read as the same surface) - see app.css's own "Chat
   composer surface" section for why those rules live there (global) instead
   of being duplicated in two scoped sheets. Only what is genuinely specific
   to THIS composer (the attach action - ChatQuestionBox offers no
   attachments) stays here. */

/* The composer's attach action (visible selection action, acceptance
   criterion): same square as .bk-composer-send, outlined/neutral so it reads
   as a secondary action in the control row. The native file input is
   stretched transparently over it (see .bk-drop-input in app.css), same
   click-opens-picker trick as the task intake's drop zone. */
.bk-composer-attach-root[b-epns6h6unp] {
    position: relative;
    flex: 0 0 auto;
}

/* Ghost rather than outlined: the composer card around it is the surface now
   (app.css's .bk-composer), so an outlined square in the control row drew a
   second box inside it. The hover fill is what makes it read as a control. */
.bk-composer-attach[b-epns6h6unp] {
    border: 1px solid transparent;
    background: transparent;
    color: var(--mud-palette-text-secondary);
}

.bk-composer-attach:hover:not(:disabled)[b-epns6h6unp] {
    background: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

/* Pending-attachment chip styles (.bk-composer-attachments, .bk-attachment-chip)
   live in ChatComposerPendingAttachments.razor.css - that component renders
   the elements, so only its own scoped sheet reaches them (CSS isolation).

   Whole-page drag-and-drop layer styles (.bk-chat-drop-layer and friends)
   live in ChatComposerDropLayer.razor.css - see that file's own comment.

   Free mode's own control-row markers (the switch, the locked chip, the
   usage chip) live in ChatFreeModeControl.razor.css - that component renders
   the elements now (ChatCoreConcernGuardTests' own line budget split it out
   of this file), so only its own scoped sheet reaches them. */
/* /Components/Shared/Chat/ChatComposerDropLayer.razor.rz.scp.css */
/* Scoped styles of the whole-page drag-and-drop layer
   (ChatComposerDropLayer.razor). Moved out of ChatComposer.razor.css: Blazor
   CSS isolation stamps a scope attribute onto the elements a component's own
   markup renders, so these selectors only ever match while they live in this
   component's own scoped sheet - see the commit that split the markup into
   ChatComposerDropLayer.razor without moving its styles here, which left the
   layer positioned nowhere and therefore never hit-testable in a real
   browser (docs/ARCHITECTURE.md, "Chat drag-and-drop attachments"). */

/* Whole-page drag-and-drop layer (drag-attachment-interop.js's bkDrop):
   invisible and unable to receive pointer/drag events at rest, so it never
   interferes with an ordinary click or the page's own text-selection
   dragging (side-thread annotations). bkDrop flips
   .bk-chat-drop-layer-active directly via CSS class, without a .NET round
   trip, the instant dataTransfer.types confirms a real file drag anywhere on
   the document - so the layer (and the transparent file input inside it) is
   already hit-testable before the file is ever released. Positioned against
   .bk-chat (see ChatSideThreadLayer.razor.css), the nearest positioned
   ancestor now that the composer sits inside the conversation column rather
   than directly under .bk-chat-page - covers the transcript, the review gate
   beside it and the composer card alike, not just the composer row, matching
   the acceptance criterion of dropping "auf den Chat". */
.bk-chat-drop-layer[b-390p9d6a2b] {
    position: absolute;
    inset: 0;
    z-index: 20;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--bk-dur-fast);
}

.bk-chat-drop-layer-active[b-390p9d6a2b] {
    opacity: 1;
    pointer-events: auto;
}

/* The layer's own MudFileUpload root and its transparent input (.bk-drop-input,
   app.css) stretch to cover the whole layer, not just its own CustomContent.
   ::deep is required: Class="bk-chat-drop-root" lands on MudFileUpload's OWN
   root div, rendered by MudFileUpload's own render tree, not by this
   component's markup - so the plain (unscoped-reaching) selector never
   matches it at all (see CLAUDE.md's own convention on reaching child-
   component/MudBlazor elements). Without this, the rule silently never
   applied: the div stayed at MudBlazor's own default position:relative with
   a collapsed ~0px height, and .bk-chat-drop-hint's inset:12px below then
   sized itself against that collapsed box instead of the full-page layer -
   squashing the whole dashed hint box into a thin sliver pinned to the very
   top of the page, smearing right through the header. */
[b-390p9d6a2b] .bk-chat-drop-root {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

.bk-chat-drop-hint[b-390p9d6a2b] {
    position: absolute;
    inset: 12px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border: 2px dashed var(--mud-palette-primary);
    border-radius: var(--bk-radius-lg);
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface) 92%);
}
/* /Components/Shared/Chat/ChatComposerPendingAttachments.razor.rz.scp.css */
/* Scoped styles of the pending-attachment preview
   (ChatComposerPendingAttachments.razor) - compact, wrapping chips instead of
   the task intake's own thumbnail grid/file-row pair, so five attachments
   stay well under the composer's own "under a third of the window height"
   ceiling. */
.bk-composer-attachments[b-kp9uuv40ak] {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 6px;
}

.bk-attachment-chip[b-kp9uuv40ak] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    max-width: 220px;
    padding: 3px 6px 3px 8px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--bk-radius-pill);
    background: var(--mud-palette-background-gray);
    font-size: 0.75rem;
    color: var(--mud-palette-text-primary);
}

.bk-attachment-chip-icon[b-kp9uuv40ak] {
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
}

.bk-attachment-chip-name[b-kp9uuv40ak] {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-attachment-chip-remove[b-kp9uuv40ak] {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    padding: 0;
    border: none;
    border-radius: var(--bk-radius-round);
    background: transparent;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

.bk-attachment-chip-remove:hover[b-kp9uuv40ak] {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 10%, transparent);
    color: var(--mud-palette-text-primary);
}
/* /Components/Shared/Chat/ChatComposerSurface.razor.rz.scp.css */
/* Scoped styles of the chat input surface (ChatComposerSurface.razor) - the
   card, its inner wrapper, the message field, the Enter-to-send hint and the
   control row. These lived in app.css for as long as ChatComposer and
   ChatQuestionBox each rendered this shell for themselves: CSS isolation
   scopes a selector to one component, and the markup lived in two. One owner
   is what lets them move here.

   The control row's BUTTONS are deliberately not here: each caller stamps
   .bk-composer-send and its variants onto buttons it renders itself, so those
   rules have to stay resolvable from the caller's own scope - app.css keeps
   them (and .bk-spinner, and .bk-composer-row-end) as the shared control
   primitive they are. --bk-control-h, set on the row below, still reaches
   them: a custom property cascades at runtime regardless of which component's
   scope declared it. */

/* Docked composer: a card of its own at the foot of the conversation column
   (concept "Eingabefeld gehoert sichtbar zum Chatverlauf und nutzt dessen
   Breite" - it used to bleed past the page's own padding as a page-wide
   footer strip; now it is a bordered card sized to the SAME column the
   transcript above it uses, wherever that column happens to sit - full page
   width with no draft open, the narrower share of the row next to a review
   gate otherwise, or ProjectSetupChat's own already-narrow column). A
   non-scrolling flex child of .bk-chat-composer-slot either way, so it stays
   at the bottom of the column while the transcript scrolls above it.

   container-type/container-name turn this card's own width into a query
   target (ChatRunSettingsPicker.razor.css's own "@container bk-composer"):
   the run-settings chip must collapse whenever THIS card is narrow, which
   happens not only on a narrow viewport but also on a wide one once a review
   gate shares the row with it (bk-chat-column's own 2-of-5 share) - a plain
   viewport media query never saw that second case, which is exactly how the
   chip's full text used to overflow this card's own edge and sit on top of
   the review gate beside it. */
/* The same cap and centring .bk-thread carries (app.css). On the CARD, not on
   its contents: capping the inner row left a full-width bordered box with its
   controls huddled in the middle of it - the box itself has to line up with
   the transcript above, since it reads as that transcript's own footer. */
.bk-composer[b-0i3c0jmvxf] {
    /* align-self, NOT margin-inline:auto: this card is a flex item of the
       column below the transcript, and an auto margin across the flex axis
       switches off the stretch that gives it its width - the card collapsed
       to the width of its own content. width:100% plus the cap plus centring
       does the same job without that trap. */
    width: 100%;
    max-width: 1040px;
    align-self: center;
    container-type: inline-size;
    container-name: bk-composer;
    flex: 0 0 auto;
    padding: 8px 14px;
    padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-lg);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
    transition: border-color var(--bk-dur-fast) var(--bk-ease-out), box-shadow var(--bk-dur-fast) var(--bk-ease-out);
}

/* The whole card carries the focus state, not the field inside it (see
   .bk-composer-input below): the message field, the hint and the control row
   read as ONE surface, so a ring around the field alone drew a second box
   inside the card and made the two borders compete. focus-within also covers
   the control row's own buttons, which belong to the same surface. */
.bk-composer:hover[b-0i3c0jmvxf] {
    border-color: var(--mud-palette-lines-inputs);
}

.bk-composer:focus-within[b-0i3c0jmvxf] {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mud-palette-primary) 16%, transparent);
}

/* Neumorphic design (app.css .bk-soft): the composer is one raised card;
   focus rings it in the accent on top of the raised shape. */
.bk-soft .bk-composer[b-0i3c0jmvxf],
.bk-soft .bk-composer:hover[b-0i3c0jmvxf] {
    border-color: transparent;
    box-shadow: var(--bk-depth-raised);
}

.bk-soft .bk-composer:focus-within[b-0i3c0jmvxf] {
    border-color: transparent;
    box-shadow: var(--bk-depth-raised), var(--bk-ring);
}

/* The inner wrapper fills the conversation column's own width (feature "Chat
   nutzt den Platz auf jedem Bildschirm effizient") and is the nearest
   POSITIONED ancestor the run-settings panel anchors to - see
   ChatRunSettingsPicker.razor.css. */
.bk-composer-inner[b-0i3c0jmvxf] {
    width: 100%;
}

/* The message/answer field: full width, its own row (acceptance criterion:
   "das Nachrichtenfeld nutzt deren volle Breite") - grows with typed content
   up to about eight lines (chat-interop.js's autosize, capped at the same
   200px as max-height below) and scrolls internally past that instead of
   pushing the transcript out of view.

   --bk-row-h is the exact one-line, border-box height of the field
   (line-height 1.4 * font-size 0.9375rem, + 9px top/bottom padding, + 1px
   top/bottom border) in rem rather than em so it resolves the same
   regardless of which element references it - both the field's initial paint
   (before chat-interop.js's autosize runs) and the control row's own
   --bk-control-h fallback rely on it. */
.bk-composer-input[b-0i3c0jmvxf] {
    --bk-row-h: calc(1.3125rem + 20px);
    display: block;
    width: 100%;
    box-sizing: border-box;
    resize: none;
    overflow-y: hidden;
    height: var(--bk-row-h);
    max-height: 200px;
    padding: 9px 2px;
    /* Transparent rather than removed: --bk-row-h above and chat-interop.js's
       own autosize both add the field's computed border width to the content
       height, so dropping the border outright would shift every height by 2px
       and leave the one-line field a hair too short on first paint. The field
       has no visible box of its own any more - .bk-composer around it is the
       surface - but its box MODEL stays exactly as it was. */
    border: 1px solid transparent;
    background: transparent;
    color: var(--mud-palette-text-primary);
    font-family: inherit;
    font-size: 0.9375rem;
    line-height: 1.4;
}

/* Only once content genuinely exceeds max-height does a real scrollbar make
   sense; chat-interop.js switches overflow-y to auto once it clamps the height. */
.bk-composer-input.bk-composer-input-scrollable[b-0i3c0jmvxf] {
    overflow-y: auto;
}

.bk-composer-input[b-0i3c0jmvxf]::placeholder {
    color: var(--mud-palette-text-secondary);
}

/* No ring of its own - .bk-composer's :focus-within carries it for the whole
   surface. Only the browser's default outline has to go. */
.bk-composer-input:focus[b-0i3c0jmvxf] {
    outline: none;
}

/* The Enter-to-send hint (acceptance criterion: available, but claims no
   permanent line of its own while the field is empty and unfocused) - it sits
   IN the control row, right-aligned in the space the row's own controls leave
   between them, and is only ever toggled with visibility, never display or
   rendering. Both halves of that matter:

   - in the row, it claims no line of its own at all (the row's height comes
     from its 2rem buttons), so the surface's height is the same whether the
     hint shows or not - appearing on focus no longer resizes the whole
     composer, which was the one thing about it people actually noticed;
   - visibility rather than display keeps its box reserved, so showing and
     hiding it never slides the attach/model/send controls sideways either.

   order:1 places it after the left-hand controls (which keep the default 0)
   and before the row-end action (order 2, see app.css) regardless of the DOM
   order each caller renders its own controls in. */
.bk-composer-hint[b-0i3c0jmvxf] {
    order: 1;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    text-align: right;
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
    visibility: hidden;
}

/* Available while the message field itself has focus, or while it holds text
   - the same rule as before, now evaluated in the browser instead of on the
   server (bk-composer-has-text is set by chat-interop.js's own input handler;
   a hint must not cost a circuit round trip, and the field itself may carry
   no focus handler at all - see the component's doc comment).

   The field's OWN focus, deliberately, not the surface's :focus-within: tabbing
   on to the attach button or the model chip leaves the field, and a reminder
   about what Enter does there would be about a key that no longer types into
   anything. Hence the sibling combinator - .bk-composer-row is the field's own
   next sibling, so no :has() is needed for it.

   The :not() carries SuppressHint (the Rueckfrage-Box drops the hint while an
   answer is in flight) rather than a separate, more specific rule having to
   out-shout these two. */
.bk-composer-input:focus ~ .bk-composer-row .bk-composer-hint:not(.bk-composer-hint-off)[b-0i3c0jmvxf],
.bk-composer-has-text .bk-composer-hint:not(.bk-composer-hint-off)[b-0i3c0jmvxf] {
    visibility: visible;
}

/* The control row underneath the message field: every action (attach, the
   model/effort chip, skip where it applies, send/interrupt) in one row that
   never grows a second line of its own on a phone (acceptance criterion:
   "braucht keine eigene Zeile"). --bk-control-h is deliberately smaller than
   the message field's own one-line --bk-row-h - the tight "no more height
   than two text lines" ceiling on the whole surface (message field + this
   row) leaves no room for a second row sized like the field itself. */
.bk-composer-row[b-0i3c0jmvxf] {
    --bk-control-h: 2rem;
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
}

/* ----- Mobile ----- */
@media (max-width: 599.98px) {
    .bk-composer[b-0i3c0jmvxf] {
        padding: 8px 12px calc(8px + env(safe-area-inset-bottom, 0px));
    }

    /* 16px keeps iOS from auto-zooming the page when the field is focused. */
    .bk-composer-input[b-0i3c0jmvxf] {
        --bk-row-h: calc(1.4rem + 20px);
        font-size: 16px;
    }

    /* A hint about Enter and Shift+Enter has nothing to say on a touch
       keyboard, and the control row has no width to spare at this size. */
    .bk-composer-hint[b-0i3c0jmvxf] {
        display: none;
    }
}
/* /Components/Shared/Chat/ChatEffortScale.razor.rz.scp.css */
/* Scoped styles of the segmented thinking-effort scale (ChatEffortScale.razor).
   Each segment is a step of increasing height, filled to the active level -
   the visual this feature calls for instead of a dropdown of level names. */

.bk-effort-scale[b-xawtx848jp] {
    display: inline-flex;
    align-items: flex-end;
    gap: 2px;
    height: 12px;
}

.bk-effort-scale-segment[b-xawtx848jp] {
    flex: 0 0 auto;
    width: 4px;
    /* Steps up from 40% to 100% of the scale's own height, one step per
       segment position (nth-child), regardless of how many segments this
       model allows - so a 3-level and a 5-level model both read as a rising
       staircase rather than segments of one fixed size. */
    height: 40%;
    border: none;
    padding: 0;
    border-radius: var(--bk-radius-xs);
    background: var(--mud-palette-lines-inputs);
    cursor: default;
}

.bk-effort-scale-segment:nth-child(1)[b-xawtx848jp] { height: 40%; }
.bk-effort-scale-segment:nth-child(2)[b-xawtx848jp] { height: 55%; }
.bk-effort-scale-segment:nth-child(3)[b-xawtx848jp] { height: 70%; }
.bk-effort-scale-segment:nth-child(4)[b-xawtx848jp] { height: 85%; }
.bk-effort-scale-segment:nth-child(5)[b-xawtx848jp] { height: 100%; }

.bk-effort-scale-segment-filled[b-xawtx848jp] {
    background: var(--mud-palette-primary);
}

.bk-effort-scale-segment-muted.bk-effort-scale-segment-filled[b-xawtx848jp] {
    background: color-mix(in srgb, var(--mud-palette-primary) 45%, var(--mud-palette-lines-inputs));
}

/* Interactive segments (the open panel's own picker) are real buttons - a
   small hit target still worth a hover/focus cue, unlike the closed chip's
   read-only <span> preview. */
button.bk-effort-scale-segment[b-xawtx848jp] {
    cursor: pointer;
}

button.bk-effort-scale-segment:hover[b-xawtx848jp],
button.bk-effort-scale-segment:focus-visible[b-xawtx848jp] {
    background: var(--mud-palette-primary-darken, var(--mud-palette-primary));
    outline: none;
}

button.bk-effort-scale-segment.bk-effort-scale-segment-filled:hover[b-xawtx848jp],
button.bk-effort-scale-segment.bk-effort-scale-segment-filled:focus-visible[b-xawtx848jp] {
    background: var(--mud-palette-primary);
}

/* The open panel's own picker (design-02: "5 wide, labelled, clearly
   tappable segments") - a full-width row of pill-shaped buttons with a
   visible level caption underneath each, instead of the closed chip's
   compact ascending staircase above (same underlying markup, ChatEffortScale
   ShowLabels="true" only changes which of these two rulesets applies). */
.bk-effort-scale-panel[b-xawtx848jp] {
    display: flex;
    align-items: stretch;
    gap: 6px;
    height: auto;
    width: 100%;
}

.bk-effort-scale-panel .bk-effort-scale-item[b-xawtx848jp] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    flex: 1 1 0;
    min-width: 0;
}

.bk-effort-scale-panel .bk-effort-scale-segment[b-xawtx848jp] {
    width: 100%;
    height: 22px;
    border-radius: var(--bk-radius-md);
}

.bk-effort-scale-panel .bk-effort-scale-item-label[b-xawtx848jp] {
    font-size: 0.6875rem;
    color: var(--mud-palette-text-secondary);
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}
/* /Components/Shared/Chat/ChatFreeModeControl.razor.rz.scp.css */
/* Scoped styles of ChatFreeModeControl.razor - free mode's own markers in the
   composer's control row (feature "Free agent chat with full access to the
   repository"). The same amber tone the mode's other markers (transcript
   banner, sidebar row) use throughout the chat surface. */

/* The switch on a brand new, not-yet-sent chat (design "New chat with the
   free-mode switch"), same square height as the model chip beside it. */
.bk-free-chat-toggle[b-70frvqp2fm] {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 10px;
    border-radius: var(--bk-radius-sm);
    border: 1px solid var(--mud-palette-lines-inputs);
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
}

.bk-free-chat-toggle:hover[b-70frvqp2fm] {
    border-color: #d97706;
    color: #633806;
}

.bk-free-chat-toggle-on[b-70frvqp2fm],
.bk-free-chat-toggle-on:hover[b-70frvqp2fm] {
    border-color: #d97706;
    background: #FAEEDA;
    color: #633806;
}

.bk-free-chat-toggle-state[b-70frvqp2fm] {
    font-weight: 600;
}

/* Neumorphic design (app.css .bk-soft): the switch is a raised pill; switched
   on it stays pressed in, with the mode's amber as a faint tint of the tone. */
.bk-soft .bk-free-chat-toggle[b-70frvqp2fm],
.bk-soft .bk-free-chat-toggle:hover[b-70frvqp2fm] {
    border-color: transparent;
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
    transition: box-shadow var(--bk-dur-fast) var(--bk-ease-out), transform var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-soft .bk-free-chat-toggle:active[b-70frvqp2fm] {
    box-shadow: var(--bk-depth-inset);
    transform: translateY(1px) scale(0.97);
}

.bk-soft .bk-free-chat-toggle-on[b-70frvqp2fm],
.bk-soft .bk-free-chat-toggle-on:hover[b-70frvqp2fm] {
    background: color-mix(in srgb, var(--mud-palette-surface) 85%, #E0A43A);
    box-shadow: var(--bk-depth-inset);
}

/* Once the first message fixed the mode (design "A running free chat"): the
   switch is replaced by this locked marker, and - only for a free chat - the
   conversation's own recorded cost/tokens next to it (feature "Free chat runs
   unbounded, its usage only recorded"), read purely as information. */
.bk-free-chat-fixed-chip[b-70frvqp2fm],
.bk-free-chat-usage-chip[b-70frvqp2fm] {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 10px;
    /* Matches the composer's own control-row radius (app.css's
       .bk-composer-send) - every control in that row is one family. */
    border-radius: var(--bk-radius-sm);
    background: #FAEEDA;
    color: #633806;
    font-size: 0.75rem;
    white-space: nowrap;
}

.bk-dark .bk-free-chat-toggle-on[b-70frvqp2fm],
.bk-dark .bk-free-chat-toggle-on:hover[b-70frvqp2fm],
.bk-dark .bk-free-chat-fixed-chip[b-70frvqp2fm],
.bk-dark .bk-free-chat-usage-chip[b-70frvqp2fm] {
    background: #4A2C05;
    color: #FAC775;
}
/* /Components/Shared/Chat/ChatLiveTurn.razor.rz.scp.css */
/* Scoped styles of the "Arbeitet..." status row and its live transcript
   (ChatLiveTurn.razor). */

/* Fixed status area between the scrollable transcript and the composer -
   deliberately NOT part of the transcript's own scroll, so "Arbeitet..."
   stays visible no matter where the user has scrolled the transcript to,
   instead of being just another turn that scrolls away with the rest. */
.bk-chat-status[b-ks7ujd0qs0] {
    flex: 0 0 auto;
    padding-top: 10px;
    border-top: 1px solid var(--mud-palette-lines-default);
}


/* Animated "the agent is thinking" indicator (no avatar, matches the flat
   look). */
.bk-typing[b-ks7ujd0qs0] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.bk-typing span[b-ks7ujd0qs0] {
    width: 7px;
    height: 7px;
    border-radius: var(--bk-radius-round);
    background: var(--mud-palette-text-secondary);
    opacity: 0.4;
    animation: bk-typing-b-ks7ujd0qs0 1.3s infinite ease-in-out;
}

.bk-typing span:nth-child(2)[b-ks7ujd0qs0] { animation-delay: 0.18s; }
.bk-typing span:nth-child(3)[b-ks7ujd0qs0] { animation-delay: 0.36s; }

@keyframes bk-typing-b-ks7ujd0qs0 {
    0%, 70%, 100% { transform: translateY(0); opacity: 0.35; }
    35% { transform: translateY(-4px); opacity: 0.9; }
}

/* Live transcript shown inline while the agent works, so the tool calls and
   partial output stream in instead of a bare spinner. Collapsed to one
   summary line by default (TranscriptView's CollapsedByDefault), so this sits
   as a second, unobtrusive line under the typing indicator rather than a
   separate boxed panel - no border/background of its own; TranscriptView's
   own bar and indented tool rows already carry the visual structure once
   expanded. Capped with its own scroll so a long-running turn cannot push the
   composer off screen - only this box scrolls, not the whole status area. */
.bk-chat-live[b-ks7ujd0qs0] {
    margin-top: 6px;
    max-height: 240px;
    overflow-y: auto;
}

/* The working-status area fills the conversation column's own width (feature
   "Chat nutzt den Platz auf jedem Bildschirm effizient"). Rendered by this
   component, so the rule lives here; it sat in app.css only while it was one
   selector list together with .bk-thread and .bk-composer-inner. */
.bk-chat-status-inner[b-ks7ujd0qs0] {
    width: 100%;
}
/* /Components/Shared/Chat/ChatPanel.razor.rz.scp.css */
/* Scoped styles of the composition shell (ChatPanel.razor): the page's own
   flex column and its header wrapper only. Every other region's styling lives
   with the component that renders it now - see ChatSideThreadLayer.razor.css,
   ChatTranscript.razor.css, ChatLiveTurn.razor.css, ChatComposer.razor.css and
   ChatTerminalPanels.razor.css.

   ::deep reaches the host page's own header fragment, which the Blazor
   CSS-isolation attribute would otherwise not touch. */

/* Fills the window. The page carries no vertical padding on a chat page
   (app.css's .bk-page:has(.bk-chat-page)), so the only chrome left to
   subtract is the mobile app bar below Lg - hence the media queries. Positioned so the whole-page
   drag-and-drop layer ChatComposer.razor renders (.bk-chat-drop-layer,
   ChatComposer.razor.css) can cover this entire element via inset:0 no matter
   how deep it actually sits in the render tree underneath. */
.bk-chat-page[b-svmcwlrxvz] {
    position: relative;
    display: flex;
    flex-direction: column;
    height: calc(100dvh - 12px);
    min-height: 0;
}

/* Below Lg (1280px) the mobile app bar reappears (app.css's own
   .bk-mobile-appbar breakpoint, widened together with the drawer so a tablet
   gets its width back too) - its 48px is the whole of the chrome now that the
   page's own vertical padding is gone. */
@media (max-width: 1279.98px) {
    .bk-chat-page[b-svmcwlrxvz] {
        height: calc(100dvh - 60px);
    }
}

/* Below 600px the mobile app bar is gone (feature "Phone navigation at the
   bottom edge" - no navigation menu remains at the top edge on a phone) and
   a fixed bottom bar takes its place instead, so the chrome to subtract
   moves from the top of the formula to the bottom: the page's own 12px top
   padding (.bk-page:has(.bk-chat-page) above) plus the bar's height
   (app.css's --bk-phone-bar-h, the one place that value is defined). */
@media (max-width: 599.98px) {
    .bk-chat-page[b-svmcwlrxvz] {
        height: calc(100dvh - 12px - var(--bk-phone-bar-h));
    }

    /* Keyboard-aware phone shell (feature "Phone navigation at the bottom
       edge, hidden while typing"): while js/keyboard-interop.js marks the
       document as keyboard-open, the bar above is gone (app.css) and the
       formula above no longer applies - sizing to it would leave a gap the
       height of the hidden bar between the composer and the keyboard. Sized
       to the measured visible height instead (--bk-kb-visible-h, the
       visualViewport height the script last read) minus only the page's own
       12px top inset, so the composer and its send button end up directly
       above the keyboard. 100dvh is only a fallback for a read that has not
       landed yet. */
    .bk-keyboard-open .bk-chat-page[b-svmcwlrxvz] {
        height: calc(var(--bk-kb-visible-h, 100dvh) - 12px);
    }
}


/* Free mode's own statement at the top of the transcript (feature "Free
   agent chat with full access to the repository", design callout 1) - the
   same amber tone the mode's other markers (composer toggle/fixed chip,
   sidebar row) use throughout the chat surface. */
.bk-free-chat-banner[b-svmcwlrxvz] {
    padding: 8px 12px;
    margin-bottom: 12px;
    border-radius: var(--bk-radius-sm);
    background: #FAEEDA;
    color: #633806;
    font-size: 0.8125rem;
}

.bk-dark .bk-free-chat-banner[b-svmcwlrxvz] {
    background: #4A2C05;
    color: #FAC775;
}

/* Its second line (feature "Free agent chat with unrestricted repository
   access and push"): the commit/push ability, set apart from the first line
   by weight alone, same design as the other banner text. */
.bk-free-chat-banner-push[b-svmcwlrxvz] {
    font-weight: 600;
    margin-top: 2px;
}

/* The pane holds a switch above its content once more than one thing is open
   (the draft and the artifacts). Both children of .bk-pane-body size
   themselves against a flex column with a definite height - the review
   gate's board and the artifact canvas each do - so this wrapper has to pass
   that height through rather than collapse it. */
.bk-pane-stack[b-svmcwlrxvz] {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    gap: 8px;
}

.bk-pane-body[b-svmcwlrxvz] {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* Deliberately not a quiet control: it is the only way back to a view that is
   open but not showing, so it has to read as a place to press rather than as a
   caption. Sits on the pane's background so the raised active segment carries
   the contrast. */
.bk-pane-tabs[b-svmcwlrxvz] {
    display: flex;
    gap: 3px;
    flex: 0 0 auto;
    align-self: flex-start;
    padding: 3px;
    background: var(--mud-palette-background-gray);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
}

.bk-pane-tabs button[b-svmcwlrxvz] {
    border: 0;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 500;
    padding: 6px 18px;
    border-radius: var(--bk-radius-sm);
    cursor: pointer;
}

.bk-pane-tabs button:hover[b-svmcwlrxvz] {
    color: var(--mud-palette-text-primary);
}

.bk-pane-tabs button.bk-pane-tab-active[b-svmcwlrxvz] {
    background: var(--mud-palette-surface);
    color: var(--mud-palette-primary);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
}

/* Everything the draft's card looks like is the shared .bk-teaser
   (wwwroot/app.css), the very same one an artifact's card uses. Only its place
   in the transcript is this component's own business. */
.bk-draft-teaser[b-svmcwlrxvz] {
    margin-top: 8px;
    /* The same measure an agent turn's own card sits in
       (.bk-turn-agent .bk-turn-body, ChatTranscript.razor.css): this card is a
       sibling of those, not a banner across the thread, and a different width
       made the two read as two different kinds of thing. */
    max-width: 75ch;
}
/* /Components/Shared/Chat/ChatQuestionBox.razor.rz.scp.css */
/* Scoped styles of the Rueckfrage-Box (ChatQuestionBox.razor). It sits at the
   exact same docked spot as ChatPanel's own free-text composer and shares its
   surface (.bk-composer, .bk-composer-inner, .bk-composer-row,
   .bk-composer-input, .bk-composer-send and its variants, .bk-composer-hint,
   see app.css's own "Chat composer surface" section) so the two modes read
   as the same surface -
   CSS isolation scopes each component's own classes independently, so reusing
   those class names here causes no collision; only one of the two ever
   renders at a time. Only what is genuinely new here (the progress line, the
   question text, the skip action) gets its own classes below. */

.bk-question-progress[b-oc0qs6ixv7] {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 6px;
}

.bk-question-text[b-oc0qs6ixv7] {
    font-size: 0.9375rem;
    margin-bottom: 10px;
}

/* The skip action reads as a quiet text link in the control row, not a
   competing button, so the answer button stays the row's obvious primary
   action. */
.bk-question-skip[b-oc0qs6ixv7] {
    flex: 0 0 auto;
    border: none;
    background: none;
    padding: 0;
    color: var(--mud-palette-text-secondary);
    text-decoration: underline;
    cursor: pointer;
    font: inherit;
    font-size: 12px;
}

.bk-question-skip:hover[b-oc0qs6ixv7] {
    color: var(--mud-palette-text-primary);
}
/* /Components/Shared/Chat/ChatQuestionRoundCard.razor.rz.scp.css */
/* Scoped styles of ChatQuestionRoundCard.razor. CSS isolation scopes each
   component's classes independently, so this duplicates the turn/bubble
   basics of ChatPanel.razor.css (.bk-turn/.bk-turn-user/.bk-turn-role/
   .bk-turn-body) the same way ChatQuestionBox.razor.css duplicates the
   composer basics - the two files never collide, they just both target the
   same visual language. Only what is genuinely new here (the per-question
   list) gets its own classes below. */

.bk-turn[b-quhdx61u3a] {
    margin-bottom: 22px;
}

.bk-turn-role[b-quhdx61u3a] {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 5px;
}

.bk-turn-user[b-quhdx61u3a] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
}

.bk-turn-user .bk-turn-role[b-quhdx61u3a] {
    align-self: flex-end;
}

.bk-turn-user .bk-turn-body[b-quhdx61u3a] {
    max-width: min(85%, 660px);
    padding: 10px 15px;
    border-radius: var(--bk-radius-lg) var(--bk-radius-lg) var(--bk-radius-sm) var(--bk-radius-lg);
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface));
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 22%, transparent);
}

.bk-dark .bk-turn-user .bk-turn-body[b-quhdx61u3a] {
    background: color-mix(in srgb, var(--mud-palette-primary) 18%, var(--mud-palette-surface));
    border-color: color-mix(in srgb, var(--mud-palette-primary) 34%, transparent);
}

/* One question/answer pair of the round - a small gap between them keeps a
   multi-question round scannable without needing a divider per pair. */
.bk-question-round-item[b-quhdx61u3a] {
    font-size: 0.9375rem;
}

.bk-question-round-item + .bk-question-round-item[b-quhdx61u3a] {
    margin-top: 10px;
}

.bk-question-round-question[b-quhdx61u3a] {
    font-weight: 600;
}

.bk-question-round-answer[b-quhdx61u3a] {
    color: var(--mud-palette-text-secondary);
}

/* A skipped question reads distinctly - italic, no implication of an actual
   answer having been given. */
.bk-question-round-skipped[b-quhdx61u3a] {
    font-style: italic;
}
/* /Components/Shared/Chat/ChatRunSettingsPicker.razor.rz.scp.css */
/* Scoped styles of the per-chat model/thinking-effort picker
   (ChatRunSettingsPicker.razor) - the closed chip that sits inline in the
   composer's own control row (see app.css's own --bk-control-h) and the
   panel this component renders directly as a plain, non-portaled child of
   its own markup once opened (see the component's own doc comment on why -
   no MudMenu/MudPopoverProvider involved anymore, so this scoped sheet
   reaches every element here without app.css's help). */

/* Deliberately NOT position:relative: the panel below anchors to the nearest
   POSITIONED ancestor, which must be .bk-composer-inner (see app.css) so it
   floats above the whole composer surface - if this wrapper claimed its own
   position:relative here, the panel would instead anchor to this small chip
   wrapper's own position within the control row. */
.bk-chat-run-settings[b-90aq6ursfx] {
    display: inline-flex;
    flex: 0 0 auto;
}

.bk-chat-run-settings-chip[b-90aq6ursfx] {
    display: inline-flex;
    align-items: center;
    height: var(--bk-control-h, 2rem);
    gap: 6px;
    padding: 0 10px;
    /* Quieter border and the composer's own control-row radius (app.css's
       .bk-composer-send): inside the composer card this chip is one of three
       controls on the same row, and the harder lines-inputs edge plus a 4px
       corner made it read as a form field dropped into a toolbar. */
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    background: transparent;
    color: var(--mud-palette-text-primary);
    cursor: pointer;
    font-size: 0.8125rem;
    white-space: nowrap;
    transition: background-color var(--bk-dur-fast) var(--bk-ease-out), border-color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-chat-run-settings-chip:hover[b-90aq6ursfx],
.bk-chat-run-settings-chip:focus-visible[b-90aq6ursfx] {
    border-color: var(--mud-palette-lines-inputs);
    background: var(--mud-palette-action-default-hover);
    outline: none;
}

/* Neumorphic design (app.css .bk-soft): a raised pill, pressed in while its
   panel is open or while held. */
.bk-soft .bk-chat-run-settings-chip[b-90aq6ursfx],
.bk-soft .bk-chat-run-settings-chip:hover[b-90aq6ursfx],
.bk-soft .bk-chat-run-settings-chip:focus-visible[b-90aq6ursfx] {
    border-color: transparent;
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
    transition: box-shadow var(--bk-dur-fast) var(--bk-ease-out), transform var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-soft .bk-chat-run-settings-chip:focus-visible[b-90aq6ursfx] {
    box-shadow: var(--bk-depth-raised-sm), var(--bk-ring);
}

.bk-soft .bk-chat-run-settings-chip[aria-expanded="true"][b-90aq6ursfx],
.bk-soft .bk-chat-run-settings-chip:active[b-90aq6ursfx] {
    box-shadow: var(--bk-depth-inset);
}

.bk-chat-run-settings-chip-icon[b-90aq6ursfx] {
    color: var(--mud-palette-text-secondary);
}

.bk-chat-run-settings-chip-model[b-90aq6ursfx] {
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 160px;
}

.bk-chat-run-settings-chip-effort[b-90aq6ursfx] {
    color: var(--mud-palette-text-secondary);
}

/* Invisible, full-viewport: catches a click anywhere outside the panel and
   closes it without changing the selection (acceptance criterion). Sits
   behind the panel (lower z-index) but above everything else, including
   MudBlazor's own Drawer (z-index 1100) and AppBar (1300) - without clearing
   both, a click anywhere over the persistent sidebar (which paints above a
   backdrop left at the composer's own low z-index) never reaches this
   element at all, since the browser hit-tests the topmost element at that
   point regardless of its transparency; same reasoning as
   ProjectAudit.razor.css's own 1350 overlay. Stays below Dialog (1400) so a
   MudDialog opened from elsewhere still layers on top of it. */
.bk-chat-run-settings-backdrop[b-90aq6ursfx] {
    position: fixed;
    inset: 0;
    z-index: 1350;
    background: transparent;
    border: none;
    cursor: default;
}

/* The opened panel: position:fixed, with its actual top/left/max-height set
   by run-settings-panel-interop.js's own bkRunSettingsPanel.position (see
   this component's own doc comment on why CSS alone cannot place it - this
   app's pages size to their content rather than force-stretching a short
   transcript, so the chip can sit anywhere from just below the header to the
   very bottom of the screen). position:fixed here is only the baseline the
   interop then repositions in the same render pass; width is a CSS-only
   concern the interop reads back via getBoundingClientRect rather than
   computing itself, capped well inside the viewport on a narrow phone. A
   scroller of its own once the clamped max-height the interop sets is
   actually less than the content needs. */
.bk-chat-run-settings-panel[b-90aq6ursfx] {
    position: fixed;
    z-index: 1351;
    width: min(420px, calc(100vw - 16px));
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 12px 14px;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--bk-radius-md);
    box-shadow: var(--mud-elevation-8, 0 6px 24px rgba(0, 0, 0, 0.18));
}

/* Focused programmatically on open (see ChatRunSettingsPicker.razor's own
   OnAfterRenderAsync) so a keyboard Escape press reaches this panel rather
   than the chip outside it - never a manual tab stop, so no visible ring. */
.bk-chat-run-settings-panel:focus[b-90aq6ursfx] {
    outline: none;
}

.bk-chat-run-settings-panel-section[b-90aq6ursfx] {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
}

.bk-chat-run-settings-panel-label[b-90aq6ursfx] {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.bk-chat-run-settings-panel-status[b-90aq6ursfx] {
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}

/* One selectable model - name plus its everyday-language hint (acceptance
   criterion: choosable without knowing the model names), the active one
   highlighted and checked. A plain <button>, not MudMenuItem, so it can carry
   the two-line text block below (same reasoning ChatEffortScale's own
   interactive segments already use custom buttons instead of MudMenuItem). */
.bk-chat-run-settings-model-option[b-90aq6ursfx] {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--bk-radius-md);
    background: transparent;
    color: var(--mud-palette-text-primary);
    text-align: left;
    cursor: pointer;
}

.bk-chat-run-settings-model-option + .bk-chat-run-settings-model-option[b-90aq6ursfx] {
    margin-top: 6px;
}

.bk-chat-run-settings-model-option:hover[b-90aq6ursfx],
.bk-chat-run-settings-model-option:focus-visible[b-90aq6ursfx] {
    border-color: var(--mud-palette-primary);
    outline: none;
}

.bk-chat-run-settings-model-option-selected[b-90aq6ursfx] {
    border-color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, transparent);
}

.bk-chat-run-settings-model-option-text[b-90aq6ursfx] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.bk-chat-run-settings-model-option-name[b-90aq6ursfx] {
    font-size: 0.875rem;
    font-weight: 600;
}

.bk-chat-run-settings-model-option-hint[b-90aq6ursfx] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.bk-chat-run-settings-model-option-check[b-90aq6ursfx] {
    flex: 0 0 auto;
    margin-left: auto;
    color: var(--mud-palette-primary);
}

.bk-chat-run-settings-reset[b-90aq6ursfx] {
    align-self: flex-start;
    border: none;
    background: transparent;
    padding: 0;
    color: var(--mud-palette-primary);
    font-size: 0.8125rem;
    text-decoration: underline;
    cursor: pointer;
}

/* ----- Narrow composer: the chip shrinks to icon + scale only, never its
   text, so the control row (attach, chip, send) never wraps onto a second
   line (the "adds no row of its own" criterion) nor overflows the composer
   card's own edge. Queried against the COMPOSER CARD's own width (app.css's
   ".bk-composer" container-type/container-name), not the viewport: a phone
   composer is narrow because the viewport is, but the same card is exactly
   as narrow on a wide screen once a review gate shares the row with it
   (bk-chat-column's own 2-of-5 share, e.g. ~350px wide at 1024px or even at
   1280px) - a plain viewport media query only ever saw the phone case, so
   the chip's full, untruncated text (well past 350px on its own) quietly
   overflowed the card and sat on top of the review gate beside it. 480px
   comfortably covers "attach + full chip + send never fit" in every draft
   column width this app's own breakpoints produce, with room to spare over
   the ~450px the full chip plus its neighbors actually need. The panel keeps
   its own width: min(...) cap from above, which naturally reduces to the
   composer's own near-full width at 360px. ----- */
@container bk-composer (max-width: 479.98px) {
    .bk-chat-run-settings-chip[b-90aq6ursfx] {
        padding: 0 8px;
    }

    .bk-chat-run-settings-chip-model[b-90aq6ursfx],
    .bk-chat-run-settings-chip-effort[b-90aq6ursfx] {
        display: none;
    }
}
/* /Components/Shared/Chat/ChatSessionRow.razor.rz.scp.css */
/* Scoped styles of ChatSessionRow.razor. The row's own states - the session
   currently open beside the list (design "Chat-Seite mit Chat-Liste
   (Desktop)") and a free chat's amber tint (feature "Free agent chat with
   full access to the repository", design callout 6) - are NOT here: the
   row's root is a MudPaper, which never carries this component's
   CSS-isolation attribute, so a scoped rule on it can never match. They
   live in app.css (.bk-chat-session-row-current, .bk-free-chat-row). */

/* ----- Dense row (the sessions list beside an open chat) -----------------
   The title is what the row is for: it gets the first line at the body size,
   and everything else - when the chat started, what state it is in - drops to
   a small second line. The previous attempt only shrank the padding, which
   left a 14px title competing with a full-size status pill in a 210px column.
   The pill is rendered by this component itself, so the scope attribute
   reaches it without ::deep; .bk-chat-row-dense is only an ancestor here
   (Blazor scopes the rightmost element). */
.bk-chat-row-main[b-v2ljd4lv8o] {
    flex: 1 1 auto;
    min-width: 0;
}

.bk-chat-row-title[b-v2ljd4lv8o] {
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.35;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-chat-row-meta[b-v2ljd4lv8o] {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 2px;
    font-size: 0.6875rem;
    line-height: 1.3;
    color: var(--mud-palette-text-secondary);
    min-width: 0;
}

/* Small enough to read as metadata next to the timestamp rather than as a
   second headline; the shared .bk-pill (app.css) keeps its colours. */
.bk-chat-row-meta .bk-pill[b-v2ljd4lv8o] {
    font-size: 0.625rem;
    padding: 1px 6px;
    line-height: 1.5;
    white-space: nowrap;
}
/* /Components/Shared/Chat/ChatSessionsSidebar.razor.rz.scp.css */
/* Scoped styles of ChatSessionsSidebar.razor - three arrangements of the same
   mounted list (see that component's own comment):
     - from 1920px up:      a permanent second column next to the chat surface,
     - 1280px to 1920px:    a column the header toggle shows and hides, which
                            shifts the chat surface instead of covering it,
     - below 1280px:        a slide-in drawer over the page, with a scrim.
   ChatPanel.razor.css sizes .bk-chat-page to the same fixed
   calc(100dvh - ...) formula used below, so nesting it one level deeper here
   changes nothing about its own height - both resolve to the same value
   independently. */

.bk-chat-sidebar-layout[b-mi345i65ub] {
    display: flex;
    flex-direction: column;
    height: calc(100dvh - 12px);
    min-height: 0;
}

/* Same three-tier formula as ChatPanel.razor.css's own .bk-chat-page - see
   its comment for why the middle (tablet) tier needs its own value now that
   the mobile app bar shows below Lg (1280px) instead of only below 600px. */
@media (max-width: 1279.98px) {
    .bk-chat-sidebar-layout[b-mi345i65ub] {
        height: calc(100dvh - 60px);
    }
}

/* Below 600px the mobile app bar is gone and a fixed bottom bar takes its
   place instead (feature "Phone navigation at the bottom edge") - see
   ChatPanel.razor.css's own comment on the same switch for .bk-chat-page,
   which this mirrors exactly. */
@media (max-width: 599.98px) {
    .bk-chat-sidebar-layout[b-mi345i65ub] {
        height: calc(100dvh - 12px - var(--bk-phone-bar-h));
    }

    /* Keyboard-aware phone shell: same reasoning and formula as
       ChatPanel.razor.css's own .bk-keyboard-open override, mirrored here for
       the sessions-sidebar layout wrapper. */
    .bk-keyboard-open .bk-chat-sidebar-layout[b-mi345i65ub] {
        height: calc(var(--bk-kb-visible-h, 100dvh) - 12px);
    }
}

/* The row carrying the list column and the chat surface beside it. No
   positioning context of its own any more: the drawer below is fixed to the
   viewport rather than inset into this element, which is what used to lay it
   over the page header inside .bk-chat-sidebar-main. */
.bk-chat-sidebar-content[b-mi345i65ub] {
    display: flex;
    align-items: stretch;
    gap: 16px;
    flex: 1 1 auto;
    min-height: 0;
}

/* The session list: fixed width, a title row that stays put and one scroll
   region under it, so a long history never grows the page - the chat surface
   beside it keeps its own single scrollbar untouched. */
.bk-chat-sessions-col[b-mi345i65ub] {
    display: flex;
    flex-direction: column;
    flex: 0 0 240px;
    width: 240px;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    padding-right: 12px;
    border-right: 1px solid var(--mud-palette-lines-default);
}

.bk-chat-sessions-col:focus[b-mi345i65ub] {
    outline: none;
}

.bk-chat-sessions-scroll[b-mi345i65ub] {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* Neumorphic design (app.css .bk-soft): the rows are raised pads, and a
   scroll container clips everything outside its padding box - room on every
   side, so their shadows are not cut off at the list's edges. */
.bk-soft .bk-chat-sessions-scroll[b-mi345i65ub] {
    padding: 6px 8px 10px 6px;
}

/* The title row belongs to the toggled arrangements alone: a permanent column
   is neither titled nor closable, and its own "Offen (n)" heading below
   already says what the list is. */
.bk-chat-sessions-panel-head[b-mi345i65ub] {
    display: none;
}

.bk-chat-sessions-close[b-mi345i65ub] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border: 0;
    border-radius: var(--bk-radius-round);
    background: none;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
    transition: background-color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-chat-sessions-close:hover[b-mi345i65ub],
.bk-chat-sessions-close:focus-visible[b-mi345i65ub] {
    background: var(--mud-palette-action-default-hover);
}

/* "Offen (n)" - the same overline+count heading style MainLayout's own
   "Wartet auf dich"/"Agenten aktiv" sections use (bk-tab-count, app.css) -
   only rendered while there is at least one open session, mirroring the
   history section's own "hidden while empty" rule below. */
.bk-chat-sessions-heading[b-mi345i65ub] {
    gap: 6px;
    padding: 0 4px 8px;
}

.bk-chat-sessions-history[b-mi345i65ub] {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.bk-chat-history-toggle[b-mi345i65ub] {
    cursor: pointer;
    user-select: none;
    gap: 6px;
    margin: 0 -4px;
    padding: 4px;
    border-radius: var(--bk-radius-sm);
    transition: background-color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-chat-history-toggle:hover[b-mi345i65ub],
.bk-chat-history-toggle:focus-visible[b-mi345i65ub] {
    background: var(--mud-palette-action-default-hover);
}

.bk-chat-history-toggle:focus-visible[b-mi345i65ub] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -1px;
}

/* The main column (ChatPanel and everything the kind's own page places
   around it) - min-width:0 is what stops its own content (the transcript,
   the review gate) from ever forcing this row wider than the viewport, the
   same reasoning every other flex child in the chat chain already follows
   (see ChatSideThreadLayer.razor.css's own .bk-chat-scroll). */
.bk-chat-sidebar-main[b-mi345i65ub] {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
}

/* No backdrop where the list is a real column - nothing is behind anything. */
.bk-chat-sessions-scrim[b-mi345i65ub] {
    display: none;
}

/* ----- Below Xl (1920px): the column is what the header toggle shows and
   hides. The approved design keeps the list docked only on a very wide
   (2560px) screen and already shows it as a header toggle at 1280px; a
   permanently docked third element below that forces the conversation and an
   opened draft into the same width budget (the same reasoning
   ChatSideThreadLayer's own mobile switch follows for its own two regions).
   The toggle BUTTON itself lives in the page header (RequirementDraft.razor,
   concept "Umschalter wandert in die Kopfzeile") and is styled there. ----- */
@media (max-width: 1919.98px) {
    .bk-chat-sessions-col[b-mi345i65ub] {
        display: none;
    }

    /* A little wider than the permanently docked column of the approved
       2560px design: a row's own second line (when it started plus its
       status pill) stops wrapping at about this width, and a column that only
       appears on demand can afford what a permanent one has to justify. */
    .bk-chat-sessions-col.bk-chat-sessions-open[b-mi345i65ub] {
        display: flex;
        flex: 0 0 280px;
        width: 280px;
    }

    /* Now that the list can be dismissed, it says what it is and carries the
       way out: the page header's toggle is no longer the only control that
       closes it (and, once this is the drawer below, no longer reachable
       while it is open). */
    .bk-chat-sessions-panel-head[b-mi345i65ub] {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 8px;
        flex: 0 0 auto;
        padding: 0 0 8px 4px;
        margin-bottom: 4px;
        border-bottom: 1px solid var(--mud-palette-lines-default);
    }
}

/* ----- Below Lg (1280px): a drawer over the page instead of a column beside
   it - a 280px column and a usable conversation no longer fit next to each
   other at all here. Fixed to the VIEWPORT (not
   inset into .bk-chat-sidebar-content), positioned and stacked like
   MainLayout's own phone sheet: below the phone bottom bar (1250) so its tabs
   stay usable, above the docked/overlay chrome below it, and below
   MudBlazor's Dialog (1400) so a dialog still layers on top.

   Always laid out, never display:none in this tier: it slides in and out from
   the left edge instead, with visibility keeping it out of the tab order and
   out of hit-testing while closed. Its own state (scroll position, expanded
   history) survives every close, the same "stays mounted" trick
   ChatSideThreadLayer's own .bk-side-reader uses. ----- */
@media (max-width: 1279.98px) {
    .bk-chat-sessions-col[b-mi345i65ub],
    .bk-chat-sessions-col.bk-chat-sessions-open[b-mi345i65ub] {
        display: flex;
        position: fixed;
        /* Clear of the mobile app bar (48px, fixed at the top edge between
           600px and 1280px); the phone tier below starts at the top instead,
           where there is no app bar any more. */
        top: 48px;
        bottom: 0;
        left: 0;
        z-index: 1245;
        flex: none;
        width: min(320px, calc(100vw - 48px));
        padding: 12px 10px;
        background: var(--mud-palette-surface);
        box-shadow: 4px 0 18px rgba(0, 0, 0, 0.24);
        transform: translateX(-100%);
        visibility: hidden;
        /* visibility is not interpolated, it FLIPS - so it is switched with a
           zero-length transition instead: immediately on the way in (below),
           and only after the slide has played out on the way back. Sharing one
           duration with transform would leave the panel hidden through the
           first half of its own opening, which silently swallows the focus
           handoff (focus() on a visibility:hidden element does nothing). */
        transition: transform var(--bk-dur-base) var(--bk-ease-out), visibility 0s linear var(--bk-dur-base);
    }

    .bk-chat-sessions-col.bk-chat-sessions-open[b-mi345i65ub] {
        transform: none;
        visibility: visible;
        transition: transform var(--bk-dur-base) var(--bk-ease-out), visibility 0s;
    }

    /* Dims the page behind the drawer and closes it on a click anywhere
       outside - which is also what keeps the page header's own toggle from
       needing a z-index of its own to stay above the list (it no longer has
       to be: a click at its position closes the drawer through this). */
    .bk-chat-sessions-scrim[b-mi345i65ub] {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 1240;
        background: rgba(0, 0, 0, 0.35);
        /* Hidden by visibility rather than by pointer-events alone (which is
           what MainLayout's own phone scrim uses): an opacity-0 layer over
           the whole page is still a visible element to anything that asks -
           assistive technology and a browser check alike. Same zero-length
           visibility switch as the panel above, so the fade still plays out
           in both directions. */
        opacity: 0;
        visibility: hidden;
        transition: opacity var(--bk-dur-base) var(--bk-ease-out), visibility 0s linear var(--bk-dur-base);
    }

    .bk-chat-sessions-scrim-open[b-mi345i65ub] {
        opacity: 1;
        visibility: visible;
        transition: opacity var(--bk-dur-base) var(--bk-ease-out), visibility 0s;
    }
}

/* Phone: no app bar above (the shell's chrome is the fixed bottom bar
   instead), so the drawer starts at the top edge and stops above that bar -
   its tabs stay visible and usable with the list open, exactly as they do
   under MainLayout's own "More" sheet. */
@media (max-width: 599.98px) {
    .bk-chat-sessions-col[b-mi345i65ub],
    .bk-chat-sessions-col.bk-chat-sessions-open[b-mi345i65ub] {
        top: 0;
        bottom: calc(var(--bk-phone-bar-h) + env(safe-area-inset-bottom, 0px));
    }
}
/* /Components/Shared/Chat/ChatSideThreadLayer.razor.rz.scp.css */
/* Scoped styles of the side-thread layer (ChatSideThreadLayer.razor): the
   transcript, the PendingReview review gate, and the state-driven side-thread
   surface (nothing / a launcher strip / a full-width reader - see
   ChatSideThreadSurfaceState), three overlays sharing the same content area
   and stacked by z-index (review under launcher under reader). Turn/
   transcript styling itself lives in ChatTranscript.razor.css; this file
   only owns the chrome AROUND the readable area.

   ::deep is used wherever a rule targets an element rendered by a child
   component or a host page's own RenderFragment (MudBlazor internals,
   ChatSideThreadRail/AnnotationThread, or RequirementDraftBoard/.bk-draft-
   actions inside Review) the Blazor CSS-isolation attribute would otherwise
   not reach. */

/* Takes all the height left between the header and the docked composer;
   min-height:0 lets its children shrink and scroll instead of overflowing
   the page. position:relative is what lets the reader below become an
   absolutely positioned layer drawn above the transcript, so opening or
   reading a strand never moves the transcript's own scroll position. */
.bk-chat[b-dlqs2fqf0r] {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    position: relative;
}

/* Only while the launcher or the reader is showing (see
   ChatSideThreadSurfaceState.Hidden) - bleeds .bk-chat past the page's own
   24px padding on its right edge, same trick .bk-composer uses, so the
   launcher/reader's own edge lands flush with the content edge. */
.bk-chat-has-rail[b-dlqs2fqf0r] {
    margin-right: -24px;
}

/* Launcher: a slim strip flush with the content edge, shown while at least
   one strand exists and the reader is not open. Absolutely positioned, so
   the transcript keeps the full width of .bk-chat-scroll. Above the
   secondary pane (z-index 22): a strand must stay reachable while a draft is
   under review. */
.bk-side-launcher[b-dlqs2fqf0r] {
    position: absolute;
    top: 12px;
    right: 0;
    z-index: 24;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 12px;
    border-radius: var(--bk-radius-pill) 0 0 var(--bk-radius-pill);
    border: 1px solid var(--mud-palette-lines-default);
    border-right: none;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(38, 36, 58, 0.16);
}

.bk-side-launcher:hover[b-dlqs2fqf0r] {
    color: var(--mud-palette-primary);
    border-color: var(--mud-palette-primary);
}

.bk-side-launcher-count[b-dlqs2fqf0r] {
    font-size: 0.6875rem;
    font-weight: 600;
    border-radius: var(--bk-radius-sm);
    padding: 1px 6px;
    background: color-mix(in srgb, var(--mud-palette-warning) 18%, transparent);
    color: var(--mud-palette-warning);
}

/* Reader: fills the whole content area, drawn above the still-mounted,
   still-scrolled transcript. The single scrolling element of the whole
   surface, so there is at most one vertical scrollbar and never a nested
   one. Highest z-index of the three overlays: it must cover the review
   gate too. */
.bk-side-reader[b-dlqs2fqf0r] {
    position: absolute;
    inset: 0;
    z-index: 30;
    background: var(--mud-palette-surface);
    overflow-y: auto;
    overflow-x: hidden;
}

/* AnnotationThread reuses the same compact .bk-anno-* classes the diff and
   proposal annotation panels also use (app.css) - those must not change
   appearance there, so the reader overrides them scoped to itself only. */
.bk-side-reader[b-dlqs2fqf0r]  .bk-anno-text {
    font-size: 0.9rem;
    line-height: 1.5;
}

.bk-side-reader[b-dlqs2fqf0r]  .bk-anno-answer {
    padding: 10px 12px;
}
/* ----- Phone ----- */
@media (max-width: 599.98px) {
    /* .bk-page's own padding shrinks to 12px on phones - the bleed must
       match. */
    .bk-chat-has-rail[b-dlqs2fqf0r] {
        margin-right: -12px;
    }

    .bk-side-launcher[b-dlqs2fqf0r] {
        top: 8px;
    }
}
/* /Components/Shared/Chat/ChatSideThreadPanel.razor.rz.scp.css */
/* The marker badge (ChatSideThreadPanel.razor): a small pill next to an
   annotatable spot, showing the global numbers of every strand already
   anchored there. Renders only when at least one strand exists - starting a
   new one happens by marking the spot itself, never through this badge, so
   there is no "+" affordance and no empty chrome left when nothing is
   anchored yet. Reading/replying/promoting moved to ChatSideThreadRail.razor -
   this badge never renders a panel of its own, so it never pushes surrounding
   content apart. */

.bk-sidethread-chip[b-hs0i08l5v9] {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    margin-top: 6px;
    vertical-align: middle;
}

.bk-sidethread-chip-nums[b-hs0i08l5v9] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: var(--bk-radius-pill);
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 40%, var(--mud-palette-lines-default));
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, transparent);
    font-size: 0.75rem;
    cursor: pointer;
    user-select: none;
    transition: border-color var(--bk-dur-fast) var(--bk-ease-out), color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-sidethread-chip-nums:hover[b-hs0i08l5v9] {
    border-color: var(--mud-palette-primary);
}
/* /Components/Shared/Chat/ChatSideThreadRail.razor.rz.scp.css */
/* The side-thread rail (ChatSideThreadRail.razor): every strand of the
   session, read at full width inside ChatSideThreadLayer's reader (its own
   scoped .bk-side-reader, see ChatSideThreadLayer.razor.css), collapsible per
   card. This component carries no scroll or height of its own any more - the
   reader is the single scrolling element of the whole surface, so opening or
   reading a strand never causes a second, nested scrollbar. */

.bk-rail[b-5id6zl96cb] {
    display: flex;
    flex-direction: column;
}

.bk-rail-head[b-5id6zl96cb] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    position: sticky;
    top: 0;
    background: var(--mud-palette-surface);
    z-index: 1;
    color: var(--mud-palette-text-secondary);
}

.bk-rail-head-title[b-5id6zl96cb] {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.bk-rail-head-count[b-5id6zl96cb] {
    font-size: 0.6875rem;
    font-weight: 600;
    border-radius: var(--bk-radius-sm);
    padding: 1px 7px;
    background: color-mix(in srgb, var(--mud-palette-warning) 18%, transparent);
    color: var(--mud-palette-warning);
}

.bk-rail-body[b-5id6zl96cb] {
    padding: 12px 16px 24px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.bk-rail-card[b-5id6zl96cb] {
    border-radius: var(--bk-radius-sm);
    border: 1px solid var(--mud-palette-lines-default);
    background: var(--mud-palette-surface);
}

.bk-rail-card-open[b-5id6zl96cb] {
    border-left: 3px solid var(--mud-palette-warning);
}

.bk-rail-card-done[b-5id6zl96cb] {
    border-left: 3px solid var(--mud-palette-success);
}

.bk-rail-card-compose[b-5id6zl96cb] {
    border-style: dashed;
    border-color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 6%, var(--mud-palette-surface));
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.bk-rail-card-head[b-5id6zl96cb] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    cursor: pointer;
    user-select: none;
    font-size: 0.875rem;
}

.bk-rail-card-num[b-5id6zl96cb] {
    font-weight: 700;
    color: var(--mud-palette-text-secondary);
    flex-shrink: 0;
}

/* No truncation: a long target label wraps onto further lines within its own
   flex item instead of being cut off with an ellipsis or pushing the row
   into a horizontal scrollbar (feature: "ohne abgeschnittene Wörter"). */
.bk-rail-card-label[b-5id6zl96cb] {
    flex: 1;
    min-width: 0;
    font-weight: 500;
    overflow-wrap: anywhere;
}

.bk-rail-card-label:hover[b-5id6zl96cb] {
    text-decoration: underline;
    color: var(--mud-palette-primary);
}

.bk-rail-card-status[b-5id6zl96cb] {
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    color: var(--mud-palette-success);
    white-space: nowrap;
}

.bk-rail-card-status-open[b-5id6zl96cb] {
    color: var(--mud-palette-warning);
}

.bk-rail-card-body[b-5id6zl96cb] {
    padding: 0 12px 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Quote/reply action rows wrap instead of forcing a horizontal scrollbar at
   narrow viewports (feature: "keine Aktion... erst nach seitlichem
   Schieben"). */
.bk-rail-card-actions[b-5id6zl96cb],
.bk-rail-compose-actions[b-5id6zl96cb] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.bk-rail-quote[b-5id6zl96cb] {
    margin: 0;
    padding: 8px 12px;
    border-left: 3px solid var(--mud-palette-lines-default);
    font-size: 0.875rem;
    font-style: italic;
    color: var(--mud-palette-text-secondary);
    background: var(--mud-palette-background-gray);
    border-radius: 0 var(--bk-radius-sm) var(--bk-radius-sm) 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}
/* /Components/Shared/Chat/ChatSurfaceHeader.razor.rz.scp.css */
/* Scoped styles of ChatSurfaceHeader.razor - moved here with the element
   itself when the header went inside the conversation column (see that
   component's own comment): scoped CSS follows whoever RENDERS the
   element, so leaving these in ChatPanel.razor.css would have silently
   stopped matching. */

/* Header wrapper around the page's own header fragment (a shared
   ProjectPageHeader in every current chat). The margin lives here (not on an
   mb-4 utility) so the mobile media query below can tighten it; the header's
   own bottom margin is dropped, this one wins. */
.bk-chat-head[b-4cv40gmlt8] {
    margin-bottom: 16px;
}

.bk-chat-head[b-4cv40gmlt8]  .bk-page-head {
    margin-bottom: 0;
}

/* Title left, status and actions as ONE group at the trailing edge. The shared
   header grows both the title (flex 1 1 320px) and a spacer between context
   and actions, so the free space was split between them and the status pill
   ended up floating at a position that depended on how long the title
   happened to be. Here the title takes only what it needs and the whole
   remainder goes into one margin before the status. */
.bk-chat-head[b-4cv40gmlt8]  .bk-page-head-title {
    flex: 0 1 auto;
}

.bk-chat-head[b-4cv40gmlt8]  .bk-page-head-spacer {
    display: none;
}

.bk-chat-head[b-4cv40gmlt8]  .bk-page-head-context {
    margin-left: auto;
}

@media (max-width: 599.98px) {
    /* Breadcrumbs duplicate the page title and eat scarce vertical space on a
       phone; the drawer plus the header's own actions cover navigation, so
       drop them here.

       Scoped to the QUIET layout on purpose. ProjectPageHeader renders two
       shapes: with a Trail (RequirementDraft, InventoryChat) the crumbs are a
       small line of their own above a title row, and hiding them costs
       nothing. WITHOUT a Trail - ProjectSetupChat - the same .bk-crumbs
       element IS the header: title, status pills and Discard all sit inside
       it, so the unscoped rule left that page with no header at all on a
       phone. .bk-page-head-quiet is set exactly when Trail is non-empty, so
       it separates the two cases at the source. ProjectSetupChat.razor.css
       trims its own one-line row to fit instead. */
    .bk-chat-head[b-4cv40gmlt8]  .bk-page-head-quiet .bk-crumbs {
        display: none;
    }

    /* The one-line layout keeps its crumb row (it IS the header there), but
       loses the page name inside it: "Projektstart" repeats what the status
       pills beside it already say, and on a phone that pair is what pushed
       the row onto a third line. The project name stays - it is the crumb
       that still navigates, via the switcher. */
    .bk-chat-head[b-4cv40gmlt8]  .bk-page-head:not(.bk-page-head-quiet) .bk-crumb-sep,
    .bk-chat-head[b-4cv40gmlt8]  .bk-page-head:not(.bk-page-head-quiet) .bk-crumb-current {
        display: none;
    }

    .bk-chat-head[b-4cv40gmlt8]  .bk-page-head:not(.bk-page-head-quiet) .bk-crumb-proj-name {
        font-size: 1.05rem;
    }

    .bk-chat-head[b-4cv40gmlt8] {
        margin-bottom: 8px;
    }

    /* Everything above the conversation stays within a quarter of the screen
       height on a phone (acceptance criterion), and neither Discard nor the
       chat-list toggle gets a full-width row of its own (a second acceptance
       criterion) - both share ONE row with the title instead. ProjectPageHeader
       itself is not touched (its own doc comment: every other project page's
       header stays exactly as it is) - this reorders its title row's own flex
       items visually via `order`, chat-only, instead. TitleIcon (the chat-list
       toggle) and Actions (Discard) join the title on that first row; Context
       (status pill + started-at) is pushed onto its own second row by giving
       it a 100%-wide flex-basis, which always starts a fresh line in a
       wrapping flex container regardless of where it sits in the DOM. */
    .bk-chat-head[b-4cv40gmlt8]  .bk-page-head-title-row {
        row-gap: 2px;
    }

    .bk-chat-head[b-4cv40gmlt8]  .bk-page-head-title-icon {
        order: 1;
    }

    /* flex-basis alone (not just font-size/line-clamp) needs overriding here:
       the flex-wrap line-break decision is made against each item's
       hypothetical main size, i.e. its flex-basis clamped by min/max - NOT
       its eventual shrunk width - so ProjectPageHeader's own 320px basis
       alone already exceeds this row's ~336px content width once the icon
       and Discard are added, wrapping Discard onto a line of its own before
       flex-shrink ever gets a say. A small basis here (min-width:0 already
       comes from ProjectPageHeader.razor.css) keeps the wrap check's math
       trivially within one line; flex-grow:1 (kept) still hands the title
       all the space actually left over once icon/actions/gaps are placed,
       so the rendered width does not depend on which small basis is picked. */
    .bk-chat-head[b-4cv40gmlt8]  .bk-page-head-title {
        order: 2;
        flex: 1 1 40px;
        font-size: 1.05rem;
        -webkit-line-clamp: 1;
        line-clamp: 1;
    }

    .bk-chat-head[b-4cv40gmlt8]  .bk-page-head-actions {
        order: 3;
        flex: 0 0 auto;
        width: auto;
    }

    /* No longer needed once Actions no longer sits at the row's far end via
       this spacer - Context claiming its own full-width line (below) does
       that job instead. */
    .bk-chat-head[b-4cv40gmlt8]  .bk-page-head-spacer {
        display: none;
    }

    .bk-chat-head[b-4cv40gmlt8]  .bk-page-head-context {
        order: 4;
        flex: 1 1 100%;
    }

    /* Discard itself drops to an icon-only button on this row - its own text
       label (bk-discard-label) is hidden by a global rule in app.css instead
       of here, since that span is authored in each host page's own Header
       fragment, not reachable from THIS component's ::deep (see
       ScopedCssOwnershipGuardTests). */
}
/* /Components/Shared/Chat/ChatSurfaceLayout.razor.rz.scp.css */
/* Geometry of the chat surface (see the component's own comment): the
   conversation column, at most one secondary pane beside it, and the switch
   that replaces the side-by-side arrangement below 1000px. Moved here out of
   ChatSideThreadLayer.razor.css, which now keeps only what it actually
   renders itself - the launcher and the reader - and which had no room left
   for a shared pane anyway (ChatCoreConcernGuard's stylesheet budget). */

/* The row: conversation plus pane. Also the element annotations-interop.js
   scopes its selectors to, which is why the pane lives inside it rather than
   next to it - a mark inside a draft card has to resolve through the same
   container as one in the transcript. */
.bk-chat-annot[b-xdbmctihv7] {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: row;
    gap: 16px;
    position: relative;
}

/* Conversation column: the scrolling transcript with the composer pinned
   below it. It takes whatever the pane leaves, which is what makes the
   divider work - the pane carries the explicit basis (--bk-pane-width). */
.bk-chat-column[b-xdbmctihv7] {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* The divider: a wide grab area centred on the line it draws. The line IS the
   separation between the two columns - the pane carries no border of its own
   any more, because two hairlines a few pixels apart are exactly what makes a
   divider feel like it grabs somewhere other than where it looks.
   13px wide against -6px on each side leaves 1px of actual layout width (the
   line), with the rest of the grab area overlapping the row's own gap. */
.bk-pane-grip[b-xdbmctihv7] {
    flex: 0 0 13px;
    align-self: stretch;
    margin: 0 -6px;
    position: relative;
    cursor: col-resize;
    touch-action: none;
    background: transparent;
    border: 0;
    z-index: 25;
}

.bk-pane-grip[b-xdbmctihv7]::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 1px;
    background: var(--mud-palette-lines-default);
    transition: background-color var(--bk-dur-fast) var(--bk-ease-out), width var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-pane-grip:hover[b-xdbmctihv7]::after,
.bk-pane-grip:focus-visible[b-xdbmctihv7]::after,
.bk-pane-grip-active[b-xdbmctihv7]::after {
    background: var(--mud-palette-primary);
    width: 2px;
}

.bk-pane-grip:focus-visible[b-xdbmctihv7] {
    outline: none;
}

/* container-type: size is a query target: .bk-proposal-card
   (ProjectSetupChat.razor.css) needs "50% of the chat area" but its own
   containing block (.bk-inline-review, content-sized) has no definite height
   a percentage could resolve against - cqh looks past it to here instead. */
.bk-chat-scroll[b-xdbmctihv7] {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    container-type: size;
    /* The transcript runs out into the composer instead of stopping at a hard
       edge: its last --bk-chat-fade of height fades away (a mask on the
       scroll box, so it stays put while the content scrolls under it), and
       the same amount of end padding lets the newest message clear the fade
       once scrolled all the way down. The top edge, where older messages
       scroll away under the page header, gets a shorter one of its own. */
    --bk-chat-fade: var(--bk-space-6);
    --bk-chat-fade-top: var(--bk-space-3);
    padding-block: var(--bk-chat-fade-top) var(--bk-chat-fade);
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--bk-chat-fade-top), #000 calc(100% - var(--bk-chat-fade)), transparent);
    mask-image: linear-gradient(to bottom, transparent, #000 var(--bk-chat-fade-top), #000 calc(100% - var(--bk-chat-fade)), transparent);
}

/* Sized to its own content however tall the transcript above it grows; a
   flex column itself, for the "Arbeitet..." row above the composer card.
   The bottom padding is the room the raised composer card's shadow needs:
   the chat page ends at the window's bottom edge, which used to cut the
   shadow off in a straight line and made the card look clipped. */
.bk-chat-composer-slot[b-xdbmctihv7] {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-bottom: var(--bk-space-6);
}

/* A phone has no pixel to spare: the bottom bar sits right under the card
   (and, typing, the keyboard), a smaller shadow margin is enough there. */
@media (max-width: 599.98px) {
    .bk-chat-composer-slot[b-xdbmctihv7] {
        padding-bottom: var(--bk-space-3);
    }

    .bk-keyboard-open .bk-chat-composer-slot[b-xdbmctihv7] {
        padding-bottom: var(--bk-space-2);
    }
}

/* THE pane: one set of rules for the review gate, an opened artifact and
   whatever comes next. min-height:0 is what lets its content scroll inside
   the column it gets instead of stretching the whole row. */
.bk-side-pane[b-xdbmctihv7] {
    /* A fixed basis rather than a share, because the divider writes it:
       chat-split-interop.js sets --bk-pane-width on the surface, and the
       conversation column takes whatever is left (flex 1 1 0 above). The
       fallback is the default share for a surface that was never dragged. */
    flex: 0 0 var(--bk-pane-width, 42%);
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    background: var(--mud-palette-surface);
    padding: 16px 20px;
}

/* The canvas used to get a tighter inset here than the review gate, because it
   draws its own grid edge to edge and only needed keeping off the divider.
   That stopped working once the pane gained a switch above its content
   (ChatPanel): the switch sits INSIDE this padding, so a different inset per
   view moved the very control the reader is aiming at. One inset for every
   view, and the canvas simply sits a few pixels further in. */

.bk-side-pane[b-xdbmctihv7]  .bk-draftboard {
    flex: 1 1 auto;
    min-height: 0;
}

/* The shared, non-isolated .bk-draft-actions (app.css) - fixed height below
   the board instead of scrolling away with it, so Uebernehmen stays
   reachable. */
.bk-side-pane[b-xdbmctihv7]  .bk-draft-actions {
    flex: 0 0 auto;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

/* Not rendered at all while both fit side by side. */
.bk-chat-switch[b-xdbmctihv7] {
    display: none;
}

/* ----- Below 1000px: one column, the switch decides which ----------------
   The old threshold was the phone breakpoint, which left a tablet (and a
   narrow window on a laptop) with two columns of about 300px - unusable for
   a draft tree, a proposal card and an artifact alike. */
@media (max-width: 999.98px) {
    .bk-chat-annot[b-xdbmctihv7] {
        flex-direction: column;
        gap: 0;
    }

    .bk-chat-switch[b-xdbmctihv7] {
        display: flex;
        flex: 0 0 auto;
        gap: 4px;
        margin-bottom: 4px;
        border-bottom: 1px solid var(--mud-palette-lines-default);
    }

    .bk-chat-switch button[b-xdbmctihv7] {
        flex: 1 1 0;
        padding: 6px 4px;
        border: none;
        background: none;
        font-size: 13px;
        font-weight: 500;
        color: var(--mud-palette-text-secondary);
        border-bottom: 2px solid transparent;
        cursor: pointer;
    }

    .bk-chat-switch-active[b-xdbmctihv7] {
        color: var(--mud-palette-primary);
        border-bottom-color: var(--mud-palette-primary) !important;
    }

    /* One column at a time, so there is nothing to drag - and the dragged
       width must not survive into the stacked layout either. */
    .bk-pane-grip[b-xdbmctihv7] {
        display: none;
    }

    .bk-side-pane[b-xdbmctihv7] {
        display: none;
        flex: 1 1 auto;
        padding: 6px 0 0;
    }

    .bk-chat-pane-active .bk-chat-scroll[b-xdbmctihv7] {
        display: none;
    }

    .bk-chat-pane-active .bk-side-pane[b-xdbmctihv7] {
        display: flex;
    }

    /* The composer stays reachable whichever side the switch shows:
       display:contents drops .bk-chat-column's own box but keeps its two
       children in the row, so they can order independently around the
       pane's single slot instead of staying stuck together. */
    .bk-chat-column[b-xdbmctihv7] {
        display: contents;
    }

    .bk-chat-scroll[b-xdbmctihv7],
    .bk-side-pane[b-xdbmctihv7] {
        order: 1;
    }

    .bk-chat-composer-slot[b-xdbmctihv7] {
        order: 2;
    }

    /* Tighter than above: this column now also carries the switch and the
       docked composer (acceptance criterion: 12+ tree rows at once). */
    .bk-side-pane[b-xdbmctihv7]  .bk-draft-actions {
        margin-top: 6px;
        padding-top: 6px;
    }
}
/* /Components/Shared/Chat/ChatTerminalPanels.razor.rz.scp.css */
/* Scoped styles of the terminal-state panels (ChatTerminalPanels.razor). */

/* The resume bar below the Applied summary (see the markup's Applied block) -
   the same "Chat fortsetzen" button the Discarded panel renders inline, here
   given its own top margin since it follows a host-owned fragment rather than
   sitting inside one shared paper. */
.bk-chat-resume-bar[b-0p62fjqsog] {
    margin-top: 12px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 12px;
}

/* Fills the remaining width so the button stays flush right even without a
   hint (an empty flex row has nothing to grow, .justify-content: flex-end
   above already covers that case) - present only for the requirement chat
   (ChatPanel.ResumeHint's own doc comment). */
.bk-chat-resume-hint[b-0p62fjqsog] {
    flex: 1;
    min-width: 200px;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}
/* /Components/Shared/Chat/ChatTranscript.razor.rz.scp.css */
/* Scoped styles of the transcript (ChatTranscript.razor): the message-loop
   turn styling only. The scroll container and centered column it renders
   inside belong to ChatSideThreadLayer.razor.css (.bk-chat-scroll/.bk-thread)
   since that component owns the wrapping markup.

   Claude Code style: the agent turn is not a bubble - it spans the full chat
   width so markdown output (tables, code, lists) has as much room as
   possible. Only the user turn is a contained bubble so question/answer stay
   visually separated.

   ::deep is used wherever a rule targets an element rendered by a child
   component (MarkdownField's .bk-markdown), which the Blazor CSS-isolation
   attribute would otherwise not reach. */

.bk-turn[b-sh37zdfjww] {
    margin-bottom: 22px;
}

.bk-turn-role[b-sh37zdfjww] {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 5px;
}

/* Agent: no chrome around the markdown, but capped to a readable measure
   (acceptance criterion: at most about 100 characters per line) now that the
   transcript column itself fills the whole content area instead of standing
   in its own 820px-wide centered strip (app.css's own "Chat: full-width
   column, per-block reading measure" section) - a "ch" unit tracks the
   current font's own average glyph width, so this stays about 100 characters
   regardless of viewport or font-size instead of a fixed pixel guess. */
.bk-turn-agent .bk-turn-body[b-sh37zdfjww] {
    max-width: 75ch;
}

/* Illustrations of an agent answer (VisualizationGallery below the markdown).
   The gallery is shared with the artifact pages, which are far wider than the
   centered reading column here, so two things are adjusted for the chat:
   min-width:0 lets the tab strip shrink inside the flex turn instead of
   stretching the whole thread, and the strip is allowed to scroll horizontally
   so three German titles do not force a wider bubble. */
.bk-turn-visuals[b-sh37zdfjww] {
    margin-top: 10px;
    min-width: 0;
}

/* Images the USER attached to their own message (ImageThumbnailGrid, the
   read-only sibling of the drop zone in the composer) - same spacing as the
   agent's own illustrations above, inheriting the bubble's max-width from
   .bk-turn-user .bk-turn-body so the grid never grows past it. */
.bk-turn-images[b-sh37zdfjww] {
    margin-top: 10px;
}

/* Non-image files the USER attached to their own message (AttachmentFileList,
   the read-only sibling of the composer's own file-row list) - same spacing
   as the image grid above. */
.bk-turn-files[b-sh37zdfjww] {
    margin-top: 10px;
}

.bk-turn-visuals[b-sh37zdfjww]  .mud-tabs-toolbar-wrapper {
    overflow-x: auto;
}

/* A picture is only useful at a readable size, but must not push the composer
   out of reach either - cap it at roughly half the viewport and let the
   full-screen dialog (one click on the picture) do the rest. */
.bk-turn-visuals[b-sh37zdfjww]  .bk-mermaid svg,
.bk-turn-visuals[b-sh37zdfjww]  .bk-run-visual-image {
    max-height: 46vh;
}

/* User: a contained bubble aligned to the trailing edge, tinted with the
   primary color so it reads as "my" message. */
.bk-turn-user[b-sh37zdfjww] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
}

.bk-turn-user .bk-turn-role[b-sh37zdfjww] {
    align-self: flex-end;
}

.bk-turn-user .bk-turn-body[b-sh37zdfjww] {
    max-width: min(85%, 660px);
    padding: 10px 15px;
    border-radius: var(--bk-radius-lg) var(--bk-radius-lg) var(--bk-radius-sm) var(--bk-radius-lg);
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface));
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 22%, transparent);
}

.bk-dark .bk-turn-user .bk-turn-body[b-sh37zdfjww] {
    background: color-mix(in srgb, var(--mud-palette-primary) 18%, var(--mud-palette-surface));
    border-color: color-mix(in srgb, var(--mud-palette-primary) 34%, transparent);
}

/* The user turn is short plain text; the markdown block is rendered inside the
   MarkdownField child component, so reach it with ::deep. */
.bk-turn-user[b-sh37zdfjww]  .bk-markdown {
    font-size: 0.9375rem;
}
/* /Components/Shared/Chat/DiagnosisCard.razor.rz.scp.css */
/* DiagnosisCard: a real <a> styled as a card (see the component's own doc
   comment on why an anchor rather than a MudPaper + @onclick div). Own
   stylesheet since this component is its only consumer, same convention
   ChatSessionRow.razor.css already follows. */
.bk-diagnosis-card[b-gtgl7t63uo] {
    display: flex;
    align-items: center;
    gap: var(--bk-space-3);
    width: 100%;
    box-sizing: border-box;
    padding: var(--bk-space-2) var(--bk-space-3);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    text-decoration: none;
    color: inherit;
}

.bk-diagnosis-card:focus-visible[b-gtgl7t63uo] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.bk-diagnosis-card + .bk-diagnosis-card[b-gtgl7t63uo] {
    margin-top: var(--bk-space-2);
}

.bk-diagnosis-card-text[b-gtgl7t63uo] {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.bk-diagnosis-card-title[b-gtgl7t63uo] {
    font-weight: 500;
    font-size: 0.875rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-diagnosis-card-criterion[b-gtgl7t63uo] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-diagnosis-card-chevron[b-gtgl7t63uo] {
    color: var(--mud-palette-text-secondary);
    flex-shrink: 0;
}

/* Phone (acceptance criterion "full width, wraps instead of being cut off"):
   the card already spans its container's full width at every size - this
   only switches the title/criterion text from a single truncated line to
   wrapping, so a long requirement or criterion name is never cut off. */
@media (max-width: 599.98px) {
    .bk-diagnosis-card-title[b-gtgl7t63uo],
    .bk-diagnosis-card-criterion[b-gtgl7t63uo] {
        white-space: normal;
    }
}
/* /Components/Shared/Chat/RequirementDraftAttachmentChangesPanel.razor.rz.scp.css */
/* RequirementDraftAttachmentChangesPanel's own layout (feature "Chat shows
   every pending attachment change") - the badge itself reuses the shared
   .bk-draft-kind/.bk-draft-kind-extend/.bk-draft-kind-archive classes from
   app.css (the same amber/error tint every other review-gate badge uses), so
   only the group/row/thumbnail shell lives here. */

.bk-attachment-changes[b-4n5vfp3qyk] {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.bk-attachment-change-group[b-4n5vfp3qyk] {
    display: flex;
    flex-direction: column;
}

.bk-attachment-change-group-title[b-4n5vfp3qyk] {
    font-size: 12px;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 6px;
}

.bk-attachment-change-row[b-4n5vfp3qyk] {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--bk-radius-sm);
    border: 1px solid var(--mud-palette-lines-default);
    margin-bottom: 6px;
}

/* A pending removal reads visibly distinct at a glance from every other kind
   (acceptance criterion) - its own red, dashed, struck-through tint instead
   of the neutral surface every other row keeps. */
.bk-attachment-change-row-removed[b-4n5vfp3qyk] {
    border-color: var(--mud-palette-error);
    border-style: dashed;
    background: color-mix(in srgb, var(--mud-palette-error) 6%, transparent);
}

.bk-attachment-change-row-removed .bk-attachment-change-name[b-4n5vfp3qyk] {
    text-decoration: line-through;
    color: var(--mud-palette-error);
}

.bk-attachment-change-thumb[b-4n5vfp3qyk] {
    width: 40px;
    height: 40px;
    border-radius: var(--bk-radius-sm);
    object-fit: cover;
    flex: 0 0 auto;
}

.bk-attachment-change-icon[b-4n5vfp3qyk] {
    width: 40px;
    height: 40px;
    border-radius: var(--bk-radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--mud-palette-background-grey);
    flex: 0 0 auto;
}

.bk-attachment-change-info[b-4n5vfp3qyk] {
    flex: 1 1 auto;
    min-width: 0;
}

.bk-attachment-change-name[b-4n5vfp3qyk] {
    font-size: 13px;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-attachment-change-meta[b-4n5vfp3qyk] {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}
/* /Components/Shared/Chat/RequirementDraftBoard.razor.rz.scp.css */
/* RequirementDraftBoard's own two-column tree/detail layout (concept "Entwurf
   im Chat als Baum: dicht und ruhig dargestellt"). The bk-draft-* building
   blocks it reuses inside the detail pane (RequirementDraftCard, its kind
   badges, the tree-operation cards) stay in wwwroot/app.css - shared across
   every review gate - only the board's own tree/row/grid shell lives here,
   plus the ::deep overrides further down that neutralize those shared
   classes' saturated color WITHIN this board only (see that rule's own
   comment).

   ChatSideThreadLayer.razor now renders this board inside its own
   .bk-side-review column - a real second column of .bk-chat-annot next to
   the still-visible, still-scrollable transcript, not an overlay covering it
   and not scrolling content of the chat transcript either - so .bk-draftboard
   fills a real, definite pixel height instead of guessing one via a
   viewport-relative max-height - everything below that flows from that one
   change. */

.bk-draftboard[b-4kgvzgrmz4] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 auto;
    min-height: 0;
}

/* One row: version, total, per-kind chips (only with more than one kind, see
   the .razor's own comment on that), a spacer, then the expand/collapse
   actions - all in the SAME line (acceptance criterion: "die Aktionen ...
   stehen in derselben Kopfzeile statt in einer eigenen Zeile darunter").
   flex-wrap allows a narrow viewport to break it into more than one visual
   line without needing a second markup row for that. */
.bk-draftboard-head[b-4kgvzgrmz4] {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    column-gap: 12px;
    row-gap: 6px;
    margin-bottom: 10px;
}

.bk-draftboard-total[b-4kgvzgrmz4] {
    font-weight: 600;
}

.bk-draftboard-chips[b-4kgvzgrmz4] {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* Neutral header chip (per-kind tally) - its own class instead of the shared,
   saturated bk-draft-kind-* pill: nothing in the head is a saturated color
   area either (acceptance criterion: "kein Element des Entwurfs [...] außer
   der Hauptaktion"). */
.bk-draftboard-count-chip[b-4kgvzgrmz4] {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    font-weight: 500;
    padding: 3px 10px;
    border-radius: var(--bk-radius-pill);
    background: color-mix(in srgb, var(--mud-palette-text-primary) 7%, transparent);
    color: var(--mud-palette-text-primary);
}

.bk-draftboard-treeactions[b-4kgvzgrmz4] {
    display: flex;
    gap: 4px;
}

/* Two independent panes, each scrolling only in itself and each filling the
   real height .bk-draftboard itself now has (ChatSideThreadLayer's own
   .bk-side-review, a window-height layer - see that file's doc comment) -
   grid-template-rows: minmax(0, 1fr) is what turns the grid's own single row
   into that definite height instead of an auto/content-sized one, which is
   what align-items: stretch (the grid default, left unset here on purpose)
   then hands down to both .bk-draftboard-tree/-detail as their own height:
   100%. Without that, a scroll region nested inside another (the very thing
   this redesign removes) would reappear one level down instead. */
.bk-draftboard-body[b-4kgvzgrmz4] {
    display: grid;
    grid-template-columns: minmax(240px, 1fr) minmax(0, 1.4fr);
    grid-template-rows: minmax(0, 1fr);
    gap: 16px;
    flex: 1 1 auto;
    min-height: 0;
}

.bk-draftboard-tree[b-4kgvzgrmz4],
.bk-draftboard-detail[b-4kgvzgrmz4] {
    min-height: 0;
    min-width: 0;
    overflow-y: auto;
}

.bk-draftboard-tree[b-4kgvzgrmz4] {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-md);
    padding: 4px 6px;
}

.bk-draftboard-treeview[b-4kgvzgrmz4] {
    width: 100%;
}

.bk-draftboard-empty[b-4kgvzgrmz4] {
    padding: 16px;
    color: var(--mud-palette-text-secondary);
    font-size: 14px;
}

/* Compresses MudTreeViewItem's own DOM below whatever its Dense="true" param
   (set on the MudTreeView in the .razor) already trims - Dense alone still
   leaves .mud-treeview-item-content at 1px/4px padding and the arrow button
   at a 32px min-height; a dense TREE of drafted requirements needs its rows
   noticeably shorter than that to fit 12+ of them in ~900px (acceptance
   criterion's own numbers) alongside the head and the tree's own border/
   padding. Values below are deliberately tight but keep the arrow/row still
   comfortably tappable. */
.bk-draftboard-treeview[b-4kgvzgrmz4]  .mud-treeview-item {
    min-height: unset;
}

.bk-draftboard-treeview[b-4kgvzgrmz4]  .mud-treeview-item-content {
    padding: 0 2px;
}

/* min-width: 0 alongside the fixed width above for the same reason
   .mud-treeview-item-label gets it below: MudBlazor's own arrow rule sets
   flex-shrink: 0 with no min-width of its own, so without this its automatic
   minimum size still comes from its inner MudIconButton's natural footprint
   (wider than the 1.5rem this component actually renders it at) instead of
   the fixed width - just enough to nudge the row past its pane at the
   tightest widths alongside the label's own version of this bug. */
.bk-draftboard-treeview[b-4kgvzgrmz4]  .mud-treeview-item-arrow {
    width: 1.5rem;
    min-width: 0;
    min-height: unset;
    margin: 0 2px;
}

.bk-draftboard-treeview[b-4kgvzgrmz4]  .mud-treeview-item-arrow .mud-icon-button {
    padding: 2px;
}

/* MudTreeViewItem's own label wrapper (BodyContent's direct parent) sets
   flex-grow:1 but no min-width, so its flex-item default (min-width: auto)
   takes its automatic minimum size from ITS OWN content's min-content width -
   which .bk-draftboard-row-rail's non-shrinking flex-basis used to make at
   least 220px REGARDLESS of how narrow the tree pane's actual column ended up
   (a two-column grid next to the review layer's own detail pane, itself next
   to the drawer and the chat's own padding - all of which can leave the tree
   column well under 220px at common widths, exactly the 1000x900 reference
   case this rule now fixes). Without min-width: 0 here, that forced a wider
   box than the pane had room for, so the ROW rendered wider than its own
   container instead of the title inside it shrinking - the title still got
   handed real width from that oversized box, but the box itself either
   overflowed or (once the rail could no longer fit at all) squeezed the title
   to zero. Reset to 0 so the label - and everything below it, including this
   row - actually shrinks to the space MudTreeView gives it. */
.bk-draftboard-treeview[b-4kgvzgrmz4]  .mud-treeview-item-label {
    min-width: 0;
}

/* One tree row (RequirementDraftBoard.razor's MudTreeViewItem BodyContent):
   a flex row, not a wrapping flex column - the title truncates to one line
   and takes whatever space is left, the rail (change kind, branch hint,
   criteria count) sits at the row's end (acceptance criterion: "eine eigene,
   für alle Einträge gleich breiten Spalte am Zeilenende [...] drängen den
   Titel nicht in eine zweite oder dritte Zeile"). A CSS Grid with a
   content-sized minmax(0, 220px) rail track next to a minmax(0, 1fr) title
   track was tried first and rejected: the rail track's own base size then
   depends on its content (up to the 220px cap), so it is not actually the
   same width on every row, and under some available-width/content
   combinations the grid track sizing algorithm gave the whole row to that
   content-sized track and collapsed the title track to 0 - titles vanished
   outright instead of truncating. A NON-shrinking fixed flex-basis rail
   (flex: 0 0 220px) was tried next and rejected too, for a subtler reason:
   .bk-draftboard-tree's own column width depends on how much of
   .bk-draftboard-body's grid this board actually gets next to the detail
   pane, the drawer and the page's own padding - at the very 1000x900
   reference width this feature is measured against, that column is well
   under 220px, so a rail that refuses to shrink either overflowed the row
   past its own pane (MudTreeViewItem's own label wrapper has no min-width of
   its own either - see the ::deep override on .mud-treeview-item-label
   above) or, once there was no room left at all, squeezed the title to zero
   width outright. The rail below is flex-shrink: 1 instead: on any row of the
   SAME draft it still resolves to the identical width, because that width is
   driven purely by the shared flex-basis/shrink math against the SAME
   container width, never by what an individual row's own badges happen to
   contain (min-width: 0 on every rail item keeps it that way, same reasoning
   as ComponentsTreeView's own indentation math) - so "gleich breite Spalte"
   still holds without ever refusing to give the title real room. The title's
   own min-width floor (below) is what then guarantees it never actually
   reaches zero, handing the rail's shrink budget all of the squeeze instead.
   The row itself is the click target that selects the entry, kept separate
   from MudTreeView's own expand-arrow button so a click never fights with
   folding a branch. */
.bk-draftboard-row[b-4kgvzgrmz4] {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 3px 8px;
    border-radius: var(--bk-radius-sm);
    cursor: pointer;
    width: 100%;
    height: 28px;
    overflow: hidden;
}

.bk-draftboard-row:hover[b-4kgvzgrmz4],
.bk-draftboard-row:focus-visible[b-4kgvzgrmz4] {
    background: color-mix(in srgb, var(--mud-palette-primary) 6%, transparent);
}

/* Selected: never color alone (acceptance criterion) - a left bar plus a
   bolder title (below) plus aria-current="true" on the row itself. Persists
   across a scroll of the tree pane since nothing here resets
   _selectedPositionId on scroll - only picking a different row, or a genuine
   rebuild of the SAME draft version, ever changes it. */
.bk-draftboard-row-selected[b-4kgvzgrmz4] {
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
    border-left: 3px solid var(--mud-palette-primary);
    padding-left: 5px;
}

.bk-draftboard-row-selected .bk-draftboard-row-title[b-4kgvzgrmz4] {
    font-weight: 700;
}

/* min-width: 64px (not 0) is the floor that keeps the title from ever
   actually reaching zero width once the rail next to it has to shrink - see
   .bk-draftboard-row's own comment on why the rail can no longer refuse to
   shrink. 64px still ellipsis-truncates almost every drafted title, it just
   guarantees SOME of it (and the row's own click target) stays visible and
   clickable at the tightest widths this grid produces. */
.bk-draftboard-row-title[b-4kgvzgrmz4] {
    flex: 1 1 64px;
    min-width: 64px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
}

/* A not-yet-existing branch (CreateParent, or a NewParentTitle shared with no
   CreateParent card at all) - marked in text (italics), not just a lighter
   tint, so it still reads correctly for a reviewer who cannot see color. */
.bk-draftboard-row-newbranch .bk-draftboard-row-title[b-4kgvzgrmz4] {
    font-style: italic;
}

.bk-draftboard-row-archived .bk-draftboard-row-title[b-4kgvzgrmz4] {
    color: var(--mud-palette-text-secondary);
}

/* The rail: right-aligned within its own column, never wrapping - nowrap plus
   overflow: hidden is what keeps a row's height constant regardless of how
   many badges a position carries at once (acceptance criterion: "eine feste
   ... Spalte ... drängen den Titel nicht in eine zweite oder dritte Zeile");
   the badge/pill/hint rules below cap and ellide their own text instead, so
   content that does not fit truncates in place rather than pushing the row
   taller. flex-basis (not a content-based cap) is what makes this the literal
   same width as every other row of the SAME draft - see .bk-draftboard-row's
   own comment on why a content-sized track was rejected. flex-shrink: 1 (not
   0) is what then lets that shared width actually give way to
   .bk-draftboard-row-title's own min-width floor once the tree pane itself is
   narrower than the rail's own 148px basis, instead of forcing the row wider
   than its pane (that same comment's own reasoning on why a non-shrinking
   rail was rejected). */
.bk-draftboard-row-rail[b-4kgvzgrmz4] {
    display: flex;
    flex: 0 1 148px;
    max-width: 148px;
    flex-wrap: nowrap;
    justify-content: flex-end;
    align-items: center;
    gap: 4px 6px;
    min-width: 0;
    overflow: hidden;
}

/* Change-kind badge: icon plus text, never a saturated fill (acceptance
   criterion) - the icon (KindIcon) and the label text (KindLabel) are what
   distinguish one kind from another here, not color. Capped at its own
   max-width (with the label itself ellided, see .bk-draftboard-badge-label)
   so the rarest, longest label ("als Randbedingung geführt") cannot alone
   force the rail to wrap. flex-shrink: 0 keeps this - the primary
   identification of a row - from being squeezed away entirely by a
   secondary rail item (previous location, criteria count) competing for the
   same fixed column width. */
.bk-draftboard-badge[b-4kgvzgrmz4] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
    white-space: nowrap;
    flex: 0 1 auto;
    flex-shrink: 0;
    min-width: 0;
    max-width: 96px;
}

.bk-draftboard-badge-label[b-4kgvzgrmz4] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* "neuer Zweig": no framed area and no icon (acceptance criterion: "belegt
   keine eigene gerahmte Fläche und nimmt nicht mehr Breite ein als der Titel
   [...] von der Kennzeichnung eines neu angelegten Eintrags auf einen Blick
   unterscheidbar") - italic muted text is what a NEW entry's own icon+bold
   badge above is not, so the two never look alike even though both may
   appear on the same branch's own row (an explicit CreateParent operation). */
.bk-draftboard-branch-hint[b-4kgvzgrmz4] {
    font-style: italic;
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    flex: 0 0 auto;
}

/* Secondary rail info (the drafted change's own old spot) - shrinks and
   ellides before the kind badge does (see .bk-draftboard-badge's own
   flex-shrink: 0) since the change kind is the more important glance fact of
   the two. */
.bk-draftboard-row-prev[b-4kgvzgrmz4] {
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1 1 auto;
    min-width: 0;
    max-width: 64px;
}

/* Criteria glance: just the count plus an icon that alone distinguishes
   "unchanged" from "some criteria change" (RequirementCriteriaSummary.
   CriteriaGlance/Describe) - not RequirementCriteriaSummary.Summarize's full
   sentence, which is what used to make this pill alone wide enough to force
   the whole rail onto a second line at common widths (acceptance criterion:
   "wie viele Akzeptanzkriterien der Eintrag hat und ob sich davon welche
   ändern", not the full diff text at a glance). The full sentence still
   reaches the reviewer as this pill's own title tooltip. */
.bk-draftboard-crit-pill[b-4kgvzgrmz4] {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    font-size: 11px;
    font-weight: 600;
    padding: 1px 7px;
    border-radius: var(--bk-radius-pill);
    background: color-mix(in srgb, var(--mud-palette-text-secondary) 12%, transparent);
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    flex: 0 0 auto;
}

.bk-draftboard-crit-pill-changed[b-4kgvzgrmz4] {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 14%, transparent);
    color: var(--mud-palette-text-primary);
}

/* "entsteht nicht": every criterion of a freshly created entry was rejected
   (feature "Einzelne Kriterien im Entwurf direkt ablehnen") - recognizable at
   the row itself, before opening the detail pane, without its own framed
   area (same reasoning as .bk-draftboard-branch-hint above, which this rule
   otherwise mirrors) so it never competes with the branch hint for the
   rail's own fixed width. */
.bk-draftboard-wontcreate-hint[b-4kgvzgrmz4] {
    font-style: italic;
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    flex: 0 0 auto;
}

/* Rendered whenever an entry is selected regardless of viewport
   (RequirementDraftBoard.razor's _mobileShowDetail flag also drives which
   pane the mobile breakpoint below shows) - hidden here by default since a
   wide viewport already shows tree and detail side by side, so a "back to
   the tree" affordance would have nothing useful to do; the mobile
   breakpoint below is the only place this becomes visible again. */
.bk-draftboard-back[b-4kgvzgrmz4] {
    display: none;
    align-items: center;
    gap: 4px;
    background: none;
    border: none;
    color: var(--mud-palette-primary);
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    padding: 4px 0;
    margin-bottom: 8px;
    flex: 0 0 auto;
}

/* Telephone viewport (acceptance criterion: two separate views with a visible
   way back, no horizontal scrolling at 360px): tree and detail become the
   only two children of a column flex, and only one shows at a time (toggled
   by RequirementDraftBoard's own _mobileShowDetail) - both stay mounted
   underneath (display:none, not removed), so neither one loses its scroll
   position while hidden, and the visible one still fills the real available
   height instead of collapsing to zero (the architecture decision's own risk
   note on this - display:none must not strip the flex context the visible
   pane needs). */
@media (max-width: 599.98px) {
    .bk-draftboard-body[b-4kgvzgrmz4] {
        display: flex;
        flex-direction: column;
        min-height: 0;
    }

    .bk-draftboard-tree[b-4kgvzgrmz4],
    .bk-draftboard-detail[b-4kgvzgrmz4] {
        flex: 1 1 auto;
        min-height: 0;
    }

    .bk-draftboard-detail[b-4kgvzgrmz4] {
        display: none;
    }

    .bk-draftboard-body-detail .bk-draftboard-tree[b-4kgvzgrmz4] {
        display: none;
    }

    .bk-draftboard-body-detail .bk-draftboard-detail[b-4kgvzgrmz4] {
        display: block;
    }

    .bk-draftboard-back[b-4kgvzgrmz4] {
        display: inline-flex;
    }

    /* Row rail shrinks to just its two most essential badges (change-kind
       icon, criteria count) so the title keeps at least two thirds of the
       row's own width instead of being squeezed down to a ~20-character
       stub (acceptance criterion) - the label text, previous-location hint
       and "wont be created" hint below all drop to icon-only or hidden
       entirely; their full wording still reaches the reviewer through the
       badge's own title tooltip and the detail pane a tap opens. 44px (down
       from 60px) is what actually clears the two-thirds floor at this row's
       own measured width (a real-browser check against a 360px viewport
       previously read 147px of 233px, 63% - short of the 66.7% required);
       the two remaining badges (an icon each, their own text label already
       hidden below) still fit this width comfortably. */
    .bk-draftboard-row-rail[b-4kgvzgrmz4] {
        flex: 0 1 44px;
        max-width: 44px;
        gap: 2px 4px;
    }

    .bk-draftboard-badge-label[b-4kgvzgrmz4],
    .bk-draftboard-row-prev[b-4kgvzgrmz4],
    .bk-draftboard-wontcreate-hint[b-4kgvzgrmz4] {
        display: none;
    }

    /* A denser row (22px, down from 28px) and a tighter head/tree padding
       give the phone's own tight height budget a little more room - together
       with the compact chat header (ChatPanel.razor.css) and the tightened
       chrome below this is what fits at least 12 rows at once in a 360x780
       viewport (acceptance criterion) instead of the 9 a real-browser check
       previously measured. */
    .bk-draftboard-row[b-4kgvzgrmz4] {
        height: 22px;
        padding: 2px 6px;
    }

    .bk-draftboard-head[b-4kgvzgrmz4] {
        margin-bottom: 4px;
    }

    .bk-draftboard-tree[b-4kgvzgrmz4] {
        padding: 3px 4px;
    }
}

/* ----- Detail pane color neutralization -----
   The detail pane reuses RequirementDraftCard (a child component) plus this
   board's own hand-rolled tree-operation cards (RenderOperationDetail). Both
   render the SAME shared bk-draft-kind, bk-draft-parent and bk-draft-move-hint
   classes app.css also gives the Zerlegungs-Gate its saturated fill from.
   Overriding those shared rules in app.css itself would repaint that other
   host too, which must stay exactly as it is - so the override lives here
   instead, scoped deep into the child component only (the architecture
   decision's own reasoning on this). Icon and text (unchanged) still carry
   which kind or which parent-assignment a card shows; only the color goes
   neutral. */
.bk-draftboard[b-4kgvzgrmz4]  .bk-draft-kind-new,
.bk-draftboard[b-4kgvzgrmz4]  .bk-draft-kind-extend,
.bk-draftboard[b-4kgvzgrmz4]  .bk-draft-kind-archive,
.bk-draftboard[b-4kgvzgrmz4]  .bk-draft-kind-delete,
.bk-draftboard[b-4kgvzgrmz4]  .bk-draft-kind-unarchive,
.bk-draftboard[b-4kgvzgrmz4]  .bk-draft-parent-existing,
.bk-draftboard[b-4kgvzgrmz4]  .bk-draft-parent-new {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 8%, transparent);
    color: var(--mud-palette-text-primary);
}

.bk-draftboard[b-4kgvzgrmz4]  .bk-draft-move-hint {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 6%, transparent);
    border-color: var(--mud-palette-lines-default);
    color: var(--mud-palette-text-primary);
}

/* Readable measure (acceptance criterion: at most about 100 characters per
   line, same as the transcript's own agent turns - see app.css's own "Chat:
   full-width column, per-block reading measure" section) now that the detail
   pane itself fills whatever width .bk-draftboard-body's grid gives it
   instead of a fixed centered column - capped on the card as a whole (not
   just its description text) so the title, criteria and rationale all wrap
   at the same measure rather than each picking their own. Scoped to this
   board only: the Zerlegungs-Gate's own use of the same shared .bk-draft-card
   is not part of this feature and must keep its current width. */
.bk-draftboard[b-4kgvzgrmz4]  .bk-draft-card {
    max-width: 75ch;
}
/* /Components/Shared/Chat/RequirementDraftResultsPanel.razor.rz.scp.css */
/* Scoped styles of RequirementDraftResultsPanel.razor - a dense, single-line
   row per affected requirement that still fits a 360px phone even with a
   very long title (acceptance criterion): the title is the only element
   allowed to shrink and truncate, every other cell (picker, key, tag, arrow)
   keeps its own fixed width. */

.bk-outcome-list[b-9gq9ybbmxc] {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-md);
    overflow: hidden;
}

.bk-outcome-row[b-9gq9ybbmxc] {
    display: flex;
    align-items: center;
    gap: var(--bk-space-2);
    padding: var(--bk-space-2) var(--bk-space-3);
    min-width: 0;
    background: var(--mud-palette-surface);
}

.bk-outcome-row + .bk-outcome-row[b-9gq9ybbmxc] {
    border-top: 1px solid var(--mud-palette-lines-default);
}

.bk-outcome-row-gone .bk-outcome-key[b-9gq9ybbmxc],
.bk-outcome-row-gone .bk-outcome-title[b-9gq9ybbmxc] {
    color: var(--mud-palette-text-secondary);
}

.bk-outcome-spacer[b-9gq9ybbmxc] {
    flex: none;
    width: 24px;
}

.bk-outcome-row[b-9gq9ybbmxc]  .bk-req-picker {
    flex: none;
    display: inline-flex;
    align-items: center;
    max-width: 110px;
    overflow: hidden;
}

.bk-outcome-row[b-9gq9ybbmxc]  .bk-req-picker-reason {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-outcome-key[b-9gq9ybbmxc] {
    flex: none;
    font-family: monospace;
    font-weight: 600;
    font-size: 0.8125rem;
}

.bk-outcome-title[b-9gq9ybbmxc] {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.875rem;
}

.bk-outcome-open[b-9gq9ybbmxc] {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    color: var(--mud-palette-primary);
    background: none;
    border: none;
    cursor: pointer;
}

.bk-outcome-open-none[b-9gq9ybbmxc] {
    visibility: hidden;
}
/* /Components/Shared/LanguageSwitchForm.razor.rz.scp.css */
/* Two-letter language segments in the sign-in page's top-right corner, in
   the app's neumorphic design: the pill around them (LoginLayout's
   .bk-login-language) is a groove pressed into the page and the active
   language is raised out of it. The colors are the bk-login-* custom
   properties defined on .bk-login-shell in LoginLayout.razor.css and
   inherited through (CSS isolation scopes selectors, not custom properties),
   with literal fallbacks in case this form is ever rendered outside that
   shell. */
.bk-lang-form[b-par9rephpc] {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 4px;
    margin: 0;
}

.bk-lang-option[b-par9rephpc] {
    display: inline-block;
    padding: 7px 10px;
    border: none;
    border-radius: var(--bk-radius-pill);
    background: transparent;
    color: var(--bk-login-fg-muted, #5A5676);
    font: inherit;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    line-height: 1;
    transition: color var(--bk-dur-fast) var(--bk-ease-out), box-shadow var(--bk-dur-fast) var(--bk-ease-out);
}

button.bk-lang-option[b-par9rephpc] {
    cursor: pointer;
}

button.bk-lang-option:hover[b-par9rephpc],
button.bk-lang-option:focus-visible[b-par9rephpc] {
    color: var(--bk-login-accent, #594AE2);
}

button.bk-lang-option:active[b-par9rephpc] {
    box-shadow: inset 2px 2px 4px var(--bk-soft-lo, rgba(0, 0, 0, 0.2)), inset -2px -2px 4px var(--bk-soft-hi, rgba(255, 255, 255, 0.6));
}

button.bk-lang-option:focus-visible[b-par9rephpc] {
    outline: 2px solid var(--bk-login-accent, #594AE2);
    outline-offset: 2px;
}

/* The request's own language: shown, not clickable (a span, see the markup). */
.bk-lang-option.is-active[b-par9rephpc] {
    color: var(--bk-login-accent, #594AE2);
    background: var(--bk-login-tone, #ECEBF2);
    box-shadow: 2px 2px 5px var(--bk-soft-lo, rgba(0, 0, 0, 0.2)), -2px -2px 5px var(--bk-soft-hi, rgba(255, 255, 255, 0.6));
}
/* /Components/Shared/PanZoomCanvas.razor.rz.scp.css */
/* The canvas fills whatever its host gives it: it is the surface, not a frame
   on one. The dot grid is drawn on this element and moved with the pan, so the
   background reads as the same plane the content lies on (canvas-interop.js
   writes both). overflow:hidden because panning, not scrolling, is how the
   surface moves; touch-action:none so a pinch reaches the zoom handler. */
.bk-canvas[b-ik31zbwdbw] {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    border-radius: var(--bk-radius-sm);
    background-color: var(--mud-palette-background-gray);
    cursor: grab;
    touch-action: none;
    user-select: none;
}

.bk-canvas-grabbing[b-ik31zbwdbw] {
    cursor: grabbing;
}

/* Everything on the canvas moves and scales together (transform-origin at the
   corner keeps the arithmetic in the script simple). Width/height 0 on
   purpose: the layer is only a coordinate system, its views are absolutely
   placed inside it. */
.bk-canvas-layer[b-ik31zbwdbw] {
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    height: 0;
    transform-origin: 0 0;
}

/* Unless the content is ONE drawing rather than placed views: then the layer
   takes the size of what it holds, and that box is what the fit measures. */
.bk-canvas-layer-sized[b-ik31zbwdbw] {
    width: max-content;
    height: max-content;
}

/* Zoom controls and the hint sit ON the canvas, above the surface, and never
   move with it - they belong to the pane, not to the plane. */
.bk-canvas-bar[b-ik31zbwdbw] {
    position: absolute;
    right: 10px;
    bottom: 10px;
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 2px 4px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    background: var(--mud-palette-surface);
}

.bk-canvas-level[b-ik31zbwdbw] {
    min-width: 46px;
    text-align: center;
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-secondary);
}

.bk-canvas-hint[b-ik31zbwdbw] {
    position: absolute;
    left: 12px;
    bottom: 16px;
    font-size: 0.6875rem;
    color: var(--mud-palette-text-secondary);
    pointer-events: none;
}

/* Neumorphic design (app.css .bk-soft): the surface is a well pressed into
   the page, on the page tone rather than a grey of its own, and its controls
   a small raised pad above it. The inset shadow paints under the placed
   views, so a card near the edge still sits on top of it. */
.bk-soft .bk-canvas[b-ik31zbwdbw] {
    border-radius: var(--bk-radius-lg);
    background-color: var(--mud-palette-background);
    box-shadow: var(--bk-depth-inset);
}

.bk-soft .bk-canvas-bar[b-ik31zbwdbw] {
    border-color: transparent;
    border-radius: var(--bk-radius-md);
    box-shadow: var(--bk-depth-raised-sm);
}

/* No room for a hint next to the controls at this width. */
@media (max-width: 999.98px) {
    .bk-canvas-hint[b-ik31zbwdbw] {
        display: none;
    }
}

/* Browser Fullscreen API applied to the canvas element itself, not an
   overlay - the user agent already stretches it to fill the whole screen
   with no chat or navigation around it. Only the rounded corners a
   full-viewport surface no longer needs are dropped here. */
.bk-canvas:fullscreen[b-ik31zbwdbw] {
    border-radius: 0;
}
/* /Components/Shared/ProjectPageHeader.razor.rz.scp.css */
/* Header of every project-scoped page: the breadcrumb doubles as the title.
   Scoped to ProjectPageHeader - no other component renders these blocks. */

.bk-page-head[b-hha32yl3ul] {
    margin-bottom: 16px;
}

.bk-crumbs[b-hha32yl3ul] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    min-width: 0;
}

/* One line layout (section pages): the crumb row carries the page title, so
   the project name and the current page are set at heading size. */
.bk-crumbs .bk-crumb-proj-name[b-hha32yl3ul] {
    font-size: 1.25rem;
    font-weight: 500;
    /* The heading face (ThemePresets.CreateTypography), since this crumb is
       the page's title; the quiet variant below stays in the text face. */
    font-family: "Space Grotesk", "Inter", system-ui, sans-serif;
    letter-spacing: -0.015em;
}

.bk-crumbs .bk-crumb-current[b-hha32yl3ul] {
    font-size: 1.05rem;
    color: var(--mud-palette-text-primary);
}

.bk-crumbs .bk-crumb-sep[b-hha32yl3ul] {
    color: var(--mud-palette-text-disabled);
}

/* Detail pages: the same row shrinks to a quiet crumb trail, either above the
   title (stacked) or as the whole header when the page renders the title in a
   surface of its own (TitleShownByPage, e.g. the feature command bar). */
.bk-page-head-quiet .bk-crumbs[b-hha32yl3ul] {
    gap: 6px;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}

.bk-page-head-stacked .bk-crumbs[b-hha32yl3ul] {
    margin-bottom: 4px;
}

.bk-page-head-quiet .bk-crumbs .bk-crumb-proj-name[b-hha32yl3ul],
.bk-page-head-quiet .bk-crumbs .bk-crumb-current[b-hha32yl3ul] {
    font-size: 0.8125rem;
    font-weight: 400;
    font-family: inherit;
    letter-spacing: normal;
}

.bk-page-head-quiet .bk-crumbs .bk-crumb-current[b-hha32yl3ul] {
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-page-head-quiet .bk-crumbs .bk-proj-dot[b-hha32yl3ul] {
    width: 8px;
    height: 8px;
}

.bk-page-head-quiet .bk-crumbs[b-hha32yl3ul]  .bk-crumb-chevron {
    font-size: 1rem;
}

/* MudMenu is inline-level and wraps the activator in a div of its own; both
   have to become flex items so the switcher and the overflow chip sit on the
   crumb baseline instead of adding a stray line box. */
.bk-crumbs[b-hha32yl3ul]  .bk-crumb-menu,
.bk-crumbs[b-hha32yl3ul]  .bk-crumb-menu .mud-menu-activator {
    display: inline-flex;
    align-items: center;
    min-width: 0;
}

.bk-crumb-proj[b-hha32yl3ul] {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
    max-width: 320px;
    padding: 2px 6px;
    margin: -2px -6px;
    border-radius: var(--bk-radius-sm);
    cursor: pointer;
    transition: background-color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-crumb-proj:hover[b-hha32yl3ul] {
    background: var(--mud-palette-action-default-hover);
}

.bk-crumb-proj-name[b-hha32yl3ul] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-crumb-proj[b-hha32yl3ul]  .bk-crumb-chevron {
    flex-shrink: 0;
    color: var(--mud-palette-text-secondary);
}

/* Overflow chip for the levels between the project and the direct parent */
.bk-crumb-more[b-hha32yl3ul] {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 8px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-md);
    font-size: 0.8125rem;
    line-height: 1;
    letter-spacing: 1px;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

.bk-crumb-more:hover[b-hha32yl3ul] {
    background: var(--mud-palette-action-default-hover);
}

/* The direct parent can be a long entity title, so it is clipped rather than
   allowed to push the row into a second line (full text in the tooltip). */
.bk-crumb-link[b-hha32yl3ul] {
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: inherit;
    text-decoration: none;
}

.bk-crumb-link:hover[b-hha32yl3ul] {
    text-decoration: underline;
}

.bk-crumb-context[b-hha32yl3ul] {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.bk-page-head-spacer[b-hha32yl3ul] {
    flex: 1 1 auto;
}

.bk-page-head-title-row[b-hha32yl3ul] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    min-width: 0;
}

.bk-page-head-title-icon[b-hha32yl3ul] {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
}

/* Long titles wrap over at most two lines and are clipped after that, so the
   header height stays stable across pages. */
.bk-page-head-title[b-hha32yl3ul] {
    flex: 1 1 320px;
    min-width: 0;
    margin: 0;
    font-size: 1.5rem;
    font-weight: 500;
    line-height: 1.35;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

.bk-page-head-context[b-hha32yl3ul],
.bk-page-head-actions[b-hha32yl3ul] {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    flex-shrink: 0;
}

@media (max-width: 599.98px) {
    .bk-crumbs .bk-crumb-proj-name[b-hha32yl3ul] {
        font-size: 1.1rem;
    }

    .bk-page-head-title[b-hha32yl3ul] {
        font-size: 1.25rem;
    }

    .bk-crumb-link[b-hha32yl3ul] {
        max-width: 150px;
    }

    /* Forces the actions group onto its own full-width row once it no longer
       fits next to the title/crumbs (it is still a flex item of .bk-crumbs /
       .bk-page-head-title-row at that point, sized by its own content) - a
       page with two or more action buttons (e.g. Requirements' "Mehrere
       auswaehlen" + "Neue Anforderung") otherwise keeps them side by side at
       their natural width, which together exceed a 360px viewport and widen
       the whole page instead of wrapping. width: 100% gives its own
       flex-wrap something to actually wrap the buttons against. */
    .bk-page-head-actions[b-hha32yl3ul] {
        flex: 1 1 100%;
        width: 100%;
    }

    /* Same reasoning and same fix as .bk-page-head-actions above, for the
       status pill row (RequirementDetail's status/kind/archived/criteria
       pills and the like): as a flex item with flex-shrink: 0, its own
       hypothetical main size is its unwrapped content width (the sum of
       every pill side by side), which several pills together routinely
       exceed a 360px viewport even though this row's own flex-wrap: wrap
       would happily stack them once it is given a row of its own to wrap
       within. */
    .bk-page-head-context[b-hha32yl3ul] {
        flex: 1 1 100%;
        width: 100%;
    }
}
/* /Components/Shared/Projects/ProjectFramePanel.razor.rz.scp.css */
/* Scoped styles of ProjectFramePanel.razor (design "Rahmen als Rail").

   The panel is a plain <div> now, not a MudPaper: it has to be a flex column
   whose middle scrolls and whose foot stays pinned, and MudPaper renders its
   own root element internally - an element Blazor CSS isolation never stamps
   with this component's scope attribute, so a scoped rule could not reach it
   with or without ::deep (the same trap ProjectSetupChat.razor.css documents
   at length for the proposal card). Painting the surface here costs three
   declarations and keeps every rule in reach.

   ::deep is used for anything rendered by a child component - MudButton's own
   root for the text actions, MudIcon's <svg> for the status marks - which the
   scope attribute would otherwise not touch. */

.bk-frame-panel[b-bir1bgbb0f] {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-md);
    overflow: hidden;
}

/* ----- Head: what the frame is, and how far it is ----- */

.bk-frame-head[b-bir1bgbb0f] {
    flex: 0 0 auto;
    padding: 14px 16px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.bk-frame-head-row[b-bir1bgbb0f] {
    display: flex;
    align-items: baseline;
    gap: 8px;
}

.bk-frame-title[b-bir1bgbb0f] {
    font-size: 1rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.bk-frame-progress[b-bir1bgbb0f] {
    margin-left: auto;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.bk-frame-progress-count[b-bir1bgbb0f] {
    font-weight: 600;
    color: var(--mud-palette-success);
}

/* One segment per row of the list below, filled from the left by how many are
   confirmed - see the markup's own comment on why not in row order. */
.bk-frame-bar[b-bir1bgbb0f] {
    display: flex;
    gap: 4px;
    margin-top: 10px;
}

.bk-frame-bar-seg[b-bir1bgbb0f] {
    flex: 1 1 0;
    height: 4px;
    border-radius: var(--bk-radius-xs);
    background: var(--mud-palette-action-disabled-background);
}

.bk-frame-bar-seg-done[b-bir1bgbb0f] {
    background: var(--mud-palette-success);
}

.bk-frame-lead[b-bir1bgbb0f] {
    display: block;
    margin-top: 10px;
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--mud-palette-text-secondary);
}

/* ----- Rows: the only part that scrolls, so the foot below never leaves ----- */

.bk-frame-rows[b-bir1bgbb0f] {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.bk-frame-row[b-bir1bgbb0f] {
    padding: 12px 16px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.bk-frame-row:last-child[b-bir1bgbb0f] {
    border-bottom: none;
}

/* The one row the user is expected to deal with next. The accent edge plus
   the tint is what makes "where am I" answerable without reading all five
   labels - the status pill alone never did that, since three rows can carry
   the same "offen" at once. 3px of the 16px left padding go to the border, so
   the label still lines up with every other row. */
.bk-frame-row-next[b-bir1bgbb0f] {
    border-left: 3px solid var(--mud-palette-primary);
    padding-left: 13px;
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, transparent);
}

.bk-frame-row-head[b-bir1bgbb0f] {
    display: flex;
    align-items: center;
    gap: 8px;
}

.bk-frame-mark[b-bir1bgbb0f] {
    display: inline-flex;
    flex: 0 0 auto;
}

/* The status marker carries the same three states as the pill on the right,
   so a row stays readable where the pill's colour is not (a reader who does
   not separate the amber and green fills, a rail narrow enough to truncate
   it). */
.bk-frame-mark[b-bir1bgbb0f]  .bk-frame-mark-done {
    color: var(--mud-palette-success);
}

.bk-frame-mark[b-bir1bgbb0f]  .bk-frame-mark-proposed {
    color: var(--mud-palette-warning);
}

.bk-frame-mark[b-bir1bgbb0f]  .bk-frame-mark-next {
    color: var(--mud-palette-primary);
}

.bk-frame-mark[b-bir1bgbb0f]  .bk-frame-mark-open {
    color: var(--mud-palette-text-disabled);
}

.bk-frame-label[b-bir1bgbb0f] {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    min-width: 0;
}

/* The pill goes to the far end of the head row, whatever the label's length. */
.bk-frame-row-head .bk-pill[b-bir1bgbb0f] {
    margin-left: auto;
}

/* Indented to the label's own text, past the status marker, so the value
   reads as belonging to the label above rather than as a new item. */
.bk-frame-row-body[b-bir1bgbb0f] {
    margin-left: 28px;
}

.bk-frame-row-value[b-bir1bgbb0f] {
    display: block;
    margin-top: 2px;
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--mud-palette-text-secondary);
    word-break: break-word;
}

/* The agreed test-label convention is a paragraph, not a label: unclamped it
   ran to a dozen lines at the rail's width and pushed the foot out of sight.
   Two lines by default; the row's own "mehr" lifts this class. */
.bk-frame-row-value-clamped[b-bir1bgbb0f] {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.bk-frame-row-value code[b-bir1bgbb0f] {
    font-family: monospace;
    color: var(--mud-palette-text-primary);
}

/* Whether the recorded approach was read out of the repository's own
   already-used test patterns or drafted with no code to read yet - shown
   next to the value regardless of clamp/expand state. */
.bk-frame-row-source[b-bir1bgbb0f] {
    display: inline-block;
    margin-top: 4px;
    font-size: 11px;
    padding: 0 7px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    color: var(--mud-palette-text-secondary);
}

/* The approach's own prose and the detected test sets, one click away behind
   "mehr" - the clamped convention alone used to be all the row ever showed. */
.bk-frame-row-sub[b-bir1bgbb0f] {
    display: block;
    margin-top: 6px;
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--mud-palette-text-secondary);
}

.bk-frame-row-sub b[b-bir1bgbb0f] {
    color: var(--mud-palette-text-primary);
    font-weight: 600;
}

/* Actions get a line of their own, right-aligned: the old panel appended the
   text button straight after the value's own inline text, which rendered as
   "noch nicht hinterlegtWEITER" with nothing between them. */
.bk-frame-row-actions[b-bir1bgbb0f] {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-top: 4px;
    margin-left: -8px;
}

.bk-frame-row-actions-end[b-bir1bgbb0f] {
    flex: 1 1 auto;
}

/* Without a spacer the whole group sits at the start; every row that has no
   .bk-frame-row-actions-end of its own pushes its actions to the far end. */
.bk-frame-row-actions:not(:has(.bk-frame-row-actions-end))[b-bir1bgbb0f] {
    justify-content: flex-end;
}

.bk-frame-row-actions[b-bir1bgbb0f]  .bk-frame-action {
    min-width: 0;
    padding: 2px 8px;
    font-size: 0.8125rem;
    font-weight: 500;
    text-transform: none;
    letter-spacing: normal;
    color: var(--mud-palette-text-secondary);
}

.bk-frame-row-actions[b-bir1bgbb0f]  .bk-frame-action-primary {
    color: var(--mud-palette-primary);
}

.bk-frame-row-actions[b-bir1bgbb0f]  .bk-frame-action-quiet {
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* Enabled dependencies as chips rather than a " - "-joined run of names:
   at the rail's width that run wrapped mid-name and read as one long string. */
.bk-frame-chips[b-bir1bgbb0f] {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 6px;
}

.bk-frame-chip[b-bir1bgbb0f] {
    font-size: 11px;
    line-height: 1.6;
    padding: 1px 8px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    color: var(--mud-palette-text-secondary);
    background: var(--mud-palette-background);
}

/* ----- Inline forms ----- */

.bk-frame-form[b-bir1bgbb0f] {
    margin: 10px 0 2px 28px;
}

.bk-frame-note[b-bir1bgbb0f] {
    display: block;
    margin-bottom: 8px;
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--mud-palette-text-secondary);
}

.bk-frame-form-actions[b-bir1bgbb0f] {
    display: flex;
    align-items: center;
    gap: 8px;
}

.bk-frame-form-actions[b-bir1bgbb0f]  .bk-frame-action {
    text-transform: none;
    letter-spacing: normal;
    color: var(--mud-palette-text-secondary);
}

/* ----- Foot: pinned, short label, what is missing named underneath ----- */

.bk-frame-foot[b-bir1bgbb0f] {
    flex: 0 0 auto;
    padding: 12px 16px;
    border-top: 1px solid var(--mud-palette-lines-default);
    background: var(--mud-palette-background);
}

.bk-frame-foot-hint[b-bir1bgbb0f] {
    display: flex;
    align-items: flex-start;
    gap: 7px;
    margin-top: 8px;
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--mud-palette-text-secondary);
}

.bk-frame-foot-hint[b-bir1bgbb0f]  .bk-frame-foot-icon {
    flex: 0 0 auto;
    font-size: 1rem;
    color: var(--mud-palette-text-disabled);
}

.bk-frame-foot-hint[b-bir1bgbb0f]  .bk-frame-foot-icon-done {
    color: var(--mud-palette-success);
}
/* /Components/Shared/Projects/ProjectFrameSummaryBar.razor.rz.scp.css */
/* Scoped styles of ProjectFrameSummaryBar.razor - the phone's one-line
   stand-in for the frame rail. Whether it is shown at all is the host page's
   decision (ProjectSetupChat.razor.css hides it above the phone breakpoint),
   so nothing here is inside a media query.

   ::deep reaches MudIcon's own <svg>, which the scope attribute does not
   touch. */

/* A real <button>, so it is reachable by keyboard and announced as an action
   - the whole bar is the hit target, which on a phone is the only size that
   works. */
.bk-frame-summary[b-xmeisrnp2u] {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 56px;
    padding: 8px 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-md);
    background: var(--mud-palette-surface);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.bk-frame-summary-main[b-xmeisrnp2u] {
    flex: 1 1 auto;
    min-width: 0;
}

.bk-frame-summary-head[b-xmeisrnp2u] {
    display: flex;
    align-items: baseline;
    gap: 7px;
}

.bk-frame-summary-title[b-xmeisrnp2u] {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.bk-frame-summary-count[b-xmeisrnp2u] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.bk-frame-summary-bar[b-xmeisrnp2u] {
    display: flex;
    gap: 3px;
    margin-top: 6px;
}

.bk-frame-summary-seg[b-xmeisrnp2u] {
    flex: 1 1 0;
    height: 3px;
    border-radius: var(--bk-radius-xs);
    background: var(--mud-palette-action-disabled-background);
}

.bk-frame-summary-seg-done[b-xmeisrnp2u] {
    background: var(--mud-palette-success);
}

/* 44px is the floor for a touch target, and this is the part of the bar a
   thumb actually aims at. */
.bk-frame-summary-cta[b-xmeisrnp2u] {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 4px;
    max-width: 50%;
    height: 44px;
    padding: 0 8px 0 10px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
    border-radius: var(--bk-radius-sm);
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
    color: var(--mud-palette-primary);
    font-size: 0.8125rem;
    font-weight: 500;
}

/* Nothing left to chase: the call to action steps back to a plain marker, but
   the sheet still opens - a settled row stays correctable until the setup has
   actually run. */
.bk-frame-summary-cta-done[b-xmeisrnp2u] {
    border-color: var(--mud-palette-lines-default);
    background: transparent;
    color: var(--mud-palette-text-secondary);
}

.bk-frame-summary-cta-text[b-xmeisrnp2u] {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-frame-summary-cta[b-xmeisrnp2u]  .bk-frame-summary-chevron {
    flex: 0 0 auto;
}
/* /Components/Shared/ProposalAnnotationOverlay.razor.rz.scp.css */
/* Anchored, resizable annotation overlay of the architecture section (see
   ProposalAnnotationOverlay.razor's own doc comment). Desktop: a
   viewport-fixed window; geometry (left/top/width/height) is set inline by
   annotations-interop.js openOverlay, which also carries the last size/
   position over to the next annotation opened in the same page session.
   Hidden until placed (bk-placed) to avoid a flash at 0,0. */
.bk-annot-overlay[b-vvw9s2zq4m] {
    position: fixed;
    z-index: 1300;
    display: flex;
    flex-direction: column;
    min-width: 320px;
    min-height: 260px;
    visibility: hidden;
    background: var(--mud-palette-surface);
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 40%, var(--mud-palette-lines-default));
    border-radius: var(--bk-radius-md);
    box-shadow: 0 2px 6px rgba(38, 36, 58, 0.16), 0 18px 44px rgba(38, 36, 58, 0.26);
}

.bk-dark .bk-annot-overlay[b-vvw9s2zq4m] {
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5), 0 18px 44px rgba(0, 0, 0, 0.55);
}

.bk-annot-overlay.bk-placed[b-vvw9s2zq4m] {
    visibility: visible;
}

.bk-annot-overlay-head[b-vvw9s2zq4m] {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    gap: 8px;
    padding: 8px 12px;
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface));
    border-bottom: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-md) var(--bk-radius-md) 0 0;
    font-weight: 600;
    font-size: 0.8125rem;
    cursor: move;
    touch-action: none;
}

.bk-annot-overlay-title[b-vvw9s2zq4m] {
    display: flex;
    align-items: center;
    min-width: 0;
    flex: 1;
    gap: 8px;
}

/* Quoted selection in the editor head, single line with ellipsis - the same
   treatment ProposalAnnotationLabels.Describe gives an existing annotation's
   own card caption, so both read consistently. ::deep because HeaderContent
   is rendered by ArchitectureTab (the host), not by this component. */
.bk-annot-overlay-title[b-vvw9s2zq4m]  .bk-annot-overlay-quote {
    flex: 1;
    min-width: 0;
    font-weight: 400;
    font-style: italic;
    font-size: 0.71875rem;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-annot-overlay-title[b-vvw9s2zq4m]  .bk-annot-overlay-count {
    font-size: 10px;
    font-weight: 600;
    border-radius: var(--bk-radius-sm);
    padding: 0 6px;
    background: var(--mud-palette-background-gray);
    color: var(--mud-palette-text-secondary);
}

/* Back path, phone only (see .bk-annot-overlay-full below) */
.bk-annot-overlay-back[b-vvw9s2zq4m] {
    display: none;
}

/* Only the card list here (or the editor form) scrolls - the head above and
   the overlay's own resizable height, not a layout constant, decide how much
   of it is visible without scrolling. */
.bk-annot-overlay-body[b-vvw9s2zq4m] {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 12px 14px 14px;
}

.bk-annot-overlay-resize[b-vvw9s2zq4m] {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 18px;
    height: 18px;
    cursor: nwse-resize;
    touch-action: none;
}

.bk-annot-overlay-resize[b-vvw9s2zq4m]::after {
    content: "";
    position: absolute;
    right: 4px;
    bottom: 4px;
    width: 8px;
    height: 8px;
    border-right: 2px solid var(--mud-palette-lines-default);
    border-bottom: 2px solid var(--mud-palette-lines-default);
}

/* Phone: a screen-filling view instead of a floating window - no drag/
   resize, and an app-bar-style back path replaces the desktop close button
   (both close the overlay; the back path additionally scrolls the proposal
   to the annotated spot, see ArchitectureTab.OnOverlayBackAsync). The
   !important pins mirror the old .bk-annot-panel-sheet rule they replace,
   overriding the inline left/top/width/height openOverlay sets for the
   desktop window. 100dvh on top of a 100vh fallback keeps the reply field
   above the fold once a virtual keyboard shrinks the visual viewport. */
.bk-annot-overlay-full[b-vvw9s2zq4m] {
    left: 0 !important;
    top: 0 !important;
    width: 100% !important;
    height: 100vh !important;
    height: 100dvh !important;
    max-width: none;
    min-width: 0;
    min-height: 0;
    border: none;
    border-radius: 0;
}

.bk-annot-overlay-full .bk-annot-overlay-head[b-vvw9s2zq4m] {
    cursor: default;
    border-radius: 0;
}

.bk-annot-overlay-full .bk-annot-overlay-back[b-vvw9s2zq4m] {
    display: inline-flex;
}

.bk-annot-overlay-full .bk-annot-overlay-close[b-vvw9s2zq4m] {
    display: none;
}

.bk-annot-overlay-full .bk-annot-overlay-resize[b-vvw9s2zq4m] {
    display: none;
}
/* /Components/Shared/PushNotificationSwitch.razor.rz.scp.css */
/* The row's label carries the current state below it, as the approved
   design's sheet shows ("Off" / "On - you get notified about ..."). */
.bk-push-label[b-1cds2pufuy] {
    display: flex;
    flex-direction: column;
    white-space: normal;
}

.bk-push-state[b-1cds2pufuy] {
    font-size: 0.75rem;
    line-height: 1.3;
    color: var(--mud-palette-text-secondary);
}

/* A small track-and-thumb switch at the row's end. */
.bk-push-toggle[b-1cds2pufuy] {
    flex: none;
    position: relative;
    width: 36px;
    height: 20px;
    border-radius: var(--bk-radius-pill);
    background: var(--mud-palette-lines-default);
    transition: background-color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-push-toggle[b-1cds2pufuy]::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    border-radius: var(--bk-radius-round);
    background: var(--mud-palette-surface);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    transition: left var(--bk-dur-fast) var(--bk-ease-spring);
}

.bk-push-toggle-on[b-1cds2pufuy] {
    background: var(--mud-palette-primary);
}

.bk-push-toggle-on[b-1cds2pufuy]::after {
    left: 18px;
}

.bk-push-row:disabled[b-1cds2pufuy] {
    opacity: 0.6;
    cursor: default;
}
/* /Components/Shared/PwaShell.razor.rz.scp.css */
/* Install offer: a floating card just above the phone's bottom bar, hidden
   unless pwa-interop.js marks the document root with bk-install-available
   (and never inside the installed app, bk-standalone). Stacked below the
   More sheet's scrim (app.css, 1240), so an opened sheet covers it, and
   out of the way while the on-screen keyboard is open. */
.bk-install-offer[b-v8owmk2qz6] {
    display: none;
    position: fixed;
    left: var(--bk-space-3);
    right: var(--bk-space-3);
    bottom: calc(var(--bk-phone-bar-h) + env(safe-area-inset-bottom, 0px) + var(--bk-space-6));
    z-index: 1230;
    align-items: center;
    gap: var(--bk-space-3);
    padding: var(--bk-space-3);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-lg);
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
    font-size: 0.875rem;
}

.bk-install-available .bk-install-offer[b-v8owmk2qz6] {
    display: flex;
}

.bk-standalone .bk-install-offer[b-v8owmk2qz6],
.bk-keyboard-open .bk-install-offer[b-v8owmk2qz6] {
    display: none;
}

/* Wider than the phone shell: no bottom bar to sit above. */
@media (min-width: 600px) {
    .bk-install-offer[b-v8owmk2qz6] {
        left: auto;
        width: 380px;
        bottom: var(--bk-space-6);
    }
}

.bk-install-offer-logo[b-v8owmk2qz6] {
    flex: none;
    line-height: 0;
}

.bk-install-offer-text[b-v8owmk2qz6] {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.bk-install-offer-title[b-v8owmk2qz6] {
    font-weight: 600;
}

.bk-install-offer-sub[b-v8owmk2qz6] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.bk-install-offer-accept[b-v8owmk2qz6] {
    flex: none;
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    border: 0;
    padding: var(--bk-space-2) var(--bk-space-3);
    border-radius: var(--bk-radius-md);
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    cursor: pointer;
}

.bk-install-offer-dismiss[b-v8owmk2qz6],
.bk-update-notice-close[b-v8owmk2qz6] {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    padding: var(--bk-space-1);
    border-radius: var(--bk-radius-round);
    background: none;
    color: inherit;
    opacity: 0.75;
    cursor: pointer;
}

/* Update notice: a small dark status line at the top edge. It takes no room
   in the page and covers nothing a tap needs besides itself. */
.bk-update-notice[b-v8owmk2qz6] {
    position: fixed;
    top: var(--bk-space-3);
    left: 50%;
    transform: translateX(-50%);
    z-index: 1400;
    display: flex;
    align-items: center;
    gap: var(--bk-space-2);
    max-width: calc(100vw - 2 * var(--bk-space-3));
    box-sizing: border-box;
    padding: var(--bk-space-2) var(--bk-space-2) var(--bk-space-2) var(--bk-space-4);
    border-radius: var(--bk-radius-md);
    background: var(--mud-palette-text-primary);
    color: var(--mud-palette-surface);
    font-size: 0.8125rem;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
}

.bk-update-notice-text[b-v8owmk2qz6] {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* /Components/Shared/ReferenceImageGallery.razor.rz.scp.css */
/* The canvas is a SURFACE, so it needs a height of its own here - unlike in
   the chat, where it fills the pane beside the conversation. Tall enough that
   a prototype is usable without scrolling the page to it, short enough that
   the criteria above stay in view; the canvas itself zooms and pans inside it,
   so nothing is ever cut off. */
.bk-requirement-canvas[b-7wjn23719d] {
    display: flex;
    height: 560px;
}

/* One under the other, each in its own card - a drawing is looked at, not
   operated, so there is nothing to place side by side. */
.bk-drawn-illustrations[b-7wjn23719d] {
    display: block;
}
/* /Components/Shared/RequirementLink.razor.rz.scp.css */
/* Inline clickable Key + Title reference, usable inside a badge pill (its own
   color), a heading (review card title) or running text (move hint) - unlike
   the block-level .bk-clickable rows in GoalDetail/FeatureDetail, this is an
   inline span. Inherits the surrounding text color by default so it blends
   into whichever context renders it; only cursor + hover underline signal
   that it is clickable. Contexts that want a distinct link color (e.g. the
   applied-view result list, .bk-applied-results in app.css) set it there. */
.bk-req-link[b-g6bpkl87x4] {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    cursor: pointer;
}

.bk-req-link:hover[b-g6bpkl87x4] {
    text-decoration: underline;
}

.bk-req-link-key[b-g6bpkl87x4] {
    font-family: monospace;
}
/* /Components/Shared/RequirementsSubNav.razor.rz.scp.css */
/* Sub-navigation bar between RequirementTreeView and ProjectConstraints -
   scoped to RequirementsSubNav, no other component renders these blocks. */

.bk-req-subnav[b-nmu179a7te] {
    display: flex;
    gap: 4px;
    margin-bottom: 16px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.bk-req-subnav-link[b-nmu179a7te] {
    display: inline-flex;
    align-items: center;
    padding: 8px 4px 10px;
    color: var(--mud-palette-text-secondary);
    text-decoration: none;
    font-size: 0.875rem;
    font-weight: 500;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    transition: color var(--bk-dur-fast) var(--bk-ease-out), border-color var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-req-subnav-link:hover[b-nmu179a7te] {
    color: var(--mud-palette-text-primary);
}

.bk-req-subnav-link-active[b-nmu179a7te] {
    color: var(--mud-palette-primary);
    border-bottom-color: var(--mud-palette-primary);
}
/* /Components/Shared/RunSourceList.razor.rz.scp.css */
.bk-run-sources[b-6vxz8ypbmf] {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.bk-run-sources-list[b-6vxz8ypbmf] {
    margin: 0;
    padding-left: 20px;
    list-style: disc;
}

.bk-run-sources-list li[b-6vxz8ypbmf] {
    margin-bottom: 4px;
    word-break: break-word;
}

.bk-run-sources-list a[b-6vxz8ypbmf] {
    color: var(--mud-palette-primary);
}
/* /Components/Shared/SandboxedHtml.razor.rz.scp.css */
/* The viewport the artifact is seen through. The frame inside it is always
   the design width; this element is what the column actually sees, and
   artifact-interop.js keeps its height in step with the scaled frame - so the
   artifact is always shown whole and this never scrolls vertically. Sideways
   it does, since an artifact zoomed past its own size is deliberately wider
   than the space it is shown in. */
.bk-artifact-viewport[b-kuvsdbvvmu] {
    --bk-artifact-design-width: 1100px;
    position: relative;
    width: 100%;
    height: 320px;
    overflow: auto;
    border-radius: var(--bk-radius-xs);
    background: var(--mud-palette-surface);
    /* A pinch on a touch screen must reach the zoom handler rather than pan
       the page underneath it. */
    touch-action: none;
}

/* Always the design width, never the column's: an artifact is laid out for
   one width, and reflowing it to whatever space it happens to get makes it a
   different design than the one it was written as. The reader zooms instead
   (ctrl+wheel, trackpad or two-finger pinch, see artifact-interop.js), and
   the scale is applied from the top-left corner so scrolling stays
   predictable. Only the starting height is here - the frame reports its own,
   and the script writes it. */
.bk-agent-artifact[b-kuvsdbvvmu] {
    display: block;
    width: var(--bk-artifact-design-width);
    height: 320px;
    border: 0;
    background: var(--mud-palette-surface);
    transform-origin: top left;
}
/* /Components/Shared/SidebarEntry.razor.rz.scp.css */
/* Sidebar entries ("Wartet auf dich" / "Agenten aktiv" in MainLayout.razor).
   Own stylesheet per project convention (component-local CSS in a scoped
   *.razor.css) since SidebarEntry is its only consumer; these rules used to
   live in the shared app.css before the leading marker became this
   component's own icon gutter instead of a caller-supplied fragment. */
.bk-side-item[b-x44o2btqob] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 14px;
    border-radius: var(--bk-radius-sm);
    text-decoration: none;
    color: inherit;
}

.bk-side-item:hover[b-x44o2btqob],
.bk-side-item-active[b-x44o2btqob] {
    background: var(--mud-palette-action-default-hover);
}

/* Neumorphic preset (app.css .bk-soft): the active entry is pressed in. */
.bk-soft .bk-side-item-active[b-x44o2btqob] {
    background: transparent;
    box-shadow: var(--bk-depth-inset);
}

/* Fixed-width icon gutter, centered on the entry's full height so it sits
   between the title and subtitle line rather than on the title's baseline,
   and so every entry's icon lands on the same vertical axis regardless of
   its own line count. The width stays constant across every icon the gutter
   ever shows so the text column next to it never shifts, which keeps the
   230px drawer scroll-free on a 360px phone. */
.bk-side-icon[b-x44o2btqob] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    flex-shrink: 0;
}

.bk-side-text[b-x44o2btqob] {
    min-width: 0;
    flex: 1;
}

.bk-side-title[b-x44o2btqob] {
    display: block;
    font-size: 0.8125rem;
    line-height: 1.35;
    color: var(--mud-palette-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-side-sub[b-x44o2btqob] {
    display: block;
    font-size: 0.6875rem;
    line-height: 1.35;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A running agent shows BitLoader (the brand's 2x2 bit loader, lit in the
   role color) in place of its icon; it stays inside the same 18px gutter, so
   the shared vertical axis holds. Reduced motion slows it down but keeps it
   moving (BitLoader.razor.css) - the running state is also in the subtitle. */

/* The role/status accent colors (AgentRoleDisplay, StatusDisplay.BarColor/
   TaskBarColor) are fixed hex values with no dark-mode variant; a light tone
   like the draft grey (#B4B2A9) that was fine as a 7px dot is more visible -
   and needs more contrast - as a full icon fill on a dark drawer background.
   Brightening every icon uniformly in dark mode keeps this generic instead
   of hand-picking a lightened hex per accent color. */
.bk-dark .bk-side-icon[b-x44o2btqob] {
    filter: brightness(1.35) saturate(1.1);
}
/* /Components/Shared/StructuredFieldList.razor.rz.scp.css */
/* Named-field view of a structured (JSON) closing message. flex-wrap lets a
   long value drop to its own line instead of forcing horizontal scroll - the
   same 360px-phone requirement StructuredTextView's raw/markdown branches
   already meet, now also covering the field-list branch. */
.bk-fields[b-eso66qemyx] {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.bk-fields-leaf[b-eso66qemyx] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 10px;
    padding: 3px 0;
}

.bk-fields-name[b-eso66qemyx],
.bk-fields-bullet[b-eso66qemyx] {
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
    letter-spacing: 0.2px;
    flex-shrink: 0;
}

.bk-fields-value[b-eso66qemyx] {
    font-size: 0.8125rem;
    overflow-wrap: anywhere;
    white-space: pre-wrap;
    min-width: 0;
}

.bk-fields-group[b-eso66qemyx] {
    margin: 4px 0;
}

.bk-fields-header[b-eso66qemyx] {
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    letter-spacing: 0.2px;
}

.bk-fields-indent[b-eso66qemyx] {
    margin-left: 8px;
    padding-left: 10px;
    border-left: 2px solid var(--mud-palette-lines-default);
}
/* /Components/Shared/StructuredTextView.razor.rz.scp.css */
/* .bk-structured-text-pre lives in the global app.css, not here: it is now
   also used by TranscriptView.razor's TranscriptEntryKind.Result case, and a
   scoped rule here would never match elements that component renders (the
   scope attribute is only added to elements this component's own markup
   produces). */

/* The prose branch's rendered markdown (.bk-markdown, shared/global) wraps
   its own pre/code blocks instead of scrolling sideways: unlike a proposal or
   context note, an agent's raw closing message can contain a single very
   long line (e.g. an unbroken path or command) that must still stay readable
   at a 360px phone width without horizontal scroll. Raw HTML from
   MarkdownRenderer.ToHtml is not part of this component's compiled markup, so
   it never carries the scope attribute - ::deep is required for the
   selector to reach it at all. */
.bk-structured-markdown[b-451py08fvg]  pre,
.bk-structured-markdown[b-451py08fvg]  code {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    overflow-x: hidden;
}
/* /Components/Shared/ThemeSwitcher.razor.rz.scp.css */
.bk-theme-option[b-1pshj1tx5c] {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

/* A miniature logo tile in the preset's own color, raised like every other
   control (the menu inherits the neumorphic shadow tokens, app.css .bk-soft). */
.bk-theme-swatch[b-1pshj1tx5c] {
    width: 14px;
    height: 14px;
    border-radius: var(--bk-radius-xs);
    flex-shrink: 0;
    background: var(--bk-swatch);
    box-shadow: var(--bk-depth-raised-sm, none);
}

/* Glow presets show their halo right in the menu, so the list itself tells
   the sci-fi presets from the plain ones. */
.bk-theme-swatch-glow[b-1pshj1tx5c] {
    box-shadow: 0 0 0 1px var(--bk-swatch), 0 0 8px 1px var(--bk-swatch);
}
/* /Components/Shared/TranscriptView.razor.rz.scp.css */
/* TranscriptView: one agent run's stream-json output as a timeline (see the
   component's own remarks). Every rule of the view lives here; only
   .bk-structured-text-pre stays in app.css because StructuredTextView shares
   it. Classes put on a MudIcon (bk-tx-chev, bk-tx-tool-icon, bk-tx-node-icon,
   bk-tx-duration-icon) land on the element MudIcon renders, not on one of
   this component's own, so those rules need ::deep; likewise the markdown
   HTML inside the closing card (MarkupString output carries no scope). */

.bk-transcript[b-dg3tffgbct] {
    display: flex;
    flex-direction: column;
    font-size: 0.8125rem;
}

/* Summary strip: tool count, problem counts, run duration, expand-all. In a
   dialog (bk-tx-bar-sticky) it sticks to the top of the dialog content's own
   scroll area - .mud-dialog-content is the scroll container - so the control
   stays reachable in a long transcript; the chat's collapsed variant stays in
   flow, it is one line of a status row there, not the head of a scroll area. */
.bk-tx-bar[b-dg3tffgbct] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    min-height: 36px;
    padding: 4px 0;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* Duration plus expand-all, kept together: margin-left: auto right-aligns
   the group on its line, and when the bar has to wrap on a narrow viewport
   the group moves to the next line as a whole instead of overflowing. */
.bk-tx-bar-actions[b-dg3tffgbct] {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
    flex-shrink: 0;
}

.bk-tx-bar-sticky[b-dg3tffgbct] {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--mud-palette-surface);
}

.bk-tx-bar-label[b-dg3tffgbct] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* Whole-view collapse toggle (TranscriptView's CollapsedByDefault): wraps the
   icon and label so only that part of the bar is clickable, leaving "Alle
   einblenden" (rendered as a sibling once expanded) unaffected. */
.bk-tx-bar-toggle[b-dg3tffgbct] {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    cursor: pointer;
}

.bk-tx-stat[b-dg3tffgbct] {
    font-size: 0.6875rem;
    font-weight: 600;
    padding: 1px 8px;
    border-radius: var(--bk-radius-pill);
    white-space: nowrap;
}

.bk-tx-stat-error[b-dg3tffgbct] {
    background: rgba(226, 75, 74, 0.12);
    color: #C62828;
}

.bk-tx-stat-blocked[b-dg3tffgbct] {
    background: #FCF3E3;
    color: #7A5310;
}

.bk-dark .bk-tx-stat-error[b-dg3tffgbct] {
    background: rgba(226, 75, 74, 0.22);
    color: #F28B8A;
}

.bk-dark .bk-tx-stat-blocked[b-dg3tffgbct] {
    background: #4A3A14;
    color: #F2CE8C;
}

.bk-tx-duration[b-dg3tffgbct] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-family: monospace;
    font-size: 0.71875rem;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.bk-tx-duration[b-dg3tffgbct]  .bk-tx-duration-icon {
    font-size: 14px;
}

/* Timeline grid per entry: time gutter | rail with one node | content. The
   gutter keeps its width even for a row whose entry carries no stamp (an
   empty gutter cell), so every row lines up and the content never moves by
   a column. --bk-node-top puts the node (and the gutter's first line, which
   aligns with it) on the first line of that row kind's content. */
.bk-tx-rows[b-dg3tffgbct] {
    display: flex;
    flex-direction: column;
}

.bk-tx-row[b-dg3tffgbct] {
    display: grid;
    grid-template-columns: 54px 16px minmax(0, 1fr);
    grid-template-areas: "time rail content";
    column-gap: 6px;
    align-items: start;
    --bk-node-top: 14px;
}

.bk-tx-row-text[b-dg3tffgbct] {
    --bk-node-top: 17px;
}

.bk-tx-row-final[b-dg3tffgbct] {
    --bk-node-top: 21px;
}

.bk-tx-row-raw[b-dg3tffgbct] {
    --bk-node-top: 13px;
}

.bk-tx-time[b-dg3tffgbct] {
    grid-area: time;
}

.bk-tx-rail[b-dg3tffgbct] {
    grid-area: rail;
}

/* minmax(0, 1fr) above already keeps the track itself from growing past the
   container, but the content cell also needs its own min-width: 0 - without
   it, a non-wrapping descendant (bk-tx-arg's single-line ellipsis) stops the
   whole row from shrinking and the tool row overflows horizontally instead
   of clipping, on exactly the narrow viewport this view must stay
   scroll-free on. */
.bk-tx-content[b-dg3tffgbct] {
    grid-area: content;
    min-width: 0;
}

.bk-tx-time[b-dg3tffgbct] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    padding-top: calc(var(--bk-node-top) - 7px);
    font-family: monospace;
    font-size: 0.6875rem;
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-secondary);
}

.bk-tx-time-clock[b-dg3tffgbct] {
    font-weight: 600;
}

.bk-tx-time-elapsed[b-dg3tffgbct] {
    opacity: 0.75;
}

/* The rail: a hairline through the whole column, starting at the first
   row's node and ending at the last row's node, with one node per row. */
.bk-tx-rail[b-dg3tffgbct] {
    position: relative;
    align-self: stretch;
}

.bk-tx-rail[b-dg3tffgbct]::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 0;
    bottom: 0;
    width: 1px;
    margin-left: -0.5px;
    background: var(--mud-palette-lines-default);
}

.bk-tx-row:first-child .bk-tx-rail[b-dg3tffgbct]::before {
    top: var(--bk-node-top);
}

.bk-tx-row:last-child .bk-tx-rail[b-dg3tffgbct]::before {
    bottom: calc(100% - var(--bk-node-top));
}

/* Plain ring: system lines, raw lines, an intermediate result */
.bk-tx-node[b-dg3tffgbct] {
    position: absolute;
    left: 50%;
    top: var(--bk-node-top);
    width: 8px;
    height: 8px;
    margin: -4px 0 0 -4px;
    border-radius: var(--bk-radius-round);
    box-sizing: border-box;
    background: var(--mud-palette-surface);
    border: 2px solid var(--mud-palette-lines-inputs);
}

.bk-tx-node-text[b-dg3tffgbct] {
    background: var(--mud-palette-primary);
    border-color: var(--mud-palette-primary);
}

/* A completed call is the quiet default; only trouble gets color */
.bk-tx-node-ok[b-dg3tffgbct] {
    background: var(--mud-palette-gray-light);
    border-color: var(--mud-palette-gray-light);
}

.bk-dark .bk-tx-node-ok[b-dg3tffgbct] {
    background: var(--mud-palette-gray-dark);
    border-color: var(--mud-palette-gray-dark);
}

.bk-tx-node-error[b-dg3tffgbct] {
    background: #E24B4A;
    border-color: #E24B4A;
}

.bk-tx-node-blocked[b-dg3tffgbct] {
    background: #EF9F27;
    border-color: #EF9F27;
}

.bk-tx-node-pending[b-dg3tffgbct] {
    border-color: var(--mud-palette-primary);
}

/* Only while the run has no closing result line yet (see _hasResultLine) */
.bk-tx-node-pulse[b-dg3tffgbct] {
    animation: bk-tx-pulse-b-dg3tffgbct 1.4s ease-in-out infinite;
}

@keyframes bk-tx-pulse-b-dg3tffgbct {
    0%, 100% { box-shadow: 0 0 0 0 rgba(var(--mud-palette-primary-rgb), 0.40); }
    60% { box-shadow: 0 0 0 5px rgba(var(--mud-palette-primary-rgb), 0); }
}

@media (prefers-reduced-motion: reduce) {
    .bk-tx-node-pulse[b-dg3tffgbct] {
        animation: none;
    }
}

/* The closing message's node is an icon, not a dot: it marks the end */
.bk-tx-node-final[b-dg3tffgbct] {
    width: 16px;
    height: 16px;
    margin: -8px 0 0 -8px;
    border: 0;
    color: #1D9E75;
    display: flex;
}

.bk-tx-node-final[b-dg3tffgbct]  .bk-tx-node-icon {
    font-size: 16px;
}

.bk-tx-node-final-error[b-dg3tffgbct] {
    color: #E24B4A;
}

.bk-tx-system[b-dg3tffgbct] {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: 28px;
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
}

/* The agent's text stays the readable spine: prose size, and a capped
   measure so a wide dialog does not stretch a paragraph across the screen */
.bk-tx-text[b-dg3tffgbct] {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: 0.9375rem;
    line-height: 1.6;
    color: var(--mud-palette-text-primary);
    padding: 5px 0 7px;
    max-width: 82ch;
}

/* Tool call: one boxless 28px row; the bordered surface appears only around
   the expanded body */
.bk-tx-tool-head[b-dg3tffgbct] {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 28px;
    padding: 0 8px 0 2px;
    border-radius: var(--bk-radius-sm);
    cursor: pointer;
    min-width: 0;
}

.bk-tx-tool-head:hover[b-dg3tffgbct] {
    background: var(--mud-palette-action-default-hover);
}

.bk-tx-tool-head:focus-visible[b-dg3tffgbct] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

.bk-tx-bar-toggle[b-dg3tffgbct]  .bk-tx-chev,
.bk-tx-tool-head[b-dg3tffgbct]  .bk-tx-chev {
    color: var(--mud-palette-text-secondary);
    opacity: 0.7;
    flex-shrink: 0;
}

.bk-tx-tool-head[b-dg3tffgbct]  .bk-tx-chev {
    transition: transform var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-tx-tool-open .bk-tx-tool-head[b-dg3tffgbct]  .bk-tx-chev {
    transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
    .bk-tx-tool-head[b-dg3tffgbct]  .bk-tx-chev {
        transition: none;
    }
}

.bk-tx-tool-head[b-dg3tffgbct]  .bk-tx-tool-icon {
    font-size: 16px;
    flex-shrink: 0;
    color: var(--mud-palette-text-secondary);
}

.bk-tx-name[b-dg3tffgbct] {
    font-weight: 600;
    font-size: 0.75rem;
    flex-shrink: 0;
}

/* One-line argument (command, file path, ...); truncates so the row stays one line */
.bk-tx-arg[b-dg3tffgbct] {
    font-family: monospace;
    font-size: 0.71875rem;
    color: var(--mud-palette-text-secondary);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bk-tx-pill[b-dg3tffgbct] {
    margin-left: auto;
    padding: 1px 8px;
    border-radius: var(--bk-radius-pill);
    font-size: 0.6875rem;
    font-weight: 600;
    flex-shrink: 0;
}

.bk-tx-pill-error[b-dg3tffgbct] {
    background: rgba(226, 75, 74, 0.12);
    color: #C62828;
}

.bk-tx-pill-blocked[b-dg3tffgbct] {
    background: #FCF3E3;
    color: #7A5310;
}

.bk-tx-pill-pending[b-dg3tffgbct] {
    background: rgba(var(--mud-palette-primary-rgb), 0.10);
    color: var(--mud-palette-primary);
}

.bk-dark .bk-tx-pill-error[b-dg3tffgbct] {
    background: rgba(226, 75, 74, 0.22);
    color: #F28B8A;
}

.bk-dark .bk-tx-pill-blocked[b-dg3tffgbct] {
    background: #4A3A14;
    color: #F2CE8C;
}

.bk-dark .bk-tx-pill-pending[b-dg3tffgbct] {
    background: rgba(var(--mud-palette-primary-rgb), 0.18);
}

.bk-tx-tool-blocked .bk-tx-tool-head[b-dg3tffgbct] {
    background: rgba(239, 159, 39, 0.10);
}

.bk-tx-tool-blocked .bk-tx-tool-head:hover[b-dg3tffgbct] {
    background: rgba(239, 159, 39, 0.16);
}

.bk-tx-tool-body[b-dg3tffgbct] {
    margin: 2px 0 8px 26px;
    padding: 8px 10px 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-sm);
    background: var(--mud-palette-background-gray);
}

.bk-tx-lbl[b-dg3tffgbct] {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-secondary);
}

.bk-tx-pre + .bk-tx-lbl[b-dg3tffgbct] {
    margin-top: 6px;
}

.bk-tx-pre[b-dg3tffgbct],
.bk-tx-raw[b-dg3tffgbct] {
    font-family: monospace;
    font-size: 0.75rem;
    line-height: 1.5;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    margin: 0;
}

.bk-tx-pre-error[b-dg3tffgbct] {
    color: #C62828;
}

.bk-dark .bk-tx-pre-error[b-dg3tffgbct] {
    color: #F28B8A;
}

.bk-tx-raw[b-dg3tffgbct] {
    color: var(--mud-palette-text-secondary);
    padding: 4px 0;
}

/* Closing message: a labeled card with a calm tint. Capped like .bk-markdown
   itself (860px) so the tint does not stretch across a wide dialog. */
.bk-tx-final[b-dg3tffgbct] {
    margin: 4px 0 6px;
    padding: 8px 12px 10px;
    max-width: 860px;
    border-radius: var(--bk-radius-sm);
    border: 1px solid rgba(29, 158, 117, 0.30);
    background: rgba(29, 158, 117, 0.07);
}

.bk-tx-final-error[b-dg3tffgbct] {
    border-color: rgba(226, 75, 74, 0.35);
    background: rgba(226, 75, 74, 0.07);
}

.bk-dark .bk-tx-final[b-dg3tffgbct] {
    background: rgba(29, 158, 117, 0.12);
}

.bk-dark .bk-tx-final-error[b-dg3tffgbct] {
    background: rgba(226, 75, 74, 0.12);
}

.bk-tx-final-head[b-dg3tffgbct] {
    display: flex;
    align-items: center;
    height: 18px;
    margin-bottom: 4px;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: #15805E;
}

.bk-tx-final-error .bk-tx-final-head[b-dg3tffgbct] {
    color: #C62828;
}

.bk-dark .bk-tx-final-head[b-dg3tffgbct] {
    color: #6FD3B1;
}

.bk-dark .bk-tx-final-error .bk-tx-final-head[b-dg3tffgbct] {
    color: #F28B8A;
}

/* min-width: 0 lets the cell actually shrink to wrap its content instead of
   forcing the row wider than its container. */
.bk-tx-final-body[b-dg3tffgbct] {
    min-width: 0;
}

/* Same 360px-wide-viewport wrapping rule as StructuredTextView's prose
   branch (.bk-structured-markdown): the card is narrower still, so a long
   unbroken line in the agent's closing message must not push it into
   horizontal scroll either. The markdown HTML is MarkupString output and
   carries no scope attribute, hence ::deep. */
.bk-tx-final-body[b-dg3tffgbct]  .bk-markdown pre,
.bk-tx-final-body[b-dg3tffgbct]  .bk-markdown code {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    overflow-x: hidden;
}

/* Inside the tinted card the shared JSON block reads as an inset panel on
   the surface color rather than another grey */
.bk-tx-final-body .bk-structured-text-pre[b-dg3tffgbct] {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
}

/* The icon-button variant of expand-all exists for phones only (below) */
.bk-tx-bar-actions[b-dg3tffgbct]  .bk-tx-all-icon {
    display: none;
}

/* Phones (below MudBlazor's Sm breakpoint). Width is the scarce resource
   there - a non-fullscreen dialog leaves about 250px - so the side gutter
   (54px plus gaps, a third of that) gives way: the time becomes a caption
   line above each entry, the rail slims to 12px and the node sits on that
   caption line (one --bk-node-top for every kind), a tool row's argument may
   wrap onto a second line before it clips, the expanded body drops its
   indent (the rail already carries the hierarchy), and the summary strip
   shortens its label and shows the icon button instead of the text button.
   The grid areas keep the DOM order - time, rail, content - unchanged, so
   the browser test's per-row gutter cells still exist and still line up. */
@media (max-width: 599.98px) {
    .bk-tx-row[b-dg3tffgbct],
    .bk-tx-row-text[b-dg3tffgbct],
    .bk-tx-row-final[b-dg3tffgbct],
    .bk-tx-row-raw[b-dg3tffgbct] {
        grid-template-columns: 12px minmax(0, 1fr);
        grid-template-areas:
            "rail time"
            "rail content";
        column-gap: 6px;
        --bk-node-top: 7px;
    }

    .bk-tx-time[b-dg3tffgbct] {
        flex-direction: row;
        align-items: baseline;
        gap: 6px;
        min-height: 14px;
        padding-top: 0;
        line-height: 14px;
    }

    .bk-tx-tool-head[b-dg3tffgbct] {
        height: auto;
        min-height: 28px;
        align-items: flex-start;
        gap: 6px;
        padding: 5px 6px 5px 0;
    }

    /* Chevron (18px), icon (16px), name and pill all centered on the
       argument's first 18px line */
    .bk-tx-tool-head[b-dg3tffgbct]  .bk-tx-tool-icon,
    .bk-tx-pill[b-dg3tffgbct] {
        margin-top: 1px;
    }

    .bk-tx-name[b-dg3tffgbct] {
        line-height: 18px;
    }

    .bk-tx-arg[b-dg3tffgbct] {
        white-space: normal;
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        overflow: hidden;
        overflow-wrap: anywhere;
        line-height: 18px;
    }

    .bk-tx-tool-body[b-dg3tffgbct] {
        margin-left: 0;
    }

    .bk-tx-bar-label-long[b-dg3tffgbct] {
        display: none;
    }

    .bk-tx-bar-actions[b-dg3tffgbct]  .bk-tx-all-text {
        display: none;
    }

    .bk-tx-bar-actions[b-dg3tffgbct]  .bk-tx-all-icon {
        display: inline-flex;
    }
}
/* /Components/Shared/VersionSwitcher.razor.rz.scp.css */
/* Chip row spacing, previously duplicated as an inline style in both
   ArchitectureTab and QaTab; scoped since only this component renders it. */
.bk-version-switcher[b-9uyejzvxu6] {
    gap: 6px;
}
/* /Components/Shared/VisualizationGallery.razor.rz.scp.css */
/* Only what the ARTIFACT card needs on top of the shared .bk-teaser shape
   (wwwroot/app.css), which the draft's own card uses as well. */

/* Which of the two open actions applies is a layout question, so CSS answers
   it: a wide screen splits the chat surface (ChatArtifactPanel), a phone
   navigates to the artifact's own page (ArtifactView), where two columns
   would leave neither usable. The breakpoint is the chat's own
   (ChatSideThreadLayer.razor.css), where .bk-chat-annot collapses to a single
   column anyway. ::deep because both are MudButtons - their root element is
   rendered by MudBlazor, which the isolation attribute does not reach. */
.bk-artifact-teaser[b-cncx14c4zk]  .bk-artifact-open-page {
    display: none;
}

@media (max-width: 999.98px) {
    .bk-artifact-teaser[b-cncx14c4zk]  .bk-artifact-open-split {
        display: none;
    }

    .bk-artifact-teaser[b-cncx14c4zk]  .bk-artifact-open-page {
        display: inline-flex;
    }
}
/* /Components/Shared/WorkerImageDependencyList.razor.rz.scp.css */
/* Scoped styles for WorkerImageDependencyList.razor - moved here from
   WorkerImageSettings.razor.css together with the markup they belong to
   (component-local CSS convention): each dependency as a compact clickable
   row (icon + name [+ usage line] + enabled toggle only) - the full details
   (key, install lines, usage note) live in the shared edit dialog opened on
   click, not inline. */

/* Empty state: a quiet dashed drop-zone look instead of a blue info alert. */
.wi-empty[b-mrelxsfy7f] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    text-align: center;
    padding: 22px 16px;
    margin-bottom: 8px;
    border: 1px dashed var(--mud-palette-lines-inputs);
    border-radius: var(--bk-radius-md);
}

/* One dependency = one compact row: icon, name (+ optional usage line),
   enabled toggle. Clicking anywhere on the row (except the toggle, which
   stops propagation in the markup) opens the edit dialog with the full
   details. */
.wi-dep-row[b-mrelxsfy7f] {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--bk-radius-md);
    margin-bottom: 8px;
    background: var(--mud-palette-surface);
    cursor: pointer;
    transition: border-color var(--bk-dur-fast) var(--bk-ease-out), background-color var(--bk-dur-fast) var(--bk-ease-out);
}

.wi-dep-row:hover[b-mrelxsfy7f] {
    border-color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 4%, var(--mud-palette-surface));
}

/* Neumorphic design (app.css .bk-soft): the empty state is a pressed-in
   well instead of a dashed outline, each dependency a raised row that
   lifts on hover and sinks in while pressed. */
.bk-soft .wi-empty[b-mrelxsfy7f] {
    border-color: transparent;
    border-radius: var(--bk-radius-md);
    box-shadow: var(--bk-depth-inset);
}

.bk-soft .wi-dep-row[b-mrelxsfy7f],
.bk-soft .wi-dep-row:hover[b-mrelxsfy7f] {
    border-color: transparent;
    border-radius: var(--bk-radius-md);
    background: var(--mud-palette-surface);
    box-shadow: var(--bk-depth-raised-sm);
    transition: box-shadow var(--bk-dur-fast) var(--bk-ease-out), transform var(--bk-dur-fast) var(--bk-ease-out);
}

.bk-soft .wi-dep-row:hover[b-mrelxsfy7f] {
    box-shadow: var(--bk-depth-lift-sm);
}

.bk-soft .wi-dep-row:active[b-mrelxsfy7f] {
    box-shadow: var(--bk-depth-inset);
    transform: translateY(1px) scale(0.99);
}

.wi-dep-row-main[b-mrelxsfy7f] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.wi-dep-row-name[b-mrelxsfy7f] {
    font-weight: 500;
    color: var(--mud-palette-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The optional short usage line (ShowUsageLine="true", e.g. the project
   setup review card) - the same ellipsis treatment as the name, one line. */
.wi-dep-row-usage[b-mrelxsfy7f] {
    font-size: 0.78rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* A disabled dependency stays visible (so it can be turned back on) but reads
   as inactive: muted icon and name, the toggle itself already shows the state. */
.wi-dep-row-disabled .wi-dep-row-name[b-mrelxsfy7f],
.wi-dep-row-disabled .wi-dep-row-usage[b-mrelxsfy7f] {
    color: var(--mud-palette-text-secondary);
}

.wi-dep-row-disabled[b-mrelxsfy7f]  .mud-icon-root {
    opacity: 0.6;
}
