/* ============================================================================
   Application shell (SSR + vanilla JS, no MudBlazor layout dependency)

   Structure (MainLayout.razor):
     .sk-shell
       > aside.app-navigation-drawer   left navigation (full height)
       > .sk-shell__backdrop           mobile overlay backdrop
       > .sk-shell__body
           > header.app-topbar         top bar + hamburger toggle + top menu
           > main.app-main             routed page content

   State is held as classes on <html>, toggled by wwwroot/js/nav-shell.js:
     html.sk-nav-collapsed   desktop: drawer slid to an icon rail (design.md D12)
     html.sk-nav-open        mobile: overlay drawer open

   All colors come from the governed set (tokens.css), via the --sk-shell-*
   bridge tokens declared under html:root there. No fallback values here —
   a fallback is a second value hiding behind a variable, which is exactly
   what PRS-1 forbids (design.md D1).
   ============================================================================ */

.sk-shell {
    --sk-topbar-height: var(--dtx-control-height-default);
    /* Figma's own sidebar is ~244px. Widened slightly to 264px so the longest current nav label in
       either supported language ("Schémas d'immatriculation") still has a fighting chance to stay
       on one line - French menu labels run longer than their English source on average - without
       reproducing the review's own "everything looks designed for a wide monitor" complaint that a
       324px rail (this file's previous width) contributed to. */
    --sk-drawer-width: 264px;
    /* Icon-rail width when collapsed (design.md D12, review item 4): icons stay
       reachable instead of the drawer disappearing entirely. */
    --sk-drawer-rail-width: 72px;
    display: flex;
    min-height: 100vh;
    /* --sk-rail-width is declared globally (tokens.css html:root), not here: the right rail
       (theme.css .dtx-rail) is rendered outside .sk-shell entirely (InteractiveShell's own island),
       so a value scoped to this element would not be visible there. */
    padding-right: var(--sk-rail-width);
    box-sizing: border-box;
}

.app-navigation-drawer {
    flex: 0 0 var(--sk-drawer-width);
    width: var(--sk-drawer-width);
    height: 100vh;
    position: sticky;
    top: 0;
    overflow: hidden;
    z-index: 1200;
    background: var(--sk-shell-bg);
    box-shadow: var(--sk-shell-drawer-shadow);
    transition: width var(--dtx-motion-slow) var(--dtx-motion-easing),
                margin-left var(--dtx-motion-slow) var(--dtx-motion-easing),
                transform var(--dtx-motion-slow) var(--dtx-motion-easing);
}

.sk-shell__body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* The direction mock-ups show no persistent bar above the page content at desktop widths - the
   page's own header (title, filters) sits directly on the canvas. This bar only still exists for
   the sub-1280px breakpoint below, where the drawer becomes a hidden overlay and needs an external
   control to open it (TopMenuComponent itself is empty at desktop widths - see its own comment).
   "Back to website" and the old "Datixxia" home-link both moved to the drawer footer instead. */
.app-topbar {
    display: none;
}

@media (max-width: 1279.98px) {
    .app-topbar {
        position: sticky;
        top: 0;
        z-index: 1100;
        display: flex;
        align-items: center;
        gap: var(--dtx-space-2);
        height: var(--sk-topbar-height);
        padding: 0 var(--dtx-space-4);
        color: var(--sk-shell-text);
        background: var(--sk-shell-topbar-bg);
        box-shadow: var(--sk-shell-topbar-shadow);
    }
}

.app-topbar__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    padding: 0;
    border: 0;
    border-radius: var(--dtx-radius);
    background: transparent;
    color: var(--sk-shell-text);
    cursor: pointer;
    transition: background-color var(--dtx-motion-fast) var(--dtx-motion-easing),
                color var(--dtx-motion-fast) var(--dtx-motion-easing);
}

.app-topbar__toggle:hover {
    background: var(--sk-shell-hover-bg);
    color: var(--sk-shell-accent);
}

.app-topbar__toggle .sk-icon {
    display: block;
    width: 24px;
    height: 24px;
    fill: currentColor;
}

.app-topbar__spacer {
    flex: 1 1 auto;
}

.app-main {
    flex: 1 1 auto;
    min-width: 0;
    background: var(--dtx-surface-canvas);
}

.app-main__container {
    width: 100%;
    box-sizing: border-box;
    /* Generous horizontal padding mirrors the previous MudMainContent px-16 gutter
       and keeps page content clear of the fixed chat tab pinned to the right edge. */
    padding: var(--dtx-space-6) var(--dtx-space-12);
}

.sk-shell__backdrop {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1150;
    background: var(--dtx-overlay-scrim);
}

/* Desktop: persistent drawer collapses to an icon rail rather than disappearing
   (design.md D12, review item 4) — icons stay reachable, the working area gains
   most of the width back, and nobody has to re-open the panel after every jump.
   Full hiding is reserved for the dashboard's dedicated "Full screen" mode. */
@media (min-width: 1280px) {
    html.sk-nav-collapsed .app-navigation-drawer {
        width: var(--sk-drawer-rail-width);
        flex-basis: var(--sk-drawer-rail-width);
    }

    html.sk-nav-collapsed .nav-brand__title,
    html.sk-nav-collapsed .nav-section__label,
    html.sk-nav-collapsed .nav-link__text,
    html.sk-nav-collapsed .nav-user__text,
    html.sk-nav-collapsed .nav-mfa-required-notice {
        display: none;
    }

    /* The logo/toggle row switches from side-by-side to a centred column, so the toggle sits
       directly under the now icon-only logo instead of off to one side with nothing beside it
       (mock-up feedback: the toggle lives next to the logo, not in its own separate spot). */
    html.sk-nav-collapsed .nav-brand {
        flex-direction: column;
        gap: 10px;
    }

    /* The .nav-shell qualifier on .nav-link is load-bearing, not decoration: NavMenu.razor.css
       styles the link via `.nav-shell ::deep .nav-link`, which compiles to
       `.nav-shell[b-xxx] .nav-link` at specificity (0,3,0). A bare `html.sk-nav-collapsed .nav-link`
       is only (0,2,1) and silently lost to it, so the expanded 0 12px padding survived into the rail
       and left exactly 12px for the 22px icon (72 - 28 shell - 4 menu - 4 border - 24 padding).
       `html.sk-nav-collapsed .nav-shell .nav-link` is (0,3,1) and wins. */
    html.sk-nav-collapsed .nav-shell .nav-link,
    html.sk-nav-collapsed .nav-user {
        justify-content: center;
        /* The expanded row's 0 12px / 6px 12px padding plus the icon's own box leaves less content
           width than the icon needs once the 72px rail's own ancestor padding (.nav-shell, .nav-menu,
           .nav-footer) is subtracted - narrower than the icon itself, which pushed the whole row
           wider than the rail (the reported horizontal-scroll bug) and left the icon rendering hard
           against one edge instead of centred. Both padding and the icon slot need to shrink here,
           not just re-centre within the old, too-wide box. */
        padding: 0 4px;
    }

    html.sk-nav-collapsed .nav-link__icon {
        min-width: 0;
    }

    /* Regression from bug 82's own fix: .nav-menu's horizontal padding grew from 2px to 4px per
       side there, to clear the focus ring in the EXPANDED drawer. The collapsed rail's own budget
       above is already tuned to the wire against the old 2px (every ancestor's padding is
       subtracted from a fixed 72px rail before anything is left for the icon) - the extra 2px per
       side left less room than the 22px icon itself needs, squeezing it down to a sliver instead
       of its square size. Restore the original 2px here; the expanded state (where bug 82's ring
       actually needed the room) is unaffected since this only applies under .sk-nav-collapsed. */
    /* Same budget, second squeeze: on a viewport shorter than the menu, .nav-menu's overflow-y: auto
       shows a vertical scrollbar, which comes out of the same fixed 72px and narrows every icon.
       The rail keeps scrolling by wheel, touch and keyboard; only the bar itself is hidden, so the
       budget no longer depends on viewport height or on how many entries a role happens to see. */
    html.sk-nav-collapsed .nav-menu {
        padding-left: 2px;
        padding-right: 2px;
        scrollbar-width: none;
    }

}

/* The dashboard's "Full screen" control (DashboardReport.razor) invokes the
   browser's native Fullscreen API on the report container, which already
   covers the whole viewport including this drawer without any CSS of ours —
   the one case design.md D12 keeps full hiding for needs no extra state here. */

/* Tablet / mobile: drawer becomes an overlay, hidden by default. */
@media (max-width: 1279.98px) {
    .app-navigation-drawer {
        position: fixed;
        top: 0;
        left: 0;
        transform: translateX(-100%);
        box-shadow: none;
    }

    html.sk-nav-open .app-navigation-drawer {
        transform: translateX(0);
        box-shadow: var(--sk-shell-drawer-shadow);
    }

    html.sk-nav-open .sk-shell__backdrop {
        display: block;
    }

    .app-main__container {
        /* Keep a wider right gutter so page content stays clear of the fixed chat
           tab pinned to the right edge (the tab is ~30px wide). */
        padding: var(--dtx-space-4) 44px var(--dtx-space-4) var(--dtx-space-4);
    }
}

/* Chat drawer: a fixed overlay pinned to the right edge, independent of the shell
   layout. We force ONLY the vertical anchoring (fixed + full height) so the panel
   never scrolls with the page. The horizontal right offset / slide is left to
   MudBlazor's own --open / --closed classes — overriding `right` here would keep
   the drawer permanently on-screen. !important is required because MudBlazor's
   own .mud-drawer rules carry equal specificity. */
.sk-chat-drawer.mud-drawer {
    position: fixed !important;
    top: 0 !important;
    height: 100vh !important;
    max-height: 100vh;
    z-index: 1300;
}

/* Open state only, offset from the viewport edge by the rail's own width (mock-up feedback: the
   drawer used to sit flush against the edge and, being z-index 1300 > the rail's 1250, covered it
   entirely - Feedback/the language switcher/sign-out became unreachable while chat was open).
   Scoped to --open (not the base rule above) so the --closed state keeps MudBlazor's own
   right: -100% offscreen offset - forcing right here unconditionally would leave the "closed"
   drawer sitting on-screen at this offset instead of off it. */
.sk-chat-drawer.mud-drawer.mud-drawer--open {
    right: var(--sk-rail-width) !important;

    /* The chat has two widths only - half the viewport and full screen. Half a narrow viewport is
       an unusable strip, so floor it, never past the space left of the rail. */
    min-width: min(420px, calc(100vw - var(--sk-rail-width)));
}

/* Inside the drawer the chat must fill the full drawer height so its input row
   stays pinned to the bottom. The shared chat.css sets height: 93dvh for the
   standalone /chat page; that leaves a gap here because the drawer is full-height
   and viewport-anchored, so override it for the drawer context only. */
.sk-chat-drawer .mud-drawer-content,
.sk-chat-drawer .chat-page-container {
    height: 100% !important;
}

/* ============================================================================
   Enhanced-navigation feedback (driven by wwwroot/js/nav-shell.js)

   Enhanced navigation fetches the next page in the background, so a clicked link
   feels unresponsive until the body swaps. These give immediate feedback:
   a top progress bar plus a highlighted, pulsing clicked link.
   ============================================================================ */

/* Top progress bar. It crawls toward 90% while the next page is fetched, then
   jumps to 100% and fades out once enhancedload fires. */
.sk-nav-progress {
    position: fixed;
    top: 0;
    left: 0;
    width: 0;
    height: 3px;
    z-index: 2000;
    opacity: 0;
    background: var(--sk-shell-accent);
    pointer-events: none;
}

.sk-nav-progress--active {
    opacity: 1;
    width: 90%;
    /* Ease that moves fast at first then slows to a crawl, like a real loader. */
    transition: width 8s cubic-bezier(0.1, 0.7, 0.1, 1);
}

.sk-nav-progress--done {
    opacity: 0;
    width: 100%;
    transition: width var(--dtx-motion-base) var(--dtx-motion-easing),
                opacity var(--dtx-motion-slow) var(--dtx-motion-easing) .15s;
}

/* Immediate state for the clicked navigation link while its page loads.
   Prefixed with .app-navigation-drawer so it reliably beats the scoped
   NavMenu .nav-link rules. */
.app-navigation-drawer .nav-link.is-loading {
    color: var(--sk-shell-text);
    background: var(--sk-shell-hover-bg);
}

.app-navigation-drawer .nav-link.is-loading .nav-link__icon {
    color: var(--sk-shell-accent);
    animation: sk-nav-pulse 1s ease-in-out infinite;
}

@keyframes sk-nav-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: .4; }
}

@media (prefers-reduced-motion: reduce) {
    .sk-nav-progress--active {
        transition: width 12s linear;
    }

    .app-navigation-drawer .nav-link.is-loading .nav-link__icon {
        animation: none;
    }
}

a, .btn-link {
    color: var(--dtx-btn-primary-bg);
}

.btn-primary {
    color: var(--dtx-text-on-fill);
    background-color: var(--dtx-btn-primary-bg);
    border-color: var(--dtx-btn-primary-bg);
}

/* :focus-visible, not :focus - tokens.css's governed rule is explicit that a mouse click must not
   leave a ring behind, and these Bootstrap selectors were contradicting it on every click. Reads
   the role token so the ring flips on a dark surface like everything else. */
.btn:focus-visible, .btn-link.nav-link:focus-visible,
.form-control:focus-visible, .form-check-input:focus-visible {
    outline: var(--dtx-focus-ring);
    outline-offset: var(--dtx-focus-ring-offset);
}

/* Deliberate, documented second exception to the governed ring - PRS-5 updated to match (decided
   BA + Architect). Text fields and dropdown selectors already carry their own built-in MudBlazor
   focus styling (a colour-changed underline/border). A first attempt kept the governed ring
   alongside that and only polished its shape (rounded corners + a soft tint) - still read as a
   duplicated, heavy indicator layered on top of a field that already announces its own focus.
   .mud-input-root, not the input/select/textarea tags alone: MudSelect's real focusable element
   (confirmed live via DevTools) is a <div tabindex="0" class="mud-select-input-slot mud-input-root
   ...">, not an <input> - its own backing <input> is type="hidden" and never receives focus at
   all, so a tag-only rule silently never matched it and the ring kept showing there specifically
   on Tab (mouse-click focus on that div doesn't register as :focus-visible in the first place, so
   it looked fine by click alone). .mud-input-root is the class MudBlazor's whole TextField-family
   (MudTextField/MudSelect/MudAutocomplete/...) puts on whichever element is actually focusable,
   input or not, so keying off it instead is robust to that per-component difference. The bare
   input/select/textarea tag rules stay alongside it for plain native form elements that carry no
   MudBlazor class at all.
   Buttons, links and menu items are unaffected - the governed rule above still applies to them
   without exception. Checkboxes and radios are explicitly excluded from this exception (the
   :not() clauses below): a MudCheckbox/MudRadio's actual <input> is visually hidden behind its own
   icon and carries no colour-changed focus styling of its own the way a text field's underline
   does - without the governed ring, keyboard focus on one would be entirely invisible. */
input:not([type="checkbox"]):not([type="radio"]):focus-visible,
select:focus-visible,
textarea:focus-visible,
.mud-input-root:not([type="checkbox"]):not([type="radio"]):focus-visible {
    outline: none !important;
}

.content {
    padding-top: 1.1rem;
}

/* Programmatic a11y focus target on page navigation (Blazor's default
   navigation-announcement pattern) — not a keyboard focus stop, so this does
   not fall under PRS-5's "no surface may suppress the indicator" (a mouse or
   keyboard user never tabs to an <h1>; only Blazor's router focuses it
   programmatically after a route change to announce the new page to screen
   readers).
   !important (bug: white ring on the home hero <h1> after bug 82's fix): the
   governed :focus-visible rule in tokens.css now carries !important so it can
   out-rank MudBlazor's own outline reset, and !important always wins over a
   plain declaration regardless of specificity - without matching !important
   here, that governed rule started beating this exception too, since most
   browsers treat the router's programmatic .focus() call as focus-visible. */
h1:focus {
    outline: none !important;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--dtx-success);
}

.invalid {
    outline: 1px solid var(--dtx-error);
}

.validation-message {
    color: var(--dtx-error);
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, var(--dtx-error);
    padding: 1rem 1rem 1rem 3.7rem;
    color: var(--dtx-text-on-fill);
}

.blazor-error-boundary::after {
    content: "An error has occurred."
}


.custom-tab .mud-tab {
    justify-content: left !important;
}

.flex-grow-2 {
    flex-grow: 2;
}


.mud-tabs.mud-tabs-vertical .mud-tabs-panels {
    width: 100%;
    flex: 1 1 auto;
    display: block;
    overflow-x: auto;
    min-width: 0;
}

.mud-tabs-vertical .mud-tooltip-root,
.mud-tabs-vertical .mud-tabs-tabbar-wrapper > .d-inline-block {
    width: auto;
}

/* Traceability: PRS-1 openspec/specs/presentation/spec.md (Single governed set of visual values)
   Plain layout container, not a single white card wrapping the whole page (mock-up feedback: the
   Figma reference has no such outer card - the title/button/filter sit directly on the page's own
   background, and only the role list and the permissions panel below are their own separate rounded
   cards - see .roles-tab-list/.roles-tab-panel below). */
.roles-shell {
    display: flex;
    flex-direction: column;
    gap: var(--dtx-space-5);
}

.roles-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--dtx-space-6);
}

.roles-title {
    color: var(--dtx-text-heading);
    font-weight: 700;
    letter-spacing: 0;
}

.roles-subtitle {
    color: var(--dtx-text-secondary);
    margin-top: 4px;
}

.roles-tabs {
    --roles-tabbar-width: 420px;
    min-height: 520px;
}

/* The role list, its own rounded card (Figma node 8:1441 "Roles list") - margin-right (not a
   border-right divider, which read as one continuous surface) is what actually separates it from
   the permissions card beside it. */
.roles-tab-list {
    width: var(--roles-tabbar-width);
    min-width: var(--roles-tabbar-width);
    max-width: var(--roles-tabbar-width);
    margin-right: var(--dtx-space-5);
    padding: var(--dtx-space-4);
    background: var(--dtx-surface-card);
    border: var(--dtx-elevation-card-border);
    border-radius: var(--dtx-radius);
}

/* The permissions panel, its own rounded card (Figma node 8:1542 "Role details"). */
.roles-tab-panel {
    padding: var(--dtx-space-6);
    background: var(--dtx-surface-card);
    border: var(--dtx-elevation-card-border);
    border-radius: var(--dtx-radius);
}

.roles-permissions-panel {
    min-height: 480px;
}

.roles-permissions-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--dtx-space-4);
    border-bottom: 1px solid var(--dtx-border-divider);
    padding-bottom: var(--dtx-space-3);
}

/* Bug 87: the Edit role/Save/Cancel/Delete actions (and the role-switch spinner) sit inline with
   the title, right-aligned, on the same row - not on their own row below it (Figma). Wraps rather
   than overflowing on narrow widths, since a long role name plus every action button is a lot for
   one row. */
.roles-permissions-header-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--dtx-space-3);
}

.roles-permissions-title {
    color: var(--dtx-text-heading);
    font-weight: 700;
    letter-spacing: 0;
}

.roles-permissions-subtitle {
    color: var(--dtx-text-secondary);
    margin-top: 2px;
}

.roles-permissions-loading {
    display: inline-flex;
    align-items: center;
    gap: var(--dtx-space-2);
    color: var(--dtx-text-secondary);
    min-height: 32px;
    white-space: nowrap;
}

.permission-matrix-wrapper {
    overflow-x: auto;
}

.permission-matrix {
    width: 100%;
    border-collapse: collapse;
}

.permission-matrix th,
.permission-matrix td {
    border-bottom: 1px solid var(--dtx-border-divider);
    padding: var(--dtx-space-2) var(--dtx-space-3);
    text-align: left;
    white-space: nowrap;
}

.permission-matrix-resource-header,
.permission-matrix-action-header {
    color: var(--dtx-text-secondary);
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
}

.permission-matrix-action-header,
.permission-matrix-cell {
    text-align: center;
}

.permission-matrix-header-control {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.permission-matrix-resource-cell {
    font-weight: 500;
}

.permission-matrix-resource-icon {
    width: 17px;
    height: 17px;
    color: var(--dtx-text-secondary);
    flex-shrink: 0;
}

.permission-matrix-na {
    color: var(--dtx-text-disabled);
}

.permission-matrix-additional {
    display: flex;
    flex-direction: column;
    margin-top: var(--dtx-space-5);
    border-top: 1px solid var(--dtx-border-divider);
    padding-top: var(--dtx-space-3);
}

.permission-matrix-additional-title {
    color: var(--dtx-text-secondary);
    margin-bottom: 4px;
}

/* Two columns (mock-up feedback): the list otherwise ran long enough to force page scrolling. */
.permission-matrix-additional-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--dtx-space-6);
}

@media (max-width: 720px) {
    .permission-matrix-additional-grid {
        grid-template-columns: 1fr;
    }
}

.roles-tab-content {
    display: grid;
    grid-template-columns: 20px minmax(0, 1fr);
    align-items: center;
    column-gap: 10px;
    row-gap: 6px;
    width: 100%;
    min-height: 46px;
    padding: 4px 2px;
    color: var(--dtx-text-heading);
}

.roles-tab-content-global {
    color: var(--dtx-btn-primary-bg);
    font-weight: 700;
}

.roles-tab-name {
    justify-self: start;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.94rem;
}

/* Figma node 8:1455 ("chip"): a light neutral pill (--dtx-surface-sunken), not the dark
   --sk-shell-active-bg this borrowed from the nav drawer's own (dark) surface context - wrong
   context entirely, since this chip sits on the page's light background, not the dark sidebar. */
.roles-tab-badge {
    grid-column: 2;
    justify-self: start;
    border: 1px solid var(--dtx-border-divider);
    border-radius: 999px;
    background: var(--dtx-surface-sunken);
    color: var(--dtx-text-secondary);
    font-size: 0.68rem;
    font-weight: 700;
    line-height: 1;
    padding: 3px 7px;
    text-transform: uppercase;
}

.roles-tab-icon {
    width: 18px;
    height: 18px;
    color: var(--dtx-text-secondary);
    flex-shrink: 0;
}

/* overflow: visible, not hidden (bug 85): MudBlazor's own .mud-ripple class (applied to every tab
   when Ripple - true, the default) sets overflow: hidden on this same element to clip its ripple
   wave to the rounded corners. An element's own outline is clipped by its own overflow, so the
   keyboard focus ring was being cut off at this tab's edges. This selector's specificity (0,2,0)
   already beats .mud-ripple's (0,1,0), so overriding back to visible here is enough - the ripple
   still plays, it just isn't clipped to the rounded corners for the fraction of a second it takes
   to expand past them. */
.roles-tabs .mud-tab {
    width: 100%;
    min-width: 0;
    max-width: none;
    justify-content: stretch !important;
    border-radius: var(--dtx-radius) !important;
    overflow: visible;
}

/* Bug 85, second clipping layer: .mud-tabs-tabbar-content (MudBlazor's own wrapper one level up
   from .mud-tab, sized to the card's content box with zero padding of its own) also carries
   overflow: hidden by default - confirmed live: with only the .mud-tab fix above, the ring was
   still cut off flush at this wrapper's own left edge, because a tab's ring paints 4px outside
   the tab regardless of the tab's own overflow, and this ancestor clips at its own boundary
   before that. Scoped to .roles-tabs only, like every other override in this block. */
.roles-tabs .mud-tabs-tabbar-content {
    overflow: visible;
}

/* Bug 85: with the ring no longer clipped, adjacent vertically-stacked tabs need clearance so a
   focused tab's ring doesn't touch the tab above/below it (or that tab's own .mud-tab-active
   border) - they previously sat flush with zero gap, which was invisible only because the ring
   itself was clipped. --dtx-space-1 (4px) exactly matches the ring's own extent (2px
   outline-width + 2px outline-offset, tokens.css), which is enough to avoid literal overlap but
   not enough to read as separate - the ring and the neighbouring tab's own border are the same
   navy and touch with no visible card background between them, reading as one merged line.
   --dtx-space-2 (8px) leaves 4px of visible card background as a clear gap. */
.roles-tabs .mud-tabs-tabbar-wrapper.mud-tabs-vertical {
    gap: var(--dtx-space-2);
}

.roles-tabs .mud-tabs-tabbar {
    flex: 0 0 var(--roles-tabbar-width);
    width: var(--roles-tabbar-width);
    min-width: var(--roles-tabbar-width);
    max-width: var(--roles-tabbar-width);
}

.roles-tabs .mud-tabs-tabbar-wrapper,
.roles-tabs .mud-tabs-tabbar-content,
.roles-tabs .mud-tabs-toolbar,
.roles-tabs .mud-tabs-toolbar-content {
    width: 100%;
}

.roles-tabs .mud-tooltip-root,
.roles-tabs .mud-tabs-tabbar-wrapper .d-inline-block {
    display: block !important;
    width: 100% !important;
}

.roles-tabs .mud-tab .mud-tab-content {
    width: 100%;
    justify-content: flex-start;
    text-align: left;
}

.roles-tabs .mud-tab:hover {
    background: var(--dtx-surface-sunken);
    border-radius: var(--dtx-radius) !important;
}

/* Figma node 8:1445 ("Role item / sel"): a light blue tint plus a matching 1px border, not the
   plain grey hover-tint tile this used to share with :hover (mock-up feedback). */
.roles-tabs .mud-tab.mud-tab-active {
    background: color-mix(in srgb, var(--dtx-btn-primary-bg) 8%, var(--dtx-surface-card));
    border: 1px solid var(--dtx-btn-primary-bg);
    border-radius: var(--dtx-radius) !important;
}

.roles-tabs .mud-tab.mud-tab-active .roles-tab-content,
.roles-tabs .mud-tab.mud-tab-active .roles-tab-name {
    color: var(--dtx-text-heading);
}

.roles-tabs .mud-tab.mud-tab-active .roles-tab-icon {
    color: var(--dtx-btn-primary-bg);
}

.roles-tabs .mud-tab.mud-tab-active .roles-tab-content-global {
    color: var(--dtx-btn-primary-bg-pressed);
}

.roles-tabs .mud-tab-slider {
    display: none;
}

@media (max-width: 960px) {
    .roles-header {
        flex-direction: column;
        align-items: stretch;
    }

    .roles-tab-list {
        width: var(--roles-tabbar-width);
        min-width: var(--roles-tabbar-width);
        margin-right: 0;
        margin-bottom: var(--dtx-space-4);
    }

    .roles-tab-panel {
        padding: var(--dtx-space-4);
    }

    .roles-permissions-header {
        flex-direction: column;
    }
}

/* Traceability: ACC-34 openspec/specs/access/spec.md (Impersonate screen) */
.sk-impersonation-banner {
    position: sticky;
    top: 0;
    z-index: 1300;
}

.sk-impersonation-banner__alert {
    border-radius: 0;
    justify-content: center;
    text-align: center;
}
