.dock-view {
    position: fixed;
    bottom: 5px;
    right: 50px;
    left: 100px;
    border-radius: 15px 15px 0 0;
}

/* Workspace environments — follows the V2 settings/card rhythm used by IAM and Developers. */
.cf-v2-environments__index-body {
    padding: var(--cf-space-4, 1rem);
}

.cf-v2-environments__metrics {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--cf-space-3, 0.75rem);
    margin-bottom: var(--cf-space-4, 1rem);
}

.cf-v2-environments .cf-v2-developers-detail__card-body {
    padding: var(--cf-space-4, 1rem);
}

.cf-v2-environments__empty-list {
    padding: var(--cf-space-4, 1rem);
}

.cf-v2-environments__data-table {
    height: 32rem;
    overflow: auto;
    scrollbar-gutter: stable;
}

.cf-v2-environments__subsection {
    padding-top: var(--cf-space-4, 1rem);
    border-top: 1px solid var(--cf-color-border, transparent);
}

.cf-v2-environments__capability {
    padding: var(--cf-space-3, 0.75rem);
    border: 1px solid var(--cf-color-border, transparent);
    border-radius: var(--cf-radius-md, 0.5rem);
}

@media (min-width: 560px) {
    .cf-v2-environments__metrics {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 960px) {
    .cf-v2-environments__metrics {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

.ai-border {
    border-radius: 5px;
    border: 2px solid var(--ai-gradient-color-1);
    box-shadow: 0 0px 15px var(--ai-gradient-color-1), inset 0 0px 15px var(--ai-gradient-color-1);
    animation: colorTransition 2s ease-in-out infinite;
}

/* V2 AI-pill glow — applied to a CFChip while an agent investigation is in
   flight. The earlier pass reused .cf-ai-thinking's keyframe and was barely
   visible against the dark navy canvas. This is a dedicated pulse with
   three layered box-shadows that breathe in unison:

     1. crisp ring (1.5–2px spread) sits on the chip outline at 75–95% opacity
     2. mid halo (4–10px blur) anchors the chip's "lit" footprint at 50–80%
     3. far aura (14–28px blur, 1–4px spread) gives the room a soft bloom

   Hue is locked to two brand AI tokens — color-1 (pink) at rest, color-3
   (purple) at peak. Dropping color-2 (orange) avoids the rainbow rotation
   the previous keyframe produced, which read as "loading bar," not as
   "thinking." Sine-like easing (0.45/0/0.55/1) gives organic respiration
   instead of mechanical ticking. 2.0s cycle = calm breath cadence.

   Border-radius is intentionally not set — the host CFChip already has
   border-radius: var(--cf-radius-full), so the shadow halo naturally
   follows the pill outline instead of being clamped to a rectangle. */
.cf-v2-ai-pill-glow {
    animation: cf-v2-ai-pill-pulse 2s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}

@keyframes cf-v2-ai-pill-pulse {
    0%, 100% {
        box-shadow:
            0 0 0 1.5px color-mix(in oklab, var(--ai-gradient-color-1, #f32170) 75%, transparent),
            0 0 6px 0 color-mix(in oklab, var(--ai-gradient-color-1, #f32170) 55%, transparent),
            0 0 16px 1px color-mix(in oklab, var(--ai-gradient-color-3, #cf23cf) 35%, transparent);
    }
    50% {
        box-shadow:
            0 0 0 2px color-mix(in oklab, var(--ai-gradient-color-3, #cf23cf) 95%, transparent),
            0 0 12px 1px color-mix(in oklab, var(--ai-gradient-color-3, #cf23cf) 80%, transparent),
            0 0 28px 4px color-mix(in oklab, var(--ai-gradient-color-1, #f32170) 55%, transparent);
    }
}

/* Static fallback retains the dual-layer + dual-hue treatment so the chip
   still reads as "AI surface" without animation. Honors users who set
   prefers-reduced-motion or platform-level motion reduction. */
@media (prefers-reduced-motion: reduce) {
    .cf-v2-ai-pill-glow {
        animation: none;
        box-shadow:
            0 0 0 1.5px color-mix(in oklab, var(--ai-gradient-color-1, #f32170) 80%, transparent),
            0 0 8px 1px color-mix(in oklab, var(--ai-gradient-color-1, #f32170) 55%, transparent),
            0 0 18px 2px color-mix(in oklab, var(--ai-gradient-color-3, #cf23cf) 40%, transparent);
    }
}

@keyframes colorTransition {
    0% {
        border-color: var(--ai-gradient-color-1);
        box-shadow: 0 0px 10px var(--ai-gradient-color-1), inset 0 0px 10px var(--ai-gradient-color-1);
    }

    25% {
        border-color: var(--ai-gradient-color-2);
        box-shadow: 0 0px 15px var(--ai-gradient-color-2), inset 0 0px 15px var(--ai-gradient-color-2);
    }

    50% {
        border-color: var(--ai-gradient-color-3);
        box-shadow: 0 0px 20px var(--ai-gradient-color-3), inset 0 0px 20px var(--ai-gradient-color-3);
    }

    75% {
        border-color: var(--ai-gradient-color-4);
        box-shadow: 0 0px 15px var(--ai-gradient-color-4), inset 0 0px 15px var(--ai-gradient-color-4);
    }

    100% {
        border-color: var(--ai-gradient-color-1);
        box-shadow: 0 0px 10px var(--ai-gradient-color-1), inset 0 0px 10px var(--ai-gradient-color-1);
    }
}

.insight-error-boundary {
    --_color: var(--color, var(--cf-status-error));
    margin: var(--cf-space-5, 20px);
    padding: var(--cf-space-5, 20px);
    border: 1px solid var(--_color);
    border-radius: 4px;
    background-color: color-mix(in srgb, var(--_color) 15%, transparent);
    color: var(--cf-text-primary);
}

/* ==========================================================================
   Onboarding card — shared vocabulary for the centered single-card pages
   used by the customer-flow under BlankLayoutV2 (Register, Invite,
   GrantAccess, ConsentConfirmed). The layout owns the chrome; each page
   drops a CFCard inside this wrapper so the card is centered, has a
   sensible max-width, and renders identically across all pages.
   Lives globally because the same wrapper class appears in 4+ Razor files
   and Blazor scoped CSS would not match across components.
   ========================================================================== */

.cf-v2-onboarding-card {
    width: 100%;
    max-width: 480px;
    margin: 0 auto;
    align-self: center;
}

.cf-v2-onboarding-card__brand {
    display: flex;
    justify-content: center;
}

.cf-v2-onboarding-card__brand img {
    width: 200px;
    max-width: 100%;
    height: auto;
    display: block;
}

.cf-v2-onboarding-card__success-icon {
    color: var(--cf-status-success-fg, #22c55e);
    font-size: 48px;
    line-height: 1;
}

.cf-v2-onboarding-card__error-icon {
    color: var(--cf-status-error-fg, #ef4444);
    font-size: 48px;
    line-height: 1;
}

/* ==========================================================================
   AgentUpdateBannerV2 — sits at the top of the CFAppShell main column.
   Rendered as the first child of <ChildContent> so it occupies real space in
   normal flow: when shown it pushes @Body content down by its own height,
   when hidden it disappears completely without leaving any reserved space.
   Block-level + full-width within the main grid area. Sticky so it stays
   pinned to the top of the main column when the user scrolls the page body.
   ========================================================================== */

.cf-v2-agent-update-banner {
    position: sticky;
    top: 0;
    /* Must sit above the CFAppShell topbar's stacking context (z-index 10) so
       the info tooltip — rendered inside this banner's stacking context — can
       pop above the topbar instead of being clipped under it. CFTooltip's own
       z-index (10000) is local to whichever ancestor creates the stacking
       context, so the banner is what actually controls tooltip layering here. */
    z-index: 12;
    display: block;
    width: 100%;
}

/* Square the corners (banner is flush against viewport edges) and sharpen the
   variant accent so the bar actually catches attention against the dark page
   surface. The default CFBanner gradient fades the variant tint to
   --cf-bg-elevated-1 at 30%, which reads as nearly transparent on dark themes
   — we widen the accent stop and tint the trailing color too. */
.cf-v2-agent-update-banner .cf-banner {
    border-radius: 0;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
    border-left-width: 5px;
}

.cf-v2-agent-update-banner .cf-banner[data-variant="info"] {
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--cf-status-info) 32%, var(--cf-bg-elevated-2)) 0%,
        color-mix(in srgb, var(--cf-status-info) 14%, var(--cf-bg-elevated-2)) 100%);
}

.cf-v2-agent-update-banner .cf-banner[data-variant="success"] {
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--cf-status-success) 32%, var(--cf-bg-elevated-2)) 0%,
        color-mix(in srgb, var(--cf-status-success) 14%, var(--cf-bg-elevated-2)) 100%);
}

.cf-v2-agent-update-banner .cf-banner[data-variant="warning"] {
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--cf-status-warning) 36%, var(--cf-bg-elevated-2)) 0%,
        color-mix(in srgb, var(--cf-status-warning) 16%, var(--cf-bg-elevated-2)) 100%);
}

.cf-v2-agent-update-banner .cf-banner[data-variant="error"] {
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--cf-status-error) 36%, var(--cf-bg-elevated-2)) 0%,
        color-mix(in srgb, var(--cf-status-error) 16%, var(--cf-bg-elevated-2)) 100%);
}

/* ==========================================================================
   V2 page shell — shared page padding for every top-level V2 page so padding
   is identical across the portal. Per-page classes (cf-v2-settings-page,
   cf-v2-incidents-page, …) opt into the shared rule by also carrying
   cf-v2-page. Keep this unscoped; per-page scoped CSS can only target its
   own elements.
   ========================================================================== */

.cf-v2-page,
.cf-v2-settings-page,
.cf-v2-incidents-page,
.cf-v2-gamebooks-page,
.cf-v2-agent-center-page,
.cf-v2-agent-configuration-page {
    padding: var(--cf-space-lg, 24px);
    min-height: 100%;
    box-sizing: border-box;
}

/* ==========================================================================
   V2 incident-detail two-card layout vocabulary
   Mobile (<720px): cards flow. Tablet+ (>=720px): viewport-anchored
   height, scroll lives INSIDE the tab panel/side-panel body, not on
   the card itself. Desktop (>=1180px): two columns. Lives globally —
   the gamebooks workbench page reuses these classes alongside the
   incident detail page itself, and Blazor scoped CSS does not pierce
   across components.
   ========================================================================== */

.cf-v2-incident-detail-page {
    min-width: 0;
    /* Top bar + page padding + breadcrumbs + header card + stack gaps. */
    --cf-detail-offset: 17rem;
    /* Grow the cards with the viewport (min 32rem) instead of capping at 42rem,
       which left dead space below the cards on tall/large screens. */
    --cf-detail-card-height: max(32rem, calc(100dvh - var(--cf-detail-offset)));
}

.cf-v2-incident-detail__loading {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cf-v2-incident-detail__content-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--cf-space-4, 1rem);
    min-width: 0;
}

.cf-v2-incident-detail__card-shell {
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

.cf-v2-incident-detail__card-header {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-v2-incident-detail__header-metrics {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cf-space-2, 0.5rem);
    color: var(--cf-text-secondary, inherit);
    font-size: var(--cf-text-body-sm, 0.875rem);
}

.cf-v2-incident-detail__header-metrics span {
    padding: var(--cf-space-1, 0.25rem) var(--cf-space-2, 0.5rem);
    border: 1px solid var(--cf-color-border);
    border-radius: var(--cf-radius-sm, 4px);
    background: var(--cf-color-surface-secondary, transparent);
    white-space: nowrap;
}

.cf-v2-incident-detail__side-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding: var(--cf-space-3, 0.75rem);
}

.cf-v2-incident-detail__panel-loader {
    min-height: 16rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

@media (min-width: 720px) {
    .cf-v2-incident-detail__card-header {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .cf-v2-incident-detail__content-grid {
        align-items: stretch;
        grid-auto-rows: var(--cf-detail-card-height);
    }

    /* Hard-pin card shells so tab content changes never push layout. */
    .cf-v2-incident-detail__card-shell {
        min-width: 0;
        height: var(--cf-detail-card-height);
        min-height: 0;
        max-height: var(--cf-detail-card-height);
    }

    /* Side panel body: its scroll surface is here, not on the card. */
    .cf-v2-incident-detail__side-panel {
        flex: 1 1 auto;
        height: 100%;
        min-height: 0;
        min-width: 0;
        overflow-y: auto;
    }
}

/* Two columns only once the viewport is wide enough that the main column keeps
   a comfortable width alongside the side card. Below this the side card drops
   to the bottom (single column) so the main content gets the full width and
   avoids unnecessary horizontal scrolling on smaller laptops. */
@media (min-width: 1400px) {
    .cf-v2-incident-detail__content-grid {
        grid-template-columns: minmax(0, 1fr) minmax(22rem, 30rem);
    }
}

/* ==========================================================================
   V2 Gamebooks Activity — shared grid vocabulary
   The column-header row in the listing and every history row use the SAME
   grid-template-columns so cells line up like a table. Lives globally
   because the header row is declared in the listing component but the row
   bodies are declared in a sibling component — Blazor scoped CSS doesn't
   pierce that boundary.

   Action column is a FIXED reserve so a row without a button still aligns
   with rows that have one. Workspace is the only flex track.
   ========================================================================== */
.cf-v2-gamebooks-grid {
    display: grid;
    align-items: center;
    column-gap: var(--cf-space-3, 0.75rem);
    width: 100%;
    min-width: 0;

    /* xs (<560px): mobile-first card-row. Two priority cells visible —
       status + id share the top track, workspace folds into a second wrap
       row, action and chevron stay on the right. We use grid-template-areas
       to wrap intelligently rather than 0px-collapsing columns, which
       guarantees workspace stays readable on phones. */
    grid-template-columns:
        minmax(0, auto)         /* status */
        minmax(0, 1fr)          /* id */
        auto                    /* action */
        1.25rem;                /* chevron */
    grid-template-areas:
        "status id        action chevron"
        "ws     ws        ws     ws"
        "meta   meta      meta   meta";
    row-gap: var(--cf-space-1, 0.25rem);
}

@media (min-width: 560px) {
    /* sm: surface the incident # + time on a second wrap row so workspace
       stays prominent. Action and chevron pinned right across both rows. */
    .cf-v2-gamebooks-grid {
        grid-template-columns:
            minmax(0, auto)     /* status */
            minmax(0, 1fr)      /* id */
            minmax(0, auto)     /* incident */
            minmax(0, auto)     /* time */
            7rem                /* action */
            1.25rem;            /* chevron */
        grid-template-areas:
            "status id        incident time   action chevron"
            "ws     ws        ws       ws     ws     ws";
    }
}

@media (min-width: 720px) {
    /* md: must fit at 720px - 16px padding = 44rem usable. Time is sized so
       the "LAST ACTIVITY" header reads fully — body values ("5d ago") fit in
       less room but the header label drives the minimum. */
    .cf-v2-gamebooks-grid {
        grid-template-columns:
            6rem                    /* status */
            5.5rem                  /* id */
            minmax(7rem, 9rem)      /* workspace */
            minmax(6rem, 1fr)       /* incident — flex */
            6.5rem                  /* time */
            7rem                    /* action */
            1.25rem;                /* chevron */
        grid-template-areas: "status id workspace incident time action chevron";
        row-gap: 0;
    }
}

@media (min-width: 960px) {
    /* lg: 960px - 24px padding = 58.5rem usable. Actor is capped at 12rem so
       it doesn't keep flexing past the longest expected name + avatar — slack
       on wide viewports flows to incident (the only 1fr track), since the
       incident "#number — title" composition is the longest variable text. */
    .cf-v2-gamebooks-grid {
        grid-template-columns:
            6rem                    /* status */
            5.5rem                  /* id */
            minmax(8rem, 12rem)     /* workspace */
            minmax(8rem, 1fr)       /* incident — flex */
            6.5rem                  /* time */
            minmax(10rem, 12rem)    /* actor — capped */
            7rem                    /* action */
            1.25rem;                /* chevron */
        grid-template-areas: "status id workspace incident time actor action chevron";
    }
}

/* Column header row — sits above the list, uses the same grid as rows BUT
   collapses to a single row layout: rows can wrap, headers cannot. */
.cf-v2-gamebooks-grid--header {
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-3, 0.75rem);
    background-color: var(--cf-bg-elevated-1);
    border-bottom: 1px solid var(--cf-color-border);
    font-size: var(--cf-text-body-sm, 0.8125rem);
    font-weight: var(--cf-font-semibold, 600);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--cf-text-secondary);
    user-select: none;

    /* Override the row's multi-row template at xs/sm — header is always
       a single row. Areas not in the row layout (ws, meta) just don't
       resolve, which is fine since those cells are display:none here. */
    grid-template-areas: "status id action chevron";
    row-gap: 0;
}

@media (min-width: 560px) {
    .cf-v2-gamebooks-grid--header {
        grid-template-areas: "status id incident time action chevron";
    }
}

@media (min-width: 720px) {
    .cf-v2-gamebooks-grid--header {
        grid-template-areas: "status id workspace incident time action chevron";
    }
}

@media (min-width: 960px) {
    .cf-v2-gamebooks-grid--header {
        grid-template-areas: "status id workspace incident time actor action chevron";
    }
}

.cf-v2-gamebooks-grid__col {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cf-v2-gamebooks-grid__col--status   { grid-area: status; }
.cf-v2-gamebooks-grid__col--id       { grid-area: id; }
/* Workspace lands in the wrap row on phones — no label needed there. md+
   re-targets it to the workspace area inline with other column heads. */
.cf-v2-gamebooks-grid__col--workspace { grid-area: ws; }
.cf-v2-gamebooks-grid__col--incident { grid-area: incident; }
.cf-v2-gamebooks-grid__col--time     { grid-area: time; }
.cf-v2-gamebooks-grid__col--actor    { grid-area: actor; }
.cf-v2-gamebooks-grid__col--action   { grid-area: action; justify-self: end; }
.cf-v2-gamebooks-grid__col--chevron  { grid-area: chevron; }

/* xs: only Status + Gamebook labels are meaningful — every other column
   is hidden in the row layout. We use display:none on the header labels
   so the header stays a single tight row even though row cells wrap below. */
.cf-v2-gamebooks-grid--header .cf-v2-gamebooks-grid__col--workspace,
.cf-v2-gamebooks-grid--header .cf-v2-gamebooks-grid__col--incident,
.cf-v2-gamebooks-grid--header .cf-v2-gamebooks-grid__col--time,
.cf-v2-gamebooks-grid--header .cf-v2-gamebooks-grid__col--actor {
    display: none;
}

@media (min-width: 560px) {
    .cf-v2-gamebooks-grid--header .cf-v2-gamebooks-grid__col--incident,
    .cf-v2-gamebooks-grid--header .cf-v2-gamebooks-grid__col--time {
        display: block;
    }
}

@media (min-width: 720px) {
    .cf-v2-gamebooks-grid--header .cf-v2-gamebooks-grid__col--workspace {
        display: block;
        grid-area: workspace;
    }
}

@media (min-width: 960px) {
    .cf-v2-gamebooks-grid--header .cf-v2-gamebooks-grid__col--actor {
        display: block;
    }
}

@media (max-width: 960px) {
    .cf-v2-page,
    .cf-v2-settings-page,
    .cf-v2-incidents-page,
    .cf-v2-gamebooks-page,
    .cf-v2-agent-center-page {
        padding: var(--cf-space-md, 16px);
    }
}

@media (max-width: 640px) {
    .cf-v2-page,
    .cf-v2-settings-page,
    .cf-v2-incidents-page,
    .cf-v2-gamebooks-page,
    .cf-v2-agent-center-page {
        padding: var(--cf-space-sm, 12px);
    }
}

/* ==========================================================================
   V2 Incidents page — mobile-first toolbar + grid helpers. Shared across
   SIEMIncidentsV2 and MultiTenantIncidentsTableV2 so both can consume the
   same vocabulary. Breakpoints: sm=560px, md=720px.
   ========================================================================== */

/* Page header row: title on the left, refresh + time filter on the right.
   Stacks on mobile, goes horizontal at sm. */
.cf-v2-incidents-page__header {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

@media (min-width: 560px) {
    .cf-v2-incidents-page__header {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: var(--cf-space-3, 0.75rem);
    }
}

.cf-v2-incidents-page__toolbar {
    display: flex;
    gap: var(--cf-space-2, 0.5rem);
    align-items: center;
    flex-wrap: wrap;
}

.cf-v2-incidents-page__toolbar-divider {
    display: none;
    width: 1px;
    align-self: stretch;
    background-color: var(--cf-color-border);
    margin-inline: var(--cf-space-1, 0.25rem);
}

@media (min-width: 560px) {
    .cf-v2-incidents-page__toolbar-divider {
        display: block;
    }
}

.cf-v2-incidents-page__update-strip {
    display: inline-flex;
    align-self: flex-start;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-3, 0.75rem);
    background-color: color-mix(in srgb, var(--cf-color-primary, #2557f9) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--cf-color-primary, #2557f9) 28%, transparent);
    border-radius: var(--cf-radius-md, 8px);
    color: var(--cf-color-primary, #2557f9);
    font: inherit;
    font-weight: 500;
    cursor: pointer;
    transition:
        background-color 0.15s ease-out,
        border-color 0.15s ease-out,
        transform 0.15s ease-out;
}

.cf-v2-incidents-page__update-strip:hover {
    background-color: color-mix(in srgb, var(--cf-color-primary, #2557f9) 16%, transparent);
    border-color: color-mix(in srgb, var(--cf-color-primary, #2557f9) 44%, transparent);
}

.cf-v2-incidents-page__update-strip:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--cf-color-primary, #2557f9) 40%, transparent);
    outline-offset: 2px;
}

.cf-v2-incidents-page__update-strip .cf-icon {
    flex-shrink: 0;
}

/* Auto-refresh control — grouped icon button + menu chevron + timestamp. */
.cf-v2-auto-refresh {
    display: inline-flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-auto-refresh__group {
    display: inline-flex;
    align-items: stretch;
    gap: 0;
}

.cf-v2-auto-refresh__group .cf-v2-auto-refresh__button.cf-btn {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    border-right-width: 0;
    padding-inline: var(--cf-space-2, 0.5rem);
    transition:
        background-color 0.15s ease-out,
        border-color 0.15s ease-out,
        color 0.15s ease-out;
}

.cf-v2-auto-refresh__group .cf-v2-auto-refresh__button--active.cf-btn {
    background-color: color-mix(in srgb, var(--cf-color-primary, #2557f9) 10%, transparent);
    border-color: var(--cf-color-primary, #2557f9);
    color: var(--cf-color-primary, #2557f9);
}

.cf-v2-auto-refresh__group .cf-v2-auto-refresh__menu-trigger.cf-icon-btn {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

.cf-v2-auto-refresh__button--spinning.cf-btn .cf-btn__icon {
    animation: cf-v2-auto-refresh-spin 1s linear infinite;
}

@keyframes cf-v2-auto-refresh-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .cf-v2-auto-refresh__button--spinning.cf-btn .cf-btn__icon {
        animation: none;
    }
}

.cf-v2-auto-refresh__timestamp {
    color: var(--cf-text-secondary, #6b7280);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Time filter wrapper — preset trigger + optional inline date range picker. */
.cf-v2-time-filter {
    display: inline-flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    flex-wrap: wrap;
}

/* Panel wraps toolbar + grid so they read as a single card surface. */
.cf-v2-incidents-panel {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-4, 1rem);
    background-color: var(--cf-color-card);
    color: var(--cf-color-card-foreground, inherit);
    border: 1px solid var(--cf-color-border);
    border-radius: var(--cf-radius-lg, 12px);
    min-width: 0;
}

.cf-v2-incidents-toolbar {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    width: 100%;
    min-width: 0;
    padding-bottom: var(--cf-space-3, 0.75rem);
    border-bottom: 1px solid var(--cf-color-border);
}

.cf-v2-incidents-toolbar__primary {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
    min-width: 0;
}

.cf-v2-incidents-toolbar__search {
    width: 100%;
    min-width: 0;
}

.cf-v2-incidents-toolbar__filters {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-v2-incidents-toolbar__desktop-filters {
    display: none;
    width: 100%;
}

@media (min-width: 560px) {
    .cf-v2-incidents-toolbar__primary {
        flex-direction: row;
        align-items: center;
        gap: var(--cf-space-3, 0.75rem);
    }

    .cf-v2-incidents-toolbar__primary .cf-v2-incidents-toolbar__search {
        flex: 1 1 auto;
        min-width: 0;
    }
}

@media (min-width: 720px) {
    .cf-v2-incidents-toolbar__desktop-filters {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: var(--cf-space-2, 0.5rem);
        min-width: 0;
    }

    .cf-v2-incidents-toolbar__mobile-filter-button {
        display: none;
    }

    .cf-v2-incidents-toolbar__clear-button {
        margin-inline-start: auto;
    }
}

.cf-v2-incidents-filter-trigger.cf-btn {
    transition:
        background-color 0.15s ease-out,
        border-color 0.15s ease-out,
        color 0.15s ease-out,
        box-shadow 0.15s ease-out;
}

.cf-v2-incidents-filter-trigger--active.cf-btn {
    background-color: color-mix(in srgb, var(--cf-color-primary, #2557f9) 10%, transparent);
    border-color: var(--cf-color-primary, #2557f9);
    color: var(--cf-color-primary, #2557f9);
}

.cf-v2-incidents-filter-trigger--active.cf-btn:hover {
    background-color: color-mix(in srgb, var(--cf-color-primary, #2557f9) 16%, transparent);
}

.cf-v2-incidents-filter-trigger--active.cf-btn:focus-visible {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--cf-color-primary, #2557f9) 28%, transparent);
}

/* Slightly larger icons on toolbar filter triggers, the auto-refresh button,
   and the time filter trigger — improves scan-ability without changing the
   overall button height. */
.cf-v2-incidents-filter-trigger.cf-btn .cf-btn__icon,
.cf-v2-auto-refresh__button.cf-btn .cf-btn__icon,
.cf-v2-time-filter__trigger.cf-btn .cf-btn__icon {
    width: 1.25em;
    height: 1.25em;
}

.cf-v2-incidents-filter-menu__item[data-selected="true"] {
    color: var(--cf-color-primary, var(--cf-color-action));
    font-weight: 600;
}

.cf-v2-incidents-filter-menu__item[data-selected="true"]:hover,
.cf-v2-incidents-filter-menu__item[data-selected="true"]:focus {
    color: var(--cf-color-primary, var(--cf-color-action));
}

.cf-v2-incidents-toolbar__active {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-3, 0.75rem);
    background-color: color-mix(in srgb, var(--cf-color-primary, #2557f9) 4%, transparent);
    border: 1px solid color-mix(in srgb, var(--cf-color-primary, #2557f9) 14%, transparent);
    border-radius: var(--cf-radius-md, 8px);
}

.cf-v2-incidents-toolbar__active-label {
    color: var(--cf-text-secondary, #6b7280);
    margin: 0;
    font-weight: 500;
    letter-spacing: 0.01em;
}

.cf-v2-incidents-toolbar__active-list {
    display: flex;
    gap: var(--cf-space-1, 0.25rem);
    align-items: center;
    min-width: 0;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: var(--cf-space-1, 0.25rem);
    scrollbar-width: thin;
}

.cf-v2-incidents-toolbar__active-list > [role="listitem"] {
    display: inline-flex;
    min-width: 0;
    flex: 0 0 auto;
}

.cf-v2-incidents-toolbar__active-chip {
    max-width: min(280px, 70vw);
}

.cf-v2-incidents-toolbar__active-chip span:first-child {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (min-width: 720px) {
    .cf-v2-incidents-toolbar__active {
        flex-direction: row;
        align-items: center;
    }

    .cf-v2-incidents-toolbar__active-list {
        flex-wrap: wrap;
        overflow: visible;
        padding-bottom: 0;
    }
}

.cf-v2-incidents-toolbar__trailing {
    display: flex;
    gap: var(--cf-space-2, 0.5rem);
    align-items: center;
    justify-content: flex-end;
    flex-shrink: 0;
    width: 100%;
}

.cf-v2-incidents-toolbar__mobile-filter-button {
    flex: 1 1 auto;
}

@media (min-width: 560px) {
    .cf-v2-incidents-toolbar__trailing {
        width: auto;
    }

    .cf-v2-incidents-toolbar__mobile-filter-button {
        flex: 0 0 auto;
    }
}

.cf-v2-incidents-filter-drawer__description {
    color: var(--cf-text-secondary, #6b7280);
    margin-top: 0;
}

.cf-v2-incidents-filter-drawer__groups {
    display: grid;
    gap: var(--cf-space-4, 1rem);
}

.cf-v2-incidents-filter-drawer__group {
    display: grid;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
    padding: 0;
    margin: 0;
    border: 0;
}

.cf-v2-incidents-filter-drawer__group legend {
    padding: 0;
    margin-bottom: var(--cf-space-2, 0.5rem);
    color: var(--cf-text-primary, inherit);
    font-weight: 600;
}

.cf-v2-incidents-filter-drawer__footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

/* Floor the FullHeight grid at desktop widths so a short viewport scrolls the page
   instead of crushing the table to a sliver; the 768px guard matches the FullHeight handoff. */
@media (min-width: 768px) {
    .cf-v2-incidents-grid .cf-data-grid {
        min-height: 24rem;
    }
}

/* PLAT-3284 — bulk selection. The bar floats over the table as a fixed, bottom-centered pill so it
   never occupies flow space above the grid: inserting it there would shift the table down AND make
   the FullHeight grid recompute its height from the new position (a visible jump). The selected-row
   class lands on CFDataGrid's own row markup, which a consumer's scoped CSS cannot reach, so all of
   these rules live globally. Tints match the grid's own data-selected treatment for consistency. */
.cf-v2-incidents-selection-bar {
    position: fixed;
    bottom: var(--cf-space-6, 1.5rem);
    left: 50%;
    transform: translateX(-50%);
    z-index: 40;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    max-width: calc(100vw - var(--cf-space-6, 1.5rem));
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-3, 0.75rem);
    background: var(--cf-bg-elevated-1, var(--cf-color-card));
    border: 1px solid color-mix(in srgb, var(--cf-color-primary) 24%, var(--cf-color-border));
    border-radius: var(--cf-radius-full, 999px);
    box-shadow: var(--cf-shadow-lg, 0 12px 32px rgba(0, 0, 0, 0.24));
    animation: cf-v2-selection-bar-in 160ms ease-out;
}

.cf-v2-incidents-selection-bar__count {
    font-weight: 600;
    white-space: nowrap;
    padding-inline-start: var(--cf-space-1, 0.25rem);
}

.cf-v2-incidents-selection-bar__actions {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    padding-inline-start: var(--cf-space-3, 0.75rem);
    border-inline-start: 1px solid var(--cf-color-border);
}

@keyframes cf-v2-selection-bar-in {
    from {
        opacity: 0;
        transform: translate(-50%, var(--cf-space-4, 1rem));
    }

    to {
        opacity: 1;
        transform: translate(-50%, 0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .cf-v2-incidents-selection-bar {
        animation: none;
    }
}

.cf-v2-incidents-grid__select {
    display: inline-flex;
    align-items: center;
    justify-content: flex-start;
}

.cf-v2-incidents-grid__row--selected {
    background: color-mix(in srgb, var(--cf-color-primary) 10%, transparent);
}

.cf-v2-incidents-grid__row--selected .cf-data-grid__cell[data-pinned="right"] {
    background-color: color-mix(in srgb, var(--cf-bg-elevated-1) 82%, var(--cf-color-primary));
}

/* Grid cell helpers — ensure chips never overflow their column. */
.cf-v2-incidents-grid .cf-chip {
    max-width: 100%;
    min-width: 0;
}

.cf-v2-incidents-grid__title {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.cf-v2-incidents-grid__title-cell {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-cs-alert-types-card__list {
    margin: 0;
    padding-left: var(--cf-space-5, 1.25rem);
}

.cf-cs-alert-types-card__list li {
    margin-bottom: var(--cf-space-1, 0.25rem);
}

.cf-cs-alert-types-card__value {
    font-family: var(--cf-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    color: var(--cf-text-muted, #5b6779);
}

.cf-v2-incidents-grid__title-cell .cf-v2-incidents-grid__title {
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-incidents-grid__id {
    color: var(--cf-color-primary, #2557f9);
    text-decoration: underline;
    cursor: pointer;
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
}

.cf-v2-incidents-grid__id:hover,
.cf-v2-incidents-grid__id:focus-visible {
    opacity: 0.85;
}

.cf-v2-incidents-grid__status,
.cf-v2-incidents-grid__owner {
    display: inline-flex;
    align-items: center;
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
}

.cf-v2-incidents-grid__chip-trigger {
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
}

.cf-v2-incidents-grid__chip-trigger:disabled {
    cursor: not-allowed;
    opacity: 0.6;
}

.cf-v2-incidents-grid__chip-trigger > .cf-chip {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
}

.cf-v2-incidents-grid__chip-label {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cf-v2-incidents-grid__cell-spinner {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
}

.cf-v2-incidents-grid__actions {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--cf-space-1, 0.25rem);
}

.cf-v2-incidents-grid__action-button {
    width: 2rem;
    padding: 0;
}

.cf-v2-incidents-grid__action-button .cf-btn__icon {
    width: 1rem;
    height: 1rem;
}

.cf-data-grid[data-clickable="true"] .cf-data-grid__row:hover .cf-v2-incidents-grid__title {
    color: var(--cf-color-primary, #2557f9);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}

.cf-v2-incidents-grid__loader {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 240px;
}

.cf-v2-incidents-grid__footer-loader {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: var(--cf-space-3, 0.75rem);
}

.cf-v2-incidents-grid__footer-actions {
    display: flex;
    justify-content: center;
    padding-top: var(--cf-space-3, 0.75rem);
}

/* Filter chip group label + horizontal wrapping chip list */
.cf-v2-incidents-toolbar__chip-group {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cf-space-1, 0.25rem);
    align-items: center;
    min-width: 0;
}

.cf-v2-incidents-toolbar__chip-group-label {
    color: var(--cf-text-secondary, #6b7280);
    margin-right: var(--cf-space-1, 0.25rem);
    white-space: nowrap;
}

/* V2 owns scrolling inside CFAppShell: the app frame is fixed to the viewport
   and .cf-app-shell__main is the vertical scroll container. Lock the document
   while the V2 shell is mounted so content growth or fixed overlays cannot
   wake up the browser-level scroller. */
html:has(.cf-v2-app),
body:has(.cf-v2-app) {
    width: 100%;
    height: 100%;
    overflow: hidden;
}

/* ==========================================================================
   IAM cards — shared vocabulary across WorkspaceUsersCardV2 +
   WorkspaceGroupsCardV2. Unscoped because Blazor scoped CSS cannot pierce
   sibling component boundaries even when both components render the same
   class names.
   ========================================================================== */

.cf-v2-iam-card__title {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-v2-iam-card__row {
    align-items: stretch;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-iam-card__identity {
    display: flex;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    min-width: 0;
    flex: 1 1 auto;
}

.cf-v2-iam-card__identity-text {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    min-width: 0;
    word-break: break-word;
    overflow-wrap: anywhere;
}

.cf-v2-iam-card__identity-name {
    display: flex;
    align-items: center;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
}

.cf-v2-iam-card__role {
    flex-shrink: 0;
    min-width: 0;
}

.cf-v2-iam-card__role .cf-select {
    min-width: 180px;
}

@media (max-width: 559px) {
    .cf-v2-iam-card__role .cf-select {
        min-width: 0;
        width: 100%;
    }
}

.cf-v2-iam-card__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-6, 1.5rem) var(--cf-space-3, 0.75rem);
    border-radius: var(--cf-radius-lg, 0.75rem);
    border: 1px dashed var(--cf-color-border, rgba(148, 163, 184, 0.3));
    background: var(--cf-color-surface-secondary, rgba(148, 163, 184, 0.04));
    color: var(--cf-text-secondary, inherit);
}

.cf-v2-iam-card__empty .cf-icon {
    width: 28px;
    height: 28px;
    opacity: 0.65;
}

.cf-v2-iam-card__empty-text {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    max-width: 60ch;
}

/* ==========================================================================
   Add Users / Add Groups drawer body — shared vocabulary used across
   AddWorkspaceUsersDrawerV2 + AddWorkspaceGroupsDrawerV2. Mobile-first.
   ========================================================================== */

.cf-v2-add-iam {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
    min-width: 0;
}

.cf-v2-add-iam__list {
    display: flex;
    flex-direction: column;
    background: var(--cf-bg-elevated-2, var(--cf-color-surface-secondary));
    border: 1px solid var(--cf-color-border, rgba(148, 163, 184, 0.2));
    border-radius: var(--cf-radius-md, 0.5rem);
    overflow: hidden;
}

/* CFDrawer Medium caps body width at ~480px, narrower than the 560px viewport
   breakpoint. Stacking identity above controls inside the drawer keeps the
   email from wrapping mid-word and guarantees the X icon button has space
   to render — putting everything on one row at 480px wide squashes the
   identity to ~120px and pushes the X off the visible edge. */

.cf-v2-add-iam__row {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-3, 0.75rem);
    border-bottom: 1px solid var(--cf-color-border, rgba(148, 163, 184, 0.2));
}

.cf-v2-add-iam__row:last-child {
    border-bottom: none;
}

.cf-v2-add-iam__identity {
    display: flex;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    min-width: 0;
    width: 100%;
}

.cf-v2-add-iam__identity-text {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    min-width: 0;
    flex: 1 1 auto;
    word-break: break-word;
    overflow-wrap: anywhere;
}

/* Role select fills the row; the X icon button anchors to the right at its
   natural size so there's always a clear hit target. */
.cf-v2-add-iam__controls {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
    min-width: 0;
}

.cf-v2-add-iam__controls .cf-select {
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-add-iam__controls .cf-icon-btn,
.cf-v2-add-iam__controls .cf-button--icon {
    flex: 0 0 auto;
}

.cf-v2-add-iam__conflict-list {
    margin: var(--cf-space-2, 0.5rem) 0 0 0;
    padding-left: var(--cf-space-5, 1.25rem);
    font-size: var(--cf-text-sm, 0.875rem);
}

.cf-v2-add-iam__footer {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

.cf-v2-add-iam__footer > .cf-btn {
    width: 100%;
    justify-content: center;
}

@media (min-width: 560px) {
    .cf-v2-add-iam__footer {
        flex-direction: row;
        justify-content: flex-end;
        width: 100%;
    }

    .cf-v2-add-iam__footer > .cf-btn {
        width: auto;
    }
}

/* ==========================================================================
   Group details drawer body
   ========================================================================== */

.cf-v2-group-details {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
    min-width: 0;
}

.cf-v2-group-details__hero {
    display: flex;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    min-width: 0;
}

.cf-v2-group-details__hero-text {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    min-width: 0;
    word-break: break-word;
    overflow-wrap: anywhere;
}

.cf-v2-group-details__stats {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-group-details__stat {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    padding: var(--cf-space-3, 0.75rem);
    border-radius: var(--cf-radius-lg, 0.75rem);
    border: 1px solid var(--cf-color-border, rgba(148, 163, 184, 0.2));
    background: var(--cf-color-surface-secondary, rgba(148, 163, 184, 0.05));
    word-break: break-word;
}

.cf-v2-group-details__members-head {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-v2-group-details__empty {
    padding: var(--cf-space-4, 1rem);
}

@media (min-width: 560px) {
    .cf-v2-group-details__stats {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--cf-space-3, 0.75rem);
    }
}

/* ==========================================================================
   Notifications tab — severity preferences + recipients
   ========================================================================== */

.cf-v2-notifications__prereq-list {
    margin: var(--cf-space-1, 0.25rem) 0 0 0;
    padding-left: var(--cf-space-5, 1.25rem);
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
}

/* Body of each Incidents / Gamebooks tab panel: stacked cards with the same
   vertical rhythm the page used before the tab split. */
.cf-v2-notifications__tab-body {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

/* Severity preference rows: optional chip column at left for color identity,
   copy column flex:1 for label + description, switch column right-anchored.
   The chip column is hidden on narrow screens since the label in the copy
   column already names the severity. */
.cf-v2-notifications-prefs__list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-notifications-prefs__row {
    display: flex;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-3, 0.75rem);
    border-radius: var(--cf-radius-lg, 0.75rem);
    border: 1px solid var(--cf-color-border, rgba(148, 163, 184, 0.2));
    background: var(--cf-color-surface-secondary, rgba(148, 163, 184, 0.04));
    min-width: 0;
}

.cf-v2-notifications-prefs__chip-col {
    flex: 0 0 auto;
    display: none;
}

.cf-v2-notifications-prefs__copy {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    min-width: 0;
    flex: 1 1 auto;
    word-break: break-word;
}

.cf-v2-notifications-prefs__switch {
    flex: 0 0 auto;
}

@media (min-width: 560px) {
    .cf-v2-notifications-prefs__chip-col {
        display: inline-flex;
        min-width: 5.5rem;
    }
}

/* Recipients row — type chip column natural width, anchored between
   identity and actions in the shared list-item. */
.cf-v2-notifications-recipients__type {
    flex: 0 0 auto;
}

@media (max-width: 559px) {
    .cf-v2-notifications-recipients__type {
        align-self: flex-start;
    }
}

/* Drawer "selected recipient" row uses a spacer so the type chip anchors
   left and the X button anchors right inside the controls strip. */
.cf-v2-add-iam__spacer {
    flex: 1 1 auto;
    min-width: 0;
}

/* V2 owns scrolling inside CFAppShell: the app frame is fixed to the viewport
   and .cf-app-shell__main is the vertical scroll container. Lock the document
   while the V2 shell is mounted so content growth, fixed overlays, or legacy
   V1 surfaces cannot wake up the browser-level scroller. */
html:has(.cf-v2-app),
body:has(.cf-v2-app) {
    width: 100%;
    height: 100%;
    overflow: hidden;
}

/* ==========================================================================
   Developers / Integration details (mobile-first)
   Shared across WebhookDetailsGeneralV2 + ServiceAccountDetailsGeneralV2.
   Unscoped so both Blazor components can share the same vocabulary.
   Breakpoints: sm=560px, md=720px, lg=960px.
   ========================================================================== */

.cf-v2-developers-detail {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
    width: 100%;
    min-width: 0;
}

/* Consistent vertical rhythm inside card bodies (grid, meta rows, lists). */
.cf-v2-developers-detail__card-body {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
    min-width: 0;
}

.cf-v2-developers-detail__loader {
    min-height: 16rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* --- Hero --- */
.cf-v2-developers-detail__hero {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    width: 100%;
    min-width: 0;
}

.cf-v2-developers-detail__hero-copy {
    display: flex;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    min-width: 0;
    flex: 1 1 auto;
}

.cf-v2-developers-detail__hero-icon {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--cf-color-surface-secondary, rgba(148, 163, 184, 0.12));
    color: var(--cf-color-icon-brand, inherit);
    flex-shrink: 0;
}

.cf-v2-developers-detail__hero-text {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
    word-break: break-word;
    overflow-wrap: anywhere;
}

.cf-v2-developers-detail__hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

.cf-v2-developers-detail__hero-actions .cf-btn {
    flex: 1 1 auto;
    min-width: 0;
    justify-content: center;
}

@media (min-width: 720px) {
    .cf-v2-developers-detail__hero {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .cf-v2-developers-detail__hero-actions {
        width: auto;
        flex-wrap: nowrap;
    }

    .cf-v2-developers-detail__hero-actions .cf-btn {
        flex: 0 0 auto;
    }
}

/* --- Section heads (used inside card header slots with trailing action) --- */
.cf-v2-developers-detail__section-head {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

.cf-v2-developers-detail__section-head .cf-btn {
    width: 100%;
    justify-content: center;
}

@media (min-width: 560px) {
    .cf-v2-developers-detail__section-head {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .cf-v2-developers-detail__section-head .cf-btn {
        width: auto;
    }
}

/* --- Two-column form grid (stacks on mobile) --- */
.cf-v2-developers-detail__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--cf-space-3, 0.75rem);
}

@media (min-width: 720px) {
    .cf-v2-developers-detail__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--cf-space-4, 1rem);
    }
}

.cf-v2-developers-detail__grid--single {
    grid-template-columns: 1fr !important;
}

/* --- URL + copy compound field --- */
.cf-v2-developers-detail__copy-field {
    display: flex;
    align-items: stretch;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-v2-developers-detail__copy-field .cf-textfield {
    flex: 1 1 auto;
    min-width: 0;
}

/* --- Meta row (inline label/value with trailing action) --- */
.cf-v2-developers-detail__meta {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
    min-width: 0;
}

.cf-v2-developers-detail__meta-copy {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    min-width: 0;
    word-break: break-all;
    overflow-wrap: anywhere;
}

/* Inline value + trailing icon action (e.g. monospace ID + copy icon). */
.cf-v2-developers-detail__value-inline {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
    flex-wrap: wrap;
}

.cf-v2-developers-detail__value-inline > .cf-v2-developers-detail__mono {
    min-width: 0;
}

.cf-v2-developers-detail__meta .cf-btn {
    width: 100%;
    justify-content: center;
}

@media (min-width: 560px) {
    .cf-v2-developers-detail__meta {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: var(--cf-space-3, 0.75rem);
    }

    .cf-v2-developers-detail__meta .cf-btn {
        width: auto;
    }
}

/* --- Label with inline help icon (used for "Permissions", "Client ID", etc.) --- */
.cf-v2-developers-detail__label-with-help {
    display: inline-flex;
    align-items: center;
    gap: var(--cf-space-1, 0.25rem);
}

/* --- List (event subscriptions, workspaces, credentials) --- */
.cf-v2-developers-detail__list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-developers-detail__list-item {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-3, 0.75rem);
    border-radius: var(--cf-radius-lg, 0.75rem);
    border: 1px solid var(--cf-color-border, rgba(148, 163, 184, 0.2));
    background: var(--cf-color-surface-secondary, rgba(148, 163, 184, 0.05));
    min-width: 0;
}

.cf-v2-developers-detail__list-copy {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
    flex: 1 1 auto;
    word-break: break-word;
    overflow-wrap: anywhere;
}

.cf-v2-developers-detail__list-title-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-v2-developers-detail__list-actions {
    display: flex;
    gap: var(--cf-space-2, 0.5rem);
    align-items: center;
    flex-wrap: wrap;
}

.cf-v2-developers-detail__list-actions .cf-btn {
    flex: 1 1 auto;
    justify-content: center;
}

@media (min-width: 560px) {
    .cf-v2-developers-detail__list-item {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: var(--cf-space-4, 1rem);
    }

    .cf-v2-developers-detail__list-item--stacked {
        flex-direction: column;
        align-items: stretch;
    }

    .cf-v2-developers-detail__list-actions {
        flex-wrap: nowrap;
    }

    .cf-v2-developers-detail__list-actions .cf-btn {
        flex: 0 0 auto;
    }
}

/* --- Event subscription row (text + toggle, with optional extras) --- */
.cf-v2-developers-detail__event-toggle {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    justify-content: flex-start;
    flex-wrap: wrap;
}

@media (min-width: 560px) {
    .cf-v2-developers-detail__event-toggle {
        justify-content: flex-end;
        flex-wrap: nowrap;
    }
}

/* --- Chip wrap (scopes, labels) --- */
.cf-v2-developers-detail__chip-wrap {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cf-space-1, 0.25rem);
    margin-top: var(--cf-space-1, 0.25rem);
}

/* --- Activity stats --- */
.cf-v2-developers-detail__stats {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-developers-detail__stat {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    padding: var(--cf-space-3, 0.75rem);
    border-radius: var(--cf-radius-lg, 0.75rem);
    border: 1px solid var(--cf-color-border, rgba(148, 163, 184, 0.2));
    background: var(--cf-color-surface-secondary, rgba(148, 163, 184, 0.05));
    word-break: break-word;
}

@media (min-width: 560px) {
    .cf-v2-developers-detail__stats {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--cf-space-4, 1rem);
    }
}

/* --- Footer / inline form actions --- */
.cf-v2-developers-detail__footer-actions {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

.cf-v2-developers-detail__footer-actions .cf-btn {
    width: 100%;
    justify-content: center;
}

@media (min-width: 560px) {
    .cf-v2-developers-detail__footer-actions {
        flex-direction: row;
        justify-content: flex-end;
        width: auto;
    }

    .cf-v2-developers-detail__footer-actions .cf-btn {
        width: auto;
    }
}

/* --- Sticky save bar --- */
.cf-v2-developers-detail__save-bar {
    position: sticky;
    bottom: 0;
    z-index: 4;
    padding: var(--cf-space-3, 0.75rem);
    margin-top: var(--cf-space-2, 0.5rem);
    background: var(--cf-color-card, var(--cf-bg-elevated-1, #1a1d23));
    border-top: 1px solid var(--cf-color-border, rgba(148, 163, 184, 0.2));
    border-radius: var(--cf-radius-lg, 0.75rem) var(--cf-radius-lg, 0.75rem) 0 0;
    box-shadow: 0 -6px 20px rgba(0, 0, 0, 0.18);
}

.cf-v2-developers-detail__save-bar-inner {
    display: flex;
    justify-content: flex-end;
    width: 100%;
}

.cf-v2-developers-detail__save-bar-inner .cf-btn {
    width: 100%;
    justify-content: center;
}

@media (min-width: 560px) {
    .cf-v2-developers-detail__save-bar-inner .cf-btn {
        width: auto;
    }
}

/* --- Monospace field for IDs --- */
.cf-v2-developers-detail__mono {
    font-family: var(--cf-font-mono, ui-monospace, SFMono-Regular, monospace);
    font-size: var(--cf-text-sm, 0.875rem);
    word-break: break-all;
}

/* ==========================================================================
   Developers / Log tabs (Request logs, Audit, Delivery events) — mobile-first
   Unscoped so all four tabs share the same header/body layout.
   ========================================================================== */

.cf-v2-developers-log-tab {
    display: block;
    width: 100%;
    min-width: 0;
}

.cf-v2-developers-log-tab__header {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--cf-space-3, 0.75rem);
    width: 100%;
    min-width: 0;
}

.cf-v2-developers-log-tab__title {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
    word-break: break-word;
    flex: 1 1 auto;
}

.cf-v2-developers-log-tab__controls {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    flex-wrap: nowrap;
    min-width: 0;
    width: 100%;
}

/* Keep the filter and refresh on a single row. Filter takes all available
   space and shrinks; refresh holds its natural size. When the whole controls
   block can't fit next to the title, it wraps below via the header's wrap. */
.cf-v2-developers-log-tab__controls > .cf-v2-time-filter {
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-developers-log-tab__refresh {
    flex: 0 0 auto;
}

.cf-v2-developers-log-tab__loader {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 16rem;
}

.cf-v2-developers-log-tab__more {
    display: flex;
    justify-content: center;
    margin-top: var(--cf-space-4, 1rem);
}

/* Chips inside log-tab CFTable cells must respect cell bounds, otherwise
   their white-space:nowrap pushes the chip past the column width into the
   neighbour. max-width:100% + min-width:0 lets the chip shrink; the cell's
   own Overflow="Clip" (set per-column) then visually clips the overflow. */
.cf-v2-developers-log-tab .cf-table__cell .cf-chip {
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The AuditMessageRenderer wraps its output in a span; when the enclosing
   cell uses line-clamp (Overflow="Ellipsis" + MaxLines>1), its span must
   propagate as inline text, not a block, so -webkit-line-clamp applies. */
.cf-v2-developers-log-tab .cf-table__cell-inner[data-overflow="ellipsis"]:not([data-max-lines="1"]) > span {
    display: inline;
}

@media (min-width: 720px) {
    .cf-v2-developers-log-tab__header {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        justify-content: space-between;
    }

    /* On desktop, controls take their natural width and sit to the right of
       the title. If they don't fit, the header's flex-wrap pushes the whole
       controls block to a second line full-width. */
    .cf-v2-developers-log-tab__controls {
        width: auto;
        justify-content: flex-end;
    }
}

/* ==========================================================================
   Log Search V2 — shared class vocabulary used across LogSearchWorkspaceV2,
   SchemaExplorerPanelV2, and LogSearchResultsGridV2. Lives here because these
   classes cross Razor files (scoped CSS can't pierce component boundaries).
   Mobile-first: base rules target phones; >= 560px / >= 960px enhance upward.
   ========================================================================== */

.cf-v2-log-search {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
    width: 100%;
    min-width: 0;
    min-height: 24rem;
    /* Mobile: the page flows naturally and the browser handles overflow.
       The viewport-lock pattern only applies on desktop (see media query
       below) — phones have too little vertical real estate for a pinned
       layout, and cumulative card heights would clip the results grid. */
}

@media (min-width: 960px) {
    .cf-v2-log-search {
        /* Desktop: cap the region to the viewport so tall schemas and
           tall result sets scroll inside their own containers instead
           of forcing a page-level scrollbar. dvh keeps the bottom of
           the results card from being clipped by mobile browser chrome
           on large-format tablets. */
        height: calc(100dvh - 10rem);
        overflow: hidden;
    }
}

/* Suppress text selection during an editor drag so the resize gesture
   doesn't paint the whole page blue. */
.cf-v2-log-search[data-dragging="true"] {
    cursor: ns-resize;
    user-select: none;
}

/* Docked in the incident dock the workspace fills the host instead of asserting
   its own floor. The page-mode `min-height: 24rem` is taller than the dock's
   default content area (306px) and way past its 160px minimum, so it would
   overflow the moment the dock is dragged down. */
.cf-v2-log-search--docked {
    height: 100%;
    min-height: 0;
    gap: var(--cf-space-2, 0.5rem);
}

/* Toolbar card */
.cf-v2-log-search__toolbar-row {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    align-items: stretch;
    width: 100%;
    min-width: 0;
}

.cf-v2-log-search__toolbar-lead {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
    flex: 1 1 auto;
}

.cf-v2-log-search__toolbar-context {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
    flex: 1 1 auto;
}

.cf-v2-log-search__toolbar-context > p {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cf-v2-log-search__toolbar-actions {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

/* Mobile: every child — including tooltip-wrapped CFButton/CFAiButton —
   stretches to fill the column so the stack reads as a uniform list of
   actions. Plain `> *` wouldn't reach the inner button when CFTooltip
   is in between, which is why Export went full-width in the earlier
   iteration but Run and AI Assist stayed auto-sized. */
.cf-v2-log-search__toolbar-actions > *,
.cf-v2-log-search__toolbar-actions .cf-btn,
.cf-v2-log-search__toolbar-actions .cf-ai-btn {
    width: 100%;
    justify-content: center;
}

@media (min-width: 560px) {
    .cf-v2-log-search__toolbar-row {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .cf-v2-log-search__toolbar-actions {
        flex-direction: row;
        width: auto;
        align-items: center;
    }

    /* Desktop: release the full-width stretch applied on mobile so each
       button hugs its label content again. */
    .cf-v2-log-search__toolbar-actions > *,
    .cf-v2-log-search__toolbar-actions .cf-btn,
    .cf-v2-log-search__toolbar-actions .cf-ai-btn {
        width: auto;
    }
}

@media (min-width: 960px) {
    .cf-v2-log-search__schema-toggle {
        display: none;
    }
}

/* AI assistant command bar - mounted inside the editor card so query
   generation feels attached to authoring instead of like a separate form. */
.cf-v2-log-search__ai-command {
    border-bottom: 1px solid color-mix(in oklab, var(--ai-gradient-color-2, #ff6b08) 28%, var(--cf-color-border, currentColor));
}

.cf-v2-log-search__ai-trigger[data-active="true"] {
    box-shadow:
        0 0 0 1px color-mix(in oklab, var(--ai-gradient-color-2, #ff6b08) 55%, transparent),
        0 12px 28px -16px color-mix(in oklab, var(--ai-gradient-color-4, #b844ee) 80%, transparent);
}

/* Run button keyboard hint — hidden below 720px to keep mobile tight. */
.cf-v2-log-search__kbd {
    display: none;
    align-items: center;
    gap: var(--cf-space-1, 0.25rem);
    padding: 0 var(--cf-space-1-5, 0.375rem);
    margin-left: var(--cf-space-2, 0.5rem);
    border-radius: var(--cf-radius-sm, 4px);
    background: color-mix(in oklab, currentColor 12%, transparent);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.5;
    opacity: 0.85;
}

@media (min-width: 720px) {
    .cf-v2-log-search__kbd {
        display: inline-flex;
    }
}

/* Content layout — schema + workspace */
.cf-v2-log-search__content {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    width: 100%;
    min-width: 0;
    /* Absorb remaining height in the root flex column so the workspace
       grows to fill it instead of shrinking to content. min-height:0 lets
       the inner grid-height math work even when the content is tall.
       overflow:hidden is belt-and-suspenders — on short desktop viewports
       the root's overflow:hidden already clips, but clipping here too
       prevents any inner scroll region from racing the root for the
       scroll bar. */
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
}

.cf-v2-log-search__schema-aside {
    display: none;
    min-width: 0;
}

.cf-v2-log-search__workspace {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    min-width: 0;
    min-height: 0;
    flex: 1 1 auto;
}

@media (min-width: 960px) {
    .cf-v2-log-search__content {
        flex-direction: row;
        align-items: stretch;
    }

    .cf-v2-log-search__schema-aside {
        display: flex;
        flex-direction: column;
        width: 320px;
        flex: 0 0 320px;
        min-height: 0;
    }

    .cf-v2-log-search__schema-card {
        height: 100%;
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        min-height: 0;
    }

    .cf-v2-log-search__schema-card .cf-card__content {
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        min-height: 0;
    }
}

/* Schema panel (shared by inline + drawer usage). The panel itself fills
   its container (the schema card on desktop, the drawer body on mobile).
   Inside, the header stays fixed-height and the schema-body scrolls within
   the remaining space. */
.cf-v2-log-search__schema {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
    flex: 1 1 auto;
    min-height: 0;
}

.cf-v2-log-search__schema-header {
    display: flex;
    align-items: center;
    gap: var(--cf-space-1-5, 0.375rem);
    margin-top: var(--cf-space-2, 0.5rem);
    flex: 0 0 auto;
}

.cf-v2-log-search__schema-body {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
    /* Mobile (drawer): cap so the schema list never outgrows the drawer
       body when mounted there. Desktop overrides this to fill the aside. */
    max-height: 50vh;
}

@media (min-width: 960px) {
    .cf-v2-log-search__schema-body {
        max-height: none;
    }
}

.cf-v2-log-search__schema-loading {
    display: flex;
    justify-content: center;
    padding: var(--cf-space-4, 1rem) 0;
}

.cf-v2-log-search__schema-solution {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
}

/* A node row (solution button or leaf table cell). Everything inside the
   schema aligns against the same left edge — no shifting around based on
   whether an item has a chevron. */
.cf-v2-log-search__schema-node {
    display: flex;
    align-items: center;
    gap: var(--cf-space-1-5, 0.375rem);
    padding: var(--cf-space-1, 0.25rem) var(--cf-space-2, 0.5rem);
    border: none;
    background: transparent;
    text-align: left;
    cursor: pointer;
    border-radius: var(--cf-radius-sm, 4px);
    color: var(--cf-text-default, inherit);
    font-size: 0.8125rem;
    min-width: 0;
    width: 100%;
    box-sizing: border-box;
}

.cf-v2-log-search__schema-node:hover {
    background: color-mix(in oklab, currentColor 8%, transparent);
}

/* Leaf table cells: not interactive, muted text. No extra left padding —
   the wrapping role="group" already indents the whole list so the table
   icon lines up under its parent solution's database icon. */
.cf-v2-log-search__schema-node--table {
    cursor: default;
    color: var(--cf-text-muted, inherit);
}

.cf-v2-log-search__schema-node--table:hover {
    background: transparent;
}

/* Indent the whole expanded tables list once, instead of padding every
   leaf individually. The offset matches the chevron slot (14px) + the
   row flex-gap (0.375rem) so the table icon sits directly below the
   solution's database icon. */
.cf-v2-log-search__schema-tables {
    display: flex;
    flex-direction: column;
    padding-inline-start: calc(14px + var(--cf-space-1-5, 0.375rem));
}

.cf-v2-log-search__schema-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1 1 auto;
}

/* Fixed-width chevron slot so collapsed and expanded rows stay aligned
   and the chevron never shifts the rest of the row. */
.cf-v2-log-search__schema-chevron {
    width: 14px;
    height: 14px;
    flex: 0 0 14px;
}

/* Editor card — height is driven by the KqlEditor Height param, which the
   component binds at runtime to a draggable pixel value. The wrapper itself
   is just a style hook + test target. */
.cf-v2-log-search__editor-card {
    overflow: hidden;
    flex: 0 0 auto;
}

.cf-v2-log-search__editor {
    width: 100%;
    min-height: 120px;
}

/* Recolor the V1 HorizontalResizeBar when it's used inside a V2 log-search
   workspace so it picks up V2 token colors instead of the component's
   original white / charcoal default. Targets the plain class name because
   the component's scoped CSS doesn't isolate the class selector itself. */
.cf-v2-log-search .horizontal-resize-bar {
    flex: 0 0 auto;
    background: var(--cf-color-border-subtle, color-mix(in oklab, currentColor 18%, transparent));
}

.cf-v2-log-search .horizontal-resize-bar .ellipse {
    background: var(--cf-text-muted, color-mix(in oklab, currentColor 55%, transparent));
}

/* Results card — grows to fill remaining column height after the toolbar
   and editor have taken their share. Low `min-height` so a tall editor
   drag shrinks the grid instead of pushing overflow off the page. */
/* Mobile: generous floor so the virtualized grid shows a useful number
   of rows without the user having to drag the editor smaller first. */
.cf-v2-log-search__results-card {
    min-height: 28rem;
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
}

/* Desktop: flex-shrinks freely down to a small header-plus-row minimum
   so a tall editor drag never clips the grid off the page. The user-
   controlled splitter between editor and results arbitrates the actual
   split, like the Azure Logs blade. */
@media (min-width: 960px) {
    .cf-v2-log-search__results-card {
        min-height: 6rem;
    }
}

/* Defense-in-depth: cap the editor card at roughly half the viewport so
   even if the drag clamp in code is raised later, the editor can't grow
   past a point where the results card would disappear. Desktop-only —
   on mobile the page flows and the editor's intrinsic height is fine. */
@media (min-width: 960px) {
    .cf-v2-log-search__editor-card {
        max-height: 55dvh;
    }
}

.cf-v2-log-search__results-card .cf-card__content {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.cf-v2-log-search__results-header {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-log-search__results-body {
    flex: 1 1 auto;
    min-height: 320px;
    display: flex;
    flex-direction: column;
}

.cf-v2-log-search__results-loading {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-6, 1.5rem);
}

/* ==========================================================================
   Command Center V2 — Shared widget vocabulary
   Unscoped because multiple widget components consume the same classes and
   Blazor scoped CSS cannot pierce component boundaries.
   ========================================================================== */

/* Command-dashboard cards fill their grid cell — 100% wide, 100% tall.
   The card itself becomes the scroll-containing parent: header stays pinned,
   body fills remaining height and clips overflow so the inner table/list
   scrolls rather than pushing the whole grid row taller. */
.cf-v2-command-grid__cell .cf-card {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

.cf-v2-command-grid__cell .cf-card__header {
    flex-shrink: 0;
}

.cf-v2-command-grid__cell .cf-card__content {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.cf-v2-command-widget {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
    width: 100%;
    min-width: 0;
}

.cf-v2-command-widget__body {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
    min-width: 0;
    min-height: 0;
    flex: 1 1 auto;
    overflow: hidden;
}

/* Inside a bounded dashboard cell, the table becomes the scrollable region.
   CFTable.cf-table__scroll ships with overflow-y: hidden so it relies on an
   outer scroll container — here we flip it to auto so long datasets scroll
   inside the card instead of inflating the row. Sibling stats strips stay
   at intrinsic height above the scrolling table. */
.cf-v2-command-grid__cell .cf-v2-command-widget__body > .cf-table {
    flex: 1 1 auto;
    min-height: 0;
}

.cf-v2-command-grid__cell .cf-v2-command-widget__body .cf-table__scroll {
    overflow-y: auto;
}

/* Tabbed table widgets (Classification Trends) nest the table inside CFTabs, so
   the direct-child override above never reaches it — the table renders at full
   height and the body's overflow: hidden clips its last row. Flex the tabs
   subtree down to the table so it scrolls internally like the untabbed widgets. */
.cf-v2-command-grid__cell .cf-v2-command-widget__body > .cf-tabs {
    flex: 1 1 auto;
    min-height: 0;
}

.cf-v2-command-grid__cell .cf-v2-command-widget__body .cf-tabs__panels {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
    padding-bottom: 0;
}

.cf-v2-command-grid__cell .cf-v2-command-widget__body .cf-tabs__panel[data-active="true"] {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

.cf-v2-command-grid__cell .cf-v2-command-widget__body .cf-tabs__panel > .cf-table {
    flex: 1 1 auto;
    min-height: 0;
}

.cf-v2-command-grid__cell .cf-v2-command-widget__stats {
    flex-shrink: 0;
}

/* Section header for widget cards — title on the left, optional trailing metric
   chip/badge on the right. Wraps on mobile via the parent's flex rules. */
.cf-v2-command-widget__header {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
}

@media (min-width: 560px) {
    .cf-v2-command-widget__header {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: var(--cf-space-3, 0.75rem);
    }
}

/* Stats strip — two-up on mobile, four-up on tablet. */
.cf-v2-command-widget__stats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--cf-space-3, 0.75rem);
    min-width: 0;
}

@media (min-width: 560px) {
    .cf-v2-command-widget__stats {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

.cf-v2-command-widget__stat {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    padding: var(--cf-space-3, 0.75rem);
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-color-surface-secondary, rgba(148, 163, 184, 0.08));
    min-width: 0;
}

.cf-v2-command-widget__stat-value {
    font-variant-numeric: tabular-nums;
}

/* Skeleton cluster used inside widget bodies while data is loading.
   Keep heights close to the rendered content so the layout doesn't jump.
   flex: 1 so the cluster grows with the stretched card. */
.cf-v2-command-widget__skeletons {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    min-height: 12rem;
    flex: 1;
}

/* Empty-state wrapper — the CFEmptyState component owns its own layout, but
   widgets wrap it in this container to give a consistent min-height and
   centre the message vertically when the card is stretched taller by an
   adjacent content-heavy sibling. */
.cf-v2-command-widget__empty {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 12rem;
    flex: 1;
}

/* Chart wrapper for donut-only widgets — centres the chart vertically
   inside whatever height the card has been stretched to. */
.cf-v2-command-widget__chart {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 12rem;
    flex: 1;
}

/* Scale the donut up inside the command dashboard cells — CFDonut's Lg preset
   is 160px which reads as small in a 26–28rem card. Override scoped to the
   dashboard so other consumers of CFDonut are unaffected. */
.cf-v2-command-grid__cell .cf-v2-command-widget__chart .cf-donut__chart {
    width: 200px;
    height: 200px;
}

@media (min-width: 1200px) {
    .cf-v2-command-grid__cell .cf-v2-command-widget__chart .cf-donut__chart {
        width: 220px;
        height: 220px;
    }
}

/* ──────────────────────────────────────────────────────────────────────────
   Tabbed incidents dialog (V2) — shell sizing override.

   The shell pins a fixed viewport-relative height so the dialog never grows
   or shrinks as panes load — content scroll lives inside the modal, not the
   dialog body. Padding is zeroed so the modal owns its own chrome rhythm
   (sticky header + sticky tab strip + scrollable pane region).

   Below 720px (tablets/phones) we go full-bleed and full-height so the
   modal acts as a page rather than a card.

   `!important` is required because the provider's `[data-size]` rules live
   in scoped CSS and match with attribute-bumped specificity.
   ────────────────────────────────────────────────────────────────────── */
.cf-dialog.cf-v2-incident-modal-shell {
    width: min(1100px, 96vw) !important;
    height: min(860px, 92vh) !important;
    max-width: min(1100px, 96vw) !important;
    max-height: 92vh !important;
    border-radius: var(--cf-radius-lg, 12px) !important;
    background: var(--cf-bg-elevated-1) !important;
    /*
       Override the provider's open animation to opacity-only. The default
       cf-dialog-in keyframes leave transform: scale(1) on the dialog after
       the animation finishes (the `to` state is retained via fill-mode: both),
       which creates a containing block for position:fixed descendants. That
       breaks portalled overlays inside the modal — CFMenu / CFAutocomplete
       popups compute coordinates from getBoundingClientRect() expecting the
       viewport as reference, but with the dialog as the containing block
       they jump to wildly wrong positions (assignee dropdown lands far from
       its trigger).
    */
    animation: cf-incident-modal-in var(--cf-duration-slow, 0.32s) var(--cf-ease-out, ease-out) both !important;
}

@keyframes cf-incident-modal-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

.cf-dialog.cf-v2-incident-modal-shell .cf-dialog__body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding: 0 !important;
    background: transparent;
    overflow: hidden;
}

@media (max-width: 720px) {
    .cf-dialog.cf-v2-incident-modal-shell {
        width: 100% !important;
        height: 100% !important;
        max-width: 100% !important;
        max-height: 100% !important;
        border-radius: 0 !important;
    }
}

/* ========================================================================
   Module configuration page (V2) — shared layout vocabulary used by
   ModuleHeroPrereqsCardV2, ModuleConfigurationViewV2, the per-module
   form components (Sentinel / CrowdStrike / SentinelOne), ModuleScopesV2,
   and CrowdStrikeAlertTypesCardV2. Lives globally because these classes
   appear in multiple .razor files; Blazor scoped CSS would not reach
   across them.
   ======================================================================== */

/* --- Hero (module summary + status chips + enable/disable button) ----- */
.cf-v2-module-config__hero {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
    align-items: stretch;
}

.cf-v2-module-config__hero-copy {
    display: flex;
    align-items: flex-start;
    gap: var(--cf-space-3, 0.75rem);
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-module-config__hero-icon {
    flex: 0 0 auto;
    width: 56px;
    height: 56px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-2, rgba(255, 255, 255, 0.04));
    color: var(--cf-text-muted, #98a2b3);
    overflow: hidden;
}

.cf-v2-module-config__hero-icon .cf-icon {
    width: 24px;
    height: 24px;
}

.cf-v2-module-config__hero-logo {
    width: 36px;
    height: 36px;
    object-fit: contain;
    display: block;
}

.cf-v2-module-config__hero-text {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    align-items: flex-start;
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-module-config__hero-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cf-space-2, 0.5rem);
    margin-top: var(--cf-space-1, 0.25rem);
}

.cf-v2-module-config__hero-actions {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-module-config__hero-actions .cf-btn {
    width: 100%;
}

@media (min-width: 720px) {
    .cf-v2-module-config__hero {
        flex-direction: row;
        align-items: flex-start;
    }

    .cf-v2-module-config__hero-actions {
        flex-direction: row;
        align-items: center;
        flex: 0 0 auto;
    }

    .cf-v2-module-config__hero-actions .cf-btn {
        width: auto;
    }
}

/* --- Prerequisites checklist (lives inside hero card) ----------------- */
.cf-v2-module-config__prereqs {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    padding-top: var(--cf-space-4, 1rem);
    margin-top: var(--cf-space-4, 1rem);
    border-top: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
}

.cf-v2-module-config__prereq-list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-module-config__prereq-row {
    display: flex;
    align-items: flex-start;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-module-config__prereq-icon {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--cf-text-muted, #98a2b3);
}

.cf-v2-module-config__prereq-icon--ok {
    color: var(--cf-status-success-fg, #34d399);
}

.cf-v2-module-config__prereq-icon--failed {
    color: var(--cf-status-error-fg, #f87171);
}

.cf-v2-module-config__prereq-icon .cf-icon {
    width: 18px;
    height: 18px;
}

.cf-v2-module-config__prereq-text {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    flex: 1 1 auto;
    min-width: 0;
}

/* --- Configuration form layout (used by every module form variant) ---- */
.cf-v2-module-config__form {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cf-v2-module-config__form-actions {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
    align-items: stretch;
    margin-top: var(--cf-space-2, 0.5rem);
}

.cf-v2-module-config__form-actions .cf-btn {
    width: 100%;
}

/* Apollo deployment affordance (PLAT-3120) — stacks the status alert, action row,
   and helper text with consistent vertical rhythm below the Sentinel form. */
.cf-v2-module-config__apollo {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    margin-top: var(--cf-space-4, 1rem);
}

/* Failed-connection affordance (PLAT-3346) — same vertical rhythm as the Apollo
   block, which it replaces while a Lighthouse deployment is in the failed state. */
.cf-v2-module-config__connection-failed {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    margin-top: var(--cf-space-4, 1rem);
}

@media (min-width: 560px) {
    .cf-v2-module-config__form-actions {
        flex-direction: row;
        justify-content: flex-end;
        align-items: center;
    }

    .cf-v2-module-config__form-actions .cf-btn {
        width: auto;
    }
}

/* Subscription autocomplete two-line item template */
.cf-v2-module-config__autocomplete-item {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
}

/* --- Required-scopes informational banner (CrowdStrike / SentinelOne) - */
.cf-v2-module-config__scopes-banner {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.06));
}

.cf-v2-module-config__scopes-list {
    margin: var(--cf-space-1, 0.25rem) 0 0 0;
    padding-left: var(--cf-space-5, 1.25rem);
    color: var(--cf-text-muted, #98a2b3);
    font-size: 0.875rem;
    line-height: 1.5;
}

.cf-v2-module-config__scopes-list li + li {
    margin-top: var(--cf-space-1, 0.25rem);
}

/* --- Module scopes (consent + permission groups + forwarding switch) -- */
.cf-v2-module-config__scopes {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cf-v2-module-config__scopes-header {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    align-items: stretch;
}

.cf-v2-module-config__scopes-identity {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-module-config__scopes-header .cf-btn {
    width: 100%;
}

@media (min-width: 560px) {
    .cf-v2-module-config__scopes-header {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .cf-v2-module-config__scopes-header .cf-btn {
        width: auto;
        flex: 0 0 auto;
    }
}

.cf-v2-module-config__permissions {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-module-config__permissions-list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-module-config__permissions-row {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    padding: var(--cf-space-2, 0.5rem) 0;
    border-bottom: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.06));
}

.cf-v2-module-config__permissions-row:last-child {
    border-bottom: none;
}

.cf-v2-module-config__forwarding {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--cf-space-4, 1rem);
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.06));
}

.cf-v2-module-config__forwarding-copy {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    flex: 1 1 auto;
    min-width: 0;
}

/* --- CrowdStrike alert types (read-only summary lists) --------------- */
.cf-v2-module-config__alert-types-list {
    margin: var(--cf-space-1, 0.25rem) 0 0 0;
    padding-left: var(--cf-space-5, 1.25rem);
    color: var(--cf-text-muted, #98a2b3);
    font-size: 0.875rem;
    line-height: 1.5;
}

.cf-v2-module-config__alert-types-list li + li {
    margin-top: var(--cf-space-1, 0.25rem);
}

.cf-v2-module-config__alert-types-list strong {
    color: var(--cf-text-primary, #f9fafb);
}

.cf-v2-module-config__alert-types-value {
    color: var(--cf-text-secondary, #cbd5e1);
}

/* --- Test Connection verification (CrowdStrike) ---------------------- */
.cf-v2-module-config__verification {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.06));
}

.cf-v2-module-config__verification-row {
    display: flex;
    align-items: flex-start;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-module-config__verification-icon {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--cf-text-muted, #98a2b3);
}

.cf-v2-module-config__verification-icon--ok   { color: var(--cf-status-success, #34d399); }
.cf-v2-module-config__verification-icon--fail { color: var(--cf-status-error-light, #f87171); }
.cf-v2-module-config__verification-icon--info { color: var(--cf-status-info-light, #5597ff); }

.cf-v2-module-config__verification-icon .cf-icon {
    width: 18px;
    height: 18px;
}

.cf-v2-module-config__verification-text {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    flex: 1 1 auto;
    min-width: 0;
}

/* ========================================================================
   CMS / Security Analytics page (V2) — Sentinel Marketplace tab
   shared layout vocabulary used across the marketplace cards (sources,
   summary, rules), the source-card primitive, and the rule deployments
   grid. Lives globally because these classes are referenced from multiple
   .razor files; Blazor scoped CSS would not reach across them.
   ======================================================================== */

/* --- Scanned-sources card header (title/last-scanned + search/scan) ---
   The CFCard's .cf-card__header is itself a flex row with
   justify-content: space-between. Our single child needs flex:1 + width:100%
   so it spans the header — otherwise it shrinks to its content and the
   internal margin-left:auto on the actions has nothing to push against,
   leaving the actions stuck on the left edge. */
.cf-v2-cms__sources-head {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    align-items: stretch;
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
}

.cf-v2-cms__sources-head-copy {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    flex: 0 1 auto;
    min-width: 0;
}

.cf-v2-cms__sources-head-actions {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    align-items: stretch;
}

.cf-v2-cms__sources-head-actions .cf-textfield,
.cf-v2-cms__sources-head-actions .cf-btn {
    width: 100%;
}

@media (min-width: 560px) {
    .cf-v2-cms__sources-head {
        flex-direction: row;
        align-items: center;
        flex-wrap: wrap;
    }

    /* Push actions to the far right regardless of how wide the title block is. */
    .cf-v2-cms__sources-head-actions {
        flex-direction: row;
        align-items: center;
        flex: 0 0 auto;
        margin-left: auto;
    }

    .cf-v2-cms__sources-head-actions .cf-textfield {
        width: 240px;
    }

    .cf-v2-cms__sources-head-actions .cf-btn {
        width: auto;
    }
}

/* --- Source-card grid -------------------------------------------------- */
.cf-v2-cms__source-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--cf-space-3, 0.75rem);
}

@media (min-width: 560px) {
    .cf-v2-cms__source-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 960px) {
    .cf-v2-cms__source-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (min-width: 1200px) {
    .cf-v2-cms__source-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

/* --- Source card primitive (selectable button) ------------------------ */
.cf-v2-cms__source-card {
    display: flex;
    align-items: stretch;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-4, 1rem);
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
    cursor: pointer;
    text-align: left;
    width: 100%;
    color: inherit;
    font: inherit;
    transition: background-color 120ms ease, border-color 120ms ease;
}

.cf-v2-cms__source-card:hover {
    background: var(--cf-bg-elevated-2, rgba(255, 255, 255, 0.06));
    border-color: var(--cf-color-border, rgba(255, 255, 255, 0.16));
}

.cf-v2-cms__source-card:focus-visible {
    outline: 2px solid var(--cf-color-accent, #6366f1);
    outline-offset: 2px;
}

.cf-v2-cms__source-card[data-selected="true"] {
    background: var(--cf-bg-elevated-3, rgba(255, 255, 255, 0.08));
    border-color: var(--cf-color-accent, #6366f1);
    cursor: default;
}

.cf-v2-cms__source-card-icon {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-2, rgba(255, 255, 255, 0.04));
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.cf-v2-cms__source-card-icon img {
    width: 30px;
    height: 30px;
    object-fit: contain;
}

.cf-v2-cms__source-card-icon .cf-icon {
    width: 22px;
    height: 22px;
    color: var(--cf-text-muted, #98a2b3);
}

.cf-v2-cms__source-card-body {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-cms__source-card-pip {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--cf-text-muted, #98a2b3);
    flex: 0 0 auto;
}

.cf-v2-cms__source-card-pip--ok      { background: var(--cf-status-success-fg, #34d399); }
.cf-v2-cms__source-card-pip--info    { background: var(--cf-color-accent, #6366f1); }
.cf-v2-cms__source-card-pip--warning { background: var(--cf-status-warning-fg, #f59e0b); }
.cf-v2-cms__source-card-pip--error   { background: var(--cf-status-error-fg, #f87171); }

/* --- Analytical rules tab header (title + counter + search + refresh) -- */
.cf-v2-cms__rules-head {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    align-items: stretch;
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
}

/* Epic G cleanup — analytical-rules multi-select bar + per-row action cluster. */
.cf-v2-cms__rules-selection-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    padding-bottom: var(--cf-space-2, 0.5rem);
}

.cf-v2-cms__rule-row-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--cf-space-1, 0.25rem);
}

.cf-v2-cms__rules-head-copy {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    flex: 0 1 auto;
    min-width: 0;
}

.cf-v2-cms__rules-head-actions {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    align-items: stretch;
}

.cf-v2-cms__rules-head-actions .cf-textfield {
    width: 100%;
}

@media (min-width: 560px) {
    .cf-v2-cms__rules-head {
        flex-direction: row;
        align-items: center;
        flex-wrap: wrap;
    }

    .cf-v2-cms__rules-head-actions {
        flex-direction: row;
        align-items: center;
        flex: 0 0 auto;
        margin-left: auto;
    }

    .cf-v2-cms__rules-head-actions .cf-textfield {
        width: 240px;
    }
}

/* --- Analytical rules filter chip rows (severity + status) ----------- */
.cf-v2-cms__rules-filter-row {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    padding-bottom: var(--cf-space-3, 0.75rem);
    border-bottom: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
}

.cf-v2-cms__rules-filter-group {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
}

.cf-v2-cms__rules-filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cf-space-2, 0.5rem);
}

@media (min-width: 720px) {
    .cf-v2-cms__rules-filter-row {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: flex-start;
        gap: var(--cf-space-5, 1.25rem);
    }

    .cf-v2-cms__rules-filter-row > .cf-btn {
        margin-left: auto;
        align-self: flex-end;
    }
}

/* Filter-chip primitive — toggles between active and inactive state via the
   data-active attribute. */
.cf-v2-cms__filter-chip {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 var(--cf-space-3, 0.75rem);
    border-radius: 999px;
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.04));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.12));
    color: var(--cf-text-secondary, #A1A1AA);
    font: inherit;
    font-size: 0.8125rem;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

.cf-v2-cms__filter-chip:hover {
    background: var(--cf-bg-elevated-2, rgba(255, 255, 255, 0.08));
    border-color: var(--cf-color-border, rgba(255, 255, 255, 0.2));
    color: var(--cf-text-primary, #ffffff);
}

.cf-v2-cms__filter-chip:focus-visible {
    outline: 2px solid var(--cf-color-accent, #6366f1);
    outline-offset: 2px;
}

.cf-v2-cms__filter-chip[data-active="true"] {
    background: color-mix(in srgb, var(--cf-status-info, #2557F9) 20%, transparent);
    border-color: var(--cf-status-info, #2557F9);
    color: var(--cf-status-info-light, #5597FF);
}

@media (prefers-reduced-motion: reduce) {
    .cf-v2-cms__filter-chip { transition: none; }
}

/* --- Rule details (general / logic / configuration) ------------------- */
.cf-v2-rule-details__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--cf-space-3, 0.75rem);
    flex: 1 1 auto;
    width: 100%;
    min-width: 0;
}

/* Epic G cleanup — rule-details header cluster (severity chip + Delete action). */
.cf-v2-rule-details__head-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-rule-details__head-text {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-rule-details__field {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
}

.cf-v2-rule-details__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--cf-space-4, 1rem);
}

@media (min-width: 720px) {
    .cf-v2-rule-details__grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

.cf-v2-rule-details__tactic-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cf-space-2, 0.5rem);
}

/* Rule description — Markdown rendered via Markdig (DisableHtml). Style the full
   set of structural elements rule authors use: headings, paragraphs, lists, code,
   blockquotes, and inline links. */
.cf-v2-rule-details__description {
    color: var(--cf-text-primary, #f4f4f5);
    font-size: 0.875rem;
    line-height: 1.55;
}

.cf-v2-rule-details__description > *:first-child {
    margin-top: 0;
}

.cf-v2-rule-details__description > *:last-child {
    margin-bottom: 0;
}

.cf-v2-rule-details__description h1,
.cf-v2-rule-details__description h2,
.cf-v2-rule-details__description h3,
.cf-v2-rule-details__description h4,
.cf-v2-rule-details__description h5,
.cf-v2-rule-details__description h6 {
    margin: var(--cf-space-4, 1rem) 0 var(--cf-space-1, 0.25rem) 0;
    font-weight: 600;
    color: var(--cf-text-primary, #f4f4f5);
    line-height: 1.3;
}

.cf-v2-rule-details__description h1 { font-size: 1.05rem; }
.cf-v2-rule-details__description h2 { font-size: 1rem; }
.cf-v2-rule-details__description h3 { font-size: 0.9375rem; }
.cf-v2-rule-details__description h4,
.cf-v2-rule-details__description h5,
.cf-v2-rule-details__description h6 { font-size: 0.875rem; }

.cf-v2-rule-details__description p {
    margin: 0 0 var(--cf-space-2, 0.5rem) 0;
}

.cf-v2-rule-details__description ul,
.cf-v2-rule-details__description ol {
    margin: 0 0 var(--cf-space-2, 0.5rem) 0;
    padding-left: var(--cf-space-5, 1.25rem);
}

.cf-v2-rule-details__description li + li {
    margin-top: var(--cf-space-0-5, 2px);
}

.cf-v2-rule-details__description a {
    color: var(--cf-status-info-light, #5597FF);
    text-decoration: underline;
    text-underline-offset: 2px;
    word-break: break-word;
}

.cf-v2-rule-details__description a:hover {
    color: var(--cf-status-info, #2557F9);
}

.cf-v2-rule-details__description code {
    padding: 0.1em 0.35em;
    border-radius: var(--cf-radius-sm, 4px);
    background: var(--cf-bg-elevated-2, rgba(255, 255, 255, 0.06));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
    font-family: var(--cf-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace);
    font-size: 0.8125rem;
}

.cf-v2-rule-details__description pre {
    margin: 0 0 var(--cf-space-2, 0.5rem) 0;
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-2, rgba(255, 255, 255, 0.06));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
    overflow: auto;
}

.cf-v2-rule-details__description pre code {
    padding: 0;
    border: none;
    background: transparent;
}

.cf-v2-rule-details__description blockquote {
    margin: 0 0 var(--cf-space-2, 0.5rem) 0;
    padding: var(--cf-space-1, 0.25rem) var(--cf-space-3, 0.75rem);
    border-left: 3px solid var(--cf-color-border, rgba(255, 255, 255, 0.16));
    color: var(--cf-text-secondary, #A1A1AA);
}

.cf-v2-rule-details__description hr {
    margin: var(--cf-space-3, 0.75rem) 0;
    border: none;
    border-top: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
}

/* Code block — inline V2 styling for the rule query, no JS dependency. */
.cf-v2-rule-details__code {
    position: relative;
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-2, rgba(255, 255, 255, 0.05));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
    overflow: hidden;
}

.cf-v2-rule-details__code pre {
    margin: 0;
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
    max-height: 320px;
    min-height: 120px;
    overflow: auto;
    font-family: var(--cf-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace);
    font-size: 0.8125rem;
    line-height: 1.55;
    color: var(--cf-text-primary, #f4f4f5);
    white-space: pre-wrap;
    word-break: break-word;
}

.cf-v2-rule-details__code-actions {
    position: absolute;
    top: var(--cf-space-2, 0.5rem);
    right: var(--cf-space-2, 0.5rem);
}

/* Entity mappings — list of identifier → column-name pills. */
.cf-v2-rule-details__entities {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-rule-details__entity-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--cf-space-3, 0.75rem);
}

@media (min-width: 720px) {
    .cf-v2-rule-details__entity-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 1100px) {
    .cf-v2-rule-details__entity-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

.cf-v2-rule-details__entity {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.06));
}

.cf-v2-rule-details__entity-row {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-v2-rule-details__entity-pill {
    flex: 1 1 0;
    min-width: 0;
    padding: var(--cf-space-1, 0.25rem) var(--cf-space-2, 0.5rem);
    border-radius: var(--cf-radius-sm, 4px);
    background: var(--cf-bg-elevated-2, rgba(255, 255, 255, 0.06));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
    font-size: 0.8125rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cf-v2-rule-details__entity-arrow {
    flex: 0 0 auto;
    color: var(--cf-text-secondary, #A1A1AA);
}

/* --- Rule configuration (deploy / auto-update / enable switches) ------ */
.cf-v2-rule-config {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cf-v2-rule-config__head {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-rule-config__head .cf-icon {
    width: 16px;
    height: 16px;
    color: var(--cf-text-secondary, #A1A1AA);
}

.cf-v2-rule-config__row {
    display: flex;
    align-items: flex-start;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-3, 0.75rem) 0;
    border-top: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.06));
}

.cf-v2-rule-config__row:first-of-type {
    border-top: none;
    padding-top: 0;
}

.cf-v2-rule-config__row-copy {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    flex: 1 1 auto;
    min-width: 0;
}

/* --- Rules grid cell helpers ------------------------------------------ */
.cf-v2-cms__rule-name,
.cf-v2-cms__rule-tactics {
    display: inline-block;
    max-width: 100%;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

/* --- Empty / no-results state ----------------------------------------- */
.cf-v2-cms__empty {
    display: flex;
    align-items: flex-start;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-6, 1.5rem) var(--cf-space-4, 1rem);
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border: 1px dashed var(--cf-color-border-subtle, rgba(255, 255, 255, 0.12));
}

.cf-v2-cms__empty .cf-icon {
    width: 28px;
    height: 28px;
    color: var(--cf-text-muted, #98a2b3);
    flex: 0 0 auto;
}

/* === FR-210 / PLAT-3068 SLA configuration form ============================ */

/* Details page layout: column stack of cards + sticky save bar. */
.cf-v2-sla-details {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
    min-width: 0;
}

.cf-v2-sla-details__list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-sla-details__list-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-3, 0.75rem);
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
    min-width: 0;
}

.cf-v2-sla-details__list-copy {
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-sla-details__list-actions {
    flex: 0 0 auto;
}

.cf-v2-sla-details__save-bar {
    position: sticky;
    bottom: 0;
    z-index: 2;
    display: flex;
    justify-content: flex-end;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-3, 0.75rem) 0;
    background: var(--cf-color-card, var(--cf-bg-elevated-1, #1a1d23));
    box-shadow: 0 -6px 20px rgba(0, 0, 0, 0.18);
}

/* Form-level "Advanced options" toggle row: label + helper text on the left,
   CFSwitch on the right; column-stacks on small screens. */
.cf-v2-sla-form__advanced-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-3, 0.75rem) 0;
    border-top: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
    border-bottom: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.08));
    min-width: 0;
}

.cf-v2-sla-form__advanced-row-text {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 2px);
    min-width: 0;
}

/* 4-up severity card grid: 1 column on mobile, 2 columns mid, 4 columns wide. */
.cf-v2-sla-form__severity-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--cf-space-3, 0.75rem);
    min-width: 0;
}

@media (min-width: 720px) {
    .cf-v2-sla-form__severity-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 1200px) {
    .cf-v2-sla-form__severity-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

/* Per-severity card: bordered tile with chip header + stacked fields. */
.cf-v2-sla-severity-card {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-4, 1rem);
    border-radius: var(--cf-radius-md, 8px);
    border: 1px solid var(--cf-color-border-subtle, rgba(255, 255, 255, 0.12));
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    min-width: 0;
}

.cf-v2-sla-severity-card__header {
    display: flex;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
}

/* Numeric inputs stack vertically inside the card so narrow card widths (half-screen 4-up grid)
   don't squeeze the labels into multi-line wraps. Matches the agent severity card rhythm where
   each field is a full-width row. */
.cf-v2-sla-severity-card__grid {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}


/* ============================================================================
   CMS Center (CMS 4.0 / PLAT-3196, Epic A)
   Shared class vocabulary for the CMS Center browse surface (CmsCenterV2) and
   the rule detail sub-page (CmsRuleDetailV2). Lives globally because both
   components declare these classes; Blazor scoped CSS would not cross the
   component boundary.
   ============================================================================ */

.cms-center__section-head {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--cf-space-2, 0.5rem);
}

.cms-center__section-head > :first-child {
    align-self: flex-start;
}

@media (min-width: 560px) {
    .cms-center__section-head {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

.cms-center__loader {
    display: flex;
    justify-content: center;
    padding: var(--cf-space-6, 1.5rem);
}

.cms-center__drawer-actions {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
}

@media (min-width: 560px) {
    .cms-center__drawer-actions {
        flex-direction: row;
        justify-content: flex-end;
    }
}

.cms-diff {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    margin-top: var(--cf-space-4, 1rem);
}

.cms-diff__query {
    font-family: var(--cf-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: var(--cf-font-size-sm, 0.8125rem);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 8px);
    padding: var(--cf-space-3, 0.75rem);
    overflow-x: auto;
}

.cms-diff-line {
    white-space: pre;
    line-height: 1.5;
}

.cms-diff-line__prefix {
    display: inline-block;
    width: 1.25ch;
    color: var(--cf-text-muted, rgba(255, 255, 255, 0.5));
}

.cms-diff-line--added {
    background: var(--cf-status-success-bg, rgba(46, 160, 67, 0.15));
    color: var(--cf-status-success-fg, #3fb950);
}

.cms-diff-line--removed {
    background: var(--cf-status-error-bg, rgba(248, 81, 73, 0.15));
    color: var(--cf-status-error-fg, #f85149);
}

.cms-center__toolbar-actions {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

@media (min-width: 560px) {
    .cms-center__toolbar-actions {
        flex-direction: row;
        align-items: center;
    }
}

.cms-center__row-actions {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--cf-space-1, 0.25rem);
}

.cms-rule-content {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cms-rule-content__meta {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--cf-space-3, 0.75rem);
}

@media (min-width: 560px) {
    .cms-rule-content__meta {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.cms-rule-content__field {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    min-width: 0;
}

/* Shared rule-content card — header (title + optional actions), copyable id, markdown description. */
.cms-rule-content__head {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

.cms-rule-content__head-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

.cms-rule-content__value-inline {
    display: flex;
    align-items: center;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
}

.cms-rule-content__mono {
    font-family: var(--cf-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.8125rem;
    overflow-wrap: anywhere;
}

.cms-rule-content__description {
    overflow-wrap: anywhere;
}

.cms-rule-content__description :first-child {
    margin-top: 0;
}

.cms-rule-content__description :last-child {
    margin-bottom: 0;
}

@media (min-width: 560px) {
    .cms-rule-content__head {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

.cms-rule-content__query {
    margin: 0;
    font-family: var(--cf-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: var(--cf-font-size-sm, 0.8125rem);
    white-space: pre-wrap;
    word-break: break-word;
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 8px);
    padding: var(--cf-space-3, 0.75rem);
    overflow-x: auto;
}

/* CMS Center — repositories-card section-head spans the full card header so the New-repository
   action sits flush top-right. */
.cms-center__section-head {
    width: 100%;
}

.cms-repo-detail__hero {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--cf-space-3, 0.75rem);
}

.cms-repo-detail__hero-text {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
}

@media (min-width: 720px) {
    .cms-repo-detail__hero {
        flex-direction: row;
        align-items: flex-start;
        justify-content: space-between;
    }
}

.cms-repo-detail__toolbar {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--cf-space-2, 0.5rem);
    margin-bottom: var(--cf-space-4, 1rem);
}

.cms-repo-detail__toolbar-count {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

@media (min-width: 560px) {
    .cms-repo-detail__toolbar {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

.cms-rule-editor__query {
    min-height: 240px;
    border: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 8px);
    overflow: hidden;
}

.cms-rule-editor__duration {
    display: flex;
    gap: var(--cf-space-2, 0.5rem);
    align-items: flex-start;
}

.cms-rule-editor__duration > :first-child {
    flex: 0 0 40%;
    min-width: 0;
}

.cms-rule-editor__duration > :last-child {
    flex: 1 1 auto;
    min-width: 0;
}

.cms-rule-content__mapping {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    padding: var(--cf-space-2, 0.5rem);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border-radius: var(--cf-radius-sm, 6px);
    margin-top: var(--cf-space-1, 0.25rem);
}

.cms-rule-editor__test {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cms-rule-editor__results {
    overflow: auto;
    max-height: 260px;
    border: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 8px);
}

.cms-rule-editor__results-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--cf-font-size-sm, 0.8125rem);
}

.cms-rule-editor__results-table th,
.cms-rule-editor__results-table td {
    text-align: left;
    padding: var(--cf-space-2, 0.5rem);
    border-bottom: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.06));
    white-space: nowrap;
}

.cms-rule-editor__results-table th {
    position: sticky;
    top: 0;
    background: var(--cf-bg-elevated-1, rgba(20, 26, 31, 1));
}

.cms-rule-editor__entities {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cms-rule-editor__entity {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-3, 0.75rem);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
    border: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 8px);
}

/* CMS 4.0 — rule detail hero (title + Edit) and sticky edit save bar. */
.cms-rule-detail__hero {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    align-items: flex-start;
}

.cms-rule-detail__savebar {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
    position: sticky;
    bottom: 0;
    padding: var(--cf-space-3, 0.75rem);
    background: var(--cf-bg-elevated-1, rgba(20, 26, 31, 1));
    border-top: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 8px);
}

@media (min-width: 560px) {
    .cms-rule-detail__hero {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .cms-rule-detail__savebar {
        flex-direction: row;
        justify-content: flex-end;
    }
}

/* CMS 4.0 (Epic D) — rule-detail hero action row (Edit + Deploy): column-stacks on mobile, inline from 560px. */
.cms-rule-detail__hero-actions {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

/* Epic G — right-aligned row action cluster (compare + rollback) in the deployments table. */
.cms-rule-detail__row-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--cf-space-1, 0.25rem);
}

/* Reusable request-error alert: message + copyable request id for support tickets. */
.request-error {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.request-error__meta {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
}

.request-error__id {
    font-family: var(--cf-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.8125rem;
    overflow-wrap: anywhere;
}

.request-error__actions {
    display: flex;
}

/* CMS 4.0 (PLAT-3358) — deploy page: card body rhythm and the sticky-free action row.
   CFCard ChildContent adds no gap between direct children, so every card body needs a flex wrapper. */
.cms-deploy__body {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

/* Primary action sits last on mobile (column-reverse puts it on top), inline and right-aligned above sm. */
.cms-deploy__actions {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
}

@media (min-width: 560px) {
    .cms-deploy__actions {
        flex-direction: row;
        justify-content: flex-end;
    }
}

/* CMS 4.0 (Epic D) — deploy: "enable on deploy" toggle row. */
.cms-deploy__enabled {
    display: flex;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
}

.cms-deploy__enabled-label {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
}

/* CMS 4.0 (PLAT-3358) — deploy: "deploy anyway" override row inside the validation card. Same shape as the
   enable-on-deploy row, boxed and tinted because it is the one control on this page that lets an operator
   proceed past a check that failed. */
.cms-deploy__override {
    display: flex;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-3, 0.75rem);
    border: 1px solid var(--cf-status-warning, #edaa4a);
    border-radius: var(--cf-radius-md, 0.5rem);
    background: var(--cf-status-warning-bg, rgba(249, 115, 22, 0.3));
}

.cms-deploy__override-label {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    min-width: 0;
}

/* CMS 4.0 (Epic D) — deploy drawer: target workspace list with per-target validation and result. */
.cms-deploy__selectall {
    padding-bottom: var(--cf-space-2, 0.5rem);
    border-bottom: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

/* Rule and workspace pickers on the deploy page. Capped at roughly ten rows and scrolled internally: a
   repository with fifty rules otherwise pushed the deploy action so far down the page that the operator had
   to scroll past the whole list to find it. max-height rather than height, so a short list still collapses to
   its content instead of leaving dead space. */
.cms-deploy__list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    max-height: 30rem;
    overflow-y: auto;
    /* Keeps the scrollbar off the checkboxes and chips. */
    padding-right: var(--cf-space-2, 0.5rem);
}

.cms-deploy__row {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    padding-bottom: var(--cf-space-2, 0.5rem);
    border-bottom: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

/* The last row's rule would otherwise sit directly against the scroll boundary and read as a cut-off item. */
.cms-deploy__list > .cms-deploy__row:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

/* Workspace checkbox row + its "already deployed" pre-flight chip, wrapping on narrow widths. */
.cms-deploy__row-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

.cms-deploy__validation {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    padding-left: var(--cf-space-6, 1.5rem);
}

/* Deploy outcomes, grouped by rule, shown after a deploy completes. */
.cms-deploy__results {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    padding-top: var(--cf-space-3, 0.75rem);
    border-top: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

.cms-deploy__result-group {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
}

.cms-deploy__result {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-0-5, 0.125rem);
}

/* The per-target validation and deploy messages must wrap fully so a long ARM error is legible. */
.cms-deploy__validation .cf-text,
.cms-deploy__result .cf-text {
    overflow-wrap: anywhere;
    white-space: normal;
}

/* CMS 4.0 (Epic G) — reconcile drawer: workspace scan results grouped by classification with per-rule actions. */
.cms-reconcile__scanning {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-8, 2rem) var(--cf-space-4, 1rem);
}

.cms-reconcile__counts {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
}

.cms-reconcile__coverage {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-3, 0.75rem);
    border: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 0.5rem);
}

.cms-reconcile__coverage-row {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-1, 0.25rem);
}

@media (min-width: 560px) {
    .cms-reconcile__coverage-row {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: var(--cf-space-3, 0.75rem);
    }
}

/* CMS 4.0 (Epic G) — Workspace Synchronization page. */
.cms-sync__hero {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

/* Card body with consistent vertical rhythm (CFCard content adds no gap between children). */
.cms-sync__card-body {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

/* Section head inside a card header: title + trailing action. */
.cms-sync__card-head {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

.cms-sync__card-head > .cf-button {
    width: 100%;
}

.cms-sync__selectall {
    padding-bottom: var(--cf-space-3, 0.75rem);
    border-bottom: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

.cms-sync__ws-list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

/* Label + value/chips row: stacks on mobile, spreads on wider screens. */
.cms-sync__meta-row {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-1, 0.25rem);
}

.cms-sync__tags {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--cf-space-1, 0.25rem);
}

/* CMS 4.0 (PLAT-3327) — the coverage workspace name and its count chips link into the workspace's
   rule-level breakdown. Kept visually identical to the previous static row: the affordance is the
   pointer and focus ring, not an underline, so the chips still read as chips. */
.cms-sync__coverage-link {
    display: inline-flex;
    align-items: center;
    gap: var(--cf-space-1, 0.25rem);
    color: inherit;
    text-decoration: none;
    border-radius: var(--cf-radius-sm, 4px);
}

.cms-sync__coverage-link:hover {
    text-decoration: underline;
}

.cms-sync__coverage-link:focus-visible {
    outline: 2px solid var(--cf-color-focus, #4c9aff);
    outline-offset: 2px;
}

.cms-sync__result-head {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
}

.cms-sync__group {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    padding-top: var(--cf-space-3, 0.75rem);
    border-top: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

.cms-sync__group-head {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

/* Post-sync outcome rows: rule name + outcome chip (Deployed / Forked / Adopted). */
.cms-sync__result-row {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    padding: var(--cf-space-2, 0.5rem) 0;
    border-bottom: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

.cms-sync__result-main {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

/* Fixed-height, scrollable list — keeps long workspace/coverage lists from pushing the page down. */
.cms-sync__scroll {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    max-height: 16rem;
    overflow-y: auto;
    padding-right: var(--cf-space-1, 0.25rem);
}

.cms-rule-detail-dialog {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cms-rule-detail-dialog__fields {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cms-rule-detail-dialog__row {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
}

.cms-sync__apply {
    display: flex;
    justify-content: flex-end;
    padding-top: var(--cf-space-2, 0.5rem);
}

@media (min-width: 560px) {
    .cms-sync__card-head {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: var(--cf-space-3, 0.75rem);
    }

    .cms-sync__card-head > .cf-button {
        width: auto;
    }

    .cms-sync__meta-row,
    .cms-sync__result-head {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: var(--cf-space-3, 0.75rem);
    }
}

.cms-reconcile__group {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    padding-top: var(--cf-space-3, 0.75rem);
    border-top: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

.cms-reconcile__row {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    padding: var(--cf-space-2, 0.5rem) 0;
}

.cms-reconcile__row-head {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-1, 0.25rem);
}

.cms-reconcile__row-tags {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--cf-space-1, 0.25rem);
}

.cms-reconcile__results {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    padding-top: var(--cf-space-3, 0.75rem);
    border-top: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

.cms-reconcile__result {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-0-5, 0.125rem);
}

.cms-reconcile__row .cf-text,
.cms-reconcile__result .cf-text {
    overflow-wrap: anywhere;
    white-space: normal;
}

@media (min-width: 560px) {
    .cms-reconcile__row-head {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: var(--cf-space-3, 0.75rem);
    }
}

@media (min-width: 560px) {
    .cms-rule-detail__hero-actions {
        flex-direction: row;
        width: auto;
    }
}

/* CMS 4.0 — rules-table search + filter row. Column-stacks on mobile; from the md breakpoint the
   search box takes two-thirds and the filter group the final third, side by side. */
.cms-repo-detail__filters {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    margin-bottom: var(--cf-space-3, 0.75rem);
}

.cms-repo-detail__search {
    min-width: 0;
}

.cms-repo-detail__filter-group {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cms-repo-detail__audit-filter {
    margin-bottom: var(--cf-space-3, 0.75rem);
}

@media (min-width: 720px) {
    .cms-repo-detail__filters {
        flex-direction: row;
        align-items: center;
    }

    .cms-repo-detail__search {
        flex: 2 1 0;
    }

    .cms-repo-detail__filter-group {
        flex: 1 1 0;
        flex-direction: row;
    }

    .cms-repo-detail__filter-group > * {
        flex: 1 1 0;
        min-width: 0;
    }
}

/* CMC stacks each entity-mapping group full-width (one per row) rather than the Sentinel multi-column
   grid. Compound selector beats the base .cf-v2-rule-details__entity-grid media rules regardless of order. */
.cf-v2-rule-details__entity-grid.cms-entity-grid--stacked {
    grid-template-columns: 1fr;
}

/* CMS 4.0 — MITRE ATT&CK tactics/techniques picker (item 10). */
.cms-mitre {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cms-mitre__loader {
    display: flex;
    justify-content: center;
    padding: var(--cf-space-4, 1rem);
}

.cms-mitre__chips {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--cf-space-1, 0.25rem);
}

.cms-mitre__chip {
    cursor: pointer;
}

.cms-mitre__chip-x {
    margin-left: var(--cf-space-1, 0.25rem);
}

.cms-mitre__tree {
    max-height: 320px;
    overflow-y: auto;
    border: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 8px);
    padding: var(--cf-space-1, 0.25rem);
}

.cms-mitre__node {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-1, 0.25rem) var(--cf-space-2, 0.5rem);
    border-radius: var(--cf-radius-sm, 4px);
}

.cms-mitre__node:hover {
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
}

.cms-mitre__node--technique {
    padding-left: var(--cf-space-6, 1.5rem);
}

.cms-mitre__node--sub {
    padding-left: var(--cf-space-10, 2.5rem);
}

.cms-mitre__twisty {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--cf-text-muted, rgba(255, 255, 255, 0.6));
    cursor: pointer;
    transition: transform 120ms ease;
}

.cms-mitre__twisty.is-open {
    transform: rotate(90deg);
}

.cms-mitre__twisty-spacer {
    display: inline-block;
    flex: 0 0 20px;
    width: 20px;
    height: 20px;
}

.cms-mitre__label {
    flex: 1 1 auto;
    min-width: 0;
    cursor: default;
}

.cms-mitre__id {
    margin-right: var(--cf-space-1, 0.25rem);
    font-family: var(--cf-font-mono, ui-monospace, "SFMono-Regular", monospace);
    color: var(--cf-text-muted, rgba(255, 255, 255, 0.6));
}

/* CMS 4.0 — Sentinel rule JSON drop zone (item 7). */
.cms-dropzone {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 72px;
    padding: var(--cf-space-3, 0.75rem);
    border: 1px dashed var(--cf-border-strong, rgba(255, 255, 255, 0.2));
    border-radius: var(--cf-radius-md, 8px);
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.02));
    text-align: center;
    transition: border-color 120ms ease, background 120ms ease;
}

.cms-dropzone.is-dragover {
    border-color: var(--cf-color-primary, #4c8dff);
    background: var(--cf-bg-elevated-2, rgba(76, 141, 255, 0.08));
}

.cms-dropzone.is-disabled {
    opacity: 0.6;
}

.cms-dropzone__input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.cms-dropzone__body {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--cf-space-2, 0.5rem);
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .cms-mitre__twisty,
    .cms-dropzone {
        transition: none;
    }
}

/* CMS 4.0 — rule version diff dialog: metadata (old/new) + side-by-side query. */
.cms-diff-dialog {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cms-diff-dialog__meta {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 8px);
    overflow: hidden;
}

.cms-diff-dialog__meta-row {
    display: grid;
    grid-template-columns: 1fr 1.5fr 1.5fr;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-2, 0.5rem);
    border-bottom: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.06));
    font-size: 0.85rem;
    word-break: break-word;
}

.cms-diff-dialog__meta-row:last-child {
    border-bottom: none;
}

.cms-diff-dialog__meta-row--head {
    font-weight: 600;
    color: var(--cf-text-muted, rgba(255, 255, 255, 0.6));
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
}

.cms-diff-dialog__meta-field {
    color: var(--cf-text-muted, rgba(255, 255, 255, 0.6));
}

.cms-diff-dialog__cell.is-removed {
    background: var(--cf-status-error-bg, rgba(239, 68, 68, 0.12));
}

.cms-diff-dialog__cell.is-added {
    background: var(--cf-status-success-bg, rgba(34, 197, 94, 0.12));
}

.cms-diff-split {
    border: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 8px);
    overflow: hidden;
    font-family: var(--cf-font-mono, ui-monospace, "SFMono-Regular", monospace);
    font-size: 0.8rem;
}

.cms-diff-split__body {
    max-height: 420px;
    overflow: auto;
}

.cms-diff-split__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
}

.cms-diff-split__row--head {
    font-weight: 600;
    color: var(--cf-text-muted, rgba(255, 255, 255, 0.6));
    background: var(--cf-bg-elevated-1, rgba(255, 255, 255, 0.03));
}

.cms-diff-split__row--head > span {
    padding: var(--cf-space-2, 0.5rem);
    border-bottom: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

.cms-diff-split__row--head > span:first-child {
    border-right: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

.cms-diff-split__cell {
    padding: 2px var(--cf-space-2, 0.5rem);
    white-space: pre-wrap;
    word-break: break-word;
    min-height: 1.4em;
}

.cms-diff-split__cell:first-child {
    border-right: 1px solid var(--cf-border-subtle, rgba(255, 255, 255, 0.08));
}

.cms-diff-split__cell.is-removed {
    background: var(--cf-status-error-bg, rgba(239, 68, 68, 0.15));
}

.cms-diff-split__cell.is-added {
    background: var(--cf-status-success-bg, rgba(34, 197, 94, 0.15));
}

/* ==========================================================================
   Defender Native Automations & Detected Products cards (FR-240 / PLAT-3241)
   Shared class vocabulary for the Defender XDR configuration-tab cards.
   ========================================================================== */

.cf-v2-native-automations__head {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    align-items: flex-start;
    /* Span the card header so space-between pushes the action to the far right. */
    width: 100%;
}

@media (min-width: 560px) {
    .cf-v2-native-automations__head {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

.cf-v2-native-automations__settling {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
}

.cf-v2-native-automations__settling-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-native-automations__rows {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-native-automations__row {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    align-items: flex-start;
}

@media (min-width: 560px) {
    .cf-v2-native-automations__row {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

.cf-v2-native-automations__row-status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

/* Chips render at parent width inside a flex column unless the container is
   flex-start — see the page-design chips rule. */
.cf-v2-detected-products__chips {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
    margin-top: var(--cf-space-2, 0.5rem);
}

.cf-v2-detected-products__mono {
    font-family: monospace;
}

.cf-v2-detected-products__consent {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
}

@media (min-width: 560px) {
    .cf-v2-detected-products__consent {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

.cf-v2-detected-products__resuming {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

/* ==========================================================================
   Atlassian CSM support widget (the floating help launcher, #jsd-widget).
   The real fix for it overlapping side-panel/dialog footer buttons lives in
   iris.components.js, which HIDES the widget while a CF overlay is open — a
   pure z-index rule can't win here because the widget is a body-level sibling
   of the Blazor <app> root (so the drawer's 9000 is trapped in <app>'s stacking
   context) and the widget sets its own inline z-index. This rule stays only as
   a harmless backstop to keep the launcher below the CF overlay band —
   CFDrawer (9000) / CFDialog (9700) / CFToast (9999) — in any edge the JS misses.
   ========================================================================== */
#jsd-widget {
    z-index: 8500 !important;
}

/* ==========================================================================
   Workspace Profiles (PLAT-3275)
   Shared class vocabulary for the profile list (WorkspaceProfilesViewV2), the
   profile detail shell (WorkspaceProfileDetailV2), its five section tabs, and
   the apply/attach surfaces. These classes appear in more than one .razor file,
   so they live here rather than in scoped stylesheets — Blazor scoped CSS does
   not reach elements declared in a different component.
   ========================================================================== */

/* ── List page ─────────────────────────────────────────────────────────── */
.cf-v2-profiles__hero {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
}

.cf-v2-profiles__toolbar {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-profiles__search {
    width: 100%;
}

.cf-v2-profiles__toolbar-add > * {
    width: 100%;
}

@media (min-width: 720px) {
    .cf-v2-profiles__toolbar {
        flex-direction: row;
        align-items: center;
    }

    .cf-v2-profiles__search {
        width: auto;
        min-width: 18rem;
    }

    /* Push the primary action to the far end; search and filters keep the left. */
    .cf-v2-profiles__toolbar-add {
        margin-inline-start: auto;
    }

    .cf-v2-profiles__toolbar-add > * {
        width: auto;
    }
}

.cf-v2-profiles__loader {
    padding-block: var(--cf-space-10, 2.5rem);
}

.cf-v2-profiles__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--cf-space-4, 1rem);
}

@media (min-width: 560px) {
    .cf-v2-profiles__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 1200px) {
    .cf-v2-profiles__grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

/* ── Profile card ──────────────────────────────────────────────────────── */
.cf-v2-profile-card {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    width: 100%;
    padding: var(--cf-space-4, 1rem);
    text-align: start;
    background: var(--cf-bg-elevated-1);
    border: 1px solid var(--cf-bg-elevated-3);
    border-radius: var(--cf-radius-lg, 0.75rem);
    cursor: pointer;
    transition: border-color 120ms ease, background-color 120ms ease;
}

.cf-v2-profile-card:hover {
    border-color: var(--cf-color-primary);
    background: var(--cf-bg-elevated-2);
}

.cf-v2-profile-card:focus-visible {
    outline: 2px solid var(--cf-color-primary);
    outline-offset: 2px;
}

.cf-v2-profile-card__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-profile-card__identity {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
    flex: 1 1 auto;
}

.cf-v2-profile-card__tags,
.cf-v2-profile-hero__tags {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
}

/* Section pips: which of the five areas carry configuration. Unconfigured ones
   stay visible but recede, so the row reads as a completeness meter rather than
   a list that changes length. */
.cf-v2-profile-card__sections {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-profile-card__pip {
    display: inline-flex;
    align-items: center;
    gap: var(--cf-space-1, 0.25rem);
    padding: var(--cf-space-0-5, 0.125rem) var(--cf-space-2, 0.5rem);
    border-radius: var(--cf-radius-sm, 0.25rem);
    font-size: 0.75rem;
    background: var(--cf-bg-elevated-2);
    color: var(--cf-text-secondary);
    opacity: 0.55;
}

.cf-v2-profile-card__pip[data-configured="true"] {
    opacity: 1;
    background: var(--cf-status-info-bg);
    color: var(--cf-status-info);
}

.cf-v2-profile-card__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-3, 0.75rem);
    padding-top: var(--cf-space-3, 0.75rem);
    border-top: 1px solid var(--cf-bg-elevated-3);
}

.cf-v2-profile-card__stat {
    display: flex;
    align-items: baseline;
    gap: var(--cf-space-1, 0.25rem);
}

.cf-v2-profile-card__stat-value {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--cf-text-primary);
    font-variant-numeric: tabular-nums;
}

.cf-v2-profile-card__stat-label {
    font-size: 0.8125rem;
    color: var(--cf-text-secondary);
}

/* ── Create dialog ─────────────────────────────────────────────────────── */
.cf-v2-profile-create {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cf-v2-profile-create__tags {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
}

/* ── Detail hero ───────────────────────────────────────────────────────── */
.cf-v2-profile-hero {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cf-v2-profile-hero__identity {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-v2-profile-hero__title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-profile-hero__actions {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-profile-hero__actions > * {
    width: 100%;
}

@media (min-width: 720px) {
    .cf-v2-profile-hero {
        flex-direction: row;
        align-items: flex-start;
        justify-content: space-between;
    }

    .cf-v2-profile-hero__actions {
        flex-direction: row;
        align-items: center;
        flex: 0 0 auto;
    }

    .cf-v2-profile-hero__actions > * {
        width: auto;
    }
}

.cf-v2-profile-drift {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

@media (min-width: 560px) {
    .cf-v2-profile-drift {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

/* ── Section save bar ──────────────────────────────────────────────────── */
.cf-v2-profile-savebar {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
    background: var(--cf-bg-elevated-1);
    border: 1px solid var(--cf-bg-elevated-3);
    border-radius: var(--cf-radius-md, 0.5rem);
    box-shadow: 0 -4px 16px rgb(0 0 0 / 12%);
}

.cf-v2-profile-savebar__message {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    color: var(--cf-text-secondary);
}

.cf-v2-profile-savebar__actions {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-profile-savebar__actions > * {
    width: 100%;
}

@media (min-width: 560px) {
    .cf-v2-profile-savebar {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .cf-v2-profile-savebar__actions {
        flex-direction: row;
        flex: 0 0 auto;
    }

    .cf-v2-profile-savebar__actions > * {
        width: auto;
    }
}

/* ── Shared row list (IAM, gamebook approvers, recipients, workspaces) ──── */
.cf-v2-profile-iam__list,
.cf-v2-profile-recipients__list,
.cf-v2-profile-workspaces__list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-profile-iam__row,
.cf-v2-profile-recipients__row,
.cf-v2-profile-workspaces__row {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-3, 0.75rem);
    background: var(--cf-bg-elevated-2);
    border-radius: var(--cf-radius-md, 0.5rem);
}

.cf-v2-profile-iam__identity,
.cf-v2-profile-recipients__identity,
.cf-v2-profile-workspaces__identity {
    display: flex;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-profile-workspaces__identity {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-0-5, 0.125rem);
}

.cf-v2-profile-iam__identity-text,
.cf-v2-profile-recipients__identity-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.cf-v2-profile-iam__controls,
.cf-v2-profile-recipients__controls,
.cf-v2-profile-workspaces__controls {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

@media (min-width: 560px) {
    .cf-v2-profile-iam__row,
    .cf-v2-profile-recipients__row,
    .cf-v2-profile-workspaces__row {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

/* ── Workspace multi-select ────────────────────────────────────────────────
   The workspaces row carries a leading checkbox, so unlike its IAM and recipient
   siblings it stays horizontal at every width — a checkbox stacked above the name it
   selects reads as unrelated to it. The row wraps instead, letting the status chip and
   detach button drop to a second line on narrow screens while the checkbox stays beside
   the name. Declared after the shared row rule so it wins on source order. */
.cf-v2-profile-workspaces__row {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
}

.cf-v2-profile-workspaces__row[data-selected="true"] {
    background: var(--cf-bg-elevated-3);
}

.cf-v2-profile-workspaces__row > .cf-v2-profile-workspaces__identity {
    /* Wide enough to be worth keeping on the first line, free to shrink below that. */
    flex: 1 1 12rem;
}

.cf-v2-profile-workspaces__row > .cf-v2-profile-workspaces__controls {
    margin-left: auto;
}

.cf-v2-profile-workspaces__selection {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-2, 0.5rem);
    padding-bottom: var(--cf-space-3, 0.75rem);
    margin-bottom: var(--cf-space-1, 0.25rem);
    border-bottom: 1px solid var(--cf-bg-elevated-3);
}

@media (min-width: 560px) {
    .cf-v2-profile-workspaces__selection {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

/* ── Toggle rows ───────────────────────────────────────────────────────── */
.cf-v2-profile-notifications__toggles {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
}

.cf-v2-profile-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-4, 1rem);
    padding: var(--cf-space-3, 0.75rem) 0;
}

.cf-v2-profile-toggle + .cf-v2-profile-toggle {
    border-top: 1px solid var(--cf-bg-elevated-3);
}

.cf-v2-profile-toggle__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}

/* ── Modules ───────────────────────────────────────────────────────────── */
.cf-v2-profile-modules__list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-profile-modules__row {
    display: flex;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-3, 0.75rem);
    background: var(--cf-bg-elevated-2);
    border: 1px solid transparent;
    border-radius: var(--cf-radius-md, 0.5rem);
    cursor: pointer;
}

.cf-v2-profile-modules__row[data-selected="true"] {
    border-color: var(--cf-color-primary);
}

.cf-v2-profile-modules__identity {
    display: flex;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-profile-modules__identity-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.cf-v2-profile-modules__icon {
    width: 24px;
    height: 24px;
    object-fit: contain;
    flex: 0 0 auto;
}

/* ── Agent severity cards ──────────────────────────────────────────────── */
.cf-v2-profile-agent__severities {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--cf-space-4, 1rem);
}

@media (min-width: 720px) {
    .cf-v2-profile-agent__severities {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.cf-v2-profile-agent__severity {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-4, 1rem);
    background: var(--cf-bg-elevated-2);
    border-radius: var(--cf-radius-md, 0.5rem);
}

.cf-v2-profile-agent__severity-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-3, 0.75rem);
}

/* Preferred-model picker on the profile Agent tab (PLAT-3357). Mirrors the create-agent
   wizard's Deployment step so a profile author sees the same experience; the wizard's rules
   are component-scoped, so the shape is restated here under the profile-agent family. */
.cf-v2-profile-agent__models {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-profile-agent__models-region {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    align-self: flex-start;
}

.cf-v2-profile-agent__models-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-6, 1.5rem) var(--cf-space-4, 1rem);
}

.cf-v2-profile-agent__model-list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-profile-agent__model-card {
    display: flex;
    align-items: flex-start;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
    background: var(--cf-bg-elevated-2, #27272A);
    border: 1px solid var(--cf-color-border, rgba(255, 255, 255, 0.08));
    border-radius: var(--cf-radius-md, 8px);
    text-align: left;
    color: inherit;
    cursor: pointer;
    transition:
        border-color 150ms var(--cf-ease-default, cubic-bezier(0.4, 0, 0.2, 1)),
        background-color 150ms var(--cf-ease-default, cubic-bezier(0.4, 0, 0.2, 1));
}

.cf-v2-profile-agent__model-card:hover {
    border-color: color-mix(in srgb, var(--cf-color-primary, #2557F9) 50%, transparent);
}

.cf-v2-profile-agent__model-card:focus-visible {
    outline: 2px solid var(--cf-color-ring, var(--cf-color-primary, #2557F9));
    outline-offset: 2px;
}

.cf-v2-profile-agent__model-card[data-selected="true"] {
    border-color: var(--cf-color-primary, #2557F9);
    background-color: color-mix(in srgb, var(--cf-color-primary, #2557F9) 8%, var(--cf-bg-elevated-2, #27272A));
}

.cf-v2-profile-agent__model-radio {
    flex: 0 0 auto;
    width: 1.125rem;
    height: 1.125rem;
    margin-top: 0.125rem;
    border-radius: var(--cf-radius-full, 100px);
    border: 1.5px solid var(--cf-color-border-strong, rgba(255, 255, 255, 0.24));
    background: transparent;
    transition:
        border-color 150ms var(--cf-ease-default, cubic-bezier(0.4, 0, 0.2, 1)),
        background-color 150ms var(--cf-ease-default, cubic-bezier(0.4, 0, 0.2, 1));
    position: relative;
}

.cf-v2-profile-agent__model-card[data-selected="true"] .cf-v2-profile-agent__model-radio {
    border-color: var(--cf-color-primary, #2557F9);
}

.cf-v2-profile-agent__model-card[data-selected="true"] .cf-v2-profile-agent__model-radio::after {
    content: "";
    position: absolute;
    inset: 3px;
    border-radius: var(--cf-radius-full, 100px);
    background: var(--cf-color-primary, #2557F9);
}

.cf-v2-profile-agent__model-body {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-profile-agent__model-head {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

.cf-v2-profile-agent__model-name {
    margin: 0;
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cf-v2-profile-agent__model-version {
    margin: 0;
    color: var(--cf-text-secondary, #A2ABB2);
}

/* ── Apply drawer & attach drawer ──────────────────────────────────────── */
.cf-v2-apply-profile,
.cf-v2-attach-workspaces {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cf-v2-apply-profile__siem {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-apply-profile__section {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-apply-profile__section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-attach-workspaces__section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-apply-profile__list,
.cf-v2-attach-workspaces__list {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    max-height: 22rem;
    overflow-y: auto;
}

.cf-v2-apply-profile__row,
.cf-v2-attach-workspaces__row {
    display: flex;
    align-items: center;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-3, 0.75rem);
    border-radius: var(--cf-radius-md, 0.5rem);
    cursor: pointer;
}

.cf-v2-apply-profile__row[data-selected="true"],
.cf-v2-attach-workspaces__row[data-selected="true"] {
    background: var(--cf-bg-elevated-2);
}

.cf-v2-apply-profile__row-text,
.cf-v2-attach-workspaces__row-text {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

.cf-v2-apply-profile__footer,
.cf-v2-attach-workspaces__footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--cf-space-2, 0.5rem);
    width: 100%;
}

/* ── Apply run ─────────────────────────────────────────────────────────── */
.cf-v2-profile-runs {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cf-v2-apply-run {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    padding: var(--cf-space-4, 1rem);
    background: var(--cf-bg-elevated-1);
    border: 1px solid var(--cf-bg-elevated-3);
    border-radius: var(--cf-radius-lg, 0.75rem);
}

/* Outcome counts read as a row rather than one number: a partial run is the
   normal case, and collapsing it to a single status would misrepresent it. */
.cf-v2-apply-run__counts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-apply-run__count {
    display: inline-flex;
    align-items: center;
    gap: var(--cf-space-1, 0.25rem);
    font-size: 0.8125rem;
    font-variant-numeric: tabular-nums;
}

.cf-v2-apply-run__count[data-tone="success"] { color: var(--cf-status-success); }
.cf-v2-apply-run__count[data-tone="warning"] { color: var(--cf-status-warning); }
.cf-v2-apply-run__count[data-tone="error"]   { color: var(--cf-status-error); }
.cf-v2-apply-run__count[data-tone="muted"]   { color: var(--cf-text-secondary); }
/* Agent deployments still running in the provider's cloud (PLAT-3357). */
.cf-v2-apply-run__count[data-tone="info"]    { color: var(--cf-status-info); }

.cf-v2-apply-run__targets {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    max-height: 32rem;
    overflow-y: auto;
}

.cf-v2-apply-run__target {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-3, 0.75rem);
    background: var(--cf-bg-elevated-2);
    border-inline-start: 2px solid transparent;
    border-radius: var(--cf-radius-md, 0.5rem);
}

/* Severity stripe: what needs attention is legible before the label is read. */
.cf-v2-apply-run__target[data-status="failed"]           { border-inline-start-color: var(--cf-status-error); }
.cf-v2-apply-run__target[data-status="partiallyapplied"] { border-inline-start-color: var(--cf-status-warning); }
.cf-v2-apply-run__target[data-status="skipped"]          { border-inline-start-color: var(--cf-status-warning); }
.cf-v2-apply-run__target[data-status="succeeded"]        { border-inline-start-color: var(--cf-status-success); }

.cf-v2-apply-run__target-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-apply-run__sections {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-apply-run__section {
    display: inline-flex;
    align-items: center;
    gap: var(--cf-space-1, 0.25rem);
    padding: var(--cf-space-0-5, 0.125rem) var(--cf-space-2, 0.5rem);
    border-radius: var(--cf-radius-sm, 0.25rem);
    font-size: 0.75rem;
    background: var(--cf-bg-elevated-3);
    color: var(--cf-text-secondary);
}

/* Green marks a section that changed something. A section that already matched keeps the neutral
   base above, so a row of ticks cannot imply work that never happened. */
.cf-v2-apply-run__section[data-status="succeeded"][data-changed="true"] {
    background: var(--cf-status-success-bg);
    color: var(--cf-status-success);
}
.cf-v2-apply-run__section[data-status="failed"]           { background: var(--cf-status-error-bg);   color: var(--cf-status-error); }
.cf-v2-apply-run__section[data-status="partiallyapplied"],
.cf-v2-apply-run__section[data-status="skipped"]          { background: var(--cf-status-warning-bg); color: var(--cf-status-warning); }

.cf-v2-apply-run__section-count {
    padding-inline: var(--cf-space-1, 0.25rem);
    border-radius: var(--cf-radius-sm, 0.25rem);
    background: var(--cf-bg-elevated-1);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.cf-v2-apply-run__section-note {
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-3, 0.75rem);
    border-radius: var(--cf-radius-sm, 0.25rem);
    background: var(--cf-bg-elevated-3);
}

.cf-v2-apply-run__section-note[data-tone="warning"] { background: var(--cf-status-warning-bg); }
.cf-v2-apply-run__section-note[data-tone="error"]   { background: var(--cf-status-error-bg); }

/* ── Apply drawer, review step (PLAT-3276) ─────────────────────────────────
   The diff an operator approves before a push. Removals are tinted so a line
   that takes something away cannot be mistaken for one that adds it — this is
   the screen where that distinction is most expensive to miss. */
.cf-v2-apply-profile__review {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

.cf-v2-apply-profile__loader {
    padding: var(--cf-space-8, 2rem) 0;
}

/* The diff is the drawer's whole purpose at this step, so it flows and lets the
   drawer body scroll. Reusing the selection list's fixed-height scroll box left
   the diff in a short pane with the rest of the drawer empty beneath it. */
.cf-v2-apply-profile__diffs {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-apply-profile__diff {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-3, 0.75rem);
    border-radius: var(--cf-radius-md, 0.375rem);
    background: var(--cf-bg-elevated-2);
}

.cf-v2-apply-profile__diff-section {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    padding-inline-start: var(--cf-space-3, 0.75rem);
    border-inline-start: 2px solid var(--cf-bg-elevated-3);
}

.cf-v2-apply-profile__change {
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    color: var(--cf-text-secondary);
}

.cf-v2-apply-profile__change[data-kind="add"]    { color: var(--cf-status-success); }
.cf-v2-apply-profile__change[data-kind="remove"] { color: var(--cf-status-error); }
.cf-v2-apply-profile__change[data-kind="update"] { color: var(--cf-status-warning); }

/* ── In-flight push banner (PLAT-3276) ────────────────────────────────
   A progress line only. The per-workspace detail belongs in Activity, where
   it is not pushing the page around while it changes under the reader. */
.cf-v2-profile-run-banner {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-v2-profile-run-banner__meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-3, 0.75rem);
}

/* ── Activity tab (PLAT-3276) ─────────────────────────────────────────── */
.cf-v2-profile-runs__title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--cf-space-2, 0.5rem);
}

/* Reads as a diff stat so a push can be judged at a glance. */
.cf-v2-profile-runs__stat {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--cf-space-2, 0.5rem);
    font-variant-numeric: tabular-nums;
}

.cf-v2-profile-runs__stat-item {
    font-size: 0.8125rem;
    font-weight: 600;
}

.cf-v2-profile-runs__stat-item[data-kind="add"]    { color: var(--cf-status-success); }
.cf-v2-profile-runs__stat-item[data-kind="update"] { color: var(--cf-status-warning); }
.cf-v2-profile-runs__stat-item[data-kind="remove"] { color: var(--cf-status-error); }

.cf-v2-profile-runs__row {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
}

.cf-v2-profile-runs__summary {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-1, 0.25rem);
}

.cf-v2-profile-runs__actions {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
}

@media (min-width: 560px) {
    .cf-v2-profile-runs__row {
        flex-direction: row;
        align-items: flex-start;
        justify-content: space-between;
    }

    .cf-v2-profile-runs__actions {
        flex-direction: row;
    }
}

/* ==========================================================================
   Entity panel shell (PLAT-3288)
   Layout contract for dock-hosted insight / investigation panels. The dock
   supplies the height; the shell owns a pinned header and exactly one scroll
   region. Panels must not set pixel heights or compute them in C# — the V1
   panels did (DockContentHeight - 250, - 10, ...) and that is what made resize
   feel janky and overflowed the dock at its 160px minimum.
   Lives here rather than in a scoped .razor.css because the class vocabulary is
   shared across every panel component.
   ========================================================================== */
.cf-entity-panel {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    /* The surface the panel is painted on. Sticky children (day headings, table
       headers) must repaint exactly this or they read as highlighted bands rather
       than as the background showing through. Kept as one variable so the panel
       tracks the dock's own surface token (.cf-dock uses --cf-bg-elevated-2). */
    --cf-entity-panel-surface: var(--cf-bg-elevated-2, #142735);
}

/* Hand scrolling to the shell so its header stays pinned while the body
   scrolls; otherwise the dock scrolls the whole panel and the entity title and
   time filter disappear. Panels not yet migrated keep the dock's own scroll, so
   this needs no flag day. The .cf-dock ancestor is here for specificity: the
   dock's scoped rule compiles to .cf-dock__panel[b-xxx] (0,2,0) and would
   otherwise tie with this selector and win on source order. */
.cf-dock .cf-dock__panel:has(> .cf-entity-panel) {
    overflow: hidden;
    padding: 0;
}

/* Mobile-first: identity stacks above the controls, then goes side-by-side. */
.cf-entity-panel__header {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-4, 1rem);
    border-bottom: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
}

@media (min-width: 560px) {
    .cf-entity-panel__header {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

/* min-width:0 is what actually lets the title ellipsis inside a flex row. */
.cf-entity-panel__identity {
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: var(--cf-space-0-5, 0.125rem);
}

.cf-entity-panel__title,
.cf-entity-panel__subtitle {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cf-entity-panel__title {
    font-size: var(--cf-text-body, 0.875rem);
    font-weight: var(--cf-font-semibold, 600);
    color: var(--cf-text-primary, inherit);
}

.cf-entity-panel__subtitle {
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-secondary, inherit);
}

/* Wraps rather than compressing: a panel that puts a search field next to the
   time filter would otherwise squeeze both to unusable widths on a narrow dock. */
.cf-entity-panel__actions {
    flex: 0 1 auto;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-entity-panel__timerange {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

/* Sized so the field is usable without crowding the time filter beside it. */
.cf-entity-panel__search {
    flex: 0 1 18rem;
    min-width: 10rem;
}

.cf-entity-panel__body {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
}

/* Panels whose body is a single grid/table hand their height straight to it. */
.cf-entity-panel__body--flush {
    padding: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Facts exploit the dock's width instead of stacking rows downward, which is
   the axis a short strip does not have. */
.cf-entity-panel__facts {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: var(--cf-space-3, 0.75rem);
}

/* Row-shaped placeholder for panels whose content is a list or a table, so the
   loading state predicts the layout that replaces it. */
.cf-entity-panel__skeleton-rows {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
}

/* Wider minimum for facts that carry hashes or long identifiers. */
.cf-entity-panel__facts--wide {
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

/* Separates a secondary block (hashes, chip lists) from the facts above it. */
.cf-entity-panel__section {
    margin-top: var(--cf-space-4, 1rem);
}

/* A banner that leads the body: spaces the content that follows it instead. */
.cf-entity-panel__notice {
    margin-bottom: var(--cf-space-3, 0.75rem);
}

/* --- Panel layout -------------------------------------------------------
   Facts on the left, membership lists on the right, so a wide dock is filled
   across rather than leaving a dead zone under a single column. Collapses to
   one column when the dock is narrow. */
.cf-entity-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--cf-space-4, 1rem);
    align-items: start;
}

@media (min-width: 900px) {
    .cf-entity-layout {
        grid-template-columns: minmax(0, 2.5fr) minmax(17rem, 1fr);
        gap: var(--cf-space-5, 1.25rem);
    }
}

.cf-entity-aside {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
    min-width: 0;
}

/* --- Facts beside a table ------------------------------------------------
   For panels that are a handful of attributes plus one event table. In a dock
   the scarce axis is height and the plentiful one is width, so the facts take a
   fixed column and the table takes the rest and all of the height. That is what
   replaces the V1 `xs=3 / xs=9` grid split whose table carried a literal
   Height="265px" regardless of how the dock was sized.
   Used inside a flush body, so this owns the remaining height itself. */
.cf-entity-split {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
}

@media (min-width: 900px) {
    .cf-entity-split {
        grid-template-columns: minmax(15rem, 20rem) minmax(0, 1fr);
        grid-template-rows: minmax(0, 1fr);
    }
}

/* Scrolls on its own only once it is a column of its own; stacked above the
   table it sizes to content so it never steals the table's rows. */
.cf-entity-split__rail {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    min-width: 0;
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
    border-bottom: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
}

@media (min-width: 900px) {
    .cf-entity-split__rail {
        min-height: 0;
        overflow-y: auto;
        border-bottom: none;
        border-right: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
    }
}

/* Rail on the trailing edge instead of the leading one, for panels whose primary
   content is the table and whose rail is a detail view of the selected row. Markup
   order is main-then-rail; the stacked layout therefore puts the detail below the
   list it belongs to, which is the reading order either way. */
@media (min-width: 900px) {
    .cf-entity-split--trailing {
        grid-template-columns: minmax(0, 1fr) minmax(18rem, 26rem);
    }

    .cf-entity-split--trailing .cf-entity-split__rail {
        border-right: none;
        border-left: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
    }
}

/* Stacked, the flexible row is the first one because that is where the table is. */
.cf-entity-split--trailing {
    grid-template-rows: minmax(0, 1fr) auto;
}

.cf-entity-split--trailing .cf-entity-split__rail {
    border-bottom: none;
    border-top: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
}

/* --- Selected-record detail rail ----------------------------------------
   Header, facts and a feed inside a scrolling rail. Used by Related incidents;
   kept generic because a selected-row detail is the obvious next need for the
   other list panels. */
.cf-entity-rail__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-entity-rail__title {
    font-size: var(--cf-text-body, 0.875rem);
    font-weight: var(--cf-font-semibold, 600);
    color: var(--cf-text-primary, inherit);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cf-entity-rail__subtitle {
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-secondary, inherit);
    overflow-wrap: anywhere;
}

/* Actions sit directly under the record they act on, before its attributes, so
   the rail answers "what can I do about this" before "what is this". */
.cf-entity-rail__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-entity-rail__section-title {
    font-size: var(--cf-text-body-xs, 0.6875rem);
    font-weight: var(--cf-font-semibold, 600);
    color: var(--cf-text-secondary, inherit);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* A compact vertical feed. Same idea as the device timeline's rail but sized for
   a side column, so the connector is dropped and the time sits above its entry
   rather than in a fixed track that would eat the width. */
.cf-entity-feed {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    min-width: 0;
}

.cf-entity-feed__item {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    padding-left: var(--cf-space-3, 0.75rem);
    border-left: 2px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
    min-width: 0;
}

.cf-entity-feed__time {
    font-family: var(--cf-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-size: var(--cf-text-body-xs, 0.6875rem);
    color: var(--cf-text-secondary, inherit);
}

.cf-entity-feed__text {
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-primary, inherit);
    overflow-wrap: anywhere;
}

.cf-entity-split__main {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
}

/* Caption above a table that needs naming ("URL clicked events for X"). */
.cf-entity-split__caption {
    flex: 0 0 auto;
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-4, 1rem) 0;
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-secondary, inherit);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The empty state for the table half, centred in the space the table would
   have filled rather than pinned to the top of it. */
.cf-entity-split__empty {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--cf-space-4, 1rem);
}

/* --- Scrollable member lists -------------------------------------------
   Roles and groups run to dozens of entries. As wrapped chips they became a
   wall; as a capped scrolling column each name sits on its own line and can
   be scanned. */
.cf-entity-list {
    display: flex;
    flex-direction: column;
    min-width: 0;
    border: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
    border-radius: var(--cf-radius-md, 0.5rem);
    overflow: hidden;
}

.cf-entity-list__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-3, 0.75rem);
    border-bottom: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
    font-size: var(--cf-text-body-sm, 0.75rem);
    font-weight: var(--cf-font-semibold, 600);
    color: var(--cf-text-secondary, inherit);
}

.cf-entity-list__body {
    display: flex;
    flex-direction: column;
    max-height: 11rem;
    overflow-y: auto;
}

.cf-entity-list__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-1-5, 0.375rem) var(--cf-space-3, 0.75rem);
    font-size: var(--cf-text-body, 0.875rem);
    color: var(--cf-text-primary, inherit);
    min-width: 0;
}

.cf-entity-list__item + .cf-entity-list__item {
    border-top: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.14));
}

.cf-entity-list__name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cf-entity-list__item[data-privileged="true"] .cf-entity-list__name {
    color: var(--cf-status-error, inherit);
    font-weight: var(--cf-font-semibold, 600);
}

.cf-entity-panel__filter {
    max-width: 16rem;
}

/* Variable-length label sets wrap inline instead of sitting in a fixed-height
   scroll box, which is what made the V1 roles/groups list overflow the dock. */
.cf-entity-panel__chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-1-5, 0.375rem);
}

.cf-entity-panel__chips + .cf-entity-panel__chips {
    margin-top: var(--cf-space-3, 0.75rem);
}

/* A titled card. Giving each fact its own bounded surface is what makes the
   grid readable at dock width: label and value stay visually paired instead of
   drifting to opposite ends of a very wide row. */
.cf-entity-fact {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
    padding: var(--cf-space-3, 0.75rem) var(--cf-space-4, 1rem);
    background: var(--cf-bg-elevated-1, color-mix(in oklab, currentColor 4%, transparent));
    border: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
    border-radius: var(--cf-radius-md, 0.5rem);
}

/* Accent the facts that should pull the eye first. */
.cf-entity-fact[data-tone="warning"] {
    border-color: var(--cf-status-warning, rgba(217, 119, 6, 0.5));
}

.cf-entity-fact[data-tone="error"] {
    border-color: var(--cf-status-error, rgba(220, 38, 38, 0.5));
}

.cf-entity-fact__label {
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-secondary, inherit);
}

.cf-entity-fact__value {
    display: flex;
    align-items: center;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
}

/* Wrap rather than truncate: a hash cut mid-string is worse than two lines,
   and the copy button is right there for the full value. */
.cf-entity-fact__text {
    min-width: 0;
    font-size: var(--cf-text-body-lg, 1rem);
    font-weight: var(--cf-font-semibold, 600);
    color: var(--cf-text-primary, inherit);
    overflow-wrap: anywhere;
}

.cf-entity-fact__text[data-mono="true"] {
    font-family: var(--cf-font-mono, ui-monospace, monospace);
    font-size: var(--cf-text-body-sm, 0.75rem);
    font-weight: var(--cf-font-normal, 400);
}

/* Long reference values stay two lines until asked for, so one verbose value
   can't push the rest of the grid out of a short dock. */
.cf-entity-fact--clamped .cf-entity-fact__text {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* --- Pinned footer ------------------------------------------------------
   Result counts and paging live outside the scroll region. In V1 the "Load More
   Logs" button sat at the bottom of the scrolling content, so at the dock's
   minimum height an analyst had to scroll past every row to reach it. */
.cf-entity-panel__footer {
    flex: 0 0 auto;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-4, 1rem);
    border-top: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
}

.cf-entity-panel__footer-count {
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-secondary, inherit);
}

/* --- Table panels -------------------------------------------------------
   CFTable is already a flex column whose .cf-table__scroll owns both scroll
   axes under a sticky header, so handing it the flush body's height is all a
   log panel needs. This is what replaces the V1 `DockContentHeight - 250`
   arithmetic: no pixel ever enters C#, and resizing the dock resizes the rows.
   The .cf-entity-panel ancestor is here for specificity — CFTable's own rules
   compile to .cf-table[b-xxx] (0,2,0) and would otherwise tie and win on
   source order. */
.cf-entity-panel__table {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.cf-entity-panel .cf-entity-panel__table .cf-table {
    height: 100%;
    border: none;
    border-radius: 0;
    background: transparent;
}

/* Same rule as the timeline's day heading: the sticky header repaints the panel
   surface, not a lighter elevation that would read as a highlighted first row. */
.cf-entity-panel .cf-entity-panel__table .cf-table__header {
    background: var(--cf-entity-panel-surface, transparent);
}

/* Secondary line under a row's primary value (a failure reason, an actor).
   Cheaper on vertical space than its own column, and it only appears on the
   rows that have something to say. */
.cf-entity-panel__cell-stack {
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: var(--cf-space-0-5, 0.125rem);
}

.cf-entity-panel__cell-primary {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--cf-text-primary, inherit);
}

.cf-entity-panel__cell-secondary {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-secondary, inherit);
}

.cf-entity-panel__cell-mono {
    font-family: var(--cf-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Record detail dialogs (PLAT-3288)
   Shared shell for the inspectors behind a log or timeline row: a lead block
   that states the record's identity and outcome, then sections of fact cards
   reusing .cf-entity-panel__facts so a row and its detail read as one design.
   ========================================================================== */
.cf-detail-dialog {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-5, 1.25rem);
    min-width: 0;
}

.cf-detail-dialog__lead {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-detail-dialog__headline {
    font-size: var(--cf-text-h5, 1.125rem);
    font-weight: var(--cf-font-semibold, 600);
    color: var(--cf-text-primary, inherit);
    overflow-wrap: anywhere;
}

/* align-items keeps chips at their intrinsic height instead of stretching to
   the line box. */
.cf-detail-dialog__lead-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-secondary, inherit);
}

.cf-detail-section {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-3, 0.75rem);
    min-width: 0;
}

.cf-detail-section__title {
    font-size: var(--cf-text-body, 0.875rem);
    font-weight: var(--cf-font-semibold, 600);
    color: var(--cf-text-primary, inherit);
}

/* ==========================================================================
   Device event details dialog (PLAT-3288)
   Only the raw vendor property bag is local to this dialog; everything above
   it comes from .cf-detail-dialog.
   ========================================================================== */
.cf-event-details__raw {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

/* Mobile-first: the title sits above its controls, then shares the row. */
.cf-event-details__raw-head {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--cf-space-2, 0.5rem);
}

@media (min-width: 560px) {
    .cf-event-details__raw-head {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
}

.cf-event-details__raw-title {
    font-size: var(--cf-text-body, 0.875rem);
    font-weight: var(--cf-font-semibold, 600);
    color: var(--cf-text-primary, inherit);
}

.cf-event-details__raw-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--cf-space-2, 0.5rem);
}

.cf-event-details__raw-empty {
    margin: 0;
    padding: var(--cf-space-4, 1rem) 0;
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-secondary, inherit);
}

/* Capped and scrollable: pack_all routinely returns thirty-plus fields, and an
   unbounded list pushes the dialog past the viewport. */
.cf-detail-props {
    display: flex;
    flex-direction: column;
    margin: 0;
    max-height: 22rem;
    overflow-y: auto;
    border: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.24));
    border-radius: var(--cf-radius-md, 0.5rem);
}

.cf-detail-prop {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--cf-space-0-5, 0.125rem);
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-3, 0.75rem);
    min-width: 0;
}

/* Fixed key track above the breakpoint so the values line up into a column the
   eye can run down; stacked below it, where a two-track grid would leave the
   value a few characters wide. */
@media (min-width: 560px) {
    .cf-detail-prop {
        grid-template-columns: minmax(9rem, 16rem) minmax(0, 1fr);
        gap: var(--cf-space-3, 0.75rem);
        align-items: start;
    }
}

.cf-detail-prop + .cf-detail-prop {
    border-top: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.14));
}

.cf-detail-prop__key {
    font-size: var(--cf-text-body-sm, 0.75rem);
    font-weight: var(--cf-font-semibold, 600);
    color: var(--cf-text-secondary, inherit);
    overflow-wrap: anywhere;
}

.cf-detail-prop__value {
    margin: 0;
    font-family: var(--cf-font-mono, ui-monospace, monospace);
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-primary, inherit);
    overflow-wrap: anywhere;
}

/* ==========================================================================
   Process tree (PLAT-3288)
   Ancestry is the whole point of this panel, so depth is expressed by an
   indent plus a guide line rather than by nesting DOM. Rows are rendered from
   a flattened list keyed on --cf-proc-depth, which keeps expansion, filtering
   and keyboard traversal to flat list operations instead of recursion.
   ========================================================================== */
.cf-proc-tree {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.cf-proc-row {
    /* Indent step doubles as the guide-line position, so the two can't drift. */
    --cf-proc-indent: 1.25rem;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    gap: var(--cf-space-2, 0.5rem);
    padding: var(--cf-space-1-5, 0.375rem) var(--cf-space-4, 1rem);
    padding-left: calc(var(--cf-space-4, 1rem) + (var(--cf-proc-depth, 0) * var(--cf-proc-indent)));
    border-left: 2px solid transparent;
    cursor: pointer;
    min-width: 0;
    transition: background-color 120ms ease;
}

.cf-proc-row:hover,
.cf-proc-row:focus-visible {
    background: var(--cf-bg-spotlight, rgba(127, 127, 127, 0.08));
    outline: none;
}

.cf-proc-row[data-selected="true"] {
    background: var(--cf-bg-spotlight, rgba(127, 127, 127, 0.12));
    border-left-color: var(--cf-color-action, #5597ff);
}

/* The alerted process is why the panel was opened; it stays findable while
   scrolling, not only once it is reached. */
.cf-proc-row[data-alert="true"] {
    background: color-mix(in srgb, var(--cf-status-error, #d64545) 8%, transparent);
}

.cf-proc-row[data-alert="true"] .cf-proc-row__name {
    color: var(--cf-status-error, inherit);
    font-weight: var(--cf-font-semibold, 600);
}

/* Fixed-size slot whether or not the row can expand, so names stay aligned
   down the column instead of stepping in and out by a chevron's width. */
.cf-proc-row__toggle {
    flex: 0 0 auto;
    width: 1.25rem;
    height: 1.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    background: none;
    color: var(--cf-text-secondary, inherit);
    cursor: pointer;
}

.cf-proc-row__toggle[data-leaf="true"] {
    cursor: default;
    visibility: hidden;
}

.cf-proc-row__body {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-0-5, 0.125rem);
    min-width: 0;
}

.cf-proc-row__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    min-width: 0;
}

.cf-proc-row__name {
    font-size: var(--cf-text-body, 0.875rem);
    color: var(--cf-text-primary, inherit);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 22rem;
}

.cf-proc-row__pid {
    font-family: var(--cf-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-size: var(--cf-text-body-xs, 0.6875rem);
    color: var(--cf-text-secondary, inherit);
}

.cf-proc-row__time {
    font-family: var(--cf-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-size: var(--cf-text-body-xs, 0.6875rem);
    color: var(--cf-text-secondary, inherit);
    margin-left: auto;
    white-space: nowrap;
}

/* The command line is the evidence, so it gets its own line at full width
   rather than being concatenated into the name as V1 did. */
.cf-proc-row__cmd {
    font-family: var(--cf-font-mono, ui-monospace, monospace);
    font-size: var(--cf-text-body-xs, 0.6875rem);
    color: var(--cf-text-secondary, inherit);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* ==========================================================================
   Entity timeline (PLAT-3288)
   The device timeline is a sequence, not a record set: the question an analyst
   opens it to answer is "what happened around the alert", which a four-column
   grid of equally-weighted cells cannot answer at a glance. A rail puts the
   ordering on screen and lets the alert row be the one thing that stands out.
   ========================================================================== */
.cf-entity-timeline {
    display: flex;
    flex-direction: column;
}

/* Sticky against .cf-entity-panel__body, which is the scroll container, so the
   date stays on screen while its events scroll under it. It repaints the panel
   surface (never a lighter elevation, which would read as a selected row) and the
   shadow extends that paint upward over the body's own top padding, which the
   sticky element's box would otherwise leave uncovered for rows to show through. */
.cf-entity-timeline__day {
    position: sticky;
    top: 0;
    z-index: 1;
    /* Bled out to the panel edges and padded back in, so the rule under the date
       runs the full width as a section divider instead of floating inside the
       body's padding. */
    margin-inline: calc(var(--cf-space-4, 1rem) * -1);
    padding: var(--cf-space-2, 0.5rem) var(--cf-space-4, 1rem) var(--cf-space-1, 0.25rem);
    background: var(--cf-entity-panel-surface, transparent);
    box-shadow: 0 calc(var(--cf-space-3, 0.75rem) * -1) 0 var(--cf-entity-panel-surface, transparent);
    border-bottom: 1px solid var(--cf-color-border, rgba(127, 127, 127, 0.18));
    margin-bottom: var(--cf-space-1, 0.25rem);
    font-size: var(--cf-text-body-xs, 0.6875rem);
    font-weight: var(--cf-font-semibold, 600);
    color: var(--cf-text-secondary, inherit);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* Mobile-first: a single stacked column, because the fixed time track and rail
   would leave the title only a few characters wide on a narrow dock. */
.cf-entity-timeline__event {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: stretch;
    gap: var(--cf-space-1, 0.25rem);
    padding: var(--cf-space-2, 0.5rem);
    border-radius: var(--cf-radius-md, 0.5rem);
    cursor: pointer;
    transition: background-color 120ms ease;
}

.cf-entity-timeline__rail {
    display: none;
}

/* Fixed time track, hairline rail, then everything else. Keeping the time
   column a fixed width is what lets the eye run straight down it. */
@media (min-width: 560px) {
    .cf-entity-timeline__event {
        grid-template-columns: 5rem 0.75rem minmax(0, 1fr);
        gap: var(--cf-space-3, 0.75rem);
    }

    .cf-entity-timeline__rail {
        display: block;
    }
}

.cf-entity-timeline__event:hover,
.cf-entity-timeline__event:focus-visible {
    background: var(--cf-bg-spotlight, rgba(127, 127, 127, 0.08));
    outline: none;
}

.cf-entity-timeline__time {
    font-family: var(--cf-font-mono, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-secondary, inherit);
    padding-top: 0.125rem;
    white-space: nowrap;
}

/* The connector runs the full row height so consecutive events read as one
   unbroken sequence; the node is drawn on top at the title's baseline. */
.cf-entity-timeline__rail {
    position: relative;
}

.cf-entity-timeline__rail::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 0;
    bottom: 0;
    width: 1px;
    transform: translateX(-50%);
    background: var(--cf-color-border, rgba(127, 127, 127, 0.24));
}

.cf-entity-timeline__rail::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 0.375rem;
    width: 0.5rem;
    height: 0.5rem;
    transform: translateX(-50%);
    border-radius: 50%;
    background: var(--cf-text-secondary, rgba(127, 127, 127, 0.8));
    box-shadow: 0 0 0 3px var(--cf-bg-elevated-1, transparent);
}

/* The rail starts at the first node under each day heading and stops at the last
   event's node, so each day reads as its own run and the sequence doesn't appear
   to continue past the data we actually have. */
.cf-entity-timeline__day + .cf-entity-timeline__event .cf-entity-timeline__rail::before {
    top: 0.625rem;
}

.cf-entity-timeline__event:last-child .cf-entity-timeline__rail::before {
    bottom: auto;
    height: 0.625rem;
}

.cf-entity-timeline__content {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-1, 0.25rem);
    min-width: 0;
}

.cf-entity-timeline__title {
    font-size: var(--cf-text-body, 0.875rem);
    color: var(--cf-text-primary, inherit);
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.cf-entity-timeline__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cf-space-2, 0.5rem);
    font-size: var(--cf-text-body-sm, 0.75rem);
    color: var(--cf-text-secondary, inherit);
    min-width: 0;
}

.cf-entity-timeline__actor {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 18rem;
}

/* The alert is the reason the panel was opened. Tint, accent node and a
   semibold title make it findable while scrolling, not only when scrolled to. */
.cf-entity-timeline__event[data-alert="true"] {
    background: color-mix(in srgb, var(--cf-status-error, #d64545) 8%, transparent);
}

.cf-entity-timeline__event[data-alert="true"] .cf-entity-timeline__title {
    font-weight: var(--cf-font-semibold, 600);
}

.cf-entity-timeline__event[data-alert="true"] .cf-entity-timeline__rail::after {
    background: var(--cf-status-error, #d64545);
    width: 0.625rem;
    height: 0.625rem;
    top: 0.3125rem;
}

.cf-entity-timeline__event[data-alert="true"] .cf-entity-timeline__time {
    color: var(--cf-status-error, inherit);
    font-weight: var(--cf-font-semibold, 600);
}

/* ==========================================================================
   Boot splash (PLAT-3289)
   ==========================================================================
   Deliberately global rather than scoped to LoadingProgress.razor, because two
   very different things render this exact markup:

     1. wwwroot/index.html, as static HTML, before the WASM runtime has
        downloaded. Scoped CSS cannot reach it: there is no b-xxxxx attribute on
        hand-written markup.
     2. <LoadingProgress>, once Blazor has started, for the authorization wait
        and the tenant-bootstrap wait.

   Blazor replaces the contents of <app> when it starts. Because both render the
   same classes, that swap is invisible: the sweep bar keeps moving and the
   lockup does not shift. Any change here has to be made once and lands on both.

   Every token carries a literal fallback. At stage 1 the app's own stylesheets
   may not have applied yet, and this is the first thing anyone sees.
   ========================================================================== */

app {
    display: block;
}

.cf-boot {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--cf-space-6, 1.5rem);
    min-height: 100vh;
    padding: var(--cf-space-6, 1.5rem);
    box-sizing: border-box;
    text-align: center;

    /* Pinned navy rather than the themed --cf-bg-default: the wordmark is the
       white-on-dark asset, so following a light theme would render it invisible. */
    color-scheme: dark;
    background:
        radial-gradient(120% 90% at 50% -10%, rgba(37, 87, 249, 0.16), transparent 60%),
        #001022;
    animation: cf-boot-in 400ms cubic-bezier(0, 0, 0.2, 1) both;
}

.cf-boot__wordmark {
    width: min(17.5rem, 70vw);
    height: auto;
}

.cf-boot__label {
    margin: 0;
    font-family: var(--cf-font-sans, 'Inter', -apple-system, 'Segoe UI', sans-serif);
    font-size: var(--cf-text-body, 0.875rem);
    color: #a2abb2;
}

.cf-boot__track {
    position: relative;
    width: min(14rem, 70vw);
    height: 2px;
    border-radius: 100px;
    background: rgba(255, 255, 255, 0.08);
    overflow: hidden;
}

.cf-boot__bar {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 40%;
    border-radius: inherit;
    background: linear-gradient(90deg, transparent, #5597ff, transparent);
    will-change: transform;
    animation: cf-boot-sweep 1.8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}

@keyframes cf-boot-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes cf-boot-sweep {
    0%   { transform: translateX(-110%); }
    100% { transform: translateX(360%); }
}

@media (prefers-reduced-motion: reduce) {
    .cf-boot {
        animation: none;
    }

    /* Slowed, not stopped: this splash can be the only thing on screen for
       several seconds on a cold load, and a frozen bar reads as a hung app. */
    .cf-boot__bar {
        animation-duration: 4s;
    }
}

/* ── Workspace analytic-rule authoring (PLAT-3329 create, PLAT-3358 edit) ──────
   Global rather than scoped to the create component: the edit page shares this exact
   vocabulary, and Blazor scoped CSS does not reach elements declared in another
   component's Razor file, so a scoped copy silently left the edit form unstyled. */
.workspace-rule-create__body {
    display: flex;
    flex-direction: column;
    gap: var(--cf-space-4, 1rem);
}

/* Label + switch: stacks on mobile, splits from sm up. */
.workspace-rule-create__toggle {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--cf-space-1, 0.25rem);
}

.workspace-rule-create__actions {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--cf-space-2, 0.5rem);
}

@media (min-width: 560px) {
    .workspace-rule-create__toggle {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .workspace-rule-create__actions {
        flex-direction: row;
        justify-content: flex-end;
    }
}
