/* Let FluentUI handle ALL theming - remove custom background/color overrides */
body {
  margin: 0;
  padding: 0;
  font-family: "Roboto", sans-serif;
  background-color: var(--neutral-fill-layer-rest);
  color: var(--neutral-foreground-rest);
}

/* Skip-to-content link (WCAG 2.4.1 Bypass Blocks). Visually hidden until it
   receives keyboard focus, then pinned to the top-left so a keyboard/AT user can
   jump past the ~15-item left nav to #main-content on every page. */
.skip-to-content {
  position: absolute;
  left: 8px;
  top: -48px;
  z-index: 1000;
  padding: 8px 16px;
  border-radius: 4px;
  background-color: var(--accent-fill-rest);
  color: var(--neutral-fill-rest, #fff);
  text-decoration: none;
  font-weight: 600;
  transition: top 0.15s ease-in-out;
}

.skip-to-content:focus,
.skip-to-content:focus-visible {
  top: 8px;
  outline: 2px solid var(--neutral-foreground-rest);
  outline-offset: 2px;
}

/* FocusOnNavigate (Routes.razor, Selector="h1") programmatically focuses the
   page <h1> after every navigation so screen readers announce the new page.
   Chromium then paints its default focus ring around the heading, which reads
   as a stray box for sighted users. A :not(:focus-visible) guard does NOT
   suppress it — Chromium classifies script-driven focus on a tabindex=-1
   heading as :focus-visible. The heading carries a negative tabindex so it is
   never reachable by keyboard Tab, which makes dropping the ring unconditionally
   safe for keyboard users. */
h1:focus {
  outline: none;
  box-shadow: none;
}

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

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

/* Validation message styling - ensure error messages are visible */
.validation-message {
  color: var(--error-color, #d13438);
  font-size: 0.875rem;
  margin-top: 4px;
  display: block;
}

/* FluentValidationSummary styling */
fluent-message-bar[intent="error"] ul {
  margin: 0;
  padding-left: 20px;
}

  fluent-message-bar[intent="error"] ul li {
    color: var(--error-color, #d13438);
  }

/* Loading States CSS - Standardized loading indicators across all Blazor components */
.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
  gap: 16px;
  min-height: 200px;
  color: var(--neutral-foreground-rest);
  background-color: var(--neutral-fill-layer-rest);
  border-radius: var(--control-corner-radius);
}

  .loading-container fluent-progress-ring {
    /* Accent color is inherited from FluentDesignTheme - no override needed */
  }

  .loading-container fluent-label {
    color: var(--neutral-foreground-hint);
    text-align: center;
    font-weight: 400;
  }

  /* Loading container variants for different contexts */
  .loading-container.compact {
    padding: 24px 16px;
    min-height: 120px;
    gap: 12px;
  }

  .loading-container.inline {
    padding: 16px;
    min-height: 80px;
    gap: 8px;
    flex-direction: row;
  }

    .loading-container.inline fluent-label {
      margin-left: 8px;
    }

/* Error message styling consistency */
fluent-message-bar[intent="error"] {
  margin: 16px 0;
  border-radius: var(--control-corner-radius);
}

/* Animation for progress ring consistency */
.loading-container fluent-progress-ring {
  animation: loading-pulse 2s ease-in-out infinite;
}

@keyframes loading-pulse {
  0%, 100% {
    opacity: 1;
  }

  50% {
    opacity: 0.7;
  }
}

/* EntraUserPicker dropdown - must be global because fluent-anchored-region
   renders as a popover outside the component DOM tree, so scoped ::deep CSS
   cannot reach it. */
.entra-user-picker-container fluent-anchored-region {
  z-index: 10000 !important;
}

.entra-user-picker-container fluent-anchored-region fluent-listbox {
  max-height: min(24rem, 50vh);
  overflow-y: auto;
}

/* Responsive loading container */
@media (max-width: 768px) {
  .loading-container {
    padding: 32px 16px;
    min-height: 160px;
  }

    .loading-container.compact {
      padding: 16px 12px;
      min-height: 100px;
    }
}

/* Snapshot display field styling — labels bold, values normal weight */
.info-field {
    margin-bottom: 4px;
}

.info-label {
    font-weight: 600;
    margin-right: 6px;
}

.info-value {
    font-weight: 400;
}


/* Spacing — margin scale (1=4px, 2=8px, 3=12px, 4=16px) */
.bt-mr-1     { margin-right: 4px; }
.bt-mr-15    { margin-right: 6px; }
.bt-mr-2     { margin-right: 8px; }
.bt-mb-1     { margin-bottom: 4px; }
.bt-mb-2     { margin-bottom: 8px; }
.bt-mb-3     { margin-bottom: 12px; }
.bt-mb-4     { margin-bottom: 16px; }
.bt-mb-1rem  { margin-bottom: 1rem; }
.bt-mt-1     { margin-top: 4px; }
.bt-mt-2     { margin-top: 8px; }
.bt-mt-3     { margin-top: 12px; }
.bt-mt-4     { margin-top: 16px; }
.bt-mt-1rem  { margin-top: 1rem; }
.bt-ml-2     { margin-left: 8px; }
.bt-ml-3     { margin-left: 12px; }
.bt-m-0      { margin: 0; }

/* Spacing — padding scale */
.bt-p-1      { padding: 8px; }
.bt-p-2      { padding: 16px; }
.bt-p-4      { padding: 32px; }
.bt-p-6      { padding: 48px; }
.bt-p-1rem   { padding: 1rem; }
.bt-p-15rem  { padding: 1.5rem; }
.bt-p-2rem   { padding: 2rem; }

/* Layout helpers */
.bt-flex-1         { flex: 1; }
.bt-flex-wrap      { flex-wrap: wrap; }
.bt-cursor-pointer { cursor: pointer; }
.bt-cursor-help    { cursor: help; }


/* Typography */
.bt-typo-xs       { font-size: 0.75rem; }
.bt-typo-sm       { font-size: 12px; }
.bt-typo-13       { font-size: 13px; }
.bt-typo-085rem   { font-size: 0.85rem; }
.bt-typo-0875rem  { font-size: 0.875rem; }

.bt-fw-medium    { font-weight: 500; }
.bt-fw-semibold  { font-weight: 600; }
.bt-fw-bold      { font-weight: bold; }

/* Width utilities — used in place of inline Style="width: X%" (magic-string elimination) */
.w-100 { width: 100%; }


/* =====================================================================
   Uniform full-width FluentUI layout
   =====================================================================
   Without these rules, <FluentTabs> on tab-driven admin pages collapses
   to content width — leaving 30-40% empty space on the right side of
   the page. Adding the rules globally (instead of per-page CSS isolation
   files) means new tab pages render at full width by default, no opt-in
   needed. Use the `bt-page-fluid` utility on the page's root container
   to also stretch FluentCard / FluentStack to fill the page.

   Discovered: PR #5232 (admin/users-enhanced) + #5234 (admin/vendor-
   management) — same fix applied to two pages with custom CSS isolation.
   Promoted to global so future pages inherit the fix automatically. */

fluent-tabs,
fluent-tab-panel {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
}

.bt-page-fluid {
    width: 100%;
    max-width: 100%;
}

.bt-page-fluid fluent-card,
.bt-page-fluid fluent-stack {
    width: 100%;
    max-width: 100%;
}


/* =====================================================================
   Mobile: turn the admin user grids (.data-grid-enhanced) into stacked
   cards (#5642)
   =====================================================================
   On phones the wide FluentDataGrid (Users → Employee / Applicant /
   Contractor / Unassigned tabs) overflowed sideways and truncated every
   column ("Not spec…", "BAN : M…"). Below 768px we restructure each
   light-DOM row into a bordered card: cells stack vertically, the first
   cell (name) is emphasised, and the header row is hidden.

   CSS-only and scoped to .data-grid-enhanced, so desktop is untouched and
   the C# build is unaffected. !important overrides the web component's
   inline grid-template-columns / grid-column. NOTE: the Applicant/Employee
   grids use Virtualize, so on mobile the scrollbar height may be slightly
   off (rows still flow normally — no overlap); verify on-device. Per-field
   labels in the cards are a follow-up. */
@media (max-width: 768px) {
    /* Hide the column-header row(s) in card mode */
    .data-grid-enhanced fluent-data-grid-row[row-type="header"],
    .data-grid-enhanced fluent-data-grid-row[row-type="sticky-header"] {
        display: none !important;
    }

    /* Each data row becomes a card */
    .data-grid-enhanced fluent-data-grid-row {
        display: flex !important;
        flex-direction: column !important;
        grid-template-columns: none !important;
        align-items: stretch;
        gap: 2px;
        height: auto !important;
        min-height: 0 !important;
        padding: 10px 12px;
        margin-bottom: 8px;
        border: 1px solid var(--neutral-stroke-rest, #d1d1d1);
        border-radius: 8px;
        background: var(--neutral-layer-1, transparent);
    }

    /* Cells stack full-width, no table borders/fixed heights */
    .data-grid-enhanced fluent-data-grid-cell {
        grid-column: unset !important;
        width: 100% !important;
        height: auto !important;
        min-height: 0 !important;
        border: none !important;
        padding: 2px 0 !important;
        white-space: normal !important;
        overflow-wrap: anywhere;
    }

    /* First cell = the person's name: make it the card title */
    .data-grid-enhanced fluent-data-grid-cell:first-child {
        font-weight: 600;
        font-size: 1rem;
        padding-bottom: 4px !important;
    }
}

/* =====================================================================
   Desktop: stop FluentDataGrid column HEADERS truncating (#6119)
   =====================================================================
   FluentDataGrid lays columns out as equal `1fr` tracks unless a grid
   explicitly sets GridTemplateColumns — and only 26 of the app's 95 grids
   do. On a 10-column admin grid that leaves ~88px per column, so the
   header labels were clipped mid-word across the app: "Depart..",
   "Requis..", "Appli…", "Comp…", "St…" (Job Postings, Users, Vendor
   Management, Reporting).

   The cheapest correct fix is to let header text WRAP rather than clip.
   Forcing per-column min-widths instead would push every wide grid into
   horizontal scrolling, which trades one readability problem for another
   and would need per-grid tuning across 95 call sites.

   Scoped to >=769px so the mobile card-mode block above (which hides the
   header row entirely) is untouched. */
@media (min-width: 769px) {
    .data-grid-enhanced fluent-data-grid-row[row-type="header"],
    .data-grid-enhanced fluent-data-grid-row[row-type="sticky-header"] {
        /* Let the row grow to fit two lines of wrapped header text. */
        height: auto;
        min-height: 44px;
        align-items: stretch;
    }

    .data-grid-enhanced fluent-data-grid-row[row-type="header"] fluent-data-grid-cell,
    .data-grid-enhanced fluent-data-grid-row[row-type="sticky-header"] fluent-data-grid-cell {
        white-space: normal;
        overflow: visible;
        text-overflow: clip;
        overflow-wrap: break-word;
        line-height: 1.2;
        height: auto;
        display: flex;
        align-items: center;
    }
}

/* ── FluentDataGrid skeleton rows ─────────────────────────────────────────────
   The progressive grid pattern: while a grid loads, render the REAL grid (so column
   headers + toolbar paint instantly) bound to placeholder rows tagged .bt-skeleton-row
   via RowClass. This rule hides each placeholder cell's content and draws an animated
   shimmer bar in its place — no per-column markup needed. See docs/loading-standard.md. */
.bt-skeleton-row [role="gridcell"],
.bt-skeleton-row td,
.bt-skeleton-row fluent-data-grid-cell {
    position: relative;
}

.bt-skeleton-row [role="gridcell"] > *,
.bt-skeleton-row td > *,
.bt-skeleton-row fluent-data-grid-cell > * {
    visibility: hidden !important;
}

.bt-skeleton-row [role="gridcell"]::after,
.bt-skeleton-row td::after,
.bt-skeleton-row fluent-data-grid-cell::after {
    content: "";
    position: absolute;
    left: 12px;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    height: 12px;
    border-radius: 4px;
    background: linear-gradient(
        90deg,
        var(--neutral-fill-secondary-rest, rgba(128, 128, 128, 0.12)) 25%,
        color-mix(in srgb, var(--neutral-foreground-rest, gray) 16%, var(--neutral-fill-secondary-rest, rgba(128, 128, 128, 0.12))) 50%,
        var(--neutral-fill-secondary-rest, rgba(128, 128, 128, 0.12)) 75%
    );
    background-size: 200% 100%;
    animation: bt-skeleton-row-shimmer 1.4s ease-in-out infinite;
}

@keyframes bt-skeleton-row-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}


/* ── FluentSkeleton shimmer visibility ───────────────────────────────────────
   The shimmer skeletons (TabHostSkeleton, NavigationLoadingRegion, dashboard
   sections) animate a moving highlight band via `animation: shimmer 2s infinite`,
   so the animation is always running. But FluentSkeleton's default highlight
   (--skeleton-animation-gradient-default) is a neutral that sits almost on top of
   the skeleton fill under this app's teal light/dark themes, so the wave is nearly
   invisible and the skeleton reads as static.

   Override the gradient with a foreground-derived highlight so the wave is visible
   in both themes. CSS custom properties cross the shadow-DOM boundary, so this
   reaches the web component's internal `.shimmer` span. color-mix is evergreen-only;
   if unsupported the whole value is invalid and FluentUI's default is used (no
   regression). Tune the 22% / opacity if the sweep is too strong or too subtle. */
fluent-skeleton[shimmer] {
    --skeleton-animation-gradient: linear-gradient(
        270deg,
        transparent 0%,
        color-mix(in srgb, var(--neutral-foreground-rest, gray) 22%, transparent) 50%,
        transparent 100%
    );
}



/* ── New Hire enrollment printable packet (#5834 / epic #5770) ────────────────
   The Review & Submit step of the unified New Hire Enrollment Portal assembles
   every completed onboarding document into a printable packet. Printing is scoped
   WITHOUT knowing the app-chrome selectors: while printing, everything is hidden
   and only the element carrying `.bt-print-target` (either the whole packet or a
   single document card) is made visible. The Review step toggles
   `body.bt-printing-newhire` for the duration of window.print() only, so no other
   page or state is ever affected. Colours are forced to print-white/black so the
   packet is legible regardless of the viewer's light/dark app theme. */
@media print {
    body.bt-printing-newhire * {
        visibility: hidden !important;
    }

    body.bt-printing-newhire .bt-print-target,
    body.bt-printing-newhire .bt-print-target * {
        visibility: visible !important;
    }

    body.bt-printing-newhire .bt-print-target {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        background: #ffffff !important;
        color: #000000 !important;
    }

    /* Screen-only affordances (Print / expand buttons, badges) never print. */
    body.bt-printing-newhire .bt-no-print {
        display: none !important;
    }

    /* In the full-packet print each document starts on its own page. */
    body.bt-printing-newhire .bt-newhire-packet.bt-print-target .bt-packet-doc {
        page-break-after: always;
        break-after: page;
    }

    body.bt-printing-newhire .bt-newhire-packet.bt-print-target .bt-packet-doc:last-child {
        page-break-after: auto;
        break-after: auto;
    }
}

/* A read-only onboarding document rendered inside the Review packet. The `inert`
   attribute already blocks all interaction; this only signals it visually. */
.bt-newhire-readonly-form {
    cursor: default;
}


/* =====================================================================
   Mobile responsive app shell (#6020)
   =====================================================================
   The desktop layout pins a persistent 250px icon nav-rail to the left and
   reserves 88px on the right for the floating NotificationBell. On a phone that
   ate ~25% of the width and shoved content into a narrow, horizontally-
   overflowing strip. Below 768px (the established mobile breakpoint — same as the
   .data-grid-enhanced card-mode block above) we convert the rail into an
   off-canvas drawer, add a fixed top app bar with a hamburger, and let content go
   full width.

   EVERYTHING here is gated behind `@media (max-width: 768px)` (plus the two
   always-on `display:none` primers just below). Desktop (≥769px) renders exactly
   as before: the app bar + backdrop are hidden, and `.nav-sidebar` /
   `.content-container` / `.content` keep the sticky-rail styling defined in the
   layout's scoped CSS. Open/close is Blazor state on MobileNavShell (the `tt-open`
   marker class); these rules react to it via :has() (already used elsewhere in
   this codebase, e.g. the NotificationBell panel-slide). */

/* The shared shell wrapper never creates a box — it only carries the `tt-open`
   marker class the :has() rules below key off. Kept live on every viewport so the
   selector resolves; its children (app bar + backdrop) are what get hidden. */
.tt-mobile-nav-shell { display: contents; }

/* Mobile-only chrome — hidden by default so desktop is untouched. */
.tt-mobile-appbar { display: none; }
.tt-nav-backdrop { display: none; }

@media (max-width: 768px) {
    /* ── Fixed top app bar (~56px): hamburger + brand ──────────────────────── */
    .tt-mobile-appbar {
        display: flex;
        align-items: center;
        gap: 8px;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        height: 56px;
        padding: 0 8px;
        /* Reserve room on the right for the floating NotificationBell, which is
           repositioned into this bar (see NotificationBell.razor.css). */
        padding-right: 60px;
        background: var(--neutral-layer-1, var(--neutral-fill-layer-rest));
        border-bottom: 1px solid var(--neutral-stroke-divider-rest, rgba(0, 0, 0, 0.12));
        z-index: 100;
        box-sizing: border-box;
    }

    .tt-hamburger {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        /* ≥44px touch target */
        min-width: 44px;
        min-height: 44px;
        padding: 0;
        border: none;
        background: transparent;
        color: var(--neutral-foreground-rest);
        cursor: pointer;
        border-radius: 6px;
        -webkit-tap-highlight-color: transparent;
    }

    .tt-hamburger:hover {
        background: var(--neutral-fill-secondary-rest, rgba(0, 0, 0, 0.06));
    }

    .tt-hamburger:focus-visible {
        outline: 2px solid var(--accent-fill-rest, #008080);
        outline-offset: 2px;
    }

    .tt-mobile-brand {
        font-weight: 600;
        font-size: 1.05rem;
        color: var(--neutral-foreground-rest);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* ── Off-canvas nav drawer (the existing .nav-sidebar) ─────────────────── */
    .nav-sidebar {
        position: fixed !important;
        left: 0;
        top: 0;
        height: 100dvh !important;
        width: min(84vw, 300px) !important;
        max-width: 84vw;
        transform: translateX(-100%) !important;
        transition: transform 0.25s ease;
        z-index: 1001;
        box-shadow: 2px 0 16px rgba(0, 0, 0, 0.25);
        background: var(--neutral-layer-1, var(--neutral-fill-layer-rest));
        overflow-y: auto;
        overflow-x: hidden;
    }

    /* Open state (Blazor toggles .tt-open on the shell) slides the drawer in. */
    body:has(.tt-mobile-nav-shell.tt-open) .nav-sidebar {
        transform: translateX(0) !important;
    }

    /* Inside the drawer always show the EXPANDED menu (labels), never the 40px
       icon rail — override FluentNavMenu's inline collapsed width / hidden labels
       that left-menu.js may have applied from a desktop "collapsed" preference. */
    .nav-sidebar #main-menu {
        width: 100% !important;
        min-width: 0 !important;
        max-width: none !important;
    }

    .nav-sidebar #main-menu .fluent-nav-text {
        display: inline-block !important;
        visibility: visible !important;
        opacity: 1 !important;
    }

    /* The app-bar hamburger is the single drawer toggle on mobile — hide
       FluentNavMenu's own collapse expander so there aren't two toggles. */
    .nav-sidebar #main-menu .expander,
    .nav-sidebar #main-menu-expander {
        display: none !important;
    }

    /* ── Tap-to-close backdrop ─────────────────────────────────────────────── */
    body:has(.tt-mobile-nav-shell.tt-open) .tt-nav-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.45);
        z-index: 1000;
    }

    /* ── Full-width content, offset below the app bar, no bell reservation ──── */
    /* The 56px app-bar offset applies only when the bar is present (authenticated
       users — the app bar is AuthorizeView-gated). data-auth is stamped on <body>
       by App.razor. */
    body[data-auth="authenticated"] .content {
        padding-top: calc(56px + clamp(0.5rem, 2vw, 1rem)) !important;
    }

    .content {
        /* Drop the 88px NotificationBell reservation — the bell now lives in the
           app bar, not floating over content. */
        padding-right: clamp(0.5rem, 2vw, 1rem) !important;
        padding-left: clamp(0.5rem, 2vw, 1rem) !important;
        max-width: 100%;
        overflow-x: hidden;
    }

    /* Lock content scroll while the drawer is open so touch-scroll doesn't bleed
       through the backdrop to the page behind it. */
    body:has(.tt-mobile-nav-shell.tt-open) .content-container {
        overflow: hidden !important;
    }

    /* ── Overflow-prone widgets scroll within THEMSELVES, never the body ────── */
    /* Hard guarantee against page-level horizontal scroll: .content-container
       already clips overflow-x. These rules let wide content stay usable (scroll
       inside its own box) instead of being clipped. */
    fluent-tabs::part(tablist) {
        overflow-x: auto;
        max-width: 100%;
    }

    .content table {
        display: block;
        overflow-x: auto;
        max-width: 100%;
    }

    /* Wide FluentDataGrids that DON'T collapse into card mode (their content is
       still wider than the phone) get their own horizontal scrollbar so the extra
       columns stay reachable instead of being clipped by the page's overflow-x
       guard. No-op when the .data-grid-enhanced card-mode rules above stack the
       rows full-width (nothing overflows to scroll). overflow-y is pinned to
       visible so this can't accidentally flip into a second vertical scroll
       container over the grid's own (virtualized) row scroller. */
    fluent-data-grid {
        overflow-x: auto;
        overflow-y: visible;
        max-width: 100%;
    }

    .content img,
    .content pre,
    .content video {
        max-width: 100%;
    }

    .content fluent-card {
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
    }
}


/* =====================================================================
   Phone-first employee self-service content polish (#6022)
   =====================================================================
   Builds ON TOP of the #6020 shell (which owns nav + full-width content +
   no-body-overflow). This section makes the employee-facing FORM content
   genuinely phone-first: single-column, full-width inputs and comfortable
   ≥44px touch targets. Everything is additive and gated behind the same
   768px breakpoint, so desktop (≥769px) is byte-for-byte unchanged.
   It does NOT touch any #6020 rule above. */
@media (max-width: 768px) {
    /* Full-width, single-column form controls. Most employee forms already
       stamp `w-100` on each field, but this guarantees it everywhere inside
       page content (e.g. inline flex rows collapse to one column) so no field
       ever forces a sideways scroll. */
    .content fluent-text-field,
    .content fluent-number-field,
    .content fluent-select,
    .content fluent-date-picker,
    .content fluent-text-area,
    .content fluent-search {
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
    }

    /* Comfortable tap targets: bump every button's control to the 44px
       minimum touch height recommended for phones (matches the app-bar
       hamburger from #6020). Width is left to the button so icon-only and
       inline buttons keep their shape. */
    .content fluent-button::part(control) {
        min-height: 44px;
    }
}

/* =====================================================================
   Mobile: applicant / careers flow phone-first polish (#6021)
   =====================================================================
   Content-level phone-first tuning for the external-candidate surface
   (public job listings, the job-detail apply dialog, the apply wizard, and
   My Applications). The #6020 shell already gives these pages full-width
   content + drawer nav and clips page-level horizontal scroll; THIS layer
   makes the CONTENT itself thumb-friendly (bigger tap targets, stacked
   inputs, full-width CTAs). Every rule is class-scoped and gated behind the
   shared 768px breakpoint, so desktop (≥769px) is untouched.

   Opt-in utility classes (added to specific FluentButtons in the flow):
     .bt-tap-lg     — grows a FluentButton's tap target to ≥44px on touch
     .bt-cta-mobile — a primary CTA that spans the full column + ≥44px on touch
   The FluentUI web components expose their inner button/input as
   ::part(control), so sizing targets that part (the host only carries the
   class). */
@media (max-width: 768px) {
    /* Bigger tap targets for the flow's key buttons (opt-in via class). */
    .bt-tap-lg::part(control) {
        min-height: 44px;
    }

    /* Primary CTAs that should span the full column on a phone. */
    .bt-cta-mobile,
    .bt-cta-mobile::part(control) {
        width: 100%;
    }

    .bt-cta-mobile::part(control) {
        min-height: 44px;
    }

    /* Apply dialog — the unauthenticated "email → apply" row stacks vertically
       and goes full width so the field + Apply button never overflow the
       ~90vw dialog on a phone. */
    .bt-apply-email-row {
        flex-direction: column !important;
        align-items: stretch !important;
    }

    .bt-apply-email-row .bt-apply-email-field,
    .bt-apply-email-row .bt-apply-email-field::part(control) {
        width: 100% !important;
        min-width: 0 !important;
    }

    .bt-apply-email-row .bt-apply-email-btn,
    .bt-apply-email-row .bt-apply-email-btn::part(control) {
        width: 100%;
        min-height: 44px;
    }
}

/* =====================================================================
   Radzen HtmlEditor — sync with FluentUI light/dark theme
   =====================================================================
   The Job Description editor on the Edit Job Posting screen
   (JobManagement/JobPostingEditor.razor) is a RadzenHtmlEditor. Radzen is
   themed globally by <RadzenTheme Theme="material" /> in App.razor, which is
   pinned to the LIGHT "material" palette. In the app's DARK FluentUI theme
   that left the editor's content surface white while the editable text
   inherited the app's light foreground — white-on-white and unreadable.

   Fix is CSS-only and needs no dark-mode selector: re-point the editor's own
   --rz-editor-* custom properties (the exact variables Radzen's own
   stylesheet consumes for every surface) at FluentUI design tokens. FluentUI
   sets those tokens on the document and flips them automatically between
   light and dark, so the editor now tracks the app theme. Scoping the
   variables on .rz-html-editor (an ancestor of every editor surface)
   overrides the :root defaults from Radzen's material.css for this component
   only. The content/toolbar surfaces are keyed to --neutral-layer-1 to match
   the surrounding FluentCards; text to --neutral-foreground-rest. Every token
   below is one FluentUI 4.13.x actually defines; fallbacks mirror the ones
   already used elsewhere in this file. (The RadzenHtmlEditorLink dialog is a
   separate Radzen modal portaled to <body>; it stays on the material palette
   but renders dark-on-light and is legible.) */
.rz-html-editor {
    /* Outer border + internal toolbar/separator dividers. */
    --rz-editor-border: 1px solid var(--neutral-stroke-rest, #d1d1d1);
    --rz-editor-separator-background-color: var(--neutral-stroke-divider-rest, rgba(128, 128, 128, 0.3));

    /* Content (contenteditable) + HTML-source surfaces match the cards. */
    --rz-editor-content-background-color: var(--neutral-layer-1, var(--neutral-fill-layer-rest));

    /* Toolbar surface + its buttons. */
    --rz-editor-toolbar-background-color: var(--neutral-layer-1, var(--neutral-fill-layer-rest));
    --rz-editor-button-background-color: var(--neutral-layer-1, var(--neutral-fill-layer-rest));
    --rz-editor-button-color: var(--neutral-foreground-rest);
    --rz-editor-button-disabled-color: var(--neutral-foreground-hint);
    --rz-editor-button-selected-background-color: var(--neutral-fill-secondary-rest, rgba(128, 128, 128, 0.2));
    --rz-editor-button-selected-color: var(--neutral-foreground-rest);

    /* In-editor dropdown popups (Font Size / Format Block). These panels live
       inside the editor DOM, so scoping the --rz-dropdown-* vars here keeps
       them legible instead of light-panel + light-text in dark mode. */
    --rz-dropdown-open-background-color: var(--neutral-layer-floating, var(--neutral-layer-1));
    --rz-dropdown-panel-border: 1px solid var(--neutral-stroke-rest, #d1d1d1);
    --rz-dropdown-item-hover-background-color: var(--neutral-fill-secondary-rest, rgba(128, 128, 128, 0.2));
    --rz-dropdown-item-hover-color: var(--neutral-foreground-rest);
    --rz-dropdown-item-selected-background-color: var(--neutral-fill-secondary-rest, rgba(128, 128, 128, 0.2));
    --rz-dropdown-item-selected-color: var(--neutral-foreground-rest);

    /* Radzen leaves the editable text color to inherit; the app's light dark-
       mode foreground was the light half of the white-on-white bug. Pin it. */
    color: var(--neutral-foreground-rest);
}

/* Make the inherited foreground explicit on the contenteditable body, the
   HTML-source textarea, and dropdown items so typed/pasted content with no
   inline color and the placeholder stay legible on the themed surface. */
.rz-html-editor .rz-html-editor-content,
.rz-html-editor .rz-html-editor-source,
.rz-html-editor .rz-html-editor-dropdown-item {
    color: var(--neutral-foreground-rest);
}

/* =====================================================================
   Disabled-control affordance (UI-audit G5)
   =====================================================================
   FluentUI's disabled state only lowers opacity via its design tokens; on
   this app's saturated teal accent (#008080) a disabled Accent button still
   reads as "teal = clickable", making Export/Send/Refresh buttons
   indistinguishable from enabled ones. Desaturating the whole control makes
   disabled unmistakably gray while leaving every enabled state (hover,
   pressed, focus-visible, loading) untouched. Applies app-wide — do not
   patch individual buttons instead. */
fluent-button[disabled],
fluent-button[aria-disabled="true"],
fluent-anchor[aria-disabled="true"] {
    filter: grayscale(0.95);
    opacity: 0.55;
    cursor: not-allowed;
}

/* Forced-colors (high-contrast) mode already renders disabled controls with
   the GrayText system color — the filter would fight it. */
@media (forced-colors: active) {
    fluent-button[disabled],
    fluent-button[aria-disabled="true"],
    fluent-anchor[aria-disabled="true"] {
        filter: none;
        opacity: 1;
    }
}

/* =====================================================================
   Portaled-dialog styles (must be GLOBAL)
   =====================================================================
   FluentUI's FluentDialog portals its content to a <fluent-dialog> provider
   at the app root, OUTSIDE the authoring component's scope. Component-scoped
   [b-xxxx] rules therefore never reach dialog content, so any styling for
   markup rendered inside a dialog has to live here, un-scoped. */

/* Reason-picker rows (ReasonPickerDialog). Clean single-line interactive
   rows: fixed icon | flexible label | chevron. Full row is the click target. */
.tt-reason-row {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    box-sizing: border-box;
    min-height: 54px;
    padding: 8px 14px;
    border: 1px solid var(--neutral-stroke-rest);
    border-radius: 8px;
    background: var(--neutral-layer-1);
    cursor: pointer;
    transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
    -webkit-appearance: none;
    appearance: none;
    text-align: left;
    color: var(--neutral-foreground-rest);
}

.tt-reason-row:hover {
    border-color: var(--accent-fill-rest);
    background: var(--neutral-layer-2);
    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.08);
}

.tt-reason-row:active {
    background: var(--neutral-layer-3);
    box-shadow: none;
}

.tt-reason-row:focus-visible {
    outline: 2px solid var(--accent-fill-rest);
    outline-offset: 2px;
    border-color: var(--accent-fill-rest);
}

.tt-reason-row__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    min-width: 36px;
    border-radius: 8px;
    background: var(--neutral-layer-3);
}

.tt-reason-row__label {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.95rem;
    font-weight: 500;
    line-height: 1.3;
}

.tt-reason-row__arrow {
    display: flex;
    align-items: center;
    opacity: 0.55;
    transition: opacity 0.15s ease, transform 0.15s ease;
}

.tt-reason-row:hover .tt-reason-row__arrow {
    opacity: 1;
    transform: translateX(2px);
}

/* Accent, on-brand focus ring for custom-clickable dialog elements that would
   otherwise show Chromium's black default outline. Covers the reason rows (via
   the rule above), the dialog header edit affordance, and the Lightweight
   "Show/Hide account numbers" toggle in the bank-account wizard. */
.tt-focus-accent:focus-visible,
.tt-reason-header:focus-visible {
    outline: 2px solid var(--accent-fill-rest);
    outline-offset: 2px;
    border-radius: 6px;
}

/* …but pointer/programmatic focus (:focus without :focus-visible) on those same
   elements must NOT fall back to Chromium's black default box — only keyboard
   focus shows the accent ring above. */
.tt-focus-accent:focus:not(:focus-visible) {
    outline: none;
}

/* The dialog header (and its title label) is programmatically focused when the
   dialog opens (negative-tabindex a11y pattern). That draws Chromium's black
   default box. Suppress it on the header container, its title, and any
   programmatically-focused (non-:focus-visible) descendant — keyboard
   :focus-visible on the actual interactive rows/buttons is handled above and is
   untouched. */
.tt-reason-header:focus,
.tt-reason-header *:focus:not(:focus-visible) {
    outline: none;
}

/* On open, FluentUI's dialog auto-focuses a STRUCTURAL, classless/roleless <div>
   wrapper it renders around the header (confirmed via DOM probe: the focused
   element is `div` with no class/role and a 1px rgb(16,16,16) outline). That's
   what drew the black box around the reason-picker title. Such a div is never an
   interactive control, so suppress its focus ring. Real controls — the reason
   rows (.tt-reason-row, role="button") and the wizard buttons — carry a class
   and/or role, so they are excluded here and keep their :focus-visible accent
   ring from the rules above. */
div:focus:not([class]):not([role]),
div:focus-visible:not([class]):not([role]) {
    outline: none;
}
