/* /Components/Layout/MainLayout.razor.rz.scp.css */
/* --bb-sticky-chrome-offset must NOT be declared here, and belongs in the :root token layer in
   app.css: the docked work item basket renders outside `.page` and reads the same value, and a
   custom property declared on `.page` does not reach a non-descendant. Declaring it here as well
   would shadow the :root value for everything inside `.page` while the basket kept the other one. */
.page[b-d6q3ufqgmk] {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100dvh;
    overflow: hidden;
}

/* Story 139.1. This rule used to read `visibility: hidden`, and that one declaration was the whole
   white-page defect: it hid the ENTIRE application shell, and the only thing that took it off was a
   flag set on the last line of an unguarded first-render JS interop chain. Any interruption of that
   chain — a dropped circuit after an idle period, a blocked module fetch — left the app invisible
   permanently, out of the accessibility tree, with only the #blazor-error-ui strip at the bottom
   edge to show for it.
   The shell is no longer hidden by anything. `.bb-shell-loading` covers it instead, so `.page` stays
   present and reachable, and Story 139.1's timeout guarantees the cover comes off.

   `.page--theme-loading` therefore has NO RULE AT ALL, deliberately. It survives only as a marker of
   MainLayout's own hydration window (`_themeStateHydrated`, set once `HydrateShellPreferencesAsync`
   reconciles against localStorage), which the e2e suite asserts on, and it must never again carry a
   declaration that can make the shell unreachable. Story 150.4 removed the prerender pass this class
   was originally emitted by; MainLayout's circuit-side render is the only render left, and it still
   emits this class on the same first-render-until-hydrated window as before. Interactivity is a
   SEPARATE condition with its own class below — the theme being unknown and the circuit not being
   live are different facts, and conflating them is what made the first attempt at this wrong. */

/* Story 139.1: the shell is inert to pointer input until MainLayout's own hydration
   (`HydrateShellPreferencesAsync`: nav-collapsed state and theme reconciled against localStorage)
   completes on the first render.

   Reasoning corrected by Story 150.4 (UX review r1 flagged the old wording as stale): this no
   longer guards against Blazor Server dropping a click on a prerendered, not-yet-interactive DOM —
   D3 removed the prerender pass, so `.page` never exists without its own circuit already live and
   already dispatching events. That specific failure mode cannot occur any more. The rule is KEPT
   anyway, for a narrower, still-real reason: a click landing before `HydrateShellPreferencesAsync`
   finishes would be handled by a live circuit, but against nav/theme state that has not yet been
   reconciled with what is actually stored — `pointer-events: none` defers that click (the browser,
   and Playwright's actionability checks, treat the shell as not yet hit-testable) rather than letting
   it act on stale state. The window is now a single async round trip on an already-live circuit, not
   the historical prerender-to-interactive gap, and the class is still removed by the same render that
   sets `data-shell-interactive`.

   Deliberately keyed on interactivity, NOT on `.page--theme-loading`: App.razor's own static
   per-request read of the theme cookie (Story 150.4) resolves and paints a theme before MainLayout
   exists at all, so `.page--theme-loading`'s absence here would not be sound evidence of
   interactivity even though, today, MainLayout happens to flip both flags in the same instant — they
   remain two separate facts, not one. */
.page--not-interactive[b-d6q3ufqgmk] {
    pointer-events: none;
}

/* Story 139.3: the pre-hydration cover. Painted in the nav rail's brand ground, which DESIGN.md
   decision 6 fixes as its own dark surface in BOTH themes — the one surface in the design system
   that is correct before the palette is known, which is exactly the situation this cover exists for.
   Story 150.4 (D3) removed the prerender pass app-wide, so the opposite of the old claim here now
   holds: this is normally SEEN on every hard load, not the exception - there is no prerendered DOM
   already painted before the circuit connects, only App.razor's static shell placeholder ahead of
   it. It covers the window from that placeholder's removal until MainLayout's own hydration
   completes, on every load, not only a first-ever visit or a genuinely slow one. */
.bb-shell-loading[b-d6q3ufqgmk] {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    background: linear-gradient(180deg, #1A3C3E, #0D1F20);
    color: #E8F1F1;
}

.bb-shell-loading__brand[b-d6q3ufqgmk] {
    font-size: 1.25rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}

.bb-shell-loading__message[b-d6q3ufqgmk] {
    font-size: 0.875rem;
    color: #9FBFBF;
}

/* Story 139.3 / FR4. Bottom-anchored deliberately: an inline banner at the top of `.page` would add
   a fourth row to the shell's three-row height contract (Story 132.3), which the e2e suite guards.
   Sits above #blazor-error-ui's z-index so the two never overlap illegibly. */
.bb-shell-notice[b-d6q3ufqgmk] {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1100;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 1rem;
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    border-top: 1px solid var(--mud-palette-divider);
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    font-size: 0.8125rem;
}

.bb-shell-notice__text[b-d6q3ufqgmk] {
    flex: 1 1 auto;
}

.bb-shell-notice__action[b-d6q3ufqgmk],
.bb-shell-notice__dismiss[b-d6q3ufqgmk] {
    flex: 0 0 auto;
    background: none;
    border: 1px solid var(--mud-palette-divider);
    border-radius: 4px;
    padding: 0.25rem 0.75rem;
    color: var(--mud-palette-primary);
    cursor: pointer;
    font: inherit;
    /* AD-13 touch floor: the visual pill is shorter than 44px, so the hit area is grown with
       padding rather than by growing the pill. */
    min-height: 2rem;
}

.bb-shell-notice__dismiss[b-d6q3ufqgmk] {
    color: var(--mud-palette-text-secondary);
    padding: 0.25rem 0.5rem;
}

.bb-shell-notice__action:hover[b-d6q3ufqgmk],
.bb-shell-notice__dismiss:hover[b-d6q3ufqgmk] {
    background-color: var(--mud-palette-action-default-hover);
}

/* Story 132.4, AC 1. The standard visually-hidden-until-focused skip link: kept in the DOM and in
   the tab order at all times (display:none or visibility:hidden would take it out of both), clipped
   to nothing until it takes focus, then dropped into the top-left corner over the chrome. */
.skip-link[b-d6q3ufqgmk] {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2000;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border-radius: 0 0 8px 0;
    border: 1px solid var(--mud-palette-primary);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font-size: 0.8rem;
    font-weight: 600;
    text-decoration: none;
}

.skip-link:focus[b-d6q3ufqgmk],
.skip-link:focus-visible[b-d6q3ufqgmk] {
    width: auto;
    height: auto;
    padding: 0.45rem 0.9rem;
    overflow: visible;
    clip-path: none;
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

main[b-d6q3ufqgmk] {
    flex: 1;
    /* Story 132.5, AC 11: `overflow` rather than `overflow-y`, so a page whose content is wider than
       the viewport scrolls sideways INSIDE the content region instead of handing the overflow to the
       document and taking the sticky chrome off screen with it. `.page` is already overflow:hidden,
       so without this the wide content would simply be clipped with no way to reach it. */
    overflow: auto;
    /* AC 1 / AD-12. `main` is its own scroll container below the chrome rather than under it, so
       nothing is hidden by the chrome today; this keeps an in-page anchor or a programmatic focus
       scroll clear of any sticky element the content area itself introduces, and stops a future
       overlaying header from silently parking the target under it. */
    scroll-padding-top: var(--bb-sticky-chrome-offset);
}

/* Story 132.4, AC 2: the shell's single live region. Visually hidden but never removed from the
   accessibility tree — clip-path rather than display:none, which would stop it announcing at all.
   Positioned out of flow so it cannot affect the .page column's three-row height contract. */
.bb-live-region[b-d6q3ufqgmk] {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.sidebar[b-d6q3ufqgmk] {
    background-image: linear-gradient(180deg, #1A3C3E 0%, #0D1F20 100%);
}

.top-bar[b-d6q3ufqgmk] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    height: 2.6rem;
    padding: 0 0.75rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
    flex-shrink: 0;
    z-index: 10;
}

.top-bar-spacer[b-d6q3ufqgmk] {
    flex: 1;
}

/* ── Compact nav toggle ({components.nav-panel}'s hamburger) ─────────────────────────────────────
   Story 132.5, AC 8/10. Lives in the top bar as its first control, and is hidden from
   {breakpoints.sm} up where the rail is permanently on screen. Sized to {spacing.touch-target-min}
   on both axes — the whole button is the hit area, so nothing is inflated to reach it. */
.nav-toggle[b-d6q3ufqgmk] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    background-color: transparent;
    color: var(--mud-palette-text-primary);
    cursor: pointer;
}

.nav-toggle:hover[b-d6q3ufqgmk] {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

.nav-toggle:focus-visible[b-d6q3ufqgmk] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* Three bars from one element plus its two pseudo-elements. currentColor throughout, so the hover
   and forced-colors treatments above recolour the glyph rather than only its border. */
.nav-toggle-bars[b-d6q3ufqgmk],
.nav-toggle-bars[b-d6q3ufqgmk]::before,
.nav-toggle-bars[b-d6q3ufqgmk]::after {
    display: block;
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background-color: currentColor;
}

.nav-toggle-bars[b-d6q3ufqgmk] {
    position: relative;
}

.nav-toggle-bars[b-d6q3ufqgmk]::before,
.nav-toggle-bars[b-d6q3ufqgmk]::after {
    content: "";
    position: absolute;
    left: 0;
}

.nav-toggle-bars[b-d6q3ufqgmk]::before {
    top: -6px;
}

.nav-toggle-bars[b-d6q3ufqgmk]::after {
    top: 6px;
}

/* AC 8: the panel is an overlay, so it needs a backdrop that dismisses. Rendered only while open,
   which at compact is the only place it can be. */
.nav-panel-backdrop[b-d6q3ufqgmk] {
    position: fixed;
    inset: 0;
    z-index: 1150;
    background-color: rgba(0, 0, 0, 0.42);
}

.top-auth-wrap[b-d6q3ufqgmk] {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    min-width: 0;
}

.identity-card[b-d6q3ufqgmk] {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.18rem 0.3rem 0.18rem 0.22rem;
    border: 1px solid rgba(var(--mud-palette-primary-rgb), 0.2);
    border-radius: 10px;
    background:
        linear-gradient(155deg, rgba(var(--mud-palette-primary-rgb), 0.14), rgba(255, 255, 255, 0.02)),
        var(--mud-palette-surface);
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.06);
}

.identity-avatar[b-d6q3ufqgmk] {
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.74rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: white;
    background: linear-gradient(135deg, #1A3C3E, #2F6B6F);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
}

.identity-main[b-d6q3ufqgmk] {
    display: flex;
    flex-direction: column;
    line-height: 1.1;
    min-width: 0;
}

.identity-eyebrow[b-d6q3ufqgmk] {
    font-size: 0.56rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--mud-palette-text-secondary);
    line-height: 1;
}

.identity-name[b-d6q3ufqgmk] {
    font-size: 0.78rem;
    font-weight: 600;
    max-width: 13.5rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.15;
}

.identity-name-row[b-d6q3ufqgmk] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    min-width: 0;
}

.identity-settings-link[b-d6q3ufqgmk] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.2rem;
    height: 1.2rem;
    border-radius: 50%;
    color: var(--mud-palette-primary);
    text-decoration: none;
    flex-shrink: 0;
}

.identity-settings-link:hover[b-d6q3ufqgmk] {
    background-color: rgba(var(--mud-palette-primary-rgb), 0.1);
    color: var(--mud-palette-primary-darken);
    text-decoration: none;
}

/* Story 136.5: the base .role-badge/.role-admin/.role-manager/.role-authenticated rules moved to
   wwwroot/app.css so WorkspaceAdmin's People tab can reuse the same class names for its Admin/
   Member badge (AC 6) — CSS isolation scopes rules in THIS file to elements this component itself
   renders, so a class defined only here would never visually apply outside MainLayout. The
   compact-width overrides below stay here, scoped to the identity bar's own badge only. */

.session-action[b-d6q3ufqgmk] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 1.7rem;
    padding: 0 0.65rem;
    border-radius: 8px;
    border: 1px solid var(--mud-palette-lines-default);
    text-decoration: none;
    font-size: 0.74rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    background-color: var(--mud-palette-surface);
    transition: background-color 120ms ease, border-color 120ms ease;
}

.session-action:hover[b-d6q3ufqgmk] {
    text-decoration: none;
    color: var(--mud-palette-primary);
    border-color: var(--mud-palette-primary);
    background-color: rgba(var(--mud-palette-primary-rgb), 0.08);
}

.session-action-primary[b-d6q3ufqgmk] {
    color: white;
    border-color: var(--mud-palette-primary);
    background-color: var(--mud-palette-primary);
}

.session-action-primary:hover[b-d6q3ufqgmk] {
    color: white;
    border-color: var(--mud-palette-primary-darken);
    background-color: var(--mud-palette-primary-darken);
}

.brand-link[b-d6q3ufqgmk] {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    text-decoration: none;
    font-weight: 600;
    font-size: 0.95rem;
    color: inherit;
}

    .brand-link:hover[b-d6q3ufqgmk] {
        color: var(--mud-palette-primary);
        text-decoration: none;
    }

/* Story 135.25: the docked basket has to start exactly where this row starts, and it cannot be a
   descendant of `.page` (one `inert` attribute up there is what makes the compact sheet modal), so it
   cannot read a custom property declared here either. `anchor-name` publishes this row's box
   document-wide, which is the one mechanism that lets a fixed-position non-descendant track it. The
   panel falls back to --bb-sticky-chrome-offset where anchor positioning is unsupported.

   A constant genuinely cannot do this job: the token is calc(2.6rem + 54px), the scope bar's MINIMUM,
   and the bar is routinely taller. Measured on the hub: this row starts at 96px at 1440px and 1920px
   but at 128px from 1024px to 1280px, where the derived code node's explanation line takes a row of
   its own, and at 122px at 900px where DESIGN.md lets the whole bar wrap. */
.content-row[b-d6q3ufqgmk] {
    display: flex;
    flex: 1;
    overflow: hidden;
    position: relative;
    min-height: 0;
    anchor-name: --bb-content-row;
}

/* ── Scope bar ({components.scope-bar}) ─────────────────────────────────────────────────────────
   The third flex-shrink: 0 row of .page, between .top-bar and .content-row (AC 1). All of it is
   styled here rather than through Mud component parameters (AD-11). ScopeBar.razor renders its own
   elements, so they are reached with ::deep — .page is this component's own element, which is what
   anchors the scoped-CSS rewrite.

   Only MudBlazor palette variables are used, never literal hexes: MudThemeProvider swaps them for
   the dark palette, which is how every other rule in this file gets dark mode for free. */
.page[b-d6q3ufqgmk]  .scope-bar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-shrink: 0;
    min-height: 54px;
    padding: 9px 16px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background-image: linear-gradient(0deg, rgba(var(--mud-palette-primary-rgb), 0.08), transparent);
    background-color: var(--mud-palette-surface);
    z-index: 9;
}

/* Story 132.5: which of the bar's two forms is on screen. `display: contents` rather than a real
   box, so above the compact boundary the wide form's nodes and pill remain direct flex children of
   .scope-bar and every rule below applies to them exactly as it did before the wrapper existed. */
.page[b-d6q3ufqgmk]  .scope-bar-wide {
    display: contents;
}

.page[b-d6q3ufqgmk]  .scope-bar-compact {
    display: none;
}

/* AC 5: an unscoped route flattens the bar to the page ground and drops the accent wash. It stays
   in the DOM and keeps its height — the pill still has to say that this screen is not scoped. */
.page[b-d6q3ufqgmk]  .scope-bar--muted {
    background-image: none;
    background-color: var(--mud-palette-background);
}

.page[b-d6q3ufqgmk]  .scope-bar-overline {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.11em;
    line-height: 1.4;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    flex-shrink: 0;
}

/* AC 3: a plain flex container, so the Epic 134/135 derived code node is appended as one more
   child. Wraps rather than overflowing, because a node pushed out of the row is a node the user
   cannot reach. */
.page[b-d6q3ufqgmk]  .scope-bar-nodes {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    min-width: 0;
}

/* The pill is the answer to "what am I looking at" — inside the bar it is right-aligned and never
   dropped. Layout only: Story 136.12's onboarding rungs render the same {components.scope-pill}
   outside the bar, so the pill's own chrome and variant hues below are deliberately NOT nested under
   `.scope-bar` — one pill component, one appearance, wherever it is hosted. */
.page[b-d6q3ufqgmk]  .scope-bar .scope-pill {
    margin-left: auto;
    flex-shrink: 0;
}

.page[b-d6q3ufqgmk]  .scope-pill {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.6rem;
    border-radius: 9999px;
    /* Forced-colors floor (DESIGN.md § Forced Colors): a transparent border becomes a CanvasText
       edge under forced colors, so the pill stays a bounded object once its tint is dropped. */
    border: 1px solid transparent;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
    max-width: 100%;
}

.page[b-d6q3ufqgmk]  .scope-pill-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.page[b-d6q3ufqgmk]  .scope-pill--single {
    color: var(--mud-palette-success);
    background-color: rgba(var(--mud-palette-success-rgb), 0.094);
}

/* Story 133.1: a resolved scope that spans several connections. Distinct from `single` because
   "everything" and "one named source" are different answers to "what am I looking at".

   Amber, per DESIGN.md § Scope pill ("blended (amber, text {colors.warning-text})") and its
   published contrast targets. The TEXT is warning-darken, not warning: DESIGN.md is explicit that
   amber is a fill/border/dot hue only and that amber text must use the darker {colors.warning-text},
   which is what PaletteLight.WarningDarken is set to — and PaletteDark.WarningDarken carries its
   {colors.warning-text-dark} companion, so this one rule reads correctly in both palettes (D20).
   Info is reserved for syncing hints. */
.page[b-d6q3ufqgmk]  .scope-pill--blended {
    color: var(--mud-palette-warning-darken);
    background-color: rgba(var(--mud-palette-warning-rgb), 0.102);
}

.page[b-d6q3ufqgmk]  .scope-pill--needpick {
    color: var(--mud-palette-error);
    background-color: rgba(var(--mud-palette-error-rgb), 0.082);
}

.page[b-d6q3ufqgmk]  .scope-pill--muted {
    color: var(--mud-palette-text-secondary);
    background-color: transparent;
}

/* Story 136.12, onboarding rung 3. Info, which DESIGN.md § Scope pill reserves for syncing hints —
   the one hue not already spoken for by single/blended/needpick. The pulsing dot the same section
   specifies is drawn as a ::before rather than a glyph so it costs no accessible name: the pill's
   text already says "Syncing…", and a decorative dot announced twice is noise. */
.page[b-d6q3ufqgmk]  .scope-pill--syncing {
    color: var(--mud-palette-info);
    background-color: rgba(var(--mud-palette-info-rgb), 0.094);
    gap: 0.4rem;
}

.page[b-d6q3ufqgmk]  .scope-pill--syncing::before {
    content: "";
    flex: 0 0 auto;
    width: 0.4rem;
    height: 0.4rem;
    border-radius: 50%;
    background-color: currentColor;
    animation: bb-scope-pill-pulse-b-d6q3ufqgmk 1.6s ease-in-out infinite;
}

@keyframes bb-scope-pill-pulse-b-d6q3ufqgmk {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.25; }
}

.page[b-d6q3ufqgmk]  .scope-bar-pill-skeleton {
    margin-left: auto;
}

/* ── Work item basket trigger ({components.work-item-basket}, Story 135.9) ───────────────────────
   AC 1: the basket's control, living in the scope-bar row rather than a menu entry. Sits after the
   pill in DOM order; the pill's own margin-left: auto already claims the row's free space, so this
   lands immediately to its right without needing a second auto margin. */
/* Story 135.24, AC 4: geometry every treatment shares, plus the QUIET default. The shipped rule
   carried an unconditional filled-primary border/background/color here, which made the control as
   loud at 0 members as at 12; those three declarations moved into --filled below and nothing else
   about the rule changed. */
.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.2rem 0.65rem;
    border-radius: 9999px;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-size: 12px;
    font-weight: 640;
    line-height: 1.4;
    cursor: pointer;
}

.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-icon {
    width: 15px;
    height: 15px;
    flex: none;
}

.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger:hover {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* The three loud declarations that used to sit unconditionally on the base rule. Colour lives here
   and in the other treatment modifiers only: --compact carries none of its own, or a compact rule
   written later would silently override whichever treatment resolved. */
.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger--filled {
    border-color: var(--mud-palette-primary);
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger--filled:hover {
    background-color: var(--mud-palette-primary-darken);
    color: var(--mud-palette-primary-text);
}

/* Reads as pressed rather than merely available: accent outline over a soft accent wash, with the
   count filled so it is the loudest thing on the control while the panel is on screen. */
.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger--open {
    border-color: var(--mud-palette-primary);
    background-color: var(--mud-palette-primary-hover);
    color: var(--mud-palette-primary);
}

/* text-secondary, not text-disabled: this is the token the other two muted controls in this same
   row already spend (.scope-pill--muted :561, .scope-node--muted .scope-node-button :729), and the
   mockup mutes all three with one token (--ink-3 at work-item-basket.html:68, :70, :84). A control
   D19 deliberately keeps in the tab order must not be the one that reads as disabled. */
.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger--muted {
    border-color: var(--mud-palette-divider);
    background-color: transparent;
    color: var(--mud-palette-text-secondary);
    cursor: default;
}

/* Cancels the base :hover accent, which would otherwise offer the control back on pointer-over.
   The focus ring at :606 is deliberately NOT cancelled: the muted control keeps its tab stop (D19),
   so it has to stay findable with a keyboard. */
.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger--muted:hover {
    border-color: var(--mud-palette-divider);
    color: var(--mud-palette-text-secondary);
}

.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-count {
    font-size: 11px;
    font-weight: 700;
    padding: 0 0.4rem;
    border-radius: 9999px;
    background-color: var(--mud-palette-background-gray);
    color: var(--mud-palette-text-secondary);
}

.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger--filled .scope-bar-work-item-basket-count {
    background-color: rgba(255, 255, 255, 0.26);
    color: var(--mud-palette-primary-text);
}

.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger--open .scope-bar-work-item-basket-count {
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

.page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger--muted .scope-bar-work-item-basket-count {
    background-color: transparent;
    color: var(--mud-palette-text-secondary);
    border: 1px solid var(--mud-palette-divider);
}

/* ── Scope node ({components.scope-node}) ─────────────────────────────────────────────────────── */
.page[b-d6q3ufqgmk]  .scope-node {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    min-width: 0;
}

.page[b-d6q3ufqgmk]  .scope-node-role {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.11em;
    line-height: 1.4;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    flex-shrink: 0;
}

.page[b-d6q3ufqgmk]  .scope-node .scope-node-button {
    /* DESIGN.md {colors.control-border} exists to clear WCAG 1.4.11's 3:1 floor for an interactive
       control's boundary, which {colors.divider} does not. It is specified as a new MudTheme
       palette token; promoting it there would restyle every input in the app, so the bar derives an
       equivalent locally from text-secondary (which already clears 3:1 in both palettes) and the
       global token move is left to whichever change actually restyles inputs. */
    border: 1px solid color-mix(in srgb, var(--mud-palette-text-secondary) 72%, var(--mud-palette-surface));
    border-radius: 0.375rem;
    background-color: var(--mud-palette-surface);
    padding: 0.15rem 0.4rem 0.15rem 0.6rem;
    min-width: 0;
    text-transform: none;
}

/* {components.scope-node.border-active}. Applied at rest, not only on hover: a resolved node and an
   unresolved one must not be indistinguishable until the pointer happens to be over them. */
.page[b-d6q3ufqgmk]  .scope-node--active .scope-node-button {
    border-color: rgba(var(--mud-palette-primary-rgb), 0.25);
}

.page[b-d6q3ufqgmk]  .scope-node--active .scope-node-button:hover {
    border-color: rgba(var(--mud-palette-primary-rgb), 0.55);
    background-color: rgba(var(--mud-palette-primary-rgb), 0.06);
}

/* {components.scope-node.border-needpick} + {components.scope-node.ring-needpick}: a choice is
   outstanding and the screen cannot resolve its scope until it is made. Warning-hued, unlike the
   pill's needpick (error-hued) — DESIGN.md specifies them separately. */
.page[b-d6q3ufqgmk]  .scope-node--needpick .scope-node-button {
    border-color: var(--mud-palette-warning);
    box-shadow: 0 0 0 3px rgba(var(--mud-palette-warning-rgb), 0.1);
}

.page[b-d6q3ufqgmk]  .scope-node--needpick .scope-node-button:hover {
    background-color: rgba(var(--mud-palette-warning-rgb), 0.08);
}

/* D19: muted is a visual reduction only. The control keeps its border, its place in the tab order
   and its accessible name — it is never removed from the accessibility tree, so this must not
   become display:none or pointer-events:none on a focusable element. */
.page[b-d6q3ufqgmk]  .scope-node--muted .scope-node-button {
    color: var(--mud-palette-text-secondary);
    background-color: transparent;
    cursor: default;
}

.page[b-d6q3ufqgmk]  .scope-node-value {
    font-size: 13px;
    font-weight: 640;
    line-height: 1.4;
    max-width: 16rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Story 134.2 (AD-6), AC 6: the derived code node's dashed treatment. A distinct border style
   rather than another border-colour, because the derived-versus-overridden distinction (Story
   134.4 adds "overridden") must never be carried by colour alone.

   Story 134.4: the node gained a real <button> (its override affordance), so the dashed edge lives
   on that button like every other scope node's does. The standalone .scope-node-value border this
   rule used to carry is gone with it — the value now sits INSIDE the button, and keeping it would
   have drawn a second dashed box inside the first. */
.page[b-d6q3ufqgmk]  .scope-node--derived .scope-node-button {
    border-style: dashed;
}

/* Story 134.4 (AC 1), {components.scope-node.border-needpick}'s amber vocabulary reused: this one
   run has been redirected somewhere other than the derived target. Border + ring rather than a
   background fill, and a REINFORCEMENT only — the "overridden" text tag is what actually carries
   the state (Story 134.2 AC 6's colour-is-never-alone rule). Composes with the dashed border-style
   above rather than replacing it: the node is still the derived one, now overridden. */
.page[b-d6q3ufqgmk]  .scope-node--overridden .scope-node-button {
    border-color: var(--mud-palette-warning);
    box-shadow: 0 0 0 3px rgba(var(--mud-palette-warning-rgb), 0.1);
}

.page[b-d6q3ufqgmk]  .scope-node--overridden .scope-node-button:hover {
    background-color: rgba(var(--mud-palette-warning-rgb), 0.08);
}

/* Story 134.3, AC 3: the needs-look explanation line wraps onto its own row under the node's
   role/value/tag row rather than squeezing into it — scoped to the derived node only, so the other
   scope-node kinds (which never carry this element) keep their single-row layout. */
.page[b-d6q3ufqgmk]  .scope-node--derived {
    flex-wrap: wrap;
}

.page[b-d6q3ufqgmk]  .scope-node-explain {
    flex-basis: 100%;
    font-size: 11px;
    line-height: 1.4;
    color: var(--mud-palette-text-secondary);
}

/* {components.scope-node-tag}: the text tag naming what kind of value the node holds ("default"
   today; "derived"/"overridden" in Stories 134.3/134.4) — never colour alone. */
.page[b-d6q3ufqgmk]  .scope-node-tag {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    line-height: 1.4;
    padding: 0.05rem 0.35rem;
    border-radius: 9999px;
    color: var(--mud-palette-text-secondary);
    background-color: color-mix(in srgb, var(--mud-palette-text-secondary) 12%, transparent);
    /* Forced-colors floor (DESIGN.md § Forced Colors): a transparent border becomes a CanvasText
       edge only if the border exists in the first place — declaring it unconditionally here is what
       keeps the tag a bounded object once forced colors drops its fill. */
    border: 1px solid transparent;
    flex-shrink: 0;
}

/* ── Compact ({breakpoints.mode-compact}, below {breakpoints.sm}) ────────────────────────────────
   AD-13: this is the shell's existing 640.98px boundary, unchanged. Story 132.5 introduces no
   threshold of its own — see the {breakpoints.md} block below for the medium/full boundary. */
@media (max-width: 640.98px) {
    /* AC 8: the nav never pushes content. Closed it is not in the layout at all; open it is
       position:fixed, so .content-row holds only `main` either way and the page behind the panel
       does not reflow when it opens. */
    .sidebar[b-d6q3ufqgmk] {
        display: none;
    }

    .sidebar--panel-open[b-d6q3ufqgmk] {
        display: flex;
        flex-direction: column;
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        z-index: 1151;
        /* {spacing.nav-panel-width} */
        width: min(88vw, 320px);
        max-width: 100%;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        box-shadow: 4px 0 24px rgba(0, 0, 0, 0.32);
    }

    /* The panel takes focus on open; the ring belongs on the items inside it, not around the whole
       drawer. */
    .sidebar--panel-open:focus[b-d6q3ufqgmk] {
        outline: none;
    }

    .top-bar[b-d6q3ufqgmk] {
        height: auto;
        min-height: 3.5rem;
        flex-wrap: wrap;
        row-gap: 0.45rem;
        padding-top: 0.4rem;
        padding-bottom: 0.4rem;
    }

    .top-bar-spacer[b-d6q3ufqgmk] {
        display: none;
    }

    .brand-link[b-d6q3ufqgmk] {
        flex: 1 1 auto;
        min-width: 0;
    }

    /* AC 10. `order: 3` used to sit here, reordering the identity cluster with CSS. It is gone:
       DOM order now IS the visual order (skip link, hamburger, brand, app-bar actions, then the
       scope control in the band below), so focus order follows the source rather than being
       produced by a flex property that assistive technology and the tab sequence both ignore.
       `width: 100%` is layout, not order — it wraps the cluster onto its own line without moving
       its position in the sequence. */
    .top-auth-wrap[b-d6q3ufqgmk] {
        width: 100%;
        justify-content: space-between;
    }

    .identity-card[b-d6q3ufqgmk] {
        flex: 1 1 auto;
        min-width: 0;
    }

    .identity-eyebrow[b-d6q3ufqgmk] {
        display: none;
    }

    .identity-name[b-d6q3ufqgmk] {
        max-width: 100%;
    }

    .role-badge[b-d6q3ufqgmk] {
        font-size: 0.64rem;
        height: 1.35rem;
        padding: 0 0.4rem;
    }

    .session-action[b-d6q3ufqgmk] {
        flex-shrink: 0;
        /* {spacing.touch-target-min}: the hit area grows, the label does not. */
        min-height: 44px;
    }

    /* ── Touch floor for the app-bar actions (review finding M8) ─────────────────────────────────
       DESIGN.md § Touch Floor requires {spacing.touch-target-min} on both axes for EVERY interactive
       control at compact, not only the ones this story introduced. Three pre-existing controls in
       the top bar were below it and were missed on the first pass: the notification bell, the theme
       toggle (both Size.Medium MudIconButtons, ~40px) and the identity card's settings cog (1.2rem,
       ~19px — by far the worst).

       In every case the BOX grows and the glyph does not: the MudIcon inside keeps Size.Small /
       1.2rem, so what changes is the area a thumb can land on, per DESIGN.md's "grow the hit area,
       not the visual pill". */
    .top-bar[b-d6q3ufqgmk]  .mud-icon-button {
        min-width: 44px;
        min-height: 44px;
    }

    .identity-settings-link[b-d6q3ufqgmk] {
        width: 44px;
        height: 44px;
        /* Sized in place rather than with an overlapping pseudo-element: a 44px box centred on a
           19px cog would extend past the identity card and swallow taps meant for Sign Out, which
           trades one target-size failure for a worse mis-tap. */
        flex-shrink: 0;
    }

    /* {spacing.content-pad-compact}. The `px-4` utility on the article is 16px and is what these
       override; the desktop branch below overrides it in the other direction. */
    article[b-d6q3ufqgmk] {
        padding-left: 14px !important;
        padding-right: 14px !important;
    }

    /* AC 2: the band becomes one full-width control. The bar keeps its landmark, its position and
       its bottom rule — only its contents collapse. {spacing.scope-summary-height} is the floor. */
    .page[b-d6q3ufqgmk]  .scope-bar {
        gap: 0;
        min-height: 48px;
        padding: 2px 14px;
    }

    /* Still the region's aria-labelledby target, which is why it is hidden rather than removed:
       a directly-referenced element contributes its text to the accessible name even when it is
       display:none, so the landmark keeps the name "Scope" that the sheet's title also carries. */
    .page[b-d6q3ufqgmk]  .scope-bar-overline {
        display: none;
    }

    .page[b-d6q3ufqgmk]  .scope-bar-wide {
        display: none;
    }

    /* Story 135.30, AC 2: {spacing.touch-target-gap} between the summary and the trigger, from the
       mockup's .cband (work-item-basket.html:242). This wrapper declared no gap of its own, and gap is
       not inherited - .scope-bar's `gap: 0` above reaches its own children, not these two - so the
       summary and the basket sat flush. */
    .page[b-d6q3ufqgmk]  .scope-bar-compact {
        display: flex;
        align-items: center;
        gap: 8px;
        width: 100%;
        min-width: 0;
    }

    /* Story 135.30, AC 2: the compact trigger is a 44px square carrying the icon and the count, and it
       SHEDS its visible label (.cbsk, work-item-basket.html:251). The --compact modifier has carried no
       rule since Story 135.24 minted it; this creates the block.

       The restriction is a MEASUREMENT, which is the only thing that makes it a legitimate NFR8(a)
       deviation. At 360px the band has 332px usable (360 minus 2 x {spacing.content-pad-compact}, which
       .scope-bar's own `padding: 2px 14px` above confirms independently of the drawing). A LABELLED
       basket control is about 180px, which leaves the scope summary about 144px - below the floor its
       own degradation order (drop the role summary, truncate the workspace name to 8 characters,
       truncate the pill) is designed to bottom out at. EXPERIENCE.md calls that summary "one full-width
       scope control" and it is the primary control in this band, so the basket is what gives.

       GEOMETRY ONLY, which Story 135.24's Task 9 required in as many words. Its four treatment
       modifiers sit at this same specificity and EARLIER in the file, so any colour declared here would
       beat whichever treatment resolved - and the muted state would stop reading as muted at compact,
       with every treatment test still passing. */
    .page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger--compact {
        min-width: 44px;
        min-height: 44px;
        justify-content: center;
        padding: 0 8px;
        gap: 5px;
        flex: none;
    }

    .page[b-d6q3ufqgmk]  .scope-bar-work-item-basket-trigger--compact .scope-bar-work-item-basket-trigger-label {
        display: none;
    }

    /* AC 3, degradation step 3. The wide bar pins the pill at `flex-shrink: 0` because there is
       always room for it in a full-width row; inside the collapsed control there is not, and a pill
       that refuses to shrink would push the workspace name below its 8ch floor — inverting the
       specified order. It shrinks last (weight 1 against the name's 20 and the role's 200), keeps
       its variant colour, and still never wraps: `.scope-pill-text` is nowrap + ellipsis. */
    .page[b-d6q3ufqgmk]  .scope-bar-compact .scope-pill {
        flex-shrink: 1;
        min-width: 0;
    }
}

@media (max-width: 480px) {
    .role-badge[b-d6q3ufqgmk] {
        display: none;
    }

    .page[b-d6q3ufqgmk]  .scope-node-value {
        max-width: 9rem;
    }
}

/* ── Medium and full ({breakpoints.sm} and up) ───────────────────────────────────────────────────
   What both wide modes share: the rail is present and in flow, and there is no hamburger. */
@media (min-width: 641px) {
    .nav-toggle[b-d6q3ufqgmk] {
        display: none;
    }

    .sidebar[b-d6q3ufqgmk] {
        width: 210px;
        flex-shrink: 0;
        overflow-y: auto;
        transition: none;
    }

    .sidebar:not(.sidebar--hydrated)[b-d6q3ufqgmk] {
        visibility: hidden;
    }

    .sidebar.sidebar--hydrated[b-d6q3ufqgmk] {
        transition: width 250ms ease;
    }

    .sidebar--collapsed[b-d6q3ufqgmk] {
        width: 3.25rem;
    }

    article[b-d6q3ufqgmk] {
        padding-left: 1rem !important;
        padding-right: 1rem !important;
    }
}

/* ── Medium ({breakpoints.mode-medium}: {breakpoints.sm} up to below {breakpoints.md}) ───────────
   AC 1 / AD-13: the third mode, expressed against the two boundaries DESIGN.md already names
   ({breakpoints.sm} 641px and {breakpoints.md} 1024px). Nothing new is introduced here — 1024px was
   specified as a token and simply had no rule consuming it yet, which is why the live CSS had only
   two modes. The shell-level delta between the two wide modes is the one DESIGN.md states: the bar
   is "allowed to wrap to a second row" at medium and is a "single-row scope bar" at full. */
@media (min-width: 641px) and (max-width: 1023.98px) {
    .page[b-d6q3ufqgmk]  .scope-bar {
        flex-wrap: wrap;
        row-gap: 0.4rem;
    }

    /* Story 135.25, AC 3: no reservation in this band — at 1024px a 424px dock minus the 210px rail
       leaves 390px of content and the hub splits that again, and the band runs down to 641px where a
       dock would leave 7px. The boundary between the two wide presentations nonetheless stays
       {breakpoints.md} rather than moving up to where that arithmetic gets comfortable: DESIGN.md
       declares two boundaries and carries no larger token, and the gate that would have flipped the
       presentation on measured hub width was removed deliberately (AC 8) — ship the dock, adapt on
       feedback.

       The basket is laid OVER the content row in this band instead, and this wash is what makes that
       read as deliberate foreground rather than a slab dropped on the page (mockup
       work-item-basket.html:98-99, which puts it on .behind::after — the page area only, never the
       chrome above it).

       pointer-events: none is load-bearing, not tidiness: the surface underneath stays fully usable,
       which is the same "any surface behind it can fill it" contract the dock delivers by geometry. */
    .content-row--basket-open[b-d6q3ufqgmk]::after {
        content: "";
        position: absolute;
        inset: 0;
        /* Neither .content-row nor `main` establishes a stacking context, so without this the wash
           sits in the z-index:auto layer and every page descendant declaring a positive z-index
           paints OVER it at full opacity - a wash reaching only the gaps between the surfaces it is
           supposed to background. Measured on the hub at 900px: .bb-hub-nav-resize is 5, and
           .bb-workflow-map-hero and .bb-workflow-map-cards are 1, so the map's hero and every card
           stayed unwashed. 30 clears those and stays far below the panel's own 1140. */
        z-index: 30;
        pointer-events: none;
        background-color: var(--mud-palette-text-primary);
        opacity: 0.05;
    }
}

/* ── Full ({breakpoints.mode-full}: {breakpoints.md} and up) — the primary target. ─────────────── */
@media (min-width: 1024px) {
    .page[b-d6q3ufqgmk]  .scope-bar {
        flex-wrap: nowrap;
    }

    /* Story 135.25, AC 2: the dock's width reservation. A flex reservation rather than a third grid
       track — `main` is flex: 1 and absorbs it, while .sidebar keeps its own width, its 250ms
       collapse transition and its compact position: fixed override untouched. The panel itself is
       out of flow and pinned to this row's box, so a real third track would be reserved for an
       element that is not in it.

       The transition IS the design argument (mockup :89-90: "that reflow IS the design argument, so
       it must be legible"), which is why it is on the reservation and not on the panel. */
    .content-row[b-d6q3ufqgmk] {
        transition: padding-right 0.22s ease;
    }

    .content-row--basket-open[b-d6q3ufqgmk] {
        padding-right: var(--bb-basket-width);
    }
}

/* ── Sortable table headers (Story 136.13) ──────────────────────────────────────────────────────
   The sort control is a span carrying role="button", not a native <button>, so nothing gives it a
   focus ring for free — it reuses the nav toggle's outline treatment above. The scroll region gets
   the same ring because tabindex="0" makes it a real tab stop. Both live here rather than in a
   component stylesheet so the one forced-colors block below stays the only one in the shell. */
.page[b-d6q3ufqgmk]  .bb-sortable-header {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    cursor: pointer;
    color: inherit;
}

.page[b-d6q3ufqgmk]  .bb-sortable-header:focus-visible,
.page[b-d6q3ufqgmk]  .bb-table-scroll:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.page[b-d6q3ufqgmk]  .bb-sortable-header-icon--idle {
    opacity: 0.35;
}

/* ── Forced colors (DESIGN.md § Forced Colors, D20) ─────────────────────────────────────────────
   BacklogBouncer runs on internal Windows 11 machines, so `forced-colors: active` is a real runtime.
   The OS drops fills, which is everything the scope pill uses to distinguish its variants, and
   replaces the palette, which takes the {colors.primary} focus ring with it.

   The pill's `border: 1px solid transparent` is declared unconditionally above (a transparent border
   becomes a CanvasText edge only if the border exists in the first place — adding it inside this
   query would be too late, the box would already have no border box to colour). What is left for
   here is the focus rings, which must come from `Highlight` rather than the palette. Epic 132
   introduces no tag of its own; the pill is the only tinted object it adds. */
@media (forced-colors: active) {
    .skip-link:focus[b-d6q3ufqgmk],
    .skip-link:focus-visible[b-d6q3ufqgmk] {
        outline: 2px solid Highlight;
        outline-offset: 2px;
    }

    .page[b-d6q3ufqgmk]  .scope-node .scope-node-button:focus-visible {
        outline: 2px solid Highlight;
        outline-offset: 2px;
    }

    /* The needpick node's meaning is carried by a warning-hued border plus a soft ring, and both
       are dropped here. Restore the boundary from the system palette so "a choice is outstanding"
       is still a visible difference rather than an invisible one. */
    .page[b-d6q3ufqgmk]  .scope-node--needpick .scope-node-button {
        border: 2px solid Highlight;
        box-shadow: none;
    }

    /* Story 134.2 (AD-6), AC 6: the dashed derived treatment is a border-style distinction, which
       forced colors leaves alone — but the colour it dashes IN is the palette-derived one above, so
       it still needs a real system-palette edge here, same as every other scope-node border. */
    .page[b-d6q3ufqgmk]  .scope-node--derived .scope-node-button {
        border-color: CanvasText;
    }

    /* Story 134.4: forced colors drops the amber border AND the ring, which would leave the
       overridden node visually identical to the plain derived one. Highlight is the same system
       token the needpick block above falls back to, and the dashed border-style survives on its
       own — so the two stay distinguishable even before the text tag is read. */
    .page[b-d6q3ufqgmk]  .scope-node--overridden .scope-node-button {
        border: 2px dashed Highlight;
        box-shadow: none;
    }

    .page[b-d6q3ufqgmk]  .scope-node-tag {
        border: 1px solid Highlight;
    }

    /* Story 136.12. The syncing pill's dot is drawn with `background-color: currentColor`, and
       forced colors resolves currentColor to the system text colour on a ::before with no own
       colour — which can leave the dot indistinguishable from the pill's own text run. Pin it to
       Highlight so "syncing" stays a visible mark, and give the pill the same bounded edge every
       other tinted object in this block gets once its fill is dropped. */
    .page[b-d6q3ufqgmk]  .scope-pill--syncing::before {
        background-color: Highlight;
    }

    .page[b-d6q3ufqgmk]  .scope-pill--syncing {
        border-color: CanvasText;
    }

    /* Story 132.5. The compact overlays lose the two things that separate them from the page behind
       them — the panel's shadow and the backdrop's alpha fill are both dropped — so the panel needs
       a real edge from the system palette or it dissolves into the content it is covering. */
    .nav-toggle:focus-visible[b-d6q3ufqgmk] {
        outline: 2px solid Highlight;
        outline-offset: 2px;
    }

    .sidebar--panel-open[b-d6q3ufqgmk] {
        border-right: 1px solid CanvasText;
    }

    /* Story 136.13: same reason as the nav toggle above — the palette-derived ring is swapped out,
       and the sort control has no native focus treatment to fall back to. */
    .page[b-d6q3ufqgmk]  .bb-sortable-header:focus-visible,
    .page[b-d6q3ufqgmk]  .bb-table-scroll:focus-visible {
        outline: 2px solid Highlight;
        outline-offset: 2px;
    }
}

/* ── Reduced motion (DESIGN.md § Do / Don't: "Honor prefers-reduced-motion for pulse/fills/meter")
   Two animated elements now: the scope bar's resolving skeleton, and Story 136.12's syncing pill dot.
   The bar still says "resolving" and the pill still says "Syncing…" — both simply stop moving. */
@media (prefers-reduced-motion: reduce) {
    .page[b-d6q3ufqgmk]  .scope-bar .mud-skeleton,
    .page[b-d6q3ufqgmk]  .scope-bar .mud-skeleton::after {
        animation: none;
    }

    /* The dot itself stays — it is part of what the syncing variant looks like — and only stops
       pulsing. Removing it would make the reduced-motion rendering a different pill. */
    .page[b-d6q3ufqgmk]  .scope-pill--syncing::before {
        animation: none;
    }

    .sidebar.sidebar--hydrated[b-d6q3ufqgmk] {
        transition: none;
    }

    /* Story 135.25: the dock's reflow arrives instantly instead of animating. The reflow is still
       the mechanism — it is only the 0.22s of motion that is dropped (mockup :100 does exactly
       this). */
    .content-row[b-d6q3ufqgmk] {
        transition: none;
    }
}

#blazor-error-ui[b-d6q3ufqgmk] {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-d6q3ufqgmk] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
/* /Components/Layout/NavMenu.razor.rz.scp.css */
/* Story 132.5: the compact toggler moved to MainLayout's top bar (`.nav-toggle`), so `.navbar-toggler`
   and its `position: absolute` overlay of the top-right corner are gone from this component. */

/* The rail is a column at every width now that the toggler is not a positioned sibling of it —
   previously this only applied above {breakpoints.sm}, which left the compact panel with no
   flex context for `.nav-scrollable`'s `flex: 1` to scroll inside. */
.nav-container[b-wl10s2io04] {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

.nav-mud-icon[b-wl10s2io04] {
    display: inline-flex;
    align-items: center;
    margin-right: 0.5rem;
    vertical-align: middle;
    /* Follows the item's own state colour rather than pinning white, so idle/hover/active read as
       one object under {components.nav-rail}'s on-dark set. */
    color: inherit;
}

/* ── {components.nav-rail} on-dark token set (DESIGN.md decision 6) ───────────────────────────────
   The rail keeps its own dark teal gradient ground in BOTH themes, so its foreground is the on-dark
   set and its accent is {colors.primary-dark} — never {colors.primary}, which is tuned for a
   {colors.surface} ground. AD-13 names these rail-chrome tokens as its single explicit exception to
   "colour lives in the MudTheme": they are declared here, in scoped CSS, and not in
   Theme/BacklogBouncerTheme.cs.

   Two values DESIGN.md does not specify, filled here and recorded in the story's Completion Notes:
   `--nav-on-dark-line` (there is no on-dark {colors.divider}; #E0E0E0 would wash out on the dark
   ground, so this follows the rail's own rgba idiom from DESIGN.md:259) and the focus ring, which
   EXPERIENCE.md:364 specifies as {colors.primary} — the same light-hue-on-dark-ground problem, so
   the rail uses {colors.primary-dark} per DESIGN.md:403. */
.nav-container[b-wl10s2io04] {
    --nav-primary-dark: #48B8BC;
    --nav-on-dark: #E8EEEE;
    --nav-on-dark-muted: #9FB0B0;
    --nav-on-dark-wash: rgba(72, 184, 188, 0.14);
    --nav-on-dark-hover: rgba(255, 255, 255, 0.06);
    --nav-on-dark-line: rgba(255, 255, 255, 0.06);
}

/* {typography.overline}: 10px / 700 / 0.11em uppercase. Shared by all three heading tiers so the
   ramp is size and weight, not three unrelated treatments. */
.nav-zone-label[b-wl10s2io04],
.nav-section-label[b-wl10s2io04],
.nav-subsection-label[b-wl10s2io04] {
    font-family: inherit;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.11em;
    line-height: 1.4;
    user-select: none;
}

/* Tier 1 — the zone label. Only the platform zone still has one; the scoped zone's was removed
   because the scope bar already states the active workspace. It reads in the muted foreground: the
   accent variant went with the scoped label, and the accent is now reserved for the selected item.
   There is no `.nav-zone-label-sub` rule any more — both spans that used it are gone. */
.nav-zone-label[b-wl10s2io04] {
    font-size: 10px;
    padding: 0.6rem 0.85rem 0.1rem;
    display: flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: wrap;
    color: var(--nav-on-dark-muted);
}

/* Neither zone paints an edge or a wash. {components.nav-rail.scoped-zone-edge} used to paint both on
   the scoped zone, drawn from the same `--nav-primary-dark` / `--nav-on-dark-wash` pair as
   `.nav-item ::deep a.active` below, which put two identical "you are here" markers in that one block
   and left the selected item nothing to stand out against. `.nav-section-divider` is the zone boundary
   now; the active item is the only highlighted thing in the rail. Do not restore an edge here. */

/* Tier 2 — the group label. Keeps the existing class so the collapsed-rail and compact rules that
   already target it keep applying. */
.nav-section-label[b-wl10s2io04] {
    color: var(--nav-on-dark-muted);
    font-size: 0.62rem;
    letter-spacing: 0.12em;
    padding: 0.55rem 0.85rem 0.25rem;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}

/* Tier 3 — the sub-group label, indented under its group and one step quieter. */
.nav-subsection-label[b-wl10s2io04] {
    color: var(--nav-on-dark-muted);
    font-size: 10px;
    letter-spacing: 0.09em;
    padding: 0.45rem 0.85rem 0.1rem 1.25rem;
    opacity: 0.72;
}

.nav-section-divider[b-wl10s2io04] {
    height: 1px;
    margin: 0.5rem 0.6rem 0.25rem;
    background-color: var(--nav-on-dark-line);
}

.nav-item[b-wl10s2io04] {
    font-size: 0.82rem;
    padding-bottom: 0.15rem;
    padding-left: 0.5rem !important;
    padding-right: 0.5rem !important;
}

    .nav-item:first-of-type[b-wl10s2io04] {
        padding-top: 0.4rem;
    }

    .nav-item:last-of-type[b-wl10s2io04] {
        padding-bottom: 0.4rem;
    }

    /* {components.nav-rail.item-idle}. The 3px transparent left border is reserved here rather than
       added on the active state, so activating an item does not shift its label sideways. */
    .nav-item[b-wl10s2io04]  .nav-link {
        color: var(--nav-on-dark-muted);
        background: none;
        border: none;
        border-left: 3px solid transparent;
        border-radius: 4px;
        height: 2rem;
        display: flex;
        align-items: center;
        /* Align icon+label to the start. <button class="nav-link"> (the "New workspace"
           action) inherits the UA default justify-content:center for buttons, which
           centered its content and made it read as an indented sub-item; anchors compute
           normal (=flex-start) so this is a no-op for them. */
        justify-content: flex-start;
        line-height: 2rem;
        width: 100%;
        padding-left: 0.6rem;
    }

/* {components.nav-rail.item-active}: on-dark text, a 3px {colors.primary-dark} left edge, and the
   accent wash. */
.nav-item[b-wl10s2io04]  a.active {
    background-color: var(--nav-on-dark-wash);
    border-left-color: var(--nav-primary-dark);
    color: var(--nav-on-dark);
    font-weight: 600;
}

/* {components.nav-rail.item-hover}: a faint white wash and NO edge — the edge is what says "you are
   here", so hover must not borrow it. */
.nav-item[b-wl10s2io04]  .nav-link:hover {
    background-color: var(--nav-on-dark-hover);
    color: var(--nav-on-dark);
}

/* EXPERIENCE.md:364 rings focus in {colors.primary}, which is tuned for {colors.surface}; on the
   permanently-dark rail that hue does not separate from the ground, so the rail rings in
   {colors.primary-dark} (DESIGN.md:403). Inset because the item is full-bleed to the rail edge. */
.nav-item[b-wl10s2io04]  .nav-link:focus-visible {
    outline: 2px solid var(--nav-primary-dark);
    outline-offset: -2px;
}

/* DESIGN.md § Forced Colors has no {components.nav-rail} entry. The active item's wash does not
   survive `forced-colors: active`, which would leave no signal for which page you are on — the same
   failure DESIGN.md:473 fixes for the hub tree's selected row, so the same remedy: a Highlight left
   edge (a border, which forced colors keeps) plus a Highlight focus ring per :476. */
@media (forced-colors: active) {
    .nav-item[b-wl10s2io04]  a.active {
        border-left-color: Highlight;
    }

    .nav-item[b-wl10s2io04]  .nav-link:focus-visible {
        outline-color: Highlight;
    }
}

/* Story 132.5: always rendered and always scrollable. The old `display: none` / `.is-open`
   `display: block` pair was the compact nav's entire show/hide mechanism, and it made the open nav
   an in-flow block inside `.content-row` — which pushed the page content down rather than overlaying
   it (AC 8). Visibility is now the shell's: `.sidebar` is display:none at compact until the panel is
   opened, and position:fixed while it is. */
.nav-scrollable[b-wl10s2io04] {
    display: block;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* Collapse toggle button — desktop only */
.nav-collapse-btn[b-wl10s2io04] {
    display: none;
    width: 100%;
    padding: 0;
    background: none;
    border: none;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    cursor: pointer;
    height: 2rem;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.nav-collapse-btn:hover[b-wl10s2io04] {
    background-color: rgba(255, 255, 255, 0.08);
}

.nav-collapse-icon[b-wl10s2io04] {
    display: inline-block;
    width: 1.1rem;
    height: 1.1rem;
    background-size: cover;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3E%3C/svg%3E");
    transition: transform 250ms ease;
}

.nav-label[b-wl10s2io04] {
    margin-left: 0.4rem;
    display: inline-flex;
    flex-direction: column;
    line-height: 1.15;
}

/* Org-name subtitle under the project-name in the Project Settings nav links (Story 84.6). */
.nav-sublabel[b-wl10s2io04] {
    font-size: 0.72rem;
    opacity: 0.7;
    margin-top: 0.05rem;
}

/* ── Compact ({breakpoints.mode-compact}) ────────────────────────────────────────────────────────
   {components.nav-panel.item-min-height}: every item grows to the touch floor. The hit area is the
   full-width row, which is already the visual object, so nothing has to be inflated to reach it. */
@media (max-width: 640.98px) {
    .nav-item[b-wl10s2io04]  .nav-link {
        height: 44px;
        line-height: 44px;
    }

    .nav-item[b-wl10s2io04] {
        padding-bottom: 4px;
    }
}

/* ── Medium and full ({breakpoints.sm} and up) ───────────────────────────────────────────────────
   Everything about the icon-only collapse lives in here, deliberately. AC 8: there is no icon-only
   state at compact — the panel is either open or closed. The collapse toggle was already
   `display: none` below this boundary, but the `.nav-container--collapsed` rules it drives were NOT
   media-gated, and the collapsed choice is persisted in localStorage: a user who collapsed the rail
   at a desk and then opened the app on a phone would have got an icon-only overlay panel with no
   labels and no control anywhere to restore them. */
@media (min-width: 641px) {
    .nav-collapse-btn[b-wl10s2io04] {
        display: flex;
    }

    .nav-container--collapsed .nav-collapse-icon[b-wl10s2io04] {
        transform: rotate(180deg);
    }

    /* In collapsed mode the headings would just be visual noise — hide them but keep the divider
       line for visual rhythm. All three tiers collapse the same way: at 3.25rem even a one-word
       heading like "Platform-wide" cannot be read against an icon-only rail. */
    .nav-container--collapsed .nav-section-label[b-wl10s2io04],
    .nav-container--collapsed .nav-zone-label[b-wl10s2io04],
    .nav-container--collapsed .nav-subsection-label[b-wl10s2io04] {
        border-top: 1px solid rgba(255, 255, 255, 0.12);
        padding: 0;
        height: 0.4rem;
        margin-top: 0.25rem;
        overflow: hidden;
        color: transparent;
    }

    .nav-container--collapsed .nav-label[b-wl10s2io04] {
        display: none;
    }

    .nav-container--collapsed .nav-item[b-wl10s2io04] {
        padding-left: 0 !important;
        padding-right: 0 !important;
    }

    .nav-container--collapsed .bi[b-wl10s2io04] {
        margin-right: 0;
    }

    .nav-container--collapsed .nav-item[b-wl10s2io04]  .nav-link {
        justify-content: center;
        padding-left: 0;
        padding-right: 0;
    }
}
/* /Components/Pages/ActivityFeed.razor.rz.scp.css */
/* Story 136.11, AC 7. The chip strip follows WorkspaceAdmin's compact tab-strip idiom (Story
   136.3): a plain native-scrolling region with an overflow-only edge fade that activity-chip-strip.js
   toggles once it has confirmed the strip actually overflows. Scroll-snap is new here — the strip is
   a short list of equal-weight filters, so snapping each chip to the leading edge keeps a partially
   scrolled strip from stranding a half-visible chip. */
.bb-chip-strip-wrapper[b-u10za1e8ti] {
    position: relative;
    margin-bottom: 1rem;
}

.bb-chip-strip[b-u10za1e8ti] {
    display: flex;
    flex-wrap: nowrap;
    gap: 0.5rem;
    overflow-x: auto;
    scrollbar-width: thin;
    scroll-snap-type: x proximity;
    padding-bottom: 0.25rem;
}

.bb-chip-strip[b-u10za1e8ti]::-webkit-scrollbar {
    height: 6px;
}

.bb-chip-strip[b-u10za1e8ti]::-webkit-scrollbar-thumb {
    background-color: var(--mud-palette-text-disabled);
    border-radius: 3px;
}

.bb-chip[b-u10za1e8ti] {
    flex: 0 0 auto;
    scroll-snap-align: start;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    background: transparent;
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-size: 0.82rem;
    padding: 0.25rem 0.85rem;
    cursor: pointer;
    white-space: nowrap;
}

.bb-chip:hover[b-u10za1e8ti] {
    background-color: var(--mud-palette-action-default-hover);
}

.bb-chip--active[b-u10za1e8ti] {
    background-color: var(--mud-palette-primary);
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

.bb-chip:focus-visible[b-u10za1e8ti] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.bb-chip-strip-wrapper[b-u10za1e8ti]::before,
.bb-chip-strip-wrapper[b-u10za1e8ti]::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0.25rem;
    width: 24px;
    pointer-events: none;
    z-index: 1;
    opacity: 0;
    transition: opacity 0.15s ease;
}

.bb-chip-strip-wrapper--scrollable[b-u10za1e8ti]::before,
.bb-chip-strip-wrapper--scrollable[b-u10za1e8ti]::after {
    opacity: 1;
}

.bb-chip-strip-wrapper[b-u10za1e8ti]::before {
    left: 0;
    background: linear-gradient(to right, var(--mud-palette-surface), transparent);
}

.bb-chip-strip-wrapper[b-u10za1e8ti]::after {
    right: 0;
    background: linear-gradient(to left, var(--mud-palette-surface), transparent);
}

/* The feed is its own scroll container so the day headers below have something to stick to — a
   header sticking to the viewport would scroll out from under the page shell instead. */
.bb-activity-feed[b-u10za1e8ti] {
    max-height: 70vh;
    overflow-y: auto;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius);
}

.bb-activity-day__header[b-u10za1e8ti] {
    position: sticky;
    top: 0;
    z-index: 2;
    margin: 0;
    padding: 0.4rem 0.85rem;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--mud-palette-text-secondary);
    /* Must stay OPAQUE, or rows scroll under the header text and it becomes illegible. Uses the
       same surface token as the edge-fade gradients above: MudBlazor emits
       --mud-palette-background-gray (American spelling), so the --mud-palette-background-grey the
       retired pages used resolves to nothing and falls back to transparent. */
    background-color: var(--mud-palette-surface);
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.bb-activity-row[b-u10za1e8ti] {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.2fr) auto;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    border: 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    padding: 0.6rem 0.85rem;
    cursor: pointer;
}

.bb-activity-row:hover[b-u10za1e8ti] {
    background-color: var(--mud-palette-action-default-hover);
}

.bb-activity-row:focus-visible[b-u10za1e8ti] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

.bb-activity-row__icon[b-u10za1e8ti] {
    display: inline-flex;
    align-items: center;
    color: var(--mud-palette-text-secondary);
}

.bb-activity-row__title[b-u10za1e8ti] {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bb-activity-row__result[b-u10za1e8ti] {
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bb-activity-row__meta[b-u10za1e8ti] {
    display: flex;
    gap: 0.5rem;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* AC 7's compact stack: type icon plus title, then the one-line result, then timestamp and
   connection name. */
@media (max-width: 720px) {
    .bb-activity-row[b-u10za1e8ti] {
        grid-template-columns: auto minmax(0, 1fr);
        row-gap: 0.2rem;
    }

    .bb-activity-row__result[b-u10za1e8ti],
    .bb-activity-row__meta[b-u10za1e8ti] {
        grid-column: 2;
        white-space: normal;
    }

    .bb-activity-row__meta[b-u10za1e8ti] {
        flex-wrap: wrap;
    }
}
/* /Components/Pages/Admin/WorkspaceAdmin.razor.rz.scp.css */
/* Configuration tab's section list (Epic 124 redesign) — sized and spaced to match the main
   NavMenu sidebar's density (see NavMenu.razor.css: 0.82rem items, 2rem row height) rather than
   MudList's default Body1-sized rows, which read as oversized next to the rest of the app chrome. */
.bb-config-section-list[b-6vguul5u3h]  .mud-list-item {
    min-height: 2rem;
    padding-top: 0.25rem;
    padding-bottom: 0.25rem;
}

.bb-config-section-list[b-6vguul5u3h]  .mud-list-item-text p {
    font-size: 0.82rem;
    line-height: 1.25rem;
}

/* Compact horizontally-scrollable tab strip (Story 136.3, Task 5; review fix B2/S1). The real
   clipping boundary MudTabs measures against is `.mud-tabs-tabbar-content` (NOT its
   `.mud-tabs-tabbar-wrapper` ancestor, which sizes to its own content and never overflows
   itself) — targeting the wrapper made the strip look styled but never actually scroll, silently
   stranding every tab past the two that fit. MudBlazor's own scroll buttons are kept (not hidden)
   as a fallback now that native scrolling on the correct element actually works; the edge-fade
   affordance below is sized to the tab-bar row itself, not the whole tab strip, and only shows
   once workspace-admin-tab-strip.js has confirmed the content actually overflows
   (`.bb-tab-strip-wrapper--scrollable`), so it never floats over panel content or implies
   scrollability where there is none. */
.bb-tab-strip-wrapper[b-6vguul5u3h] {
    position: relative;
}

.bb-tab-strip-wrapper[b-6vguul5u3h]  .mud-tabs-tabbar-content {
    overflow-x: auto !important;
    scrollbar-width: thin;
}

.bb-tab-strip-wrapper[b-6vguul5u3h]  .mud-tabs-tabbar-content::-webkit-scrollbar {
    height: 6px;
}

.bb-tab-strip-wrapper[b-6vguul5u3h]  .mud-tabs-tabbar-content::-webkit-scrollbar-thumb {
    background-color: var(--mud-palette-text-disabled);
    border-radius: 3px;
}

.bb-tab-strip-wrapper[b-6vguul5u3h]::before,
.bb-tab-strip-wrapper[b-6vguul5u3h]::after {
    content: "";
    position: absolute;
    top: 0;
    height: 36px;
    width: 24px;
    pointer-events: none;
    z-index: 1;
    opacity: 0;
    transition: opacity 0.15s ease;
}

.bb-tab-strip-wrapper--scrollable[b-6vguul5u3h]::before,
.bb-tab-strip-wrapper--scrollable[b-6vguul5u3h]::after {
    opacity: 1;
}

.bb-tab-strip-wrapper[b-6vguul5u3h]::before {
    left: 0;
    background: linear-gradient(to right, var(--mud-palette-surface), transparent);
}

.bb-tab-strip-wrapper[b-6vguul5u3h]::after {
    right: 0;
    background: linear-gradient(to left, var(--mud-palette-surface), transparent);
}

/* Overview tab identity header monogram (Story 136.3, Task 2). */
.bb-workspace-monogram[b-6vguul5u3h] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    font-weight: 600;
    font-size: 1.1rem;
    flex-shrink: 0;
}

/* Story 136.5, AC 8: at compact width the workspace-membership table becomes stacked cards
   (name, email, role badge) instead of a horizontally-scrolled table — the one table on this page
   called out for that treatment; no other table gets it as part of this story. 640.98px is the
   app's existing compact boundary (MainLayout.razor.css / NavMenu.razor.css's
   CompactModeMediaQuery), not a new one invented for this story. Both wrapper divs are literal
   HTML authored directly in WorkspaceAdmin.razor, so this file's CSS-isolation scope attribute
   lands on them without needing ::deep. */
.bb-member-cards[b-6vguul5u3h] {
    display: none;
}

@media (max-width: 640.98px) {
    .bb-members-table-wrap[b-6vguul5u3h] {
        display: none;
    }

    .bb-member-cards[b-6vguul5u3h] {
        display: block;
    }
}

.bb-member-card[b-6vguul5u3h] {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--mud-palette-table-lines);
}

.bb-member-card:last-child[b-6vguul5u3h] {
    border-bottom: none;
}

.bb-member-card-name[b-6vguul5u3h] {
    font-weight: 500;
}

.bb-member-card-email[b-6vguul5u3h] {
    font-size: 0.82rem;
}

/* Story 136.9, AC 2: the archive type-to-confirm field is capped on roomy viewports so it reads as
   one deliberate input inside the danger zone rather than a page-wide banner, and goes full width at
   the app's existing compact boundary (640.98px, same threshold as the member-card switch above and
   MainLayout/NavMenu's CompactModeMediaQuery) where a capped field would leave the name being typed
   clipped. The wrapper is literal HTML in WorkspaceAdmin.razor, so the isolation scope attribute
   lands on it directly; the MudTextField inside is a component, hence ::deep for its own root. */
.bb-archive-confirm-field[b-6vguul5u3h] {
    max-width: 24rem;
}

.bb-archive-confirm-field[b-6vguul5u3h]  .mud-input-control {
    width: 100%;
}

@media (max-width: 640.98px) {
    .bb-archive-confirm-field[b-6vguul5u3h] {
        max-width: none;
    }
}

/* Review fix S9: .bb-member-card is a flex column with the default align-items: stretch, which
   blockifies the badge (declared inline-flex in app.css) into a full-width flex item — measured
   350px wide versus 48px in the table. A pill spanning the whole card reads as a banner. */
.bb-member-card .role-badge[b-6vguul5u3h] {
    align-self: flex-start;
}
/* /Components/Pages/Admin/WorkspaceDirectory.razor.rz.scp.css */
/* Epic 138 Story 138.5 - the first aria-sort-compliant table in this codebase.
   MudBlazor 9.5.0's MudTableSortLabel is a non-keyboard-operable span and emits no aria-sort, so
   the header cells and their sort controls are hand-built and styled here rather than inherited. */

/* An accessible name for the table that does not occupy layout. Not `display: none` and not
   `visibility: hidden`: both remove the element from the accessibility tree, which is exactly the
   thing this caption exists to be in. */
.bb-visually-hidden[b-m522kwn9yu] {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.bb-workspace-directory-table th[b-m522kwn9yu] {
    white-space: nowrap;
    vertical-align: bottom;
}

/* Numeric columns use tabular figures so counts do not jitter between rows (DESIGN.md). */
.bb-workspace-directory-table td[b-m522kwn9yu] {
    font-variant-numeric: tabular-nums;
}

.bb-sort-control[b-m522kwn9yu] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
    user-select: none;
    /* The control is the whole header cell's hit area rather than just its text, so it reaches the
       touch-target minimum by growing the hit area rather than by growing the visible label. */
    min-height: 44px;
    padding: 0 4px;
    border-radius: 4px;
}

/* :focus-visible only, so a mouse click does not leave a ring behind, while a keyboard user always
   sees where they are. */
.bb-sort-control:focus-visible[b-m522kwn9yu] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* Under a forced-colors theme the palette variable resolves to a colour the user agent overrides,
   so the ring is restated in the system keyword the platform guarantees to render. */
@media (forced-colors: active) {
    .bb-sort-control:focus-visible[b-m522kwn9yu] {
        outline: 2px solid Highlight;
        outline-offset: 2px;
    }
}

.bb-sort-indicator[b-m522kwn9yu] {
    font-size: 0.75rem;
    line-height: 1;
}

/* Every lifecycle action is a persistent control sized for touch, never a hover reveal. */
[b-m522kwn9yu] .bb-row-action {
    min-height: 44px;
}

/* Compact. The threshold matches the ratified compact query used by MainLayout.razor; CSS cannot
   read the {breakpoints.*} token directly, so the single ratified literal is mirrored rather than a
   new one invented. */
@media (max-width: 640.98px) {
    [b-m522kwn9yu] .bb-row-action {
        min-height: 44px;
        min-width: 44px;
    }

    .bb-sort-control[b-m522kwn9yu] {
        min-height: 44px;
    }
}
/* /Components/Pages/Feedback/FeedbackSubmit.razor.rz.scp.css */
.bb-rating-invalid[b-1q8ektpxqo] {
    border: 1px solid var(--mud-palette-error);
    padding: 4px;
    border-radius: 4px;
}
/* /Components/Pages/InitiativeStatus.razor.rz.scp.css */
/* Styles scoped to the InitiativeStatus page. */

.bb-initiative-add-input[b-0omzivplef] {
    flex: 1;
    max-width: 16rem;
}
/* /Components/Pages/QualityAnalysis.razor.rz.scp.css */
.bb-readiness-toolbar[b-vphs92azql] {
    flex-wrap: wrap;
}

.bb-readiness-filter[b-vphs92azql] {
    min-width: min(100%, 34rem);
    flex: 1 1 34rem;
}

.bb-readiness-select[b-vphs92azql] {
    min-width: 11rem;
    flex: 0 0 11rem;
}

.bb-readiness-toolbar[b-vphs92azql] {
    align-items: center;
}

.bb-readiness-table[b-vphs92azql] {
    --bb-id-col-width: 5.25rem;
    --bb-org-col-width: 13.5rem;
}

.bb-col-id[b-vphs92azql] {
    min-width: var(--bb-id-col-width);
}

.bb-col-org-project[b-vphs92azql] {
    min-width: var(--bb-org-col-width);
}

.bb-readiness-open-workflow-link[b-vphs92azql] {
    display: inline-flex;
    color: inherit;
    text-decoration: none;
}

.bb-readiness-table .bb-col-id-sticky[b-vphs92azql],
.bb-readiness-table .bb-col-org-project-sticky[b-vphs92azql] {
    position: sticky;
    z-index: 2;
    background:
        linear-gradient(180deg,
            color-mix(in srgb, var(--mud-palette-surface) 98%, transparent),
            color-mix(in srgb, var(--mud-palette-surface) 98%, transparent)),
        color-mix(in srgb, var(--mud-palette-surface) 98%, transparent);
}

.bb-readiness-table .bb-col-id-sticky[b-vphs92azql] {
    left: 0;
}

.bb-readiness-table .bb-col-org-project-sticky[b-vphs92azql] {
    left: var(--bb-id-col-width);
    box-shadow: 10px 0 16px -14px rgba(0, 0, 0, 0.45);
    border-right: 1px solid rgba(var(--mud-palette-divider-rgb), 0.55);
}

.bb-readiness-table thead .bb-col-id-sticky[b-vphs92azql],
.bb-readiness-table thead .bb-col-org-project-sticky[b-vphs92azql] {
    z-index: 3;
}

.bb-org-project-cell[b-vphs92azql] {
    display: grid;
    gap: 0.1rem;
    min-width: 10rem;
}

.bb-org-project-chip-row[b-vphs92azql] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    align-items: center;
}

.bb-project-chip[b-vphs92azql],
.bb-mobile-project-chip[b-vphs92azql] {
    max-width: 100%;
}

.bb-org-name[b-vphs92azql] {
    color: var(--mud-palette-text-secondary);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-weight: 600;
}

.bb-project-name[b-vphs92azql] {
    font-weight: 600;
    color: rgba(var(--mud-palette-text-primary-rgb), 0.88);
}

.bb-title-cell[b-vphs92azql] {
    display: grid;
    gap: 0.35rem;
}

.bb-title-text[b-vphs92azql] {
    font-weight: 500;
}

.bb-mobile-org-project[b-vphs92azql] {
    display: none;
    gap: 0.35rem;
    flex-wrap: wrap;
}

.bb-gap-analysis-shell[b-vphs92azql] {
    display: grid;
    gap: 1rem;
}

.bb-gap-analysis-summary[b-vphs92azql] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 1rem 1.25rem;
    border-radius: 18px;
    border: 1px solid rgba(var(--mud-palette-primary-rgb), 0.16);
    background:
        radial-gradient(circle at top left, rgba(211, 47, 47, 0.18), transparent 38%),
        linear-gradient(145deg, rgba(var(--mud-palette-primary-rgb), 0.06), color-mix(in srgb, var(--mud-palette-surface) 18%, transparent)),
        var(--mud-palette-surface);
}

.bb-gap-analysis-list[b-vphs92azql] {
    display: grid;
    gap: 0.875rem;
}

.bb-gap-card[b-vphs92azql] {
    padding: 1rem 1.25rem;
    border: 1px solid rgba(var(--mud-palette-primary-rgb), 0.14);
    border-radius: 18px;
    background:
        linear-gradient(180deg, rgba(var(--mud-palette-primary-rgb), 0.05), color-mix(in srgb, var(--mud-palette-surface) 18%, transparent)),
        var(--mud-palette-surface);
    box-shadow: 0 14px 30px rgba(0, 0, 0, 0.14);
}

.bb-gap-card-header[b-vphs92azql] {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: 0.875rem;
}

.bb-gap-checktype[b-vphs92azql] {
    display: inline-block;
    margin-bottom: 0.2rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.bb-gap-stats[b-vphs92azql] {
    text-align: right;
    white-space: nowrap;
}

.bb-gap-meter[b-vphs92azql] {
    position: relative;
    overflow: hidden;
    height: 14px;
    border-radius: 999px;
    background:
        linear-gradient(90deg, rgba(198, 40, 40, 0.14), rgba(245, 124, 0, 0.18)),
        color-mix(in srgb, var(--mud-palette-surface) 72%, transparent);
}

.bb-gap-meter-fill[b-vphs92azql] {
    height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, #c62828 0%, #ef6c00 55%, #ffb300 100%);
    box-shadow: 0 0 22px rgba(239, 108, 0, 0.28);
}

/* Epic 117 Story 117.4: adoption-depth meter. Reuses the gap-meter structure with an adoption-
   positive (teal/green) fill so it reads as progress rather than drag. */
.bb-adoption-meter[b-vphs92azql] {
    position: relative;
    overflow: hidden;
    height: 14px;
    border-radius: 999px;
    background:
        linear-gradient(90deg, rgba(46, 125, 50, 0.12), rgba(42, 100, 102, 0.14)),
        color-mix(in srgb, var(--mud-palette-surface) 72%, transparent);
}

.bb-adoption-meter-fill[b-vphs92azql] {
    height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, #2a6466 0%, #2e7d32 100%);
    box-shadow: 0 0 22px rgba(46, 125, 50, 0.28);
}

@media (max-width: 760px) {
    .bb-col-org-project[b-vphs92azql],
    .bb-col-org-project-sticky[b-vphs92azql] {
        display: none;
    }

    .bb-readiness-filter[b-vphs92azql] {
        min-width: 100%;
        flex-basis: 100%;
    }

    .bb-readiness-select[b-vphs92azql] {
        min-width: 100%;
        flex-basis: 100%;
    }

    .bb-readiness-table[b-vphs92azql] {
        --bb-id-col-width: 4.5rem;
    }

    .bb-mobile-org-project[b-vphs92azql] {
        display: flex;
    }

    .bb-gap-card-header[b-vphs92azql],
    .bb-gap-analysis-summary[b-vphs92azql] {
        flex-direction: column;
        align-items: flex-start;
    }

    .bb-gap-stats[b-vphs92azql] {
        text-align: left;
    }
}
/* /Components/Pages/Workflow.razor.rz.scp.css */
/* Workflow page — Story 76.1 */
/* Tree component styles live in WorkflowTree.razor.css (Story 76.4). */

/* Story 135.22 (AC 1): the mockup's .hub-selector (:160-166) - the bar that holds the two ways of
   choosing what the hub shows. It wraps the row below plus the run-lock and pinned-activation alerts,
   so the surface is here and the flex row stays where it was. */
.bb-hub-selector[b-w12e9gcvvp] {
    background: var(--bb-surface);
    border: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 12px;
    padding: 10px 14px;
    margin-bottom: 14px;
}

/* The mockup's .field (:167-172) sits a tier above the bar it is in. MudTextField renders its own
   outlined chrome from its own component, so this reaches it through ::deep from the row - see the
   Dev Agent Record for the NFR8 deviation covering the chrome itself. */
.bb-hub-toolbar-row[b-w12e9gcvvp]  .mud-input-outlined .mud-input-slot {
    background: var(--bb-surface-2);
}

/* Story 135.14 (AC 1): the toolbar row holding the id input, its Load button and the pinned badge.
   Wraps rather than overflowing at narrow widths; the badge trails the id control so the reading order
   matches the two ways of picking an item (type one, or pick a pinned one). */
.bb-hub-toolbar-row[b-w12e9gcvvp] {
    flex-wrap: wrap;
}

.bb-hub-toolbar-pinned[b-w12e9gcvvp] {
    display: flex;
    align-items: center;
    /* Keeps the NotAuthorized fallback's sentence from stretching the row to the page width. */
    max-width: 22rem;
}

/* ── Story 135.11 (AC1): the hub's two-column body ────────────────────────────────────────────────
   Grid is the unqualified default; @media (max-width: 640.98px) below is the ONLY breakpoint, folding
   it back to a single column below the SAME boundary Story 135.8 established. Fix cycle (review-135-11,
   patch #12): this used to be split across a max-width:640.98px block and a min-width:640.99px block,
   which left a 0.01px gap (640.985px matched neither) where the rail toggle rendered but its
   collapsed-state rules — defined only inside the wide block — did not apply. One breakpoint, no gap
   by construction. Story 135.8's compact breadcrumb-over-list is a different mechanism on the other
   side of that boundary and is untouched here.

   Story 135.8 (AC4, Task 4.1)'s compact touch floor for the root pin toggle moved with the toggle
   itself into WorkflowHubHeader.razor.css — .bb-workflow-root-pin-row no longer exists. */

/* Story 135.17 (AC 1): column-gap: 0 with the 16px moved onto the content column's own padding, so the
   nav column's new right border reads as a divider between the two columns rather than a line floating in
   a gap. The content's distance from the tree is byte-for-byte what the gap gave it. */
.bb-hub-body[b-w12e9gcvvp] {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 0;
    row-gap: 16px;
    align-items: start;
}

/* Story 135.22: the inset is a custom property because WorkflowHubHeader has to cancel it. Its accent
   wash and its bottom hairline are the top edge of this column and must meet the nav column's divider,
   so the header pulls itself back out by exactly this much (WorkflowHubHeader.razor.css). Two literals
   in two files that have to agree is the drift this story exists to remove; custom properties inherit
   through the DOM regardless of CSS isolation, so one declaration serves both. */
.bb-hub-content-column[b-w12e9gcvvp] {
    min-width: 0;
    --bb-hub-content-inset: 16px;
    padding-left: var(--bb-hub-content-inset);
}

/* The rail and the tree are BOTH always in the DOM (see Workflow.razor's left column for why
   unmounting the tree would lose its collapse state); exactly one is shown. Below the boundary the
   rail never shows at all, so the single column always holds the tree's own responsive views. */
.bb-hub-rail-slot[b-w12e9gcvvp] {
    display: none;
}

.bb-hub-navcol-top[b-w12e9gcvvp] {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 10px;
    border-bottom: 1px solid var(--mud-palette-lines-default, #e0e0e0);
}

.bb-hub-navcol-spacer[b-w12e9gcvvp] {
    flex: 1;
}

.bb-hub-rail-toggle[b-w12e9gcvvp] {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    appearance: none;
    border: 1px solid transparent;
    border-radius: 8px;
    background: none;
    color: var(--mud-palette-text-secondary, #757575);
    cursor: pointer;
}

.bb-hub-rail-toggle:hover[b-w12e9gcvvp] {
    background: var(--bb-surface-3);
    border-color: var(--mud-palette-lines-default, #e0e0e0);
    color: var(--mud-palette-primary, #594ae2);
}

.bb-hub-rail-toggle-glyph[b-w12e9gcvvp] {
    display: inline-block;
    font-size: 0.8rem;
    line-height: 1;
    transition: transform 120ms ease;
}

/* Expanded: the glyph points back at the content it can be folded away from. */
.bb-hub-rail-toggle[aria-expanded="true"] .bb-hub-rail-toggle-glyph[b-w12e9gcvvp] {
    transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
    .bb-hub-rail-toggle-glyph[b-w12e9gcvvp] {
        transition: none;
    }
}

.bb-hub-navcol-label[b-w12e9gcvvp] {
    font-size: 0.59375rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary, #757575);
    white-space: nowrap;
}

/* The width readout's home. Not `display: none` and not `visibility: hidden`: both remove the element
   from the accessibility tree, which is the only thing it is still here to be. Same clip technique as
   WorkflowActionBar.razor.css's and WorkflowChildrenReport.razor.css's own utilities. */
.bb-hub-visually-hidden[b-w12e9gcvvp] {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* Story 135.17 (AC 1, AC 4): the panel surface, its divider, and the positioning context the resize
   handle is anchored against. The width is a custom property rather than a plain value so the collapsed
   rail's own `width: auto` below still wins - see the JS drag handler for the same reason. */
.bb-hub-nav-column[b-w12e9gcvvp] {
    position: relative;
    width: var(--bb-nav-width, 300px);
    min-width: 0;
    background: var(--bb-surface-2);
    border-right: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    /* .bb-hub-body is align-items: start, which was invisible while this column had neither background
       nor border. It no longer is: the content column routinely runs three times taller, so a
       content-height column would stop the surface and the divider a third of the way down and read as a
       floating box rather than a seam. Only this column opts out; the grid's own alignment is untouched. */
    align-self: stretch;
}

.bb-hub-nav-column--collapsed[b-w12e9gcvvp] {
    width: auto;
}

/* Story 135.17 (AC 4, AC 5): a plain <button>, not role="separator". The window-splitter role was
   considered and rejected: the 135.8 review found an explicit role erasing a control's implicit one
   (role="listitem" removed the compact rows' buttons from the accessibility tree entirely), and the value
   feedback a splitter would have carried is delivered by the header's live width readout instead. */
.bb-hub-nav-resize[b-w12e9gcvvp] {
    position: absolute;
    top: 0;
    right: -3px;
    bottom: 0;
    width: 7px;
    z-index: 5;
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    cursor: col-resize;
}

.bb-hub-nav-resize[b-w12e9gcvvp]::after {
    content: "";
    position: absolute;
    inset: 0 3px;
    background: transparent;
    transition: background 120ms ease;
}

.bb-hub-nav-resize:hover[b-w12e9gcvvp]::after,
.bb-hub-nav-resize:focus-visible[b-w12e9gcvvp]::after,
.bb-hub-nav-resize--dragging[b-w12e9gcvvp]::after {
    background: var(--mud-palette-primary, #594ae2);
}

.bb-hub-nav-resize:focus-visible[b-w12e9gcvvp] {
    outline: none;
}

@media (prefers-reduced-motion: reduce) {
    .bb-hub-nav-resize[b-w12e9gcvvp]::after {
        transition: none;
    }
}

/* A collapsed rail has no width to drag. */
.bb-hub-nav-column--collapsed .bb-hub-nav-resize[b-w12e9gcvvp] {
    display: none;
}

.bb-hub-nav-column--collapsed .bb-hub-tree-slot[b-w12e9gcvvp] {
    display: none;
}

.bb-hub-nav-column--collapsed .bb-hub-rail-slot[b-w12e9gcvvp] {
    display: block;
}

/* The header's own content is what sizes a collapsed column (it is width: auto), so everything the
   collapsed state does not use has to go, not just the label: a surviving spacer sized the rail to
   roughly twice WorkflowNavigationRail's own 50px. The width readout no longer occupies layout at all,
   but a collapsed rail has no resize handle either, so there is nothing left for it to announce. */
.bb-hub-nav-column--collapsed .bb-hub-navcol-label[b-w12e9gcvvp],
.bb-hub-nav-column--collapsed .bb-hub-navcol-spacer[b-w12e9gcvvp],
.bb-hub-nav-column--collapsed .bb-hub-navcol-width[b-w12e9gcvvp] {
    display: none;
}

/* The toggle and the pin toggle are the only new controls on the compact path, and the toggle is
   hidden here, so this is the only compact rule the grid itself needs. */
@media (max-width: 640.98px) {
    .bb-hub-body[b-w12e9gcvvp] {
        display: block;
    }

    /* AC1: the rail is a wide-viewport affordance. At compact width the nav column is the full-width
       single column and Story 135.8's own breadcrumb-over-list is what compacts it, so a rail toggle
       here would offer a state with no visible effect. */
    .bb-hub-navcol-top[b-w12e9gcvvp] {
        display: none;
    }

    /* Story 135.17 (AC 7): the same reasoning applies to the resize handle - the column is already the
       only column, so a handle here would offer a state with no visible effect. The panel keeps its
       surface and turns its divider through 90 degrees to sit under the content it now stacks above. */
    .bb-hub-nav-resize[b-w12e9gcvvp] {
        display: none;
    }

    .bb-hub-nav-column[b-w12e9gcvvp] {
        width: auto;
        border-right: 0;
        border-bottom: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    }

    /* The property, not the padding: the header cancels the inset by reading the same value, so zeroing
       only the padding would leave it pulling 16px out of a column that no longer has any. */
    .bb-hub-content-column[b-w12e9gcvvp] {
        --bb-hub-content-inset: 0px;
    }
}

/* Story 135.9 (AC 4): the Map Select-mode toggle, beside (not inside) WorkflowViewSwitch — matches
   its aria-pressed toggle-button shape so the two read as siblings, not as a mismatched pair. */
.bb-workflow-select-mode-toggle[b-w12e9gcvvp] {
    appearance: none;
    border: 1px solid var(--mud-palette-lines-default, rgba(0, 0, 0, 0.12));
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.6));
    font-size: 0.8125rem;
    font-weight: 600;
    padding: 5px 14px;
    border-radius: 8px;
    cursor: pointer;
}

.bb-workflow-select-mode-toggle:hover[b-w12e9gcvvp] {
    border-color: var(--mud-palette-primary, #594ae2);
    color: var(--mud-palette-primary, #594ae2);
}

.bb-workflow-select-mode-toggle[aria-pressed="true"][b-w12e9gcvvp] {
    background: var(--mud-palette-primary, #594ae2);
    border-color: var(--mud-palette-primary, #594ae2);
    color: var(--mud-palette-primary-text, #fff);
}

@media (max-width: 640.98px) {
    .bb-workflow-select-mode-toggle[b-w12e9gcvvp] {
        min-height: 44px;
        min-width: 44px;
    }
}
/* /Components/Shared/AddConnectionCard.razor.rz.scp.css */
/* Story 136.15 (AC1) - the guided-creation provider tile group. Scoped rather than global: every
   element below is declared by AddConnectionCard.razor itself, so CSS isolation reaches it. The one
   case that forced a global rule elsewhere (app.css:657) is MudDialog's own actions container,
   which the library renders as an ANCESTOR of this component's output. */

.bb-prov-tiles-group[b-jffb5d1s2m] {
    border: 0;
    margin: 0;
    padding: 0;
    min-width: 0;
}

.bb-prov-tiles-legend[b-jffb5d1s2m] {
    padding: 0;
    margin-bottom: 0.5rem;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
}

.bb-prov-tiles[b-jffb5d1s2m] {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.625rem;
}

@media (max-width: 520px) {
    .bb-prov-tiles[b-jffb5d1s2m] {
        grid-template-columns: 1fr;
    }
}

.bb-prov-tile[b-jffb5d1s2m] {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.125rem;
    /* {spacing.touch-target-min}: the tile is the tap target on a phone. */
    min-width: 44px;
    min-height: 44px;
    padding: 0.875rem;
    text-align: center;
    background-color: var(--mud-palette-surface);
    border: 1.5px solid var(--mud-palette-lines-default);
    border-radius: 0.625rem;
    cursor: pointer;
}

.bb-prov-tile:hover[b-jffb5d1s2m] {
    border-color: var(--mud-palette-primary);
}

.bb-prov-tile--selected[b-jffb5d1s2m] {
    border-color: var(--mud-palette-primary);
    background-color: rgba(var(--mud-palette-primary-rgb), 0.08);
}

/* D-B: muted, not `disabled` - the radio stays in the accessibility tree so a screen-reader user
   still learns the provider is coming. */
.bb-prov-tile--muted[b-jffb5d1s2m] {
    cursor: default;
    opacity: 0.62;
}

.bb-prov-tile--muted:hover[b-jffb5d1s2m] {
    border-color: var(--mud-palette-lines-default);
}

/* The radio covers the tile so the whole tile is the hit area, but stays focusable rather than
   display:none (which would drop it out of the radio group entirely). */
.bb-prov-tile-input[b-jffb5d1s2m] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: inherit;
}

.bb-prov-tile:has(.bb-prov-tile-input:focus-visible)[b-jffb5d1s2m] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.bb-prov-tile-name[b-jffb5d1s2m] {
    font-size: 0.8125rem;
    font-weight: 600;
}

.bb-prov-tile-family[b-jffb5d1s2m] {
    font-size: 0.6875rem;
    color: var(--mud-palette-text-secondary);
}

/* {components.provider-tag} `unavailable` variant (DESIGN.md): a tag ON THE PROVIDER NAME, not the
   mockup's absolutely positioned corner badge (D-A). */
.bb-provider-tag[b-jffb5d1s2m] {
    display: inline-block;
    margin-left: 0.375rem;
    padding: 1px 5px;
    border-radius: 4px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    vertical-align: middle;
}

.bb-provider-tag--unavailable[b-jffb5d1s2m] {
    color: var(--mud-palette-text-secondary);
    background-color: var(--mud-palette-background);
    border: 1px solid var(--mud-palette-divider);
}

@media (forced-colors: active) {
    .bb-prov-tile[b-jffb5d1s2m] {
        border-color: ButtonText;
    }

    .bb-prov-tile--selected[b-jffb5d1s2m] {
        border-color: Highlight;
    }

    /* opacity carries no meaning in forced-colors mode; the "soon" tag and aria-disabled do. */
    .bb-prov-tile--muted[b-jffb5d1s2m] {
        opacity: 1;
        border-color: GrayText;
    }

    .bb-provider-tag--unavailable[b-jffb5d1s2m] {
        color: GrayText;
        border-color: GrayText;
    }
}
/* /Components/Shared/Admin/UserManagementPanel.razor.rz.scp.css */
/* Review fix B2: moved from the now-thin UserManagement.razor.css (Story 136.5). This is a
   Blazor CSS-isolation file, so these classes only ever visually apply to markup THIS component
   renders — the markup using them moved here from UserManagement.razor's own body, but the CSS
   rules were left behind, so the compiled scope attribute never matched anything this panel
   rendered (same class of bug the role-badge relocation fixed, just missed on this second class).
   Unlike role-badge, these genuinely should stay scoped: only this one component renders them.

   Angled project-name column headers — supports many projects without overflow.
   Rotated -45deg with transform-origin at bottom-left so text grows up-and-right
   from the column it labels. */
.bb-um-rot-header[b-hryog7pdyh] {
    height: 140px;
    vertical-align: bottom;
    padding: 0;
    background: var(--mud-palette-surface);
    border-bottom: 2px solid var(--mud-palette-table-lines);
    min-width: 32px;
    max-width: 32px;
    width: 32px;
}

.bb-um-rot-header > div[b-hryog7pdyh] {
    position: relative;
    width: 32px;
    height: 100%;
}

.bb-um-rot-header > div > span[b-hryog7pdyh] {
    position: absolute;
    bottom: 6px;
    left: 50%;
    transform-origin: left bottom;
    transform: rotate(-45deg);
    white-space: nowrap;
    font-size: 0.75rem;
    line-height: 1.2;
    color: var(--mud-palette-text-primary);
    padding: 0 4px;
}

.bb-um-rot-header.bb-um-inactive > div > span[b-hryog7pdyh] {
    opacity: 0.55;
}
/* /Components/Shared/Configuration/QualityAnalysisPromptViewer.razor.rz.scp.css */
/* Story 146.2 (AC 6): bounded, internally-scrolling prompt body — same border/radius/max-height/
   overflow-y shape as WorkflowPinnedPanel.razor.css's .bb-pinned-panel-list. Profiles run 47-98
   lines, so the region must not grow unbounded. */
.qa-prompt-viewer-scroll[b-k6ndgl1tae] {
    border: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 8px;
    max-height: 320px;
    overflow-y: auto;
    padding: 12px;
    background: var(--bb-surface-2);
}
/* /Components/Shared/ConnectionCard.razor.rz.scp.css */
/* {components.connection-card}'s health badge (Story 136.16, AC 1). Scoped rather than a block in
   app.css because every element these rules target is declared by ConnectionCard.razor itself, so
   CSS isolation reaches all of them — app.css is reserved for the cases it cannot (see its own
   comment at the CreateWorkspaceDialog actions rule). Only MudBlazor palette variables, never
   literal hues, so the dark palette swap reaches this component like every other surface. */

/* Geometry from the mockup's `.health` rule (ux-workspace-redesign/mockups/workspace-admin.html). */
.bb-connection-health[b-de29guva5v] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11.5px;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}

.bb-connection-health-dot[b-de29guva5v] {
    width: 8px;
    height: 8px;
    flex-shrink: 0;
    border-radius: 50%;
    background-color: currentColor;
}

/* {colors.success} */
.bb-connection-health--ok[b-de29guva5v] {
    color: var(--mud-palette-success);
}

/* The one variant whose dot and label cannot share a hue, so the dot opts out of currentColor:
   DESIGN.md § Colour is explicit that amber is a fill/border/icon/dot hue only, because
   {colors.warning} measures about 2.7:1 as text and fails AA. The dot keeps {colors.warning}; the
   LABEL takes the darker {colors.warning-text}, which is what PaletteLight/PaletteDark.WarningDarken
   carries - the same split MainLayout.razor.css's blended scope pill already applies. */
.bb-connection-health--pending[b-de29guva5v] {
    color: var(--mud-palette-warning-darken);
}

.bb-connection-health--pending .bb-connection-health-dot[b-de29guva5v] {
    background-color: var(--mud-palette-warning);
}

/* {colors.error} */
.bb-connection-health--error[b-de29guva5v] {
    color: var(--mud-palette-error);
}

@media (forced-colors: active) {
    /* Same idiom as WorkspaceStatusPill.razor.css: hue stops being the carrier here, so the visible
       label is what distinguishes the three states while the dot keeps a bounded, CanvasText-visible
       form rather than disappearing into the forced background. The pending variant is named
       explicitly because its own dot rule above is more specific than the bare one. */
    .bb-connection-health-dot[b-de29guva5v],
    .bb-connection-health--pending .bb-connection-health-dot[b-de29guva5v] {
        background-color: CanvasText;
    }
}
/* /Components/Shared/CreateWorkspaceDialog.razor.rz.scp.css */
/* Story 136.1, AC9 — the guided creation flow's own compact treatment. Both the wide stepper
   (AddProjectWizard-style step header + SetupLifecycleMeter) and the compact "Step N of 4 · stage"
   line always render; CSS picks one by breakpoint, matching the ScopeBar/NavMenu convention
   already used elsewhere for wide/compact forms of the same content.

   Review fix B1: this file is scoped to elements DECLARED in CreateWorkspaceDialog.razor, so it
   can style these two divs (both written directly in that file) but NOT MudDialog's own paper or
   actions container — those are rendered by MudBlazor's own template, an ANCESTOR of this
   component's output, never a descendant, so no selector in a scoped stylesheet (::deep included)
   can ever match them. The full-screen/sticky-footer behavior lives in code
   (DialogOptions.FullScreen, toggled via IBrowserViewportService) and in the GLOBAL stylesheet
   (wwwroot/app.css, targeting MudDialog's ActionsClass) instead — see that file. */

.bb-cw-stepper-compact[b-kz67z5v2p6] {
    display: none;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    margin-bottom: 1rem;
}

@media (max-width: 640.98px) {
    .bb-cw-stepper-wide[b-kz67z5v2p6] {
        display: none;
    }

    .bb-cw-stepper-compact[b-kz67z5v2p6] {
        display: block;
    }
}
/* /Components/Shared/FeedbackTestimonialCarousel.razor.rz.scp.css */
.carousel-card[b-on4soxen0x] {
    opacity: 1;
    transition: opacity 0.3s ease;
}

.carousel-sr-only[b-on4soxen0x] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
/* /Components/Shared/InvestigateMappingRung.razor.rz.scp.css */
/* Story 136.12 (AC 3) — the INV rung's post-pick confirmation line.

   Owned by this component rather than by OnboardingRungPanel, because it deliberately OUTLIVES the
   panel: a successful "Set default mapping" save retires the rung, and the line naming the
   repository the run will read from has to survive that (review finding S2). A rule living in the
   panel's scoped stylesheet could not reach it here.

   Only MudBlazor palette variables, never literal hues, matching the convention every other new
   component in this epic follows. */

.bb-rung-confirmation[b-9amwjk20gm] {
    max-width: 34rem;
    margin: 0.5rem auto 1rem;
    padding: 0.6rem 1rem;
    border: 1px solid var(--mud-palette-success);
    border-radius: 8px;
    background-color: rgba(var(--mud-palette-success-rgb), 0.08);
    color: var(--mud-palette-success-darken);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.5;
    text-align: center;
}

@media (max-width: 640.98px) {
    .bb-rung-confirmation[b-9amwjk20gm] {
        max-width: 100%;
        margin: 0.5rem 0 0.75rem;
    }
}

@media (forced-colors: active) {
    /* The tinted fill and the success hue both go; the border is what keeps the line a bounded,
       findable object rather than a run of body text. */
    .bb-rung-confirmation[b-9amwjk20gm] {
        border-color: CanvasText;
        background-color: Canvas;
        color: CanvasText;
    }
}
/* /Components/Shared/KpiCard.razor.rz.scp.css */
.bb-kpi[b-hx0ts5gtdi] {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-height: 3.5rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-left-width: 3px;
    border-radius: 8px;
    background-color: var(--mud-palette-surface);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    transition: border-color 120ms ease, box-shadow 120ms ease;
}

.bb-kpi:hover[b-hx0ts5gtdi] {
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}

.bb-kpi--default[b-hx0ts5gtdi] {
    border-left-color: var(--mud-palette-lines-default);
}

.bb-kpi--success[b-hx0ts5gtdi] {
    border-left-color: var(--mud-palette-success);
}

.bb-kpi--warning[b-hx0ts5gtdi] {
    border-left-color: var(--mud-palette-warning);
}

.bb-kpi--error[b-hx0ts5gtdi] {
    border-left-color: var(--mud-palette-error);
}

.bb-kpi--info[b-hx0ts5gtdi] {
    border-left-color: var(--mud-palette-info);
}

.bb-kpi-icon-wrap[b-hx0ts5gtdi] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    flex-shrink: 0;
}

.bb-kpi-body[b-hx0ts5gtdi] {
    display: flex;
    flex-direction: column;
    line-height: 1.1;
    min-width: 0;
    flex: 1;
}

.bb-kpi-label[b-hx0ts5gtdi] {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 0.15rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bb-kpi-value[b-hx0ts5gtdi] {
    display: inline-flex;
    align-items: baseline;
    gap: 0.25rem;
    line-height: 1.1;
}

.bb-kpi-value[b-hx0ts5gtdi]  .mud-typography-h5 {
    font-size: 1.4rem;
    line-height: 1.1;
    font-weight: 600;
}
/* /Components/Shared/OnboardingRungPanel.razor.rz.scp.css */
/* {components.empty-state} — Story 136.12's dashed onboarding panel.

   No dashed PANEL precedent existed in this codebase; the only dashed edge was the derived scope
   node's (MainLayout.razor.css). This follows that treatment's discipline: the dash is a border
   STYLE, so the panel stays distinguishable when forced colors drops every hue, and nothing here is
   carried by colour alone.

   Only MudBlazor palette variables, never literal hues, matching the SetupLifecycleMeter/KpiCard
   convention so MudThemeProvider's dark-palette swap reaches this panel too.

   Every inner rule is written `.bb-rung-panel ::deep X` rather than plain `X`. The panel takes a
   RenderFragment (rung 1's workspace chooser, the INV rung's confirmation line), and those elements
   belong to the CALLING component's isolation scope — without ::deep the chooser's buttons would
   carry the shared action class and none of its styling. */

.bb-rung-panel[b-xjbkfws6iy] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    max-width: 34rem;
    margin: 1rem auto;
    padding: 2rem;
    text-align: center;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 12px;
    background-color: var(--mud-palette-surface);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    color: var(--mud-palette-text-secondary);
    background-color: color-mix(in srgb, var(--mud-palette-text-secondary) 10%, transparent);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__headline {
    margin: 0;
    font-size: 1.125rem;
    font-weight: 600;
    line-height: 1.4;
    color: var(--mud-palette-text-primary);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__paragraph {
    margin: 0;
    max-width: 42ch;
    font-size: 0.875rem;
    line-height: 1.5;
    color: var(--mud-palette-text-secondary);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__slot,
.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-workspace-choices {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem;
}

/* A real control, styled — not a chip styled to look like one. The <a> and <button> forms share
   this class so the two render identically whichever the host's action turned out to be. */
.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* {spacing.touch-target-min}, applied at every width rather than only at compact: a 44px target
       is not a compact-only courtesy. */
    min-height: 44px;
    padding: 0 1.25rem;
    border: 1px solid transparent;
    border-radius: 9999px;
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.4;
    text-decoration: none;
    cursor: pointer;
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__action--primary {
    color: var(--mud-palette-primary-text);
    background-color: var(--mud-palette-primary);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__action--primary:hover {
    background-color: var(--mud-palette-primary-darken);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__action--secondary {
    color: var(--mud-palette-primary);
    background-color: transparent;
    border-color: var(--mud-palette-primary);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__action--secondary:hover {
    background-color: rgba(var(--mud-palette-primary-rgb), 0.08);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__action:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    width: 100%;
    padding-top: 0.75rem;
    border-top: 1px solid var(--mud-palette-divider);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-title {
    margin: 0;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-note {
    margin: 0;
    font-size: 0.875rem;
    color: var(--mud-palette-text-secondary);
}

/* Wide: a comma-run of names reads as one sentence. Compact turns the same list into stacked rows
   (see the compact block below) — EXPERIENCE.md line 436. */
.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0 0.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-row:not(:last-child)::after {
    content: ",";
    color: var(--mud-palette-text-secondary);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-name {
    font-size: 0.875rem;
    color: var(--mud-palette-text-primary);
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-link {
    color: var(--mud-palette-primary);
    text-decoration: underline;
}

.bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-link:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* ── Compact ({breakpoints.mode-compact}) ────────────────────────────────────────────────────────
   AD-13: the shell's existing 640.98px boundary, not a third threshold. EXPERIENCE.md line 436: the
   panel goes full-width with reduced padding and a smaller badge; the headline and paragraph are
   UNCHANGED because they are the instruction; the primary action becomes a full-width button; the
   admin list becomes stacked tappable rows rather than a comma-run. */
@media (max-width: 640.98px) {
    .bb-rung-panel[b-xjbkfws6iy] {
        max-width: 100%;
        margin: 0.5rem 0;
        padding: 1.25rem 1rem;
        border-radius: 8px;
    }

    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__badge {
        width: 2.25rem;
        height: 2.25rem;
    }

    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__actions {
        flex-direction: column;
        width: 100%;
    }

    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__action {
        width: 100%;
    }

    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-list {
        flex-direction: column;
        align-items: stretch;
        width: 100%;
        gap: 0;
    }

    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-row {
        display: flex;
        align-items: center;
        justify-content: center;
        min-height: 44px;
        border-top: 1px solid var(--mud-palette-divider);
    }

    /* The comma separator belongs to the inline run only — it would render as a stray character at
       the end of a stacked row. */
    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-row:not(:last-child)::after {
        content: none;
    }

    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-link {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        min-height: 44px;
    }
}

@media (forced-colors: active) {
    /* The dashed edge is a border STYLE and survives; the colour it dashes in does not, so it needs
       a real system-palette edge — the same fix the derived scope node's border takes. */
    .bb-rung-panel[b-xjbkfws6iy] {
        border-color: CanvasText;
    }

    /* The badge and the primary action are both distinguished by fill alone in the normal palette,
       and forced colors drops both. Give each a real boundary so the button still reads as a button
       and the badge still reads as a bounded object. */
    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__badge {
        border: 1px solid CanvasText;
    }

    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__action {
        border-color: CanvasText;
    }

    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__action:focus-visible,
    .bb-rung-panel[b-xjbkfws6iy]  .bb-rung-panel__help-link:focus-visible {
        outline: 2px solid Highlight;
        outline-offset: 2px;
    }
}
/* /Components/Shared/Scope/ScopeSheet.razor.rz.scp.css */
/* {components.scope-sheet}. Only MudBlazor palette variables are used, never literal hues, so the
   dark palette swap MudThemeProvider performs reaches this component like every other shell
   surface. The one literal is the backdrop, which DESIGN.md specifies as a fixed black alpha in
   both palettes. */

.scope-sheet-backdrop[b-kh10ifm9xl] {
    position: fixed;
    inset: 0;
    z-index: 1150;
    background-color: rgba(0, 0, 0, 0.42);
}

.scope-sheet[b-kh10ifm9xl] {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1151;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;

    /* {components.scope-sheet}: only the top corners round, capped at 80dvh so the sheet can never
       become the whole screen, and padded for the home indicator on a notched phone. */
    max-height: 80dvh;
    overflow-y: auto;
    padding: 0.5rem 14px calc(0.75rem + env(safe-area-inset-bottom, 0px));
    border-radius: 0.875rem 0.875rem 0 0;
    background-color: var(--mud-palette-surface);
    box-shadow: 0 -8px 28px rgba(0, 0, 0, 0.22);
}

/* The panel takes focus on open (it is the fallback target when it has no focusable child), so it
   must not be an unlabelled focus ring around the whole sheet when that happens. */
.scope-sheet:focus[b-kh10ifm9xl] {
    outline: none;
}

.scope-sheet-grabber[b-kh10ifm9xl] {
    flex-shrink: 0;
    align-self: center;
    width: 36px;
    height: 4px;
    margin-bottom: 0.35rem;
    border-radius: 9999px;
    background-color: var(--mud-palette-lines-default);
}

.scope-sheet-title[b-kh10ifm9xl] {
    margin: 0;
    font-size: 1rem;
    font-weight: 680;
    line-height: 1.3;
    color: var(--mud-palette-text-primary);
}

.scope-sheet-pill-line[b-kh10ifm9xl] {
    margin: 0 0 0.35rem;
    font-size: 0.8rem;
    line-height: 1.4;
    color: var(--mud-palette-text-secondary);
}

.scope-sheet-group[b-kh10ifm9xl] {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-width: 0;
}

.scope-sheet-group-label[b-kh10ifm9xl] {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.11em;
    line-height: 1.4;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* Story 133.1, AC 10: sits above a role group's own label when the workspace holds more than one
   connection family. Heavier than the role label because it is the outer of the two headings. */
.scope-sheet-family-label[b-kh10ifm9xl] {
    font-size: 0.8rem;
    font-weight: 700;
    line-height: 1.4;
    color: var(--mud-palette-text-primary);
}

.scope-sheet-note[b-kh10ifm9xl],
.scope-sheet-empty[b-kh10ifm9xl] {
    margin: 0.15rem 0 0.35rem;
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--mud-palette-text-secondary);
}

.scope-sheet-rows[b-kh10ifm9xl] {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* {components.scope-sheet.row}: the touch floor is the ROW, which is already a full-width control,
   so the hit area is the visual object here and nothing has to be inflated to reach 44px. */
.scope-sheet-row[b-kh10ifm9xl] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    min-height: 44px;
    padding: 0.4rem 0.6rem;
    border: none;
    border-radius: 0.375rem;
    background-color: transparent;
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-size: 0.9rem;
    text-align: left;
    cursor: pointer;
}

.scope-sheet-row:hover[b-kh10ifm9xl] {
    background-color: rgba(var(--mud-palette-primary-rgb), 0.06);
}

.scope-sheet-row:focus-visible[b-kh10ifm9xl] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

.scope-sheet-row--current[b-kh10ifm9xl] {
    background-color: rgba(var(--mud-palette-primary-rgb), 0.08);
    font-weight: 640;
}

/* Story 138.1, AC 5: a retained archived workspace's row. Colour only — the row keeps its 44px
   touch target, its hover and focus treatment, its place in the tab order and its accessible name
   (the pill inside it is part of that name), and it stays operable, because switching into the
   workspace is how its admin reaches Settings to restore it. */
.scope-sheet-row--muted .scope-sheet-row-name[b-kh10ifm9xl] {
    color: var(--mud-palette-text-secondary);
}

.scope-sheet-row-name[b-kh10ifm9xl] {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.scope-sheet-row-check[b-kh10ifm9xl] {
    flex-shrink: 0;
    color: var(--mud-palette-primary);
}

/* Story 138.6: the sheet's footer. Introduced by this story — there was no footer before, only
   Close — so it holds both the new system-admin action and Close, keeping them the last things in
   the sheet regardless of how many workspace rows precede them. */
.scope-sheet-footer[b-kh10ifm9xl] {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    flex-shrink: 0;
    margin-top: 0.5rem;
}

.scope-sheet-manage-workspaces[b-kh10ifm9xl],
.scope-sheet-close[b-kh10ifm9xl] {
    flex-shrink: 0;
    min-height: 44px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 0.375rem;
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
}

.scope-sheet-manage-workspaces:hover[b-kh10ifm9xl],
.scope-sheet-close:hover[b-kh10ifm9xl] {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

.scope-sheet-manage-workspaces:focus-visible[b-kh10ifm9xl],
.scope-sheet-close:focus-visible[b-kh10ifm9xl] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* DESIGN.md § Forced Colors: the OS drops the fills that distinguish the current row and separate
   the sheet from the page behind it, so both need a real border box to recolour. */
@media (forced-colors: active) {
    .scope-sheet[b-kh10ifm9xl] {
        border: 1px solid CanvasText;
    }

    .scope-sheet-row--current[b-kh10ifm9xl] {
        border: 2px solid Highlight;
    }

    .scope-sheet-row:focus-visible[b-kh10ifm9xl],
    .scope-sheet-manage-workspaces:focus-visible[b-kh10ifm9xl],
    .scope-sheet-close:focus-visible[b-kh10ifm9xl] {
        outline: 2px solid Highlight;
    }
}
/* /Components/Shared/Scope/ScopeSummary.razor.rz.scp.css */
/* {components.scope-summary} — the collapsed scope control (Story 132.5, AC 2/3/4).

   Only MudBlazor palette variables, never literal hues, so MudThemeProvider's dark-palette swap
   reaches this control like the rest of the shell. The scope pill inside it is styled by the band's
   own `.scope-bar .scope-pill` rules in MainLayout.razor.css — it is the same component in the same
   landmark, and giving it a second set of rules here is how the two forms of the bar would start
   disagreeing about what a `needpick` pill looks like. */

.scope-summary[b-e3ilbzqhkh] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    width: 100%;
    min-width: 0;

    /* {spacing.touch-target-min}. The whole control is the hit area, so the target is met by the
       control's own height rather than by inflating any of the things inside it. */
    min-height: 44px;
    padding: 0.25rem 0.5rem;

    /* Matches {components.scope-node}'s control border, and for the same reason: {colors.divider}
       does not clear WCAG 1.4.11's 3:1 floor for an interactive control's boundary. Derived locally
       from text-secondary exactly as the node does, rather than promoting a palette token that
       would restyle every input in the app. */
    border: 1px solid color-mix(in srgb, var(--mud-palette-text-secondary) 72%, var(--mud-palette-surface));
    border-radius: 0.375rem;
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.scope-summary:focus-visible[b-e3ilbzqhkh] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* {components.scope-node.border-active}, applied at rest rather than only on hover: a resolved
   control and an unresolved one must not be indistinguishable until the pointer is over them. */
.scope-summary--active[b-e3ilbzqhkh] {
    border-color: rgba(var(--mud-palette-primary-rgb), 0.25);
}

/* {components.scope-summary.border-needpick} + ring: the "you must pick something" signal survives
   the collapse. Warning-hued, unlike the pill's needpick, which DESIGN.md specifies as error-hued. */
.scope-summary--needpick[b-e3ilbzqhkh] {
    border-color: var(--mud-palette-warning);
    box-shadow: 0 0 0 3px rgba(var(--mud-palette-warning-rgb), 0.1);
}

/* D19: muted is a visual and interaction reduction, never a removal. The control keeps its border,
   its tab stop, and its accessible name — so this must not become display:none or
   pointer-events:none, which would take a focusable element out of reach without saying so. */
.scope-summary--muted[b-e3ilbzqhkh] {
    color: var(--mud-palette-text-secondary);
    background-color: transparent;
    cursor: default;
}

.scope-summary-icon[b-e3ilbzqhkh] {
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
}

.scope-summary--active .scope-summary-icon[b-e3ilbzqhkh] {
    color: var(--mud-palette-primary);
}

/* ── AC 3: the degradation order, expressed as shrink priority ───────────────────────────────────
   Flexbox distributes shrinkage in proportion to each item's shrink factor, so the weights below
   make the order real rather than nominal: the role summary gives up its width first, the workspace
   name next until it hits its 8ch floor, and the pill only after both. It is the priority that is
   specified, not any particular pixel width, which is why this is not a set of breakpoints. */

/* {components.scope-summary.workspace-name}: single line, ellipsis, min 8ch. Never wraps — a
   two-line control would push the band past its height budget on every long workspace name. */
.scope-summary-name[b-e3ilbzqhkh] {
    flex: 0 1 auto;
    flex-shrink: 20;
    min-width: 8ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
    font-weight: 640;
    line-height: 1.4;
}

/* {components.scope-summary.role-summary}: "first element to drop when width runs out". */
.scope-summary-role[b-e3ilbzqhkh] {
    flex: 0 1 auto;
    flex-shrink: 200;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--mud-palette-text-secondary);
    font-size: 11px;
    line-height: 1.4;
}

.scope-summary-chevron[b-e3ilbzqhkh] {
    flex: 0 0 auto;
    color: var(--mud-palette-primary);
}

.scope-summary--muted .scope-summary-chevron[b-e3ilbzqhkh] {
    /* Nothing to open here (AC 4), so the affordance that says "this opens something" goes with it.
       Kept in the box rather than removed so the control does not change width between states. */
    visibility: hidden;
}

/* Story 138.1, AC 5: the selected workspace is archived. This surface renders no per-workspace
   rows, so the treatment lands on the control's own name. Colour only — the control keeps its
   border, its tab stop, its accessible name and, unlike the muted state, its interactivity: the
   sheet still opens and Settings is still reachable through it. */
.scope-summary--archived .scope-summary-name[b-e3ilbzqhkh] {
    color: var(--mud-palette-text-secondary);
}

/* {breakpoints.xs}, already live in this shell for the role badge. Below it the role summary is
   dropped outright rather than left as a lone ellipsis, which is what "drop the role-summary text"
   asks for and what a 320px viewport has room for. No new threshold. */
@media (max-width: 480px) {
    .scope-summary-role[b-e3ilbzqhkh] {
        display: none;
    }
}

@media (forced-colors: active) {
    .scope-summary:focus-visible[b-e3ilbzqhkh] {
        outline: 2px solid Highlight;
        outline-offset: 2px;
    }

    /* The needpick meaning is carried by a warning-hued border plus a soft ring, and the OS drops
       both. Restore the boundary from the system palette so "a choice is outstanding" stays a
       visible difference. */
    .scope-summary--needpick[b-e3ilbzqhkh] {
        border: 2px solid Highlight;
        box-shadow: none;
    }
}
/* /Components/Shared/Scope/ScopeWorkspaceNode.razor.rz.scp.css */
/* Story 138.1, AC 5: the muted treatment for a retained archived workspace's menu row.

   Isolated to this component rather than added to MainLayout.razor.css, whose scope-bar rules are
   written as `.page ::deep .scope-bar ...`. MudMenu portals its popup out to MudPopoverProvider at
   the document root, so a row inside it is not under `.page` at all and those selectors never reach
   it. The element targeted here is the ChildContent div this component itself renders, which does
   carry this stylesheet's scope attribute.

   D19's muting contract, quoted from MainLayout.razor.css: muted is a visual reduction only. The
   row keeps its border, its place in the tab order and its accessible name, so this must never
   become display:none or pointer-events:none. It is deliberately still clickable — switching into
   an archived workspace is how its admin reaches Settings to restore it. */

.scope-node-menu-row[b-dbntd45qy7] {
    width: 100%;
}

.scope-node-menu-row--muted[b-dbntd45qy7] {
    color: var(--mud-palette-text-secondary);
}
/* /Components/Shared/SetupLifecycleMeter.razor.rz.scp.css */
/* {components.setup-lifecycle-meter} — five-stage setup readout (Story 136.2).

   Only MudBlazor palette variables, never literal hues, matching the ScopeSummary/KpiCard
   convention so MudThemeProvider's dark-palette swap reaches this control too. */

.setup-lifecycle-meter[b-1v4nk2k1lx] {
    display: flex;
    width: 100%;
}

.setup-lifecycle-meter-list[b-1v4nk2k1lx] {
    display: flex;
    align-items: flex-start;
    width: 100%;
    list-style: none;
    margin: 0;
    padding: 0;
}

.setup-lifecycle-meter-stage[b-1v4nk2k1lx] {
    position: relative;
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    min-width: 0;
}

/* {components.setup-lifecycle-meter.dots}: {rounded.full} per DESIGN.md § Shapes. */
.setup-lifecycle-meter-dot[b-1v4nk2k1lx] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1;
    z-index: 1;
    transition: background-color 150ms ease, border-color 150ms ease, box-shadow 150ms ease, color 150ms ease;
}

.setup-lifecycle-meter-label[b-1v4nk2k1lx] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

/* Done: filled with the primary hue and a check glyph — never Live (structurally, see the
   component's CompletableLifecycleStage). */
.setup-lifecycle-meter-stage--done .setup-lifecycle-meter-dot[b-1v4nk2k1lx] {
    background-color: var(--mud-palette-primary);
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

.setup-lifecycle-meter-stage--done .setup-lifecycle-meter-label[b-1v4nk2k1lx] {
    color: var(--mud-palette-text-primary);
}

/* Current: hollow with an accent halo (DESIGN.md § Elevation & Depth — "the one deliberate glow").
   Live renders this way at rest, never the done treatment above. Halo alpha is 0.08 to match
   DESIGN.md line 72's accent-soft token exactly (rgba(42,100,102,0.08)) — review fix, was 0.18. */
.setup-lifecycle-meter-stage--current .setup-lifecycle-meter-dot[b-1v4nk2k1lx] {
    background-color: var(--mud-palette-surface);
    border: 2px solid var(--mud-palette-primary);
    box-shadow: 0 0 0 4px rgba(var(--mud-palette-primary-rgb), 0.08);
    color: var(--mud-palette-primary);
}

.setup-lifecycle-meter-stage--current .setup-lifecycle-meter-label[b-1v4nk2k1lx] {
    color: var(--mud-palette-text-primary);
    font-weight: 600;
}

/* Todo: DESIGN.md line 283 — "fill {colors.background}, 2px {colors.divider} border,
   {colors.text-secondary} numeral". Review fix: was filled with the same --surface token as the
   current dot (erasing the fill difference the token intends) and a 1px border (inherited from the
   base rule above, which this now fully overrides with the shorthand). */
.setup-lifecycle-meter-stage--todo .setup-lifecycle-meter-dot[b-1v4nk2k1lx] {
    background-color: var(--mud-palette-background);
    border: 2px solid var(--mud-palette-divider);
    color: var(--mud-palette-text-secondary);
}

/* Connector leading into each stage (skipped on the first). Active up to and including the current
   stage, per DESIGN.md's setup-lifecycle-meter row. */
.setup-lifecycle-meter-stage:not(:first-child)[b-1v4nk2k1lx]::before {
    content: "";
    position: absolute;
    top: 0.72rem;
    right: 50%;
    width: 100%;
    height: 2px;
    background-color: var(--mud-palette-divider);
    z-index: 0;
    transition: background-color 150ms ease;
}

.setup-lifecycle-meter-stage--connector-active:not(:first-child)[b-1v4nk2k1lx]::before {
    background-color: var(--mud-palette-primary);
}

/* {components.setup-lifecycle-meter} at compact (AC8, DESIGN.md § Responsive & Platform,
   "Lifecycle meter at compact"): five stages stacked vertically with a vertical connector, so the
   current stage is never scrolled offscreen. Settings Overview only — Story 136.1 owns Create
   mode's own compact stepper. */
.setup-lifecycle-meter--compact .setup-lifecycle-meter-list[b-1v4nk2k1lx] {
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
}

.setup-lifecycle-meter--compact .setup-lifecycle-meter-stage[b-1v4nk2k1lx] {
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
}

.setup-lifecycle-meter--compact .setup-lifecycle-meter-label[b-1v4nk2k1lx] {
    white-space: normal;
}

.setup-lifecycle-meter--compact .setup-lifecycle-meter-stage:not(:first-child)[b-1v4nk2k1lx]::before {
    top: auto;
    right: auto;
    left: 0.72rem;
    bottom: 100%;
    width: 2px;
    height: 0.5rem;
}

@media (forced-colors: active) {
    /* AC7: state differs by glyph, not fill — the fill/halo that separates done/current/todo in the
       normal palette does not survive forced-colors. Restore the check glyph's contrast on done
       stages and give the current dot the Highlight outline idiom already used in
       ScopeSummary.razor.css. */
    .setup-lifecycle-meter-stage--done .setup-lifecycle-meter-dot[b-1v4nk2k1lx] {
        background-color: Canvas;
        border-color: CanvasText;
        color: CanvasText;
    }

    .setup-lifecycle-meter-stage--current .setup-lifecycle-meter-dot[b-1v4nk2k1lx] {
        border: 1px solid CanvasText;
        outline: 2px solid Highlight;
        outline-offset: 2px;
        box-shadow: none;
    }

    .setup-lifecycle-meter-stage:not(:first-child)[b-1v4nk2k1lx]::before {
        background-color: CanvasText;
    }

    .setup-lifecycle-meter-stage--connector-active:not(:first-child)[b-1v4nk2k1lx]::before {
        background-color: Highlight;
    }
}

@media (prefers-reduced-motion: reduce) {
    /* Review fix: the connector's transition is declared on
       .setup-lifecycle-meter-stage:not(:first-child)::before, specificity (0,3,1). The override below
       must repeat :not(:first-child) — without it this selector is only (0,2,1) and never wins the
       cascade against the rule it's meant to override (confirmed in the generated scoped CSS bundle). */
    .setup-lifecycle-meter-dot[b-1v4nk2k1lx],
    .setup-lifecycle-meter-stage:not(:first-child)[b-1v4nk2k1lx]::before {
        transition: none;
    }
}
/* /Components/Shared/WorkspaceArchivedRung.razor.rz.scp.css */
/* Story 138.7, AC 3 / EXPERIENCE.md:430 — the who-can-help list is a stacked set of tappable
   {spacing.touch-target-min} rows (name + mailto:), not a comma-run of names. */

.archived-rung-helpers[b-r53z2y40j0] {
    list-style: none;
    margin: 0.5rem 0 0;
    padding: 0;
    width: 100%;
    max-width: 320px;
}

.archived-rung-helpers li[b-r53z2y40j0] {
    display: flex;
}

.archived-rung-helpers a[b-r53z2y40j0] {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 44px;
    padding: 0.4rem 0.6rem;
    color: var(--mud-palette-primary);
    text-decoration: none;
}

.archived-rung-helpers a:hover[b-r53z2y40j0],
.archived-rung-helpers a:focus-visible[b-r53z2y40j0] {
    text-decoration: underline;
}
/* /Components/Shared/WorkspaceStatusPill.razor.rz.scp.css */
/* {components.status-pill}. Its own isolated stylesheet rather than a block in
   MainLayout.razor.css: those rules are layout-scoped (`.page ::deep .scope-bar ...`) and this pill
   is rendered inside a MudMenu popup, which MudBlazor portals out to MudPopoverProvider at the
   document root — outside `.page` entirely. Only MudBlazor palette variables are used, never literal
   hues, so the dark palette swap reaches this component like every other surface. */

.status-pill[b-tofrejk3yl] {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex-shrink: 0;
    padding: 0.05rem 0.45rem;
    /* {rounded.full} */
    border-radius: 9999px;
    /* DESIGN.md § Forced Colors: a transparent border becomes a CanvasText edge under forced
       colors, so the pill stays a bounded object once its tint is dropped. Inherited from the
       existing scope-pill rule, not new to this component. */
    border: 1px solid transparent;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1.5;
    text-transform: uppercase;
    white-space: nowrap;
}

.status-pill-dot[b-tofrejk3yl] {
    width: 6px;
    height: 6px;
    flex-shrink: 0;
    background-color: currentColor;
}

/* Round for the two in-use states... */
.status-pill--live .status-pill-dot[b-tofrejk3yl],
.status-pill--setup .status-pill-dot[b-tofrejk3yl] {
    border-radius: 9999px;
}

/* ...square for archived, so the distinction survives a user who cannot separate the hues. */
.status-pill--archived .status-pill-dot[b-tofrejk3yl] {
    border-radius: 1px;
}

/* text {colors.success} on {colors.success}18 — the same tint ratio the shipped scope pill uses for
   its success variant, so the two read as one system. */
.status-pill--live[b-tofrejk3yl] {
    color: var(--mud-palette-success);
    background-color: color-mix(in srgb, var(--mud-palette-success) 9%, transparent);
}

/* text {colors.warning-text} on {colors.warning}18 */
.status-pill--setup[b-tofrejk3yl] {
    color: var(--mud-palette-warning);
    background-color: color-mix(in srgb, var(--mud-palette-warning) 9%, transparent);
}

/* Inert: a neutral fill and the secondary text colour, which already clears AA against both the
   light and dark surface in this theme (it is the same token the muted scope pill and the scope
   node's role label rely on). Never amber, never red. */
.status-pill--archived[b-tofrejk3yl] {
    color: var(--mud-palette-text-secondary);
    background-color: color-mix(in srgb, var(--mud-palette-text-secondary) 12%, transparent);
}

@media (forced-colors: active) {
    .status-pill[b-tofrejk3yl] {
        border-color: CanvasText;
    }

    /* currentColor resolves to the forced text colour, which would make all three dots identical;
       the shape distinction is what still carries. */
    .status-pill-dot[b-tofrejk3yl] {
        background-color: CanvasText;
    }
}
/* /Components/Workflow/WorkflowActionBar.razor.rz.scp.css */
/* Story 135.22 (AC 1): the mockup's .actionbar (:440-445). The bar was a bare flex row with a gap and no
   surface of its own, so five outlined buttons read as five loose controls rather than as one row of
   verbs. No margin-bottom (the mockup's :444): the reason line below is this component's own and has to
   stay attached to the buttons it explains, and the region's separation from the detail pane below is
   already carried by its host wrapper. */
.bb-action-bar[b-u5h3glbqm5] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    border: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 11px;
    background: var(--bb-surface-2);
}

/* The mockup's .lbl (:446-449): what the row of verbs is for, stated once instead of on each button. */
.bb-action-bar-group-label[b-u5h3glbqm5] {
    margin-right: 2px;
    font-size: 0.59375rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary, #757575);
}

/* .actbtn (:450-455): neutral on --bb-surface, going primary on hover. Five primary-outlined buttons on
   a tinted bar competed with each other and with the bar; the accent belongs to the one being pointed at. */
.bb-action-bar-button[b-u5h3glbqm5] {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 12px;
    border: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 8px;
    background-color: var(--bb-surface);
    color: inherit;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.bb-action-bar-button:hover:not(.bb-action-bar-button--disabled)[b-u5h3glbqm5] {
    border-color: var(--mud-palette-primary, #594ae2);
    color: var(--mud-palette-primary, #594ae2);
}

.bb-action-bar-button:focus-visible[b-u5h3glbqm5] {
    outline: 2px solid var(--mud-palette-primary, #594ae2);
    outline-offset: 2px;
}

/* Story 135.15 (AC 2): the aria-describedby target for a disabled verb's reason — present in the
   DOM (so a screen reader can read it) but not part of the visual layout. Same clip technique as
   WorkflowChildrenReport.razor.css's own visually-hidden utility. */
.bb-action-bar-visually-hidden[b-u5h3glbqm5] {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* AC 2: never the native `disabled` attribute — this bar always keeps the button focusable and
   clickable in the DOM, and relies on aria-disabled plus this class for the visual/behavioral
   "unavailable" treatment instead. */
.bb-action-bar-button--disabled[b-u5h3glbqm5] {
    border-color: var(--mud-palette-lines-default, #e0e0e0);
    color: var(--mud-palette-text-secondary, #757575);
    cursor: default;
    /* The mockup's [aria-disabled="true"] (:456). The border no longer distinguishes an unavailable verb
       now that the enabled one is neutral-bordered too, so the fade is what carries it. */
    opacity: 0.5;
}

.bb-action-bar-button--busy[b-u5h3glbqm5] {
    cursor: wait;
}

.bb-action-bar-spinner[b-u5h3glbqm5] {
    flex-shrink: 0;
}

.bb-action-bar-tag[b-u5h3glbqm5] {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    padding: 1px 6px;
    border-radius: 10px;
    flex-shrink: 0;
}

/* AC 2: config-off, type-not-enabled, structural, and planned must be visibly distinct — and
   planned must never read like the others switched something off. */
.bb-action-bar-tag--config-off[b-u5h3glbqm5] {
    background-color: var(--mud-palette-warning, #ed6c02);
    color: #fff;
}

/* gray-darker, not gray-default, because this chip carries white text: MudBlazor emits no numeric
   grey scale at all (only gray-default #9E9E9E, gray-light #BDBDBD, gray-darker #616161), and the
   nearest name to the old --mud-palette-grey-500 by value would be gray-default at ~2.7:1 against
   #fff. gray-darker measures ~6.2:1 and is the same value in both palettes. */
.bb-action-bar-tag--type-not-enabled[b-u5h3glbqm5] {
    background-color: var(--mud-palette-gray-darker, #616161);
    color: #fff;
}

.bb-action-bar-tag--structural[b-u5h3glbqm5] {
    background-color: var(--mud-palette-error, #d32f2f);
    color: #fff;
}

.bb-action-bar-tag--planned[b-u5h3glbqm5] {
    background-color: var(--mud-palette-info, #2196f3);
    color: #fff;
}

.bb-action-bar-reason[b-u5h3glbqm5] {
    min-height: 1.25rem;
    margin-top: 4px;
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary, #757575);
}

/* ── Story 135.8 (AC2): compact overflow menu ──────────────────────────────────────────────────
   Both the inline bar above and .bb-action-bar-compact are always in the DOM; only one shows per
   the shell's existing (max-width: 640.98px) boundary (no new threshold). */
.bb-action-bar-compact[b-u5h3glbqm5] {
    display: none;
    position: relative;
}

.bb-action-bar-compact-trigger[b-u5h3glbqm5] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 6px 16px;
    border: 1px solid var(--mud-palette-primary, #594ae2);
    border-radius: 4px;
    background-color: transparent;
    color: var(--mud-palette-primary, #594ae2);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.bb-action-bar-compact-menu[b-u5h3glbqm5] {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 5;
    min-width: 100%;
    margin-top: 4px;
    border: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 4px;
    background: var(--mud-palette-surface, #fff);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    overflow: hidden;
}

.bb-action-bar-compact-item[b-u5h3glbqm5] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    width: 100%;
    text-align: left;
    appearance: none;
    border: none;
    border-bottom: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    background: transparent;
    font: inherit;
    color: inherit;
    cursor: pointer;
    padding: 8px 12px;
}

.bb-action-bar-compact-item:last-child[b-u5h3glbqm5] {
    border-bottom: none;
}

.bb-action-bar-compact-item[aria-disabled="true"][b-u5h3glbqm5] {
    color: var(--mud-palette-text-secondary, #757575);
    cursor: default;
}

.bb-action-bar-compact-item-label[b-u5h3glbqm5] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
}

.bb-action-bar-compact-item-icon[b-u5h3glbqm5] {
    flex-shrink: 0;
}

.bb-action-bar-compact-item-reason[b-u5h3glbqm5] {
    font-size: 0.78rem;
    color: var(--mud-palette-text-secondary, #757575);
}

@media (max-width: 640.98px) {
    .bb-action-bar[b-u5h3glbqm5],
    .bb-action-bar-reason[b-u5h3glbqm5] {
        display: none;
    }

    .bb-action-bar-compact[b-u5h3glbqm5] {
        display: block;
    }

    /* {spacing.touch-target-min}: the hit area grows, the label does not. */
    .bb-action-bar-compact-trigger[b-u5h3glbqm5],
    .bb-action-bar-compact-item[b-u5h3glbqm5] {
        min-height: 44px;
    }
}
/* /Components/Workflow/WorkflowChildrenReport.razor.rz.scp.css */
.bb-children-report[b-492kgm16af] {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background: var(--mud-palette-surface);
    margin-top: 8px;
    /* Measured, not assumed (Dev Notes): the host canvas is width:max-content at compact, so without a
       clamp a 12-child table grew this card to 801px inside a 375px viewport. max-width caps the card's
       max-content contribution, which pushes the overflow into the table's own scroller below. */
    max-width: calc(100vw - 2rem);
}

.bb-children-report-head[b-492kgm16af] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 10px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.bb-children-report-title[b-492kgm16af] {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 0.8125rem;
    font-weight: 700;
}

.bb-children-report-status[b-492kgm16af] {
    font-weight: 400;
    color: var(--mud-palette-text-secondary);
}

.bb-children-report-actions[b-492kgm16af] {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.bb-children-report-button[b-492kgm16af] {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 6px;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    padding: 4px 10px;
    font: inherit;
    font-size: 0.75rem;
    cursor: pointer;
}

.bb-children-report-button--ghost[b-492kgm16af] {
    background: transparent;
    color: inherit;
}

.bb-children-report-button:disabled[b-492kgm16af] {
    cursor: default;
    opacity: 0.6;
}

.bb-children-report-error[b-492kgm16af] {
    padding: 8px 12px;
    color: var(--mud-palette-error);
}

.bb-children-report-note[b-492kgm16af] {
    padding: 0 12px;
    margin: 6px 0;
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
}

.bb-children-report-body[b-492kgm16af] {
    padding: 12px;
}

.bb-children-report-summary[b-492kgm16af] {
    margin: 0 0 10px;
    font-size: 0.8125rem;
}

.bb-children-report-bar-row[b-492kgm16af] {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
    font-size: 0.75rem;
}

.bb-children-report-bar-label[b-492kgm16af] {
    flex: 0 0 4rem;
    color: var(--mud-palette-text-secondary);
}

.bb-children-report-bar[b-492kgm16af] {
    display: flex;
    flex: 1 1 auto;
    height: 8px;
    min-width: 0;
    border-radius: 4px;
    overflow: hidden;
    background: var(--mud-palette-action-disabled-background);
}

.bb-children-report-bar-value[b-492kgm16af] {
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
}

.bb-children-report-seg[b-492kgm16af] {
    display: block;
    height: 100%;
}

.bb-children-report-seg--high[b-492kgm16af] {
    background: var(--mud-palette-error);
}

.bb-children-report-seg--medium[b-492kgm16af] {
    background: var(--mud-palette-warning);
}

.bb-children-report-seg--low[b-492kgm16af],
.bb-children-report-seg--done[b-492kgm16af] {
    background: var(--mud-palette-success);
}

.bb-children-report-seg--completing[b-492kgm16af] {
    background: var(--mud-palette-success-lighten);
}

.bb-children-report-seg--inprogress[b-492kgm16af] {
    background: var(--mud-palette-info);
}

.bb-children-report-seg--unknown[b-492kgm16af],
.bb-children-report-seg--notstarted[b-492kgm16af],
.bb-children-report-seg--other[b-492kgm16af] {
    background: var(--mud-palette-action-disabled);
}

/* Dev Notes: a container with a realistic 8-12 children must scroll inside this wrapper rather than
   widening the card or the page body. Same technique WorkflowMap.razor.css already uses for the Map
   canvas. */
.bb-children-report-table-scroll[b-492kgm16af] {
    overflow-x: auto;
    max-height: 22rem;
    overflow-y: auto;
    margin: 10px 0;
}

.bb-children-report-table[b-492kgm16af] {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.75rem;
}

.bb-children-report-table th[b-492kgm16af],
.bb-children-report-table td[b-492kgm16af] {
    text-align: left;
    vertical-align: top;
    padding: 6px 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.bb-children-report-child-title[b-492kgm16af] {
    display: block;
    font-weight: 600;
}

.bb-children-report-child-reasoning[b-492kgm16af] {
    display: block;
    margin-top: 2px;
    color: var(--mud-palette-text-secondary);
}

.bb-children-report-chip[b-492kgm16af] {
    display: inline-block;
    border-radius: 999px;
    border: 1px solid var(--mud-palette-lines-default);
    padding: 1px 8px;
    margin-right: 4px;
    white-space: nowrap;
}

.bb-children-report-chip--high[b-492kgm16af] {
    border-color: var(--mud-palette-error);
    color: var(--mud-palette-error);
}

.bb-children-report-chip--medium[b-492kgm16af] {
    border-color: var(--mud-palette-warning);
    color: var(--mud-palette-warning);
}

.bb-children-report-chip--low[b-492kgm16af] {
    border-color: var(--mud-palette-success);
    color: var(--mud-palette-success);
}

.bb-children-report-highlights[b-492kgm16af] {
    margin: 10px 0;
    padding-left: 1.2rem;
    font-size: 0.75rem;
}

.bb-children-report-highlights li[b-492kgm16af] {
    margin-bottom: 6px;
}

.bb-children-report-highlight-finding[b-492kgm16af] {
    display: block;
    font-weight: 600;
}

.bb-children-report-highlight-reasoning[b-492kgm16af] {
    display: block;
    color: var(--mud-palette-text-secondary);
}

.bb-children-report-effort[b-492kgm16af] {
    font-size: 0.75rem;
}

.bb-children-report-effort-range[b-492kgm16af] {
    display: block;
    font-weight: 600;
}

.bb-children-report-effort-rationale[b-492kgm16af] {
    display: block;
    margin-top: 2px;
}

.bb-children-report-footnote[b-492kgm16af] {
    display: block;
    margin-top: 4px;
    font-style: italic;
    color: var(--mud-palette-text-secondary);
}

.bb-children-report-visually-hidden[b-492kgm16af] {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* Story 135.20 (AC 8), built as the mockup draws it (workflow-hub-visual-redesign.html:542-556): below
   the threshold the per-child table becomes stacked blocks. The reasoning caption has to survive at every
   width (the retired page's UX-DR2: a hover-only value is neither readable in place nor testable, and
   reading a caption while scrolling sideways defeats it just as thoroughly), and a column that silently
   disappears reads as missing data rather than hidden - which rules out progressive column-dropping too.
   The sideways scroller above is replaced here, not left underneath: all three of its properties have to
   go, not just overflow-x. Overriding overflow-x alone is inert, because CSS Overflow 3 computes a
   `visible` axis back to `auto` while the other axis is still `auto`; and max-height would otherwise trap
   the stacked blocks in a 22rem nested scroller, trading the sideways scroll for a vertical one. */
@media (max-width: 820px) {
    .bb-children-report-table-scroll[b-492kgm16af] {
        overflow: visible;
        max-height: none;
    }

    .bb-children-report-table[b-492kgm16af],
    .bb-children-report-table tbody[b-492kgm16af],
    .bb-children-report-table tr[b-492kgm16af],
    .bb-children-report-table td[b-492kgm16af] {
        display: block;
        width: 100%;
    }

    .bb-children-report-table thead[b-492kgm16af] {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
        white-space: nowrap;
    }

    .bb-children-report-table[b-492kgm16af] {
        border: 0;
        background: none;
    }

    .bb-children-report-table tr[b-492kgm16af] {
        background: var(--bb-surface);
        border: 1px solid var(--mud-palette-lines-default);
        border-radius: 10px;
        padding: 10px 12px;
        margin-bottom: 10px;
    }

    .bb-children-report-table td[b-492kgm16af] {
        border: 0;
        padding: 2px 0;
    }

    .bb-children-report-table td[data-k][b-492kgm16af]::before {
        content: attr(data-k) " ";
        font-size: 10.5px;
        letter-spacing: 0.07em;
        text-transform: uppercase;
        font-weight: 700;
        color: var(--mud-palette-text-secondary);
        margin-right: 6px;
    }
}

@media (max-width: 640.98px) {
    /* Story 135.8 (AC4): {spacing.touch-target-min} - the hit area grows, the label does not. */
    .bb-children-report-button[b-492kgm16af] {
        min-height: 44px;
    }
}
/* /Components/Workflow/WorkflowDetailPane.razor.rz.scp.css */
/* Story 135.20: the tab strip, the Overview facts grid and the Analysis check rows, built from the
   governing mockup (workflow-hub-visual-redesign.html:459-498 and :580-585) on Story 135.16's tokens.
   Isolated rather than in app.css: the strip has exactly one consumer. */

.bb-detail-tabstrip[b-63phjt8f8v] {
    display: flex;
    gap: 2px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    margin-bottom: 16px;
    /* What keeps the strip off the PAGE's horizontal scroll at compact: a strip too wide for the
       viewport scrolls inside itself instead of widening the body. */
    overflow-x: auto;
    /* CSS Overflow 3: a computed `visible` on one axis becomes `auto` when the other axis is not
       `visible`, so `overflow-x: auto` alone cannot mean "horizontal only": it silently made the strip
       vertically scrollable too. The tabs exactly fill the content box at a fractional 41.797px, which
       rounds scrollHeight one pixel past clientHeight, and Chrome rendered a full-height vertical
       scrollbar down the right of the tab row for that one pixel. */
    overflow-y: hidden;
}

.bb-detail-tab[b-63phjt8f8v] {
    appearance: none;
    border: 0;
    background: none;
    cursor: pointer;
    padding: 9px 14px 10px;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    color: var(--mud-palette-text-secondary);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.bb-detail-tab:hover[b-63phjt8f8v] {
    color: var(--mud-palette-text-primary);
    background: var(--bb-surface-2);
}

.bb-detail-tab[aria-selected="true"][b-63phjt8f8v] {
    color: var(--mud-palette-primary);
    border-bottom-color: var(--mud-palette-primary);
}

.bb-detail-tab:focus-visible[b-63phjt8f8v] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

/* The count/state chip is what buys back the at-a-glance read that tabs cost: a tab reads as empty,
   stale or loud without being opened. */
.bb-detail-tabchip[b-63phjt8f8v] {
    font-size: 10.5px;
    font-weight: 700;
    border-radius: 100px;
    padding: 0 7px;
    line-height: 17px;
    background: var(--bb-surface-3);
    color: var(--mud-palette-text-secondary);
}

.bb-detail-tabchip--accent[b-63phjt8f8v] {
    background: var(--bb-accent-soft);
    color: var(--mud-palette-primary);
}

.bb-detail-tabchip--warn[b-63phjt8f8v] {
    background: var(--bb-warn-soft);
    color: var(--mud-palette-warning-darken);
}

.bb-detail-tabchip--bad[b-63phjt8f8v] {
    background: var(--bb-bad-soft);
    color: var(--mud-palette-error);
}

/* The count chip is the mockup's bare .tabchip (:472-475), so this restates the base neutral rather than
   overriding it - declared because ChipFor emits the modifier, and a class that is emitted but undefined
   reads as styled when it is not. */
.bb-detail-tabchip--neutral[b-63phjt8f8v] {
    background: var(--bb-surface-3);
    color: var(--mud-palette-text-secondary);
}

.bb-detail-tabchip--empty[b-63phjt8f8v] {
    background: transparent;
    color: var(--mud-palette-text-disabled);
    font-weight: 600;
}

.bb-detail-tabpanel[hidden][b-63phjt8f8v] {
    display: none;
}

.bb-detail-facts[b-63phjt8f8v] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1px;
    background: var(--mud-palette-lines-default);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 11px;
    overflow: hidden;
}

.bb-detail-fact[b-63phjt8f8v] {
    background: var(--bb-surface);
    padding: 10px 14px;
}

.bb-detail-fact-k[b-63phjt8f8v] {
    font-size: 10.5px;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.bb-detail-fact-v[b-63phjt8f8v] {
    font-size: 13.5px;
    font-weight: 600;
    margin-top: 2px;
}

.bb-detail-fact-v--muted[b-63phjt8f8v] {
    font-weight: 400;
    color: var(--mud-palette-text-secondary);
}

.bb-detail-fact-tier[b-63phjt8f8v] {
    font-size: 10.5px;
    font-weight: 700;
    border-radius: 100px;
    padding: 1px 8px;
    background: var(--bb-surface-3);
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* NFR8: the mockup draws this tier as a risk-coloured .pill (:881, .pill.low/.med/.high at :531-534), not
   as a neutral marker - a SprintReady and a NeedsRefinement tier rendering identically grey is the read
   the pill exists to give. Keyed on the tier the same way app.css's shared .bb-score-chip is; the base
   rule above stays as the fallback for a tier neither names. */
.bb-detail-fact-tier--sprintready[b-63phjt8f8v] {
    background: var(--bb-good-soft);
    color: var(--mud-palette-success);
}

.bb-detail-fact-tier--acceptable[b-63phjt8f8v] {
    background: var(--bb-warn-soft);
    color: var(--mud-palette-warning-darken);
}

.bb-detail-fact-tier--needsrefinement[b-63phjt8f8v] {
    background: var(--bb-bad-soft);
    color: var(--mud-palette-error);
}

.bb-detail-prose[b-63phjt8f8v] {
    margin-top: 14px;
    background: var(--bb-surface-2);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 11px;
    padding: 13px 15px;
}

.bb-detail-prose h3[b-63phjt8f8v] {
    font-size: 12.5px;
    letter-spacing: 0.02em;
    margin: 0 0 6px;
}

.bb-detail-prose p[b-63phjt8f8v] {
    margin: 0;
    font-size: 13px;
    color: var(--mud-palette-text-secondary);
}

.bb-detail-prose p.bb-detail-prose-empty[b-63phjt8f8v] {
    color: var(--mud-palette-text-disabled);
}

.bb-detail-section[b-63phjt8f8v] {
    background: var(--bb-surface-2);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    padding: 14px 16px;
    margin-bottom: 14px;
}

.bb-detail-section-head[b-63phjt8f8v] {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}

.bb-detail-section-head h3[b-63phjt8f8v] {
    font-size: 13.5px;
    margin: 0;
}

/* Mockup .section-head .sp (:506) and .section-head .when (:507): the spacer pushes the event count to
   the far end of the head. Named for what they do rather than kept as the mockup's two-letter classes. */
.bb-detail-section-head-spacer[b-63phjt8f8v] {
    flex: 1;
}

.bb-detail-section-head-when[b-63phjt8f8v] {
    font-size: 11.5px;
    color: var(--mud-palette-text-secondary);
}

/* Story 135.21: the processing timeline, from the mockup's drawn .timeline / .tl region (:591-602). */
.bb-detail-timeline[b-63phjt8f8v] {
    position: relative;
    padding-left: 20px;
}

.bb-detail-timeline[b-63phjt8f8v]::before {
    content: "";
    position: absolute;
    left: 5px;
    top: 4px;
    bottom: 4px;
    width: 1px;
    background: var(--mud-palette-lines-default);
}

.bb-detail-timeline-entry[b-63phjt8f8v] {
    position: relative;
    padding: 7px 0;
    font-size: 12.5px;
}

/* The base marker ring is also the THIRD outcome state's marker: ActivityOutcome has Success, Failed and
   Skipped, and the mockup draws only .ok and .fail - so a Skipped (or unrecognised) outcome renders this
   disabled-tone ring by carrying no modifier class, and needs no new colour. */
.bb-detail-timeline-entry[b-63phjt8f8v]::before {
    content: "";
    position: absolute;
    left: -18px;
    top: 13px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--bb-surface);
    border: 2px solid var(--mud-palette-text-disabled);
}

.bb-detail-timeline-entry--ok[b-63phjt8f8v]::before {
    border-color: var(--mud-palette-success);
}

.bb-detail-timeline-entry--fail[b-63phjt8f8v]::before {
    border-color: var(--mud-palette-error);
}

.bb-detail-timeline-when[b-63phjt8f8v] {
    display: block;
    font-size: 11px;
    color: var(--mud-palette-text-secondary);
}

.bb-detail-timeline-what[b-63phjt8f8v] {
    font-weight: 600;
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
}

.bb-detail-timeline-outcome[b-63phjt8f8v] {
    font-weight: 400;
    color: var(--mud-palette-text-secondary);
}

.bb-detail-timeline-detail[b-63phjt8f8v] {
    color: var(--mud-palette-text-secondary);
}

/* The epic's --bb-bad-soft tint goes on the ERROR BLOCK, not on the .tl row: the mockup distinguishes a
   failure by marker border-colour alone (:599) and applies no background to .tl.fail, so tinting the row
   would change drawn geometry. This block exists only on a failure, so the tint still lands where the
   epic wants it. overflow-wrap because ErrorMessage is unbounded and a truncated failure reason is the
   thing this tab exists to prevent. */
.bb-detail-timeline-error[b-63phjt8f8v] {
    margin-top: 4px;
    padding: 6px 9px;
    border-radius: 8px;
    background: var(--bb-bad-soft);
    color: var(--mud-palette-text-primary);
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
    overflow-wrap: anywhere;
}

.bb-detail-timeline-severity[b-63phjt8f8v] {
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--mud-palette-error);
    white-space: nowrap;
}

/* Story 135.23: the Drafts tab's before/after rows, from the mockup's drawn .diff region (:559-574).
   Class names carry this file's own bb-detail-* convention rather than the mockup's bare .dk/.dv/.dlbl. */
.bb-detail-diff[b-63phjt8f8v] {
    background: var(--bb-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 11px;
    overflow: hidden;
}

.bb-detail-diffrow[b-63phjt8f8v] {
    display: flex;
    gap: 14px;
    padding: 11px 14px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.bb-detail-diffrow:first-child[b-63phjt8f8v] {
    border-top: 0;
}

.bb-detail-diff-k[b-63phjt8f8v] {
    flex: none;
    width: 140px;
    font-size: 10.5px;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    font-weight: 700;
    color: var(--mud-palette-text-secondary);
    padding-top: 2px;
}

.bb-detail-diff-v[b-63phjt8f8v] {
    flex: 1;
    min-width: 0;
    font-size: 12.5px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.bb-detail-diff-label[b-63phjt8f8v] {
    display: inline-block;
    width: 34px;
    flex: none;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* overflow-wrap because an enriched description is unbounded and can arrive with no break opportunity
   at all. The cells wrap rather than scroll or truncate: a diff that hides half a value defeats itself,
   and a scrolling cell would put the page's own horizontal scrollbar back at 320px. */
.bb-detail-diff-was[b-63phjt8f8v],
.bb-detail-diff-now[b-63phjt8f8v] {
    padding: 4px 8px;
    border-radius: 7px;
    overflow-wrap: anywhere;
}

.bb-detail-diff-was[b-63phjt8f8v] {
    color: var(--mud-palette-text-secondary);
    background: var(--bb-surface-2);
}

.bb-detail-diff-now[b-63phjt8f8v] {
    background: var(--bb-good-soft);
    border: 1px solid var(--bb-good-line);
}

.bb-detail-diff-empty[b-63phjt8f8v] {
    font-style: italic;
    color: var(--mud-palette-text-disabled);
}

.bb-detail-diff-unchanged[b-63phjt8f8v] {
    font-size: 12.5px;
    color: var(--mud-palette-text-disabled);
}

@media (max-width: 820px) {
    /* The mockup's own :575-578. The Report tab's stacked-table block at :542-556 is a different query
       for a different element and belongs to Story 135.20. */
    .bb-detail-diffrow[b-63phjt8f8v] {
        flex-direction: column;
        gap: 6px;
    }

    .bb-detail-diffrow .bb-detail-diff-k[b-63phjt8f8v] {
        width: auto;
    }
}

.bb-detail-checkrow[b-63phjt8f8v] {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
    border-top: 1px solid var(--mud-palette-lines-default);
    font-size: 12.5px;
}

.bb-detail-checkrow:first-of-type[b-63phjt8f8v] {
    border-top: 0;
}

/* Story 146.3: a category never scored on this run (Evaluated == false) is neutral, not a failure -
   the row is a Playwright hook as much as a style, so its opacity must stay visibly distinct from a
   genuine-zero row's full-strength color. */
.bb-detail-checkrow--not-evaluated[b-63phjt8f8v] {
    opacity: 0.7;
}

.bb-detail-checkrow-name[b-63phjt8f8v] {
    flex: 1;
}

.bb-detail-checkrow-track[b-63phjt8f8v] {
    width: 110px;
    height: 5px;
    border-radius: 100px;
    background: var(--bb-surface-3);
    overflow: hidden;
    flex: none;
}

.bb-detail-checkrow-track i[b-63phjt8f8v] {
    display: block;
    height: 100%;
    background: var(--mud-palette-primary);
}

.bb-detail-checkrow-val[b-63phjt8f8v] {
    width: 52px;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-secondary);
}

.bb-detail-checkrow-feedback[b-63phjt8f8v] {
    margin: 0 0 6px;
    padding-left: 30px;
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}

@media (max-width: 640.98px) {
    /* Story 135.8 (AC4): {spacing.touch-target-min} - the hit area grows, the label does not. Same
       treatment WorkflowChildrenReport.razor.css:254-259 already gives its own buttons. */
    .bb-detail-tab[b-63phjt8f8v] {
        min-height: 44px;
    }
}

/* The subject line the detail-only rung opts into (ShowSubjectHeading). Deliberately the same visual
   weights as WorkflowHubHeader's own .bb-hub-head-id block, so the two rungs read as one surface even
   though only one of them mounts that header. Values are duplicated rather than shared because both
   files are CSS-isolated: a shared class would not cross the scope boundary. */
.bb-detail-subject[b-63phjt8f8v] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 9px;
    min-width: 0;
    margin-bottom: 12px;
}

.bb-detail-subject-type[b-63phjt8f8v] {
    padding: 2px 8px;
    border-radius: 5px;
    background: var(--mud-palette-action-default-hover, rgba(0, 0, 0, 0.04));
    color: var(--mud-palette-text-secondary, #757575);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.bb-detail-subject-title[b-63phjt8f8v] {
    margin: 0;
    font-size: 1.03rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    overflow-wrap: anywhere;
}

.bb-detail-subject-title--muted[b-63phjt8f8v] {
    color: var(--mud-palette-text-secondary);
    font-weight: 500;
}
/* /Components/Workflow/WorkflowDetailReportHost.razor.rz.scp.css */
/* Story 135.20 (AC 7c): the rollup read's caller-safe failure message. The hero renders the same message
   as a styled line (WorkflowMapRollup.razor.css); without a rule of its own here CSS isolation leaves it
   as bare body text inside the Report tab, so the same failure reads as an error in one view and as
   content in the other. */
.bb-detail-report-host-error[b-s5gea7hq7y] {
    margin-bottom: 10px;
    padding: 8px 12px;
    border: 1px solid var(--mud-palette-error);
    border-radius: 8px;
    background: var(--bb-bad-soft);
    color: var(--mud-palette-error);
    font-size: 0.75rem;
}
/* /Components/Workflow/WorkflowEdges.razor.rz.scp.css */
/* Story 135.6 review fix: these rules used to live in WorkflowTree.razor.css, which rendered its edge
   SVG inline and so kept them inside its own CSS-isolation scope. Story 135.6 deleted that canvas and
   made WorkflowMap.razor the FIRST component to render edges through WorkflowEdges.razor — leaving the
   classes this component's markup emits with no stroke rule anywhere in the app. An SVG <path> with a
   two-point "d" and no stroke paints nothing (the SVG default is fill:black; stroke:none), so every
   parent-child connector and dependency edge rendered invisibly while the arrowhead markers — the one
   CLOSED path — still filled. The rules belong here, in the stylesheet scoped to the component that
   emits the classes, so any future consumer inherits them. */

.bb-workflow-edges-svg[b-fzrzog1fhd] {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    overflow: visible;
}

/* Story 135.22 (AC 6, AC 7): color-mix rather than rgba(var(--mud-palette-primary-rgb), 0.45). The two
   forms compute the same colour - srgb mixing toward `transparent` is premultiplied, so 45% of an opaque
   colour is that colour at alpha 0.45 - and the raw computation is what the token layer exists to own.
   WorkflowMap.razor.css's legend swatch carries the same declaration, because the legend has to name what
   is actually drawn. */
.bb-workflow-edge--parent-child[b-fzrzog1fhd] {
    stroke: color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
    stroke-width: 1.75;
    fill: none;
}

/* Story 135.22 (AC 8, and the recolour Story 135.18 found and left here): the mockup draws a dependency
   in --mud-palette-warning (.e-dep, :405-407), not in --mud-palette-secondary. Secondary is a second
   accent and read as a variant of the parent-child line beside it; warning says "this one is waiting on
   something". The arrowhead below and the legend's dashed swatch move with it - all three are the same
   drawn object, and recolouring one leaves the other two lying about it. */
.bb-workflow-edge--dependency[b-fzrzog1fhd] {
    stroke: var(--mud-palette-warning);
    stroke-width: 1.5;
    stroke-dasharray: 6 4;
    stroke-linejoin: round;
    fill: none;
    opacity: 0.85;
}

/* Design call: Sally. Drawn immediately before the dashed stroke on the same path, so two dependency
   curves overlapping in a busy row cut cleanly against the canvas instead of hatching into each other. */
.bb-workflow-edge--dependency-halo[b-fzrzog1fhd] {
    stroke: var(--mud-palette-background, #f5f5f5);
    stroke-width: 4.5;
    fill: none;
}

/* Rendered only by the dependency path (WorkflowEdges.razor's marker-end), so it tracks the stroke above
   rather than being a colour of its own. */
.bb-workflow-edge-arrowhead[b-fzrzog1fhd] {
    fill: var(--mud-palette-warning);
}

/* Story 135.18 (AC 5): the hover/focus raise. Applied by workflow-tree.js's subscribeEdgeHighlight,
   which toggles them on every path whose data-edge-nodes names the hovered or focused card. Opacity and
   stroke-width only, so nothing here has to compose a palette colour. */
.bb-workflow-edge--lit[b-fzrzog1fhd] {
    opacity: 1;
    stroke-width: 2.4;
}

.bb-workflow-edge--dim[b-fzrzog1fhd] {
    opacity: 0.18;
}
/* /Components/Workflow/WorkflowHubHeader.razor.rz.scp.css */
/* Story 135.11 (AC5): the consolidated header row. Mirrors the mockup's .hubhead — one row that wraps
   rather than a fixed grid, so the compact width (max-width: 640.98px) needs no rule of its own here. */

/* Story 135.22 (AC 1): .hubhead's accent wash, drawn OVER --bb-surface rather than over the page, so the
   header reads as the top of the content column rather than as a tinted band floating on the page.
   The negative margin cancels the content column's own inset (--bb-hub-content-inset, declared on
   .bb-hub-content-column in Workflow.razor.css): the wash and the hairline below it are that column's top
   edge and have to meet the hierarchy panel's divider, while the 16px padding puts this row's text back
   in line with the Map or Detail content underneath. */
.bb-hub-head[b-4gwbj2f3xf] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px;
    margin-left: calc(-1 * var(--bb-hub-content-inset, 0px));
    padding: 11px 16px;
    border-bottom: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    background: linear-gradient(0deg, var(--bb-accent-soft), transparent), var(--bb-surface);
}

.bb-hub-head-left[b-4gwbj2f3xf] {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}

.bb-hub-head-ancestors[b-4gwbj2f3xf] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 2px;
}

.bb-hub-head-anctop[b-4gwbj2f3xf] {
    margin-right: 3px;
    font-size: 0.5625rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--mud-palette-text-disabled, #9e9e9e);
}

/* The unavailable-reason branch is a SENTENCE, not a label: .bb-hub-head-anctop is a 9px uppercase
   letter-spaced disabled-grey eyebrow sized for "IN" and "TOP OF THE TREE", and an 88-character
   sentence set in it was the least readable text in the header (review fix F6). Sized and coloured
   like the crumbs beside it instead - secondary rather than disabled, because unlike the eyebrow this
   is content the reader has to actually read. */
.bb-hub-head-ancnote[b-4gwbj2f3xf] {
    font-size: 0.72rem;
    font-weight: 500;
    line-height: 1.35;
    color: var(--mud-palette-text-secondary, #757575);
    overflow-wrap: anywhere;
}

.bb-hub-head-ancrumb[b-4gwbj2f3xf] {
    appearance: none;
    border: 0;
    background: none;
    font: inherit;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary, #757575);
    padding: 1px 4px;
    border-radius: 4px;
    cursor: pointer;
}

.bb-hub-head-ancrumb:hover[b-4gwbj2f3xf] {
    color: var(--mud-palette-primary, #594ae2);
    background: var(--mud-palette-primary-hover, rgba(89, 74, 226, 0.08));
}

.bb-hub-head-ancsep[b-4gwbj2f3xf] {
    color: var(--mud-palette-text-disabled, #9e9e9e);
    font-size: 0.69rem;
}

.bb-hub-head-id[b-4gwbj2f3xf] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 9px;
    min-width: 0;
}

.bb-hub-head-typebadge[b-4gwbj2f3xf] {
    padding: 2px 8px;
    border-radius: 5px;
    background: var(--mud-palette-action-default-hover, rgba(0, 0, 0, 0.04));
    color: var(--mud-palette-text-secondary, #757575);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.bb-hub-head-idmono[b-4gwbj2f3xf] {
    font-family: var(--mud-typography-default-family, monospace);
    font-size: 0.72rem;
    color: var(--mud-palette-text-disabled, #9e9e9e);
}

/* The anchor form needs its own colour: the rule above is a scoped class and outranks app.css's
   `a { color: var(--mud-palette-primary) }`, so without this the link would render in the same
   disabled grey as the unlinked span and carry no affordance at all. The unlinked span (no provider
   Url) deliberately keeps the grey — there is nothing to click. */
/* Underlined always, not on hover only: the linked and unlinked forms sit in the same slot with the same
   font and size, so colour would be the sole difference between "clickable" and "not" (WCAG 1.4.1). */
a.bb-hub-head-idmono[b-4gwbj2f3xf] {
    color: var(--mud-palette-primary, #594ae2);
    text-decoration: underline;
}

/* margin: 0 because this is an h2 (see the markup's note on why): a heading's UA margin would push it
   out of the flex row's baseline and add ~17px above and below the header. Every other value here is
   what it carried as a span, so the promotion changes semantics only. */
.bb-hub-head-title[b-4gwbj2f3xf] {
    margin: 0;
    font-size: 1.03rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    overflow-wrap: anywhere;
}

/* The stated-absence form, matching .bb-detail-subject-title--muted on the pane that states the same
   absence on the other rung. */
.bb-hub-head-title--muted[b-4gwbj2f3xf] {
    color: var(--mud-palette-text-secondary, #757575);
    font-weight: 500;
}

.bb-hub-head-right[b-4gwbj2f3xf] {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

/* Story 135.14 (AC 3): the root pin and the selection pin sit side by side. They carry the same glyph
   because they do the same thing, so the SUBJECT is what has to be distinguishable at a glance — hence
   the visible caption beside each, rendered only while both are on screen (see the markup's own note on
   why a tooltip alone was not enough). The selection pin additionally carries an outlined chip so the
   pair reads as two controls rather than one control with a label. */
.bb-hub-head-pins[b-4gwbj2f3xf] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 10px;
}

.bb-hub-head-pin[b-4gwbj2f3xf] {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    min-width: 0;
}

.bb-hub-head-pin-subject[b-4gwbj2f3xf] {
    max-width: 12rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--mud-palette-text-disabled, #9e9e9e);
}

.bb-hub-head-pin--selection[b-4gwbj2f3xf] {
    border: 1px dashed var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 999px;
    padding: 1px 8px 1px 1px;
}

.bb-hub-head-hint[b-4gwbj2f3xf] {
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--mud-palette-text-disabled, #9e9e9e);
}

/* Story 135.8 (AC4)'s touch floor, carried onto the pin toggle in its new home — the rule that used to
   live on .bb-workflow-root-pin-row in Workflow.razor.css, which Story 135.11 retires. */
@media (max-width: 640.98px) {
    .bb-hub-head-right[b-4gwbj2f3xf]  .mud-icon-button {
        min-width: 44px;
        min-height: 44px;
    }

    /* Fix cycle (review-135-11, patch #3/#4): WorkflowNavigationTree.razor already renders its own
       compact breadcrumb-over-list below this same boundary, over the identical ancestor chain — this
       row would be a second, redundant set of clickable crumbs at that width. Hiding it also moots the
       missing-touch-floor finding on .bb-hub-head-ancrumb, since none render here anymore.

       Scoped to the CRUMB rendering (review fix F3). The selector used to be .bb-hub-head-ancestors,
       which also hid the container's two other renderings — "Top of the tree" and the
       ancestors-unavailable sentence — and neither is a duplicate of anything the tree draws. On the
       standalone rung it is worse than redundant to hide them: that rung renders no
       alert-workflow-ancestors-unavailable at all (there is no ancestor-read failure to report), so
       below 641px the reason a parented item is drawn as a hierarchy of one disappeared from the page
       entirely and the one row read as the whole truth. */
    .bb-hub-head-ancestors--crumbs[b-4gwbj2f3xf] {
        display: none;
    }
}
/* /Components/Workflow/WorkflowMap.razor.rz.scp.css */
.bb-workflow-map-scroll[b-6ggql66paw] {
    position: relative;
}

.bb-workflow-map-canvas[b-6ggql66paw] {
    position: relative;
}

/* Story 135.18 (AC 1). The canvas is three bands with declared heights: the hero, a connector gutter
   that only holds parent/child rays, then card rows separated by a dependency lane that only holds
   dependency cables. The hero's own margin-bottom is deliberately absent — with one it made the
   hero-to-first-row distance 72px and the declared 56px band a fiction. The z-index puts the hero and
   the grid above the edge SVG, which is rendered after them in DOM order and absolutely positioned, so
   a future routing mistake passes behind a card rather than through its face. */
.bb-workflow-map-hero[b-6ggql66paw] {
    position: relative;
    z-index: 1;
    padding: 14px 18px;
    border-radius: 12px;
    border: 1px solid var(--bb-accent-line);
    background: linear-gradient(135deg, var(--bb-accent-soft), transparent 62%), var(--bb-surface-2);
}

.bb-workflow-map-gutter[b-6ggql66paw] {
    height: var(--bb-map-gutter);
}

.bb-workflow-map-hero-stats[b-6ggql66paw] {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin: 4px 0 8px;
}

.bb-workflow-map-hero-stat[b-6ggql66paw] {
    background: var(--bb-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 9px;
    padding: 6px 12px;
    min-width: 88px;
}

.bb-workflow-map-hero-stat-value[b-6ggql66paw] {
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1.2;
}

.bb-workflow-map-hero-stat-label[b-6ggql66paw] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.6));
}

/* .bb-workflow-map-rollup's own rules moved to WorkflowMapRollup.razor.css in Story 135.18: that is the
   component whose markup carries the class, and a CSS-isolation scope only ever matches its own
   component's elements — the rule was compiling to .bb-workflow-map-rollup[b-<WorkflowMap>] against an
   element stamped [b-<WorkflowMapRollup>] and had never applied. Story 135.22 deleted
   .bb-workflow-map-feature-exec from here for the same reason: WorkflowMapRollup.razor:81 is what emits
   it, so the rule had never applied either, and moving it would be a visual change nothing asked for. */
.bb-workflow-map-rollup-forbidden[b-6ggql66paw] {
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.6));
}

/* Story 135.18 (AC 2). A grid, not a wrapping flex row: align-items: stretch gives every card in a row
   the same height, so a row has exactly one bottom edge, the lane below it is a reserved band of known
   height, and an edge cannot cross a card at any card count for any content — with no collision routine
   to maintain. row-gap IS the dependency lane, which is why it reads the same token WorkflowEdges'
   MapLaneHeightPx is checked against. */
.bb-workflow-map-cards[b-6ggql66paw] {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(var(--bb-map-cardmin), 1fr));
    column-gap: var(--bb-map-colgap);
    row-gap: var(--bb-map-lane);
    align-items: stretch;
}

.bb-workflow-map-empty[b-6ggql66paw] {
    font-size: 0.875rem;
    color: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.6));
}

.bb-workflow-map-legend[b-6ggql66paw] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    margin-top: 12px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.6));
}

.bb-workflow-map-legend-item[b-6ggql66paw] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.bb-workflow-map-legend-swatch[b-6ggql66paw] {
    display: inline-block;
    width: 18px;
    height: 0;
    border-top-width: 1.75px;
    border-top-style: solid;
}

/* Same colours WorkflowEdges.razor.css uses for the two line kinds, so the legend swatches match what
   is actually drawn rather than an independent palette choice. Both moved with it in Story 135.22: the
   solid one from a raw rgba to the equivalent color-mix (AC 7), the dashed one to --mud-palette-warning
   (AC 8). A legend that keeps the old colour after the renderer changes is worse than no legend. */
.bb-workflow-map-legend-swatch--solid[b-6ggql66paw] {
    border-top-color: color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
}

.bb-workflow-map-legend-swatch--dashed[b-6ggql66paw] {
    border-top-color: var(--mud-palette-warning);
    border-top-style: dashed;
}

/* AC8: at compact, the Map keeps its hero/cards/edges in a horizontally scrollable canvas inside its
   own container — the page body never scrolls sideways. Same "compact" breakpoint the layout shell
   already uses (NavMenu.razor.css / MainLayout.razor.css). */
@media (max-width: 640.98px) {
    .bb-workflow-map-scroll[b-6ggql66paw] {
        overflow-x: auto;
    }

    /* Story 135.18 (AC 7): min-content, not width:max-content. The grid's tracks are
       minmax(--bb-map-cardmin, 1fr), and max-content resolves a flexible track against the content's
       max-content contribution rather than against that minimum, so the canvas scrolled to whatever the
       longest card title wanted. min-content is the mockup's own .mapcanvas rule and makes the track
       minimum the thing that scrolls. */
    .bb-workflow-map-canvas[b-6ggql66paw] {
        min-width: min-content;
    }
}
/* /Components/Workflow/WorkflowMapCard.razor.rz.scp.css */
/* Story 135.18 (AC 2, AC 4). No fixed width: the card is a grid item now, and a fixed width inside an
   auto-fill grid defeats the track sizing (--bb-map-cardmin is the minimum, and a 1fr track is what
   widens it). The 3px left accent is the single --bb-type-work: every Map card is a direct child of the
   hero, so all of them sit at one hierarchy position — Dev Note 3 records why the mockup's three
   type-name-keyed variants cannot be reproduced here. */
.bb-workflow-map-card[b-k2ltoy7fes] {
    display: flex;
    flex-direction: column;
    gap: 6px;
    text-align: left;
    padding: 11px 13px 12px;
    border-radius: 11px;
    border: 1px solid var(--mud-palette-lines-default, rgba(0, 0, 0, 0.12));
    border-left: 3px solid var(--bb-type-work);
    background: var(--mud-palette-surface, #fff);
    cursor: pointer;
    font: inherit;
    color: inherit;
    transition: border-color 120ms ease, background 120ms ease;
}

.bb-workflow-map-card:hover[b-k2ltoy7fes] {
    border-color: var(--bb-accent-line);
    background: var(--bb-surface-2);
}

.bb-workflow-map-card:focus-visible[b-k2ltoy7fes] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.bb-workflow-map-card[aria-pressed="true"][b-k2ltoy7fes] {
    border-color: var(--mud-palette-primary, #594ae2);
    box-shadow: 0 0 0 2px var(--mud-palette-primary, #594ae2) inset;
}

.bb-workflow-map-card-kicker[b-k2ltoy7fes] {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.75rem;
}

.bb-workflow-map-card-type-id[b-k2ltoy7fes] {
    color: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.6));
}

.bb-workflow-map-card-title[b-k2ltoy7fes] {
    font-weight: 600;
    font-size: 0.9375rem;
    line-height: 1.3;
}

.bb-workflow-map-card-score[b-k2ltoy7fes] {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.75rem;
}

.bb-workflow-map-card-score meter[b-k2ltoy7fes] {
    width: 80px;
}

.bb-workflow-map-card-fact[b-k2ltoy7fes],
.bb-workflow-map-card-last-action[b-k2ltoy7fes] {
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.6));
}

.bb-workflow-map-card-excerpt[b-k2ltoy7fes] {
    font-size: 0.75rem;
    font-style: italic;
    color: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.6));
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.bb-workflow-map-card-deps[b-k2ltoy7fes] {
    font-size: 0.75rem;
    color: var(--mud-palette-warning-darken, #a35b00);
}

.bb-workflow-map-card-progress[b-k2ltoy7fes] {
    display: flex;
    align-items: center;
    gap: 6px;
}

.bb-workflow-map-card-task-dots[b-k2ltoy7fes] {
    display: inline-flex;
    gap: 3px;
}

.bb-workflow-map-card-task-dot[b-k2ltoy7fes] {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--mud-palette-lines-default, rgba(0, 0, 0, 0.2));
}

.bb-workflow-map-card-task-dot--done[b-k2ltoy7fes] {
    background: var(--mud-palette-success, #2e7d32);
}

.bb-workflow-map-card-status-lines[b-k2ltoy7fes] {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.bb-workflow-map-card-status-line[b-k2ltoy7fes] {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.75rem;
    color: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.6));
}

.bb-workflow-map-card-status-dot[b-k2ltoy7fes] {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.4));
}

.bb-workflow-map-card-status-dot--good[b-k2ltoy7fes] {
    background: var(--mud-palette-success, #2e7d32);
}

.bb-workflow-map-card-status-dot--bad[b-k2ltoy7fes] {
    background: var(--mud-palette-error, #c62828);
}

.bb-workflow-map-card-status-value[b-k2ltoy7fes] {
    font-weight: 600;
}

.bb-workflow-map-card-status-when[b-k2ltoy7fes] {
    color: var(--mud-palette-text-disabled, rgba(0, 0, 0, 0.4));
    margin-left: auto;
}
/* /Components/Workflow/WorkflowMapRollup.razor.rz.scp.css */
.bb-workflow-map-rollup-scroll[b-oq9tj3qz4c] {
    position: relative;
}

.bb-workflow-map-rollup-canvas[b-oq9tj3qz4c] {
    position: relative;
}

/* Story 135.18 (AC 6), the mockup's .rollupline. These rules live here rather than in
   WorkflowMap.razor.css because this component's markup is what carries the class, and a CSS-isolation
   scope only matches its own component's elements — WorkflowMap.razor.css's copy compiled against the
   wrong scope attribute and had never applied. */
.bb-workflow-map-rollup[b-oq9tj3qz4c] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 11px;
    padding-top: 9px;
    border-top: 1px solid var(--bb-accent-line);
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}

.bb-workflow-map-rollup-risk-bar[b-oq9tj3qz4c] {
    display: flex;
    flex: 1;
    min-width: 120px;
    height: 6px;
    border-radius: 100px;
    overflow: hidden;
    background: var(--bb-surface-3);
}

.bb-workflow-map-rollup-risk-seg[b-oq9tj3qz4c] {
    display: block;
    height: 100%;
}

.bb-workflow-map-rollup-risk-seg--low[b-oq9tj3qz4c] { background: var(--mud-palette-success); }
.bb-workflow-map-rollup-risk-seg--medium[b-oq9tj3qz4c] { background: var(--mud-palette-warning); }
.bb-workflow-map-rollup-risk-seg--high[b-oq9tj3qz4c] { background: var(--mud-palette-error); }
.bb-workflow-map-rollup-risk-seg--unknown[b-oq9tj3qz4c] { background: var(--mud-palette-text-disabled); }

.bb-workflow-map-rollup-report-link[b-oq9tj3qz4c] {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-weight: 600;
    color: var(--mud-palette-primary);
    text-decoration: none;
    cursor: pointer;
}

.bb-workflow-map-rollup-report-link:hover[b-oq9tj3qz4c] {
    text-decoration: underline;
}

.bb-workflow-map-feature-exec[b-oq9tj3qz4c] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
}

/* The hub's own button treatment, matching WorkflowActionBar.razor.css's .bb-action-bar-button
   (the mockup's .actbtn): neutral on --bb-surface, going primary on hover. This was a bare <button>
   carrying only the compact hit-area rule below, so it rendered in the user agent's default chrome and
   did not read as a control at all. */
.bb-workflow-map-feature-exec-button[b-oq9tj3qz4c] {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 12px;
    border: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 8px;
    background-color: var(--bb-surface);
    color: inherit;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.bb-workflow-map-feature-exec-button:hover:not(:disabled)[b-oq9tj3qz4c] {
    border-color: var(--mud-palette-primary, #594ae2);
    color: var(--mud-palette-primary, #594ae2);
}

.bb-workflow-map-feature-exec-button:focus-visible[b-oq9tj3qz4c] {
    outline: 2px solid var(--mud-palette-primary, #594ae2);
    outline-offset: 2px;
}

.bb-workflow-map-feature-exec-button:disabled[b-oq9tj3qz4c] {
    color: var(--mud-palette-text-secondary, #757575);
    cursor: default;
    opacity: 0.5;
}

/* Story 135.8 (AC3, Task 3.2): reuses the exact WorkflowMap.razor.css:88 technique — at compact, wide
   content scrolls inside its own container rather than the page body. */
@media (max-width: 640.98px) {
    .bb-workflow-map-rollup-scroll[b-oq9tj3qz4c] {
        overflow-x: auto;
    }

    .bb-workflow-map-rollup-canvas[b-oq9tj3qz4c] {
        width: max-content;
        min-width: 100%;
    }

    /* Story 135.8 (AC4, Task 4.1): {spacing.touch-target-min} — the hit area grows, the label does not. */
    .bb-workflow-map-feature-exec-button[b-oq9tj3qz4c] {
        min-height: 44px;
    }

    /* Story 135.18: the "Open the report" affordance is a new interactive control in this same rollup
       line, so it inherits that rule rather than sitting quietly outside it. */
    .bb-workflow-map-rollup-report-link[b-oq9tj3qz4c] {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
    }
}
/* /Components/Workflow/WorkflowNavigationRail.razor.rz.scp.css */
/* Story 135.11 (AC3): the collapsed left column. Width matches the mockup's own .rail (50px), so the
   grid's left track narrows to a strip rather than reflowing the content column. */

.bb-nav-rail[b-yygxbu2ncd] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    width: 50px;
    padding: 10px 0;
}

.bb-nav-rail-path[b-yygxbu2ncd] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

.bb-nav-rail-step[b-yygxbu2ncd] {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    appearance: none;
    border: 1px solid transparent;
    border-radius: 7px;
    background: none;
    cursor: pointer;
}

.bb-nav-rail-step:hover[b-yygxbu2ncd] {
    background: var(--mud-palette-action-default-hover, rgba(0, 0, 0, 0.04));
}

/* AC3/AD-21: the ONLY per-step distinction is topological — where the step sits in the path — never
   its work-item type. */
.bb-nav-rail-step--current[b-yygxbu2ncd] {
    background: var(--mud-palette-primary-hover, rgba(89, 74, 226, 0.08));
    border-color: var(--mud-palette-primary, #594ae2);
}

.bb-nav-rail-step-dot[b-yygxbu2ncd] {
    width: 8px;
    height: 8px;
    border: 1px solid var(--mud-palette-text-secondary, #757575);
    border-radius: 50%;
}

.bb-nav-rail-step--current .bb-nav-rail-step-dot[b-yygxbu2ncd] {
    border-color: var(--mud-palette-primary, #594ae2);
    background: var(--mud-palette-primary, #594ae2);
}

.bb-nav-rail-tick[b-yygxbu2ncd] {
    width: 1px;
    height: 8px;
    background: var(--mud-palette-lines-default, #e0e0e0);
}
/* /Components/Workflow/WorkflowNavigationTree.razor.rz.scp.css */
/* Story 135.17: the tree is the panelled column's scroll area now (mockup .navscroll), so it carries no
   border or radius of its own - the column's own surface and right border are the panel. The
   :focus-visible ring below stays: this container is the tree's single tab stop and the ring is the only
   signal it has focus. */
.bb-nav-tree[b-0hw5hs136y] {
    outline: none;
    padding: 6px 0 10px;
    max-height: 560px;
    overflow-y: auto;
}

.bb-nav-tree:focus-visible[b-0hw5hs136y] {
    box-shadow: inset 0 0 0 2px var(--mud-palette-primary, #594ae2);
}

.bb-nav-row[b-0hw5hs136y] {
    position: relative;
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 5px 10px 5px 6px;
    cursor: pointer;
    border-left: 3px solid transparent;
    /* Story 135.3, AC5: the level-change transition is decoration over an already-complete state change —
       aria-selected/aria-level and every other signal below update synchronously in the same render; this
       transition only smooths how the highlight arrives. */
    transition: background-color 150ms ease, border-color 150ms ease;
}

.bb-nav-row:hover[b-0hw5hs136y] {
    background: var(--bb-surface-3);
}

/* The roving cursor and the committed selection are two different states - arrows move the cursor and
   never commit - so they keep two different fills rather than being merged into one.

   Both double their class deliberately, to outrank the :hover rule above. The mockup gets the same
   precedence for free (.tnode:hover and .tnode[aria-selected="true"] are equal specificity, so the later
   selected rule wins); here the isolation attribute plus :hover would otherwise beat a single class and
   the pointer would erase the selection fill on the row it is resting on. */
.bb-nav-row.bb-nav-row--cursor[b-0hw5hs136y] {
    background-color: var(--mud-palette-action-default-hover, rgba(89, 74, 226, 0.08));
}

.bb-nav-row.bb-nav-row--selected[b-0hw5hs136y] {
    background: var(--bb-accent-soft);
    border-left-color: var(--mud-palette-primary, #594ae2);
    font-weight: 600;
}

/* One hairline per ancestor level, so depth reads from the rails rather than from empty padding. The
   negative top/bottom is what makes a rail bleed into its neighbours and read as one continuous line. */
.bb-nav-row-guides[b-0hw5hs136y] {
    display: flex;
    flex: none;
    align-self: stretch;
}

.bb-nav-row-guides i[b-0hw5hs136y] {
    width: 12px;
    flex: none;
    position: relative;
}

.bb-nav-row-guides i[b-0hw5hs136y]::before {
    content: "";
    position: absolute;
    left: 5px;
    top: -3px;
    bottom: -3px;
    width: 1px;
    background: var(--mud-palette-lines-default, #e0e0e0);
}

.bb-nav-row-type-icon[b-0hw5hs136y] {
    flex: none;
    width: 16px;
    height: 16px;
    display: grid;
    place-items: center;
}

/* MudIcon renders its own <svg>, which this component's isolated CSS cannot reach without ::deep - the
   same technique WorkflowDetailPane.razor.css uses for MudIconButton. */
.bb-nav-row-type-icon[b-0hw5hs136y]  svg {
    width: 14px;
    height: 14px;
}

.bb-nav-row-type-icon--portfolio[b-0hw5hs136y] {
    color: var(--bb-type-portfolio);
}

.bb-nav-row-type-icon--container[b-0hw5hs136y] {
    color: var(--bb-type-container);
}

.bb-nav-row-type-icon--work[b-0hw5hs136y] {
    color: var(--bb-type-work);
}

.bb-nav-row-type-icon--subtask[b-0hw5hs136y] {
    color: var(--bb-type-subtask);
}

.bb-nav-row-chevron[b-0hw5hs136y] {
    display: inline-block;
    width: 14px;
    flex-shrink: 0;
    transition: transform 150ms ease;
}

.bb-nav-row-chevron--collapsed[b-0hw5hs136y] {
    transform: rotate(0deg);
}

.bb-nav-row-chevron:not(.bb-nav-row-chevron--collapsed)[b-0hw5hs136y] {
    transform: rotate(90deg);
}

.bb-nav-row-chevron-spacer[b-0hw5hs136y] {
    display: inline-block;
    width: 14px;
    flex-shrink: 0;
}

.bb-nav-row-title[b-0hw5hs136y] {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.8125rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Story 135.3, AC5: instant under reduced motion — the transition above is decoration only, never the
   sole signal the selection moved (the row's border/weight and aria-selected update either way). */
@media (prefers-reduced-motion: reduce) {
    .bb-nav-row[b-0hw5hs136y],
    .bb-nav-row-chevron[b-0hw5hs136y] {
        transition: none;
    }
}

/* ── Story 135.8 (AC1, AD-13): compact breadcrumb-over-list ────────────────────────────────────
   Both .bb-nav-tree (above) and .bb-nav-compact are always in the DOM; only one is shown per the
   shell's existing (max-width: 640.98px) boundary — no new threshold, matching WorkflowMap.razor.css's
   own compact rule for this same component family. display:none also removes the hidden view from
   the accessibility tree and the tab order, so nothing doubles up for keyboard/AT users. */
.bb-nav-compact[b-0hw5hs136y] {
    display: none;
}

.bb-nav-breadcrumb[b-0hw5hs136y] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    padding: 8px;
    border: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 4px 4px 0 0;
    border-bottom: none;
}

.bb-nav-breadcrumb-crumb[b-0hw5hs136y] {
    appearance: none;
    border: none;
    background: transparent;
    color: var(--mud-palette-primary, #594ae2);
    font: inherit;
    font-size: 0.8125rem;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 4px;
}

.bb-nav-breadcrumb-crumb:hover[b-0hw5hs136y] {
    background-color: var(--mud-palette-action-default-hover, rgba(89, 74, 226, 0.08));
}

.bb-nav-breadcrumb-sep[b-0hw5hs136y] {
    color: var(--mud-palette-text-secondary, #757575);
}

.bb-nav-breadcrumb-current[b-0hw5hs136y] {
    font-size: 0.8125rem;
    font-weight: 600;
    overflow-wrap: anywhere;
}

.bb-nav-compact-list[b-0hw5hs136y] {
    border: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 0 0 4px 4px;
    max-height: 480px;
    overflow-y: auto;
}

.bb-nav-compact-list-empty[b-0hw5hs136y] {
    padding: 8px;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary, #757575);
}

.bb-nav-compact-row[b-0hw5hs136y] {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    text-align: left;
    appearance: none;
    border: none;
    border-bottom: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    background: transparent;
    font: inherit;
    color: inherit;
    cursor: pointer;
    padding: 4px 8px;
}

.bb-nav-compact-row:last-child[b-0hw5hs136y] {
    border-bottom: none;
}

.bb-nav-compact-row-type[b-0hw5hs136y] {
    font-size: 0.75rem;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary, #757575);
    flex-shrink: 0;
    min-width: 4.5em;
}

.bb-nav-compact-row-title[b-0hw5hs136y] {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bb-nav-compact-row-id[b-0hw5hs136y] {
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary, #757575);
    flex-shrink: 0;
}

@media (max-width: 640.98px) {
    .bb-nav-tree[b-0hw5hs136y] {
        display: none;
    }

    .bb-nav-compact[b-0hw5hs136y] {
        display: block;
    }

    /* {spacing.touch-target-min}: the hit area grows, the label does not (DESIGN.md's "grow the hit
       area, not the visual pill" — same technique as MainLayout.razor.css's compact touch-floor rules). */
    .bb-nav-breadcrumb-crumb[b-0hw5hs136y],
    .bb-nav-compact-row[b-0hw5hs136y] {
        min-height: 44px;
    }
}
/* /Components/Workflow/WorkflowPinnedPanel.razor.rz.scp.css */
/* Story 135.14 (AC 2): the compact badge and the popover it expands. The root is the popover's
   positioning context, and stays inline so it can sit in the hub toolbar row beside the id input
   without stretching it. */
.bb-pinned-badge-root[b-7krhln8h8b] {
    position: relative;
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
}

/* Story 135.22 (AC 1, AC 3): this badge is the shipped form of the mockup's .pinbadge (:173-176), the one
   drawn part of a component the story otherwise exempts from fidelity. On the accent pair rather than a
   neutral outline: it is the second way into an item and belongs with the toolbar's accent, not with the
   page chrome. */
.bb-pinned-badge[b-7krhln8h8b] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    appearance: none;
    font: inherit;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--mud-palette-primary, #594ae2);
    background: var(--bb-accent-soft);
    border: 1px solid var(--bb-accent-line);
    border-radius: 100px;
    padding: 4px 11px;
    cursor: pointer;
}

.bb-pinned-badge:hover:not(:disabled)[b-7krhln8h8b] {
    border-color: var(--mud-palette-primary, #594ae2);
}

.bb-pinned-badge:disabled[b-7krhln8h8b] {
    cursor: default;
    opacity: 0.6;
}

.bb-pinned-badge-count[b-7krhln8h8b] {
    min-width: 1.4em;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--bb-surface-3);
    font-variant-numeric: tabular-nums;
    text-align: center;
}

.bb-pinned-badge-count--unknown[b-7krhln8h8b] {
    color: var(--mud-palette-text-disabled, #9e9e9e);
}

/* The list is disclosed OVER the page rather than pushing it down: reserving the space again would
   undo the whole point of replacing the always-expanded region.

   Anchored to the badge's RIGHT edge, not its left. The badge is the last control in the hub toolbar
   row, so a left-anchored popover ran off the right edge of the viewport and clipped every row's own
   activate/unpin buttons — caught by a rendered screenshot, invisible to the DOM-level tests, which is
   the failure mode a purely DOM-asserted popover has. */
.bb-pinned-popover[b-7krhln8h8b] {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 20;
    min-width: 22rem;
    max-width: min(28rem, 90vw);
    padding: 8px;
    background: var(--bb-surface);
    border: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 12px;
    box-shadow: var(--mud-elevation-8, 0 5px 5px -3px rgba(0, 0, 0, 0.2));
}

/* Story 135.8 (AC3, Task 3.1): bounded, internally-scrolling list — matches
   WorkflowNavigationTree.razor.css's .bb-nav-tree pattern (border/radius/max-height/overflow-y),
   at every width, not only compact: the list previously grew unbounded above the tree regardless
   of viewport. */
.bb-pinned-panel-list[b-7krhln8h8b] {
    border: 1px solid var(--mud-palette-lines-default, #e0e0e0);
    border-radius: 8px;
    max-height: 320px;
    overflow-y: auto;
    background: var(--bb-surface-2);
}

/* Story 135.8 (AC4, Task 4.1): {spacing.touch-target-min} at compact — the hit area grows, the
   glyph does not. MudIconButton renders its own internal <button>, which needs ::deep to reach from
   this component's .razor.css (same technique as MainLayout.razor.css's .top-bar ::deep rule). */
@media (max-width: 640.98px) {
    .bb-pinned-panel-row-actions[b-7krhln8h8b]  .mud-icon-button {
        min-width: 44px;
        min-height: 44px;
    }

    /* Story 135.14: the badge is now the only way into this list, so it inherits the same touch floor. */
    .bb-pinned-badge[b-7krhln8h8b] {
        min-height: 44px;
    }

    .bb-pinned-popover[b-7krhln8h8b] {
        min-width: 0;
        width: max-content;
        max-width: 90vw;
    }
}
/* /Components/Workflow/WorkflowReleaseNoteReport.razor.rz.scp.css */
.bb-release-note-report[b-quz5idc64h] {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background: var(--mud-palette-surface);
    margin-top: 8px;
    padding: 12px;
    max-width: calc(100vw - 2rem);
}

.bb-release-note-caption[b-quz5idc64h] {
    margin: 0 0 6px 0;
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
}

/* Bounded, internally-scrolling read-only long-text disclosure (DESIGN.md), never monospace. */
.bb-release-note-body[b-quz5idc64h] {
    max-height: 320px;
    overflow-y: auto;
    white-space: pre-wrap;
}

.bb-release-note-note[b-quz5idc64h] {
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
}
/* /Components/Workflow/WorkflowViewSwitch.razor.rz.scp.css */
/* Story 135.22 (AC 1): the mockup's .viewswitch (:288-304). The track reads --bb-surface-3 rather than
   the flat --mud-palette-background-gray it used to, so the pressed segment's own --bb-surface has a
   tier to sit above instead of only a drop shadow to imply one. */
.bb-workflow-view-switch[b-pw4fj24i5f] {
    display: inline-flex;
    gap: 2px;
    padding: 2px;
    border-radius: 9px;
    background: var(--bb-surface-3);
    border: 1px solid var(--mud-palette-lines-default, rgba(0, 0, 0, 0.12));
}

.bb-workflow-view-switch-button[b-pw4fj24i5f] {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: none;
    background: transparent;
    color: var(--mud-palette-text-secondary, rgba(0, 0, 0, 0.6));
    font-size: 0.8125rem;
    font-weight: 600;
    padding: 5px 15px;
    border-radius: 7px;
    cursor: pointer;
}

.bb-workflow-view-switch-button:hover[b-pw4fj24i5f] {
    background: var(--mud-palette-action-default-hover, rgba(0, 0, 0, 0.04));
}

/* An accent INSET RING, not a drop shadow. A shadow is a light-mode idiom that all but disappears
   against a dark track, and the ring is drawn from the same accent hairline the rest of the hub uses. */
.bb-workflow-view-switch-button[aria-pressed="true"][b-pw4fj24i5f] {
    background: var(--bb-surface);
    color: var(--mud-palette-primary, #594ae2);
    box-shadow: inset 0 0 0 1px var(--bb-accent-line);
}

/* The mockup's .viewswitch svg (:304) at 14px. MudIcon renders the <svg> from its own component, so it
   carries no scope attribute of this stylesheet's and can only be reached through ::deep - the same
   technique WorkflowHubHeader.razor.css uses for the pins' MudIconButton. */
.bb-workflow-view-switch-button[b-pw4fj24i5f]  .mud-icon-root {
    font-size: 14px;
    flex-shrink: 0;
}

.bb-workflow-view-switch-button[aria-disabled="true"][b-pw4fj24i5f] {
    color: var(--mud-palette-text-disabled, rgba(0, 0, 0, 0.38));
    cursor: not-allowed;
}

/* Story 135.8 (AC4, Task 4.1): {spacing.touch-target-min} at compact — the hit area grows, the
   label does not. */
@media (max-width: 640.98px) {
    .bb-workflow-view-switch-button[b-pw4fj24i5f] {
        min-height: 44px;
        min-width: 44px;
    }
}
/* /Components/WorkItemBasket/WorkItemBasketPanel.razor.rz.scp.css */
/* {components.work-item-basket}. Only MudBlazor palette variables, never literal hues, so the dark
   palette swap reaches this component like every other shell surface — except the backdrop, which
   DESIGN.md fixes as a literal black alpha in both palettes (matching scope-sheet's own backdrop). */

.work-item-basket-backdrop[b-b3yu4jb44n] {
    position: fixed;
    inset: 0;
    z-index: 1150;
    background-color: rgba(0, 0, 0, 0.42);
}

.work-item-basket[b-b3yu4jb44n] {
    display: flex;
    flex-direction: column;
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
}

.work-item-basket:focus[b-b3yu4jb44n] {
    outline: none;
}

/* Story 135.25: --panel now carries TWO geometries, and the {breakpoints.md} 1024px boundary below
   chooses between them — the DOCK at mode-full (the content row reserves its width beside it, so the
   page keeps every pixel it had, narrower) and the OVERLAY at mode-medium (laid over the content row
   with a deeper shadow and a non-interactive ink wash, because in that band there is no width to
   give). The modifier keeps its name: Story 135.24 renamed it one wave ago and renaming it again for
   a geometry split would be churn, but leaving the split undocumented is the thing that would
   actually mislead.

   What both share is the box: the panel is pinned to the CONTENT ROW rather than the viewport, so it
   starts below the top bar and the scope bar the way the mockup's frame() draws it
   (work-item-basket.html:951-964 renders the scope bar full width ABOVE the stage that holds the
   dock). It stays out of flow because it is rendered outside `.page` — that DOM position is what
   lets one `inert` attribute cover the whole shell behind the compact sheet, and it is not
   negotiable. --bb-sticky-chrome-offset is read from the :root token layer for the same reason.

   The page behind it stays reachable at both widths: "any surface behind it can fill it" (Backlog
   Health's row-selection action, Map's Select mode) is now true by geometry rather than aspiration. */
.work-item-basket--panel[b-b3yu4jb44n] {
    position: fixed;
    top: var(--bb-sticky-chrome-offset);
    right: 0;
    bottom: 0;
    z-index: 1140;
    width: min(var(--bb-basket-width), 100vw);
    border-left: 1px solid var(--mud-palette-lines-default);
    /* The exact top edge: MainLayout publishes .content-row's box as --bb-content-row and this
       tracks it. TWO fallbacks are declared and they catch different failures, so neither is
       redundant. The `top` declaration above catches a browser that cannot PARSE anchor(): the
       declaration below is then invalid at parse time and dropped, and the earlier one wins. The
       argument inside anchor() catches a browser that parses it but cannot RESOLVE the anchor -
       css-anchor-position-1 3.2.1 makes that invalid at computed-value time, which happens AFTER the
       cascade has already discarded the earlier declaration, so without the argument `top` would
       compute to `auto` and the panel would become a content-height box pinned to the bottom edge.

       The token cannot do this job on its own: it is calc(2.6rem + 54px), the scope bar's MINIMUM,
       and the bar is taller whenever a node wraps (measured on the hub: the row starts at 96px at
       1440px but at 128px at 1280px). Wherever the token is all there is, the panel's top strip
       overlays the bar's lower band by that difference. */
    top: anchor(--bb-content-row top, var(--bb-sticky-chrome-offset));
    /* Mockup .dock (:112). overflow: hidden is the one that acts here: it contains the panel's own
       overflow inside its box. min-height: 0 is carried for parity with the mockup and is inert on
       this element - a fixed box with both `top` and `bottom` resolved is not a flex item, so its
       min-height already computes to 0. The declaration that actually keeps the footer's Run CTA in
       view is min-height: 0 on .work-item-basket-members below. */
    min-height: 0;
    overflow: hidden;
}

/* mode-medium: the overlay. The deeper single-sided shadow (mockup :113-114) against the dock's
   shallower one, because here the panel is above the content rather than beside it and has to say
   so. The 5% wash that completes this treatment is painted by the shell on .content-row::after —
   it belongs to the page area, not to this component's box. */
@media (min-width: 641px) and (max-width: 1023.98px) {
    .work-item-basket--panel[b-b3yu4jb44n] {
        box-shadow: -18px 0 44px -26px rgba(20, 40, 40, 0.42);
    }
}

/* mode-full: the dock. The shell reserves this width on .content-row, so nothing is covered and the
   shadow is only the seam between two adjacent surfaces. */
@media (min-width: 1024px) {
    .work-item-basket--panel[b-b3yu4jb44n] {
        box-shadow: -14px 0 34px -22px rgba(20, 40, 40, 0.35);
    }
}

/* AC 7, compact: the modal bottom sheet, matching scope-sheet's own shape. */
.work-item-basket--sheet[b-b3yu4jb44n] {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1151;
    max-height: 80dvh;
    /* Story 135.10: the verb bar (5 verb cards, skip lines, per-run outcomes) can push total content
       past 80dvh — without this, overflow is visible by default and the excess paints below the
       sheet's own box, over the backdrop's screen area, intercepting clicks meant for the backdrop
       (the exact "subtree intercepts pointer events" failure this line fixes). */
    overflow-y: auto;
    border-radius: 0.875rem 0.875rem 0 0;
    box-shadow: 0 -8px 28px rgba(0, 0, 0, 0.22);
    padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* Story 135.30, AC 8: the mockup's .grabber (work-item-basket.html:218), rendered only at compact so
   the rule needs no media query of its own. Sized from the SHIPPED scope-sheet-grabber (36x4) rather
   than the drawing's 34x4 where the two disagree: the point is that the app's two bottom sheets read as
   one language, and a 2px difference minted here would be the only thing distinguishing them. The
   margin is the mockup's, because unlike .scope-sheet this panel has no top padding for the ornament to
   sit inside. */
.work-item-basket-grabber[b-b3yu4jb44n] {
    flex-shrink: 0;
    width: 36px;
    height: 4px;
    margin: 8px auto 0;
    border-radius: 9999px;
    background-color: var(--mud-palette-lines-default);
}

.work-item-basket-header[b-b3yu4jb44n] {
    flex: none;
    padding: 0.75rem 1rem 0.5rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.work-item-basket-header-row[b-b3yu4jb44n] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.work-item-basket-title[b-b3yu4jb44n] {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 660;
    line-height: 1.3;
}

/* 32x32 on a 17px glyph, with negative vertical margins so the grown target does not grow the header
   row - the same rule .work-item-basket-row-remove states for the same reason. */
.work-item-basket-pin[b-b3yu4jb44n] {
    margin-left: auto;
    margin-top: -0.4rem;
    margin-bottom: -0.4rem;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: none;
    background: none;
    border-radius: 0.375rem;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

.work-item-basket-pin:hover[b-b3yu4jb44n] {
    color: var(--mud-palette-text-primary);
    background-color: var(--mud-palette-action-default-hover);
}

.work-item-basket-pin[aria-pressed="true"][b-b3yu4jb44n] {
    color: var(--mud-palette-primary);
}

.work-item-basket-pin:focus-visible[b-b3yu4jb44n] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* ::deep because the class lands on MudIcon's own <svg>, a child component's element, which never
   carries this stylesheet's scope attribute - without it the rule is dead and the glyph renders at
   MudBlazor's 24px default. Same reason .work-item-basket-row-remove-icon uses it below. */
.work-item-basket-pin[b-b3yu4jb44n]  .work-item-basket-pin-icon {
    width: 17px;
    height: 17px;
}

/* The pin takes the auto margin when it is present, so Close sits next to it rather than the two
   splitting the free space. The pin renders only at wide, so at compact this never matches and
   Close keeps its own auto margin below. */
.work-item-basket-pin ~ .work-item-basket-close[b-b3yu4jb44n] {
    margin-left: 0;
}

.work-item-basket-close[b-b3yu4jb44n] {
    margin-left: auto;
    border: none;
    background: none;
    font: inherit;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

.work-item-basket-close:hover[b-b3yu4jb44n] {
    color: var(--mud-palette-primary);
}

.work-item-basket-chips[b-b3yu4jb44n] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.45rem;
}

.work-item-basket-chip[b-b3yu4jb44n] {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    padding: 0.05rem 0.45rem;
    border-radius: 0.25rem;
    background-color: var(--mud-palette-background-gray);
    color: var(--mud-palette-text-secondary);
}

.work-item-basket-chip--temporary[b-b3yu4jb44n] {
    text-transform: uppercase;
}

/* Story 135.29, AC 3/AC 8: the mockup's .clearbtn (work-item-basket.html:128-129) on the header's
   chips row at margin-left: auto. Borderless and unboxed is what retires the fourth button scale the
   footer version was - the three tiers left are commit (the Run CTA), control (the fill and verb
   controls) and inline (this, Close, and the confirm band's two buttons). */
.work-item-basket-clear[b-b3yu4jb44n] {
    margin-left: auto;
    border: none;
    background: none;
    font: inherit;
    font-size: 0.69rem;
    font-weight: 600;
    padding: 0.125rem 0.25rem;
    border-radius: 0.3125rem;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

/* {colors.error-text} rather than the base error hue: this is 11px text, so it takes the derived
   foreground companion for the same reason the --bad outcome tone does. */
.work-item-basket-clear:hover[b-b3yu4jb44n] {
    color: var(--bb-bad-text);
}

.work-item-basket-clear:focus-visible[b-b3yu4jb44n] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* Story 135.29, AC 3: the mockup's .confirm (work-item-basket.html:130), inside the header container
   beneath its two rows. An error-tinted fill under an error hairline, so the one destructive action in
   the panel does not look like the rest of the header. */
.work-item-basket-confirm-clear[b-b3yu4jb44n] {
    margin-top: 0.5625rem;
    padding: 0.5rem 0.625rem;
    border: 1px solid var(--mud-palette-error);
    border-radius: 0.5rem;
    background-color: var(--bb-bad-soft);
    color: var(--mud-palette-text-primary);
    font-size: 0.72rem;
}

.work-item-basket-confirm-clear-prompt[b-b3yu4jb44n] {
    display: block;
}

/* Mockup .cr (:131). */
.work-item-basket-confirm-clear-row[b-b3yu4jb44n] {
    display: flex;
    align-items: center;
    gap: 0.4375rem;
    margin-top: 0.4375rem;
}

/* Mockup .cbtn (:132). The commit button beside it is MudBlazor's Filled/Error, which brings its own
   treatment - the mockup's .cbtn.danger is the same fill and the same on-error label, so it is not
   restyled here. */
.work-item-basket-confirm-clear-cancel[b-b3yu4jb44n] {
    font: inherit;
    font-size: 0.69rem;
    font-weight: 660;
    padding: 0.25rem 0.625rem;
    border-radius: 0.375rem;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

.work-item-basket-confirm-clear-cancel:hover[b-b3yu4jb44n] {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

.work-item-basket-confirm-clear-cancel:focus-visible[b-b3yu4jb44n] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* The inline tier's own measurements, applied to the MudButton so the commit does not arrive at
   MudBlazor's default button scale beside an 11px cancel. */
.work-item-basket-confirm-clear[b-b3yu4jb44n]  .work-item-basket-confirm-clear-commit {
    font-size: 0.69rem;
    font-weight: 660;
    padding: 0.25rem 0.625rem;
    border-radius: 0.375rem;
    min-width: 0;
    text-transform: none;
}

.work-item-basket-fillrow[b-b3yu4jb44n] {
    flex: none;
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
    padding: 0.6rem 1rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.work-item-basket-fillbtn[b-b3yu4jb44n] {
    font: inherit;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.3rem 0.6rem;
    border-radius: 0.4375rem;
    border: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

.work-item-basket-fillbtn:hover:not(:disabled)[b-b3yu4jb44n] {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

.work-item-basket-fillbtn:disabled[b-b3yu4jb44n] {
    cursor: not-allowed;
    opacity: 0.55;
}

/* Story 135.29, AC 8: demoted out of solid accent into the control tier beside its plain sibling.
   A second solid-accent commit in a panel whose whole point after Story 135.27 is that ONE button runs
   things is the competition that story removed. Accent border and accent text keep it
   distinguishable from the plain fillbtn without claiming to be the primary action; the mockup's own
   pastebox has no Add control at all (:772-775 is a textarea and a hint), so there was nothing to
   copy. */
.work-item-basket-fillbtn--primary[b-b3yu4jb44n] {
    align-self: flex-start;
    background-color: var(--bb-accent-soft);
    border-color: var(--bb-accent-line);
    color: var(--mud-palette-primary);
}

.work-item-basket-fillbtn--primary:hover:not(:disabled)[b-b3yu4jb44n] {
    border-color: var(--mud-palette-primary);
}

.work-item-basket-pastebox[b-b3yu4jb44n] {
    flex: none;
    padding: 0.6rem 1rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-background);
}

/* Story 135.28: the mockup's .ranhead (work-item-basket.html:199-202), which takes the verb bar's
   place in the dispatched state. flex: none like every other section except the member list — the
   band is two lines of fixed height, and the unbounded run log it replaces is what used to push the
   footer out of the panel. */
.work-item-basket-dispatched-band[b-b3yu4jb44n] {
    flex: none;
    padding: 0.625rem 1rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-primary-hover);
}

.work-item-basket-dispatched-band-title[b-b3yu4jb44n] {
    display: flex;
    align-items: center;
    gap: 0.4375rem;
    font-size: 0.78rem;
    font-weight: 660;
    color: var(--mud-palette-primary);
}

.work-item-basket-dispatched-band-title[b-b3yu4jb44n]  svg {
    width: 15px;
    height: 15px;
    flex: none;
}

.work-item-basket-dispatched-band-note[b-b3yu4jb44n] {
    margin-top: 0.1875rem;
    font-size: 0.69rem;
    color: var(--mud-palette-text-secondary);
}

/* {components.work-item-basket.members}: the member list scrolls INSIDE the panel with the footer
   pinned and reachable (AC 6). min-height:0 is required — a flex item defaults to min-height:auto,
   which refuses to shrink below its content, so without it the list overflows instead of scrolling.

   Story 135.25, AC 10: this is the ONLY section that gives. Every other one is flex: none, so a
   growing skip line or run log can never squeeze the list the basket exists to show. Removing the
   min-height: 0 below is also the mutation that proves the footer-in-bounds guard. */
.work-item-basket-members[b-b3yu4jb44n] {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.work-item-basket-group[b-b3yu4jb44n] {
    position: sticky;
    top: 0;
    padding: 0.4rem 1rem 0.15rem;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    background-color: var(--mud-palette-surface);
}

/* Story 135.28: the mockup's .mrow anatomy (work-item-basket.html:172-183) — icon, a text column
   holding the title over one or two meta lines, then the remove control. align-items: flex-start
   rather than center because the column is now taller than the icon. */
.work-item-basket-row[b-b3yu4jb44n] {
    display: flex;
    align-items: flex-start;
    gap: 0.5625rem;
    padding: 0.4375rem 1rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    font-size: 0.75rem;
}

/* The icon is rendered by MudIcon, whose root element is the child component's own, so the panel's
   scoped attribute never lands on it — ::deep is what reaches it. */
.work-item-basket-row[b-b3yu4jb44n]  .work-item-basket-row-icon {
    flex: none;
    margin-top: 0.1875rem;
    width: 14px;
    height: 14px;
    color: var(--mud-palette-text-secondary);
}

/* Story 135.29, AC 9: the token this hook was minted for. ONE accent, deliberately - the per-position
   differentiation --bb-type-defect and --bb-type-subtask would carry is blocked (no provider-neutral
   hierarchy classifier is reachable from Web, and the basket has no topology to derive a position from
   because its members share no parent by definition). Story 135.28's deferred-work entry, "The member
   row's type icon is ONE glyph", owns that decision; this story matches it rather than adding a second
   record of the same blocker. */
.work-item-basket-row[b-b3yu4jb44n]  .work-item-basket-row-icon--work {
    color: var(--bb-type-work);
}

.work-item-basket-row-text[b-b3yu4jb44n] {
    flex: 1 1 auto;
    min-width: 0;
}

.work-item-basket-row-title[b-b3yu4jb44n] {
    display: block;
    color: var(--mud-palette-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.work-item-basket-row-meta[b-b3yu4jb44n] {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    min-width: 0;
    font-size: 0.66rem;
    color: var(--mud-palette-text-secondary);
}

.work-item-basket-row-id[b-b3yu4jb44n] {
    flex-shrink: 0;
    font-family: ui-monospace, "Cascadia Code", Menlo, Consolas, monospace;
    color: var(--mud-palette-text-secondary);
}

/* min-width: 0 is what makes the ellipsis reachable. A flex item defaults to min-width: auto, which
   for white-space: nowrap floors it at the whole string, so without this the parent line overflows the
   row and gives the member list a horizontal scrollbar instead of clipping. Real ADO titles are long
   enough to hit it in a 424px dock. */
.work-item-basket-row-parent[b-b3yu4jb44n] {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The mockup's .outcome / .dot (work-item-basket.html:185-187). The dot takes currentColor, so the
   tone modifier below colours the sentence and its marker in one declaration. */
.work-item-basket-row-outcome[b-b3yu4jb44n] {
    display: inline-flex;
    align-items: center;
    gap: 0.3125rem;
    min-width: 0;
    font-weight: 600;
}

.work-item-basket-row-outcome-dot[b-b3yu4jb44n] {
    flex: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: currentColor;
}

.work-item-basket-row-outcome--good[b-b3yu4jb44n] {
    color: var(--mud-palette-success);
}

/* {colors.warning-text}, not the base warning hue. BacklogBouncerTheme parks amber TEXT in
   WarningDarken precisely because #F57C00 measures ~2.7:1 on the light surface: the base hue is a
   fill/border/icon/dot value only. WarningDarken carries #8F4700 in light and #FFA726 in dark, both
   AA at this 0.66rem size, and the dot inherits it through currentColor. */
.work-item-basket-row-outcome--warn[b-b3yu4jb44n] {
    color: var(--mud-palette-warning-darken);
}

/* Story 135.29: the derived error-as-text companion, not the base error hue. review-135-28 measured
   var(--mud-palette-error) at 4.39:1 in the dark palette on this surface at 10.56px/600 - just under
   AA - and the token layer derives --bb-bad-text by mixing toward the palette's own text colour, which
   lifts light to 7.68:1 and dark to 5.35:1. The dot takes currentColor, so the sentence and its marker
   move together in one declaration, exactly as the --warn rule above does with WarningDarken. */
.work-item-basket-row-outcome--bad[b-b3yu4jb44n] {
    color: var(--bb-bad-text);
}

.work-item-basket-row-outcome--none[b-b3yu4jb44n] {
    color: var(--mud-palette-text-secondary);
}

/* The mockup dims the whole row (.mrow.skipped, opacity: .5). Measured against both palettes, that
   puts the row's own text at 2.6:1 (light) and 2.9:1 (dark) against the panel surface, and the meta
   lines lower still — so the drawing is narrowed to the icon, and every text run stays at full
   opacity. Dimming the sentence that says WHY the member was not in the run would have defeated the
   story. The kind stays legible without it: it is written in words and carried in the tone hue. */
.work-item-basket-row--not-in-run[b-b3yu4jb44n]  .work-item-basket-row-icon {
    opacity: 0.5;
}

/* Story 135.29, AC 5: the mockup's .mrow .rm (work-item-basket.html:179-182) and the rule its own
   comment states - "32px hit area on a 14px glyph: the target grows, the visual control does not". The
   negative margins are what keep the grown box from growing the row, and the member list is the one
   thing the panel exists to show.

   32px rather than 44px at these widths is not a shortfall: DESIGN.md:455 scopes the touch floor to
   compact, and Story 135.30 owns the 44px compact override. Its selector must BEAT this rule's
   specificity, not match it - the mockup documents that silent failure at :276-278. */
.work-item-basket-row-remove[b-b3yu4jb44n] {
    flex: none;
    width: 32px;
    height: 32px;
    margin: -6px -8px -6px 0;
    display: grid;
    place-items: center;
    border: none;
    border-radius: 6px;
    background: none;
    line-height: 1;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

/* MudIcon's root element is the child component's own, so the panel's scoped attribute never lands on
   it - ::deep is what reaches it, the same as the row's type icon above. */
.work-item-basket-row-remove[b-b3yu4jb44n]  .work-item-basket-row-remove-icon {
    width: 14px;
    height: 14px;
}

.work-item-basket-row-remove:hover[b-b3yu4jb44n] {
    color: var(--mud-palette-error);
    background-color: var(--bb-bad-soft);
}

.work-item-basket-row-remove:focus-visible[b-b3yu4jb44n] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

/* Story 135.29, AC 2/AC 9: the two WorkspaceEmptyState instances this panel can render.
   WorkspaceEmptyState is a full-page shape - MudPaper `pa-8` (32px on every side), a Size.Large icon
   and an h6 - which is heavy in a 424px dock and not viable in a compact sheet whose whole member-list
   budget is around 112px. It has 14 consumers, so the density is corrected from HERE with ::deep rules
   scoped to the two wrappers rather than by widening the shared component with a Class or Dense
   parameter. MainLayout.razor.css's ::deep block for the basket trigger is the in-repo precedent.

   Values are the mockup's own: .emptybox is 26px/20px padding with a 30px glyph at 60% opacity, a
   13px/660 heading and an 11.5px body capped at 30ch (:189-192); .whocan is 12px/16px margin,
   11px/13px padding, 9px radius, a surface-2 fill with a line hairline, a 12px/660 heading, a 14px
   warning glyph and an 11.5px body (:194-197). Story 135.30 adjusts these rather than re-deriving.

   !important on the padding, the margin-bottoms and align-items is NOT decoration and must not be
   tidied away. WorkspaceEmptyState dresses those four elements in MudBlazor utility classes - pa-8 on
   the paper, mb-2/mb-1/mb-4 on the glyph, title and body, align-center on the paper - and MudBlazor
   9.5.0 ships every one of them as !important (`.pa-8{padding:32px !important}`,
   `.align-center{align-items:center !important}`, verified in the packaged MudBlazor.min.css). An
   author !important is only beatable by another author !important, at any specificity, so without
   these the whole block silently resolves back to 32px on all sides, centre alignment and a 16px
   trailing margin - measured in Chromium at 2026-08-26, which is how this was caught. Only the
   declarations that actually collide carry it; the sizes, colours and line-heights below do not. */
.work-item-basket-empty[b-b3yu4jb44n]  .mud-paper {
    padding: 26px 20px !important;
    background-color: transparent;
    text-align: center;
}

.work-item-basket-empty[b-b3yu4jb44n]  .mud-icon-root {
    width: 30px;
    height: 30px;
    font-size: 30px;
    opacity: 0.6;
    margin-bottom: 0.5625rem !important;
}

.work-item-basket-empty[b-b3yu4jb44n]  .mud-typography-h6 {
    margin-bottom: 0.25rem !important;
    font-size: 0.8125rem;
    font-weight: 660;
    line-height: 1.35;
}

.work-item-basket-empty[b-b3yu4jb44n]  .mud-typography-body2 {
    margin-bottom: 0 !important;
    max-width: 30ch;
    font-size: 0.72rem;
    line-height: 1.45;
    color: var(--mud-palette-text-secondary);
}

.work-item-basket-who-can-help[b-b3yu4jb44n] {
    flex: none;
    margin: 0.75rem 1rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 0.5625rem;
    background-color: var(--bb-surface-2);
}

/* align-items: flex-start rather than the component's own centre: this band is a paragraph of guidance
   in a 424px column, not a centred full-page state, and centring three lines of prose makes the
   ragged edge the first thing the eye follows. */
.work-item-basket-who-can-help[b-b3yu4jb44n]  .mud-paper {
    padding: 11px 13px !important;
    background-color: transparent;
    align-items: flex-start !important;
    text-align: left;
}

.work-item-basket-who-can-help[b-b3yu4jb44n]  .mud-icon-root {
    width: 14px;
    height: 14px;
    font-size: 14px;
    margin-bottom: 0 !important;
    color: var(--mud-palette-warning);
}

.work-item-basket-who-can-help[b-b3yu4jb44n]  .mud-typography-h6 {
    margin-bottom: 0.25rem !important;
    font-size: 0.75rem;
    font-weight: 660;
    line-height: 1.35;
}

.work-item-basket-who-can-help[b-b3yu4jb44n]  .mud-typography-body2 {
    margin-bottom: 0 !important;
    font-size: 0.72rem;
    line-height: 1.45;
    color: var(--mud-palette-text-secondary);
}

.work-item-basket-footer[b-b3yu4jb44n] {
    flex: none;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    padding: 0.6rem 1rem;
    border-top: 1px solid var(--mud-palette-lines-default);
}

/* Story 135.27: the single primary CTA, from the mockup's .fbtn.primary (work-item-basket.html:206-210).
   It sits in the footer BELOW the member list in DOM and reading order, so a keyboard or screen-reader
   user meets the items before the button that runs on them. */
.work-item-basket-run[b-b3yu4jb44n] {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    font: inherit;
    font-size: 0.75rem;
    font-weight: 660;
    padding: 0.4375rem 0.8125rem;
    border-radius: 0.5rem;
    border: 1px solid var(--mud-palette-primary);
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    cursor: pointer;
}

/* D19: aria-disabled, never the native disabled attribute, so the reason stays reachable. That makes
   this rule the only visual signal the CTA cannot run. */
.work-item-basket-run[aria-disabled="true"][b-b3yu4jb44n] {
    background-color: var(--mud-palette-background-gray);
    border-color: var(--mud-palette-lines-default);
    color: var(--mud-palette-text-secondary);
    cursor: not-allowed;
}

.work-item-basket-run:focus-visible[b-b3yu4jb44n],
.work-item-basket-back-to-collecting:focus-visible[b-b3yu4jb44n] {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* Story 135.28: the dispatched state's single primary, in the position the Run CTA vacated and with
   the same treatment, so the footer does not restyle itself as the state changes. */
.work-item-basket-back-to-collecting[b-b3yu4jb44n] {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    font: inherit;
    font-size: 0.75rem;
    font-weight: 660;
    padding: 0.4375rem 0.8125rem;
    border-radius: 0.5rem;
    border: 1px solid var(--mud-palette-primary);
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    cursor: pointer;
}

.work-item-basket-run-spinner[b-b3yu4jb44n] {
    flex-shrink: 0;
}

.work-item-basket-hint[b-b3yu4jb44n] {
    flex: 1 1 160px;
    font-size: 0.68rem;
    color: var(--mud-palette-text-secondary);
}

/* ── Story 135.30: the compact composition ───────────────────────────────────────────────────────
   Nothing here changes what the sheet IS. Story 135.9's scrim, Esc, focus trap, `inert` background and
   80dvh cap are untouched, and so is every wide presentation - this whole block is inside the media
   query for that reason. What it adds is the layout the sheet contract never specified: the touch floor
   met by GROWING THE HIT AREA rather than the visual control (DESIGN.md:521's do/do-not pair), and a
   footer that stacks because two 44px buttons do not fit side by side in the band's 332px.

   ON SPECIFICITY, because the failure mode is silent in three ways at once - the class is in the DOM,
   the rule is in the stylesheet, and every class-based assertion passes. The mockup documents the trap
   at :276-278: ITS 32px base is `.mrow .rm` (0,2,0), so a naive `.ctouch-rm` (0,1,0) loses and the
   target stays at 32px with nothing failing. This app's base rules are all SINGLE classes, so an
   override of equal specificity later in the same file already wins by source order and there is
   nothing to beat. No descendant selector was manufactured here to reproduce a problem this file does
   not have. What guards it is the COMPUTED-BOX assertion in work-item-basket.spec.ts, never a class
   check, and that holds for any box-size rule below. */
@media (max-width: 640.98px) {
    /* .ctouch-x (:279). The header's Close control, which is a text button rather than a glyph one -
       "Close" is about 33px wide at this size, so the square is what carries the width. */
    .work-item-basket-close[b-b3yu4jb44n] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 44px;
        height: 44px;
    }

    .work-item-basket-clear[b-b3yu4jb44n] {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 44px;
    }

    /* .ctouch (:262) on the two fill controls and the paste box's Add, which share this class.
       min-width as well as min-height, which the mockup's own .ctouch does not carry: DESIGN.md:455
       scopes the floor to BOTH axes, and the paste box's Add is a two-word-shorter label that measured
       43.7px wide with only the height rule - under the floor on the axis nobody was looking at. */
    .work-item-basket-fillbtn[b-b3yu4jb44n] {
        min-width: 44px;
        min-height: 44px;
    }

    .work-item-basket-confirm-clear-cancel[b-b3yu4jb44n] {
        min-height: 44px;
    }

    .work-item-basket-confirm-clear[b-b3yu4jb44n]  .work-item-basket-confirm-clear-commit {
        min-height: 44px;
    }

    /* .ctouch-row (:275). */
    .work-item-basket-row[b-b3yu4jb44n] {
        min-height: 44px;
    }

    /* .ctouch-rm (:278). The negative margins are scaled with the box - -8px/-12px at 44px against
       Story 135.29's -6px/-8px at 32px - so growing the target does not grow the row. The member list
       is the one thing the panel exists to show, and it is also the only section that gives. */
    .work-item-basket-row-remove[b-b3yu4jb44n] {
        width: 44px;
        height: 44px;
        margin: -8px -12px -8px 0;
    }

    /* .cfoot (:280). Two 44px buttons do not fit side by side in the 332px the band has at 360px, and
       shrinking them below the touch minimum is not an option. */
    .work-item-basket-footer[b-b3yu4jb44n] {
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
    }

    /* .cfull (:281), scoped to the footer's ACTIONS rather than to every child. The volatility hint is
       a footer child too, and stretching it would turn one line of text into a button-shaped block.
       Written for one action and for two: `align-items: stretch` above already gives any future action
       its width (Epic 136 Story 136.11's "Open in Activity", deferred by Story 135.28 because there is
       no Activity destination yet), and this gives it the floor. No placeholder stands in for it.

       justify-content is a translation necessity rather than an addition: the mockup's .fbtn is a plain
       button, which centres its own label at width:100%, while the shipped CTA is display:inline-flex
       to hold its spinner and would otherwise render the label hard against the left edge. */
    .work-item-basket-footer > button[b-b3yu4jb44n] {
        width: 100%;
        min-height: 44px;
        justify-content: center;
    }

    /* The hint carries `flex: 1 1 160px` for the wide ROW. In a column that basis is a HEIGHT, so left
       alone it would claim 160px of a sheet whose entire member-list budget is around that. */
    .work-item-basket-hint[b-b3yu4jb44n] {
        flex: none;
    }
}

@media (forced-colors: active) {
    .work-item-basket--panel[b-b3yu4jb44n],
    .work-item-basket--sheet[b-b3yu4jb44n] {
        border: 1px solid CanvasText;
    }
}
/* /Components/WorkItemBasket/WorkItemBasketVerbBar.razor.rz.scp.css */
/* {components.work-item-basket-verb-chip}. Story 135.27: translated rule for rule from
   mockups/work-item-basket.html:144-163 plus .provisional at :40, keeping this file's own
   var(--mud-palette-*, #fallback) convention. Story 135.29 owns the basket's --bb-* token conversion,
   so nothing here is pre-converted.

   Story 135.10 review fix (should-fix), still true: aria-disabled="true" chips (never the native
   disabled attribute — same AD-9c/AD-21 reason WorkflowActionBar.razor.css documents) must carry a
   visual affordance of their own, and Implement's provisional ceiling must not be pixel-identical to a
   settled one. */

/* flex:none is load-bearing (mockup :165-169): the member list is the ONLY section of the panel that
   gives, so a growing skip line or run log can never squeeze it. */
.work-item-basket-verb-bar[b-nzv3jsmnac] {
    flex: none;
    padding: 11px 16px;
    border-bottom: 1px solid var(--mud-palette-lines-default, #e0e0e0);
}

.work-item-basket-verb-bar-loading[b-nzv3jsmnac] {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #757575);
}

/* flex-wrap is load-bearing rather than cosmetic (mockup :144-146): five chips do not fit the panel's
   424px on one line, and the wrap is what keeps them one group instead of five ragged-width cards. */
.work-item-basket-verb-chips[b-nzv3jsmnac] {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

.work-item-basket-verb-chip[b-nzv3jsmnac] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    /* Story 135.22 (AC 6): color-mix rather than rgba(var(--mud-palette-primary-rgb), ...). Same colour -
       srgb mixing toward `transparent` is premultiplied, so N% of an opaque colour is that colour at
       alpha N/100 - and no --bb-* tint carries these two alphas, so nothing is retuned to reach one. */
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 32%, transparent);
    border-radius: 8px;
    background-color: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
    color: var(--mud-palette-primary, #594ae2);
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}

.work-item-basket-verb-chip[b-nzv3jsmnac]  svg {
    width: 14px;
    height: 14px;
    flex: none;
}

/* The count is a pill, never text appended to the label: appended text makes every chip a different
   width for a reason the user cannot see, which is what the shipped bar did with "Validate 3". */
.work-item-basket-verb-chip-count[b-nzv3jsmnac] {
    min-width: 19px;
    padding: 0 6px;
    border-radius: 100px;
    background-color: var(--mud-palette-primary, #594ae2);
    color: var(--mud-palette-primary-text, #fff);
    font-size: 10px;
    font-weight: 700;
    text-align: center;
}

.work-item-basket-verb-chip[aria-pressed="true"][b-nzv3jsmnac] {
    background-color: var(--mud-palette-primary, #594ae2);
    border-color: var(--mud-palette-primary, #594ae2);
    color: var(--mud-palette-primary-text, #fff);
}

.work-item-basket-verb-chip[aria-pressed="true"] .work-item-basket-verb-chip-count[b-nzv3jsmnac] {
    background-color: rgba(255, 255, 255, 0.26);
}

.work-item-basket-verb-chip[aria-disabled="true"][b-nzv3jsmnac] {
    background-color: var(--mud-palette-background-gray, #f5f5f5);
    border-color: var(--mud-palette-lines-default, #e0e0e0);
    color: var(--mud-palette-text-secondary, #757575);
    cursor: not-allowed;
}

.work-item-basket-verb-chip[aria-disabled="true"] .work-item-basket-verb-chip-count[b-nzv3jsmnac] {
    background-color: var(--mud-palette-lines-default, #e0e0e0);
    color: var(--mud-palette-text-secondary, #757575);
}

.work-item-basket-verb-chip:focus-visible[b-nzv3jsmnac] {
    outline: 2px solid var(--mud-palette-primary, #594ae2);
    outline-offset: 2px;
}

.work-item-basket-verb-capline[b-nzv3jsmnac] {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 8px;
    font-size: 10px;
    font-weight: 600;
    color: var(--mud-palette-text-secondary, #757575);
}

/* A number awaiting an engineering answer is visibly not a promise, and it is a badge rather than
   parenthetical prose so it cannot be read as part of the ceiling sentence. */
.work-item-basket-verb-capline-provisional[b-nzv3jsmnac] {
    padding: 0 5px;
    border: 1px solid var(--mud-palette-warning, #ed6c02);
    border-radius: 4px;
    background-color: color-mix(in srgb, var(--mud-palette-warning, #ed6c02) 12%, transparent);
    color: var(--mud-palette-warning, #ed6c02);
    font-size: 8.5px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.work-item-basket-verb-skip[b-nzv3jsmnac] {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px dashed var(--mud-palette-lines-default, #e0e0e0);
    font-size: 11px;
    color: var(--mud-palette-text-secondary, #757575);
}

.work-item-basket-verb-skip strong[b-nzv3jsmnac] {
    color: var(--mud-palette-warning, #ed6c02);
}

.work-item-basket-verb-overline[b-nzv3jsmnac] {
    margin-top: 8px;
    padding: 6px 10px;
    border: 1px solid var(--mud-palette-warning, #ed6c02);
    border-radius: 7px;
    background-color: color-mix(in srgb, var(--mud-palette-warning, #ed6c02) 12%, transparent);
    font-size: 11px;
    color: var(--mud-palette-warning, #ed6c02);
}

.work-item-basket-verb-bar-error[b-nzv3jsmnac] {
    margin-top: 8px;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--mud-palette-error, #d32f2f);
}

/* Story 135.30, AC 4: at compact the strip is ONE 44px row that scrolls horizontally, not a wrapped
   block. MEASURED rather than chosen (work-item-basket.html:263-271): with the row wrapping, five 44px
   chips become three rows on a 360x640 phone and, with the ceiling and skip lines, consume the whole
   510px sheet - leaving the member list 10px. The basket stops showing its own contents. Scrolling the
   strip restores the list to about 112px.

   {components.hub-action-button}'s "wraps at mode-medium and mode-compact" is deliberately NOT followed
   here, and the reason is structural rather than a preference: the hub action bar sits on a page with
   no vertical cap; this sits in a capped sheet competing with a list. DESIGN.md:450 sanctions the
   container directly - wide content scrolls inside its own overflow-x:auto container, and the page body
   never scrolls horizontally.

   A media query rather than a parameter: below {breakpoints.sm} the panel is always the sheet (Story
   135.25), so the boundary the stylesheet already owns selects the compact case on its own, and the bar
   needs no new knowledge of the panel's presentation to fall out of step with.

   Story 135.27's "do not give the chip row its own scroll or a min-height" is a WIDE-only statement
   which hands the compact case here one line later. The min-height it forbids is a vertical floor on
   the ROW; this one is on each CHIP, which is the touch target.

   The chips are real buttons in DOM order, so Tab reaches every one and the browser scrolls the focused
   chip into view - no roving tabindex, no arrow-key handler; this is a scroll container around an
   existing tab sequence, not a new widget. The ceiling, skip and over-ceiling lines are SIBLINGS of the
   chip row rather than children, so none of them is swept into the horizontal scroll. */
@media (max-width: 640.98px) {
    .work-item-basket-verb-chips[b-nzv3jsmnac] {
        flex-wrap: nowrap;
        overflow-x: auto;
        gap: 8px;
        scroll-snap-type: x proximity;
        scrollbar-width: thin;
        padding-bottom: 2px;
    }

    .work-item-basket-verb-chip[b-nzv3jsmnac] {
        flex: none;
        scroll-snap-align: start;
        min-height: 44px;
    }

    /* Review fix. A scroll container clips its children's outlines - an outline is not part of
       scrollable overflow, so it cannot be scrolled into view either - and the ring above sits 4px
       OUTSIDE the chip's border box (2px wide at 2px offset) against a strip with no padding to
       spare. Measured focused at 360x740: 0px of room above the chip, 0px to the left of the first
       one, 2px below, so the ring renders as two vertical strokes with its top and bottom cut off.
       Drawn inside instead, which is the answer .bb-detail-tab already gives for the same reason
       (WorkflowDetailPane.razor.css:43-45, Story 135.20's scrolling tab strip). Costs no layout, so
       the vertical budget AC 7 measures is untouched.

       The ARMED chip is filled with {colors.primary}, so an inset ring in that same colour would be
       invisible against its own fill - it takes the on-primary token its label already spends. */
    .work-item-basket-verb-chip:focus-visible[b-nzv3jsmnac] {
        outline-offset: -2px;
    }

    .work-item-basket-verb-chip[aria-pressed="true"]:focus-visible[b-nzv3jsmnac] {
        outline-color: var(--mud-palette-primary-text, #fff);
    }
}
