/* Layout & Utility */
.full-width {
    width: 100%;
}

/* Validation */
.validation-message {
    color: #f44336;
    font-size: .8rem;
    margin: 3px 0 0;
    text-align: start;
    font-weight: 400;
    line-height: 1.66;
    letter-spacing: .03333em;
}

/* MudBlazor Components */
.mud-snackbar-location-bottom-left {
    bottom: 50px !important;
}

.mud-snackbar-location-bottom-right {
    bottom: 50px !important;
}

.mud-progress-linear {
    margin: 0 !important;
}

/* External Login Buttons */
.external-login {
    display: flex;
    align-items: center;
    margin-top: 5px;
    margin-bottom: 5px;
    height: 40px;
    padding: 0 16px;
    font-size: 16px;
    text-decoration: none;
    border-radius: 4px;
    color: #fff;
    transition: background-color 0.3s;
}

.external-login-icon {
    background-repeat: no-repeat;
    background-size: contain;
    width: 35px;
    height: 35px;
    margin-right: 8px;
}

.microsoft-external-login {
    background-color: #2F2F2F;
}

.microsoft-external-login-icon {
    background-image: url('../assets/icons/external-auth/auth-microsoft.png');
}

.google-external-login {
    background-color: #4285F4;
}

.google-external-login-icon {
    background-image: url('../assets/icons/external-auth/auth-google.png');
}

.twitter-external-login {
    background-color: #1DA1F2;
}

.twitter-external-login-icon {
    background-image: url('../assets/icons/external-auth/auth-twitter.png');
}

.linkedin-external-login {
    background-color: #0A66C2;
}

.linkedin-external-login-icon {
    background-image: url('../assets/icons/external-auth/auth-linkedin.png');
}

.facebook-external-login {
    background-color: #1877F2;
}

.facebook-external-login-icon {
    background-image: url('../assets/icons/external-auth/auth-facebook.png');
}

/* Header right-hand controls (dark mode, language, login, announcement toggle) */
.header-right-controls {
    display: flex;
    align-items: center;
    margin-left: 8px;
    flex: 0 0 auto;
}

/* Announcement notice strip — single full-width row below the app bar, above the
   breadcrumb toolbar. Theme-aware via Mud palette vars so it reads correctly in light
   and dark; severity is carried by the icon + chip (colour + label), never the strip fill. */
.announcement-strip {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 40px;
    padding: 2px 8px 2px 4px;
    background-color: var(--mud-palette-surface);
    border-bottom: 1px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-primary);
    overflow: hidden;
}

.announcement-strip__nav,
.announcement-strip__dismiss,
.announcement-strip__details,
.announcement-strip__severity-icon,
.announcement-strip__chip {
    flex: 0 0 auto;
}

.announcement-strip__title {
    flex: 0 0 auto;
    font-weight: 600;
    letter-spacing: 0.2px;
    white-space: nowrap;
}

.announcement-strip__message {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.86rem;
    opacity: 0.85;
}

.announcement-strip__meta {
    flex: 0 0 auto;
    white-space: nowrap;
    font-size: 0.75rem;
    opacity: 0.7;
}

.announcement-strip__dismiss {
    margin-left: 2px;
}

/* Meta (schedule) is secondary — drop it before the message truncates on narrow viewports;
   it remains available in the "View details" dialog. */
@media (max-width: 959px) {
    .announcement-strip__meta {
        display: none;
    }
}

/* Announcement details dialog */
.announcement-details__chips {
    display: flex;
    gap: 8px;
    margin-bottom: 12px;
}

.announcement-details__schedule {
    opacity: 0.7;
}

/* Sticky footer — WHY this override exists:
   MudBlazor's .mud-layout is not a flex container, so .mud-main-content collapses to
   its content height. On a short page the meta footer then floats mid-screen instead of
   sitting at the bottom of the viewport. Making main-content a full-viewport-height
   column + margin-top:auto on the footer is the classic sticky-footer fix.
   The app bar is position:fixed (it does not consume layout height), so 100dvh is the
   correct target — do NOT subtract app-bar height. dvh (not vh) so the mobile browser
   URL bar collapsing does not produce a phantom scrollbar. */
.mud-main-content {
    display: flex;
    flex-direction: column;
    min-height: 100dvh;
}

/* Layout Meta Footer */
.layout-meta-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin: 14px 0 8px;
    margin-top: auto; /* sticky footer — absorbs the free space in .mud-main-content's column */
    /* The 14px top gap from the margin shorthand is overridden by margin-top:auto above,
       so it is re-expressed as top padding (14 + 8) to keep the footer off the last
       content row on long/scrolling pages. */
    padding: 22px 12px 8px;
    font-size: 0.75rem;
    letter-spacing: 0.2px;
    /* Theme-aware: the previous hardcoded rgba(255,255,255,.68) was invisible in light
       mode. MudBlazor re-computes this token per theme, so the footer stays legible in
       both without a prefers-color-scheme fork. */
    color: var(--mud-palette-text-secondary);
}

.layout-meta-footer__separator {
    opacity: 0.5;
}

/* Footer links stay quiet/muted — inherit the footer's muted colour, underline on hover only. */
.layout-meta-footer__link,
.layout-meta-footer__link:hover,
.layout-meta-footer__link:focus {
    color: inherit;
    text-decoration: none;
}

.layout-meta-footer__link:hover {
    text-decoration: underline;
}

/* ── CAPA shared presentation ───────────────────────────────────────────────
   Single source for CAPA surface styling so the register / hub / worklist don't
   inline color or font-size (UX spec §6.7 colour-isn't-the-only-signal, §6.9 AA;
   replaces the repeated inline font-size smell flagged in Triage). */
.capa-overdue {
    display: inline-flex;
    align-items: center;
    color: var(--mud-palette-error);
    font-weight: 600;
}

/* My CAPA Actions worklist — tablet-first card row; subtle lift signals it's tappable. */
.capa-action-card {
    transition: box-shadow 0.15s ease-in-out;
}

/* ── CAPA Advanced entitlement states (SOL-158) ──────────────────────────────
   Two distinct treatments, deliberately NOT one shared style:

   .capa-entitlement-hint is a REFUSAL surface (the RCA method picker, the node
   dialog). It explains why an option isn't there and carries no tier, price, or
   upsell language — the commercial boundary must not leak onto a refusal.

   .capa-upsell is the honest empty state on the compliance dashboard, which Rod
   ratified as the one place tier naming belongs. Muted on purpose: it stands in
   for a data panel and must never out-shout the real figures beside it. */
.capa-entitlement-hint,
.capa-upsell__body {
    color: var(--mud-palette-text-secondary);
}

/* NB: MudBlazor 9.1 emits --mud-palette-background-gray (American spelling), NOT -grey.
   Verified against staticwebassets/MudBlazor.min.css in the installed package. */
.capa-upsell {
    background-color: var(--mud-palette-background-gray);
    border-style: dashed;
}

/* ── Design-system shared presentation (DMS remediation §C) ──────────────────
   Cosmetic-only classes for the shared design-system components + the DMS
   surfaces adopting them, so no surface inlines style="..." (UX-F17 smell lift).
   The .ds- prefix marks design-system-owned styling; .dms- marks DMS-page styling. */

/* LoadStateView panels — constrains the no-leak / retry / empty copy width so the
   regulated-surface message reads as a centred block, not a full-bleed paragraph. */
.ds-loadstate-detail {
    max-width: 420px;
}

/* DMS Edit/Add — the classification-row chrome that was inlined as
   style="border:1px solid var(--mud-palette-divider);border-radius:4px;" ×2. */
.dms-level-row {
    border: 1px solid var(--mud-palette-divider);
    border-radius: 4px;
}

/* DMS PDF viewer — the full-height flex column + framed iframe, lifted off the
   page-level inline style="height: calc(...)" / style="flex: 1 1 auto; ..." smells. */
.dms-viewer-container {
    height: calc(100vh - 140px);
    display: flex;
    flex-direction: column;
}

.dms-viewer-frame {
    flex: 1 1 auto;
    width: 100%;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
}

.capa-action-card:hover {
    box-shadow: var(--mud-elevation-4);
}

/* ── QR label print (G-2 / AssetQrDialog) ────────────────────────────────────
   The .qr-label-print div is always rendered but off-screen in normal view.
   During @media print we use visibility (not display) so the rule cascades to
   child elements inside the MudBlazor dialog portal — visibility:visible CAN
   override a parent's visibility:hidden; display:none on a parent cannot be
   overridden by a child. The fixed position anchors the label to the top-left
   corner of the print page, independent of the portal's scroll context. */
.qr-label-print {
    position: fixed;
    top: -9999px;
    left: -9999px;
    visibility: hidden;
}

@media print {
    body * {
        visibility: hidden;
    }

    .qr-label-print,
    .qr-label-print * {
        visibility: visible;
    }

    .qr-label-print {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        background: white;
        padding: 24px;
        box-sizing: border-box;
    }
}

/* SOL-19 (R-9): ComplianceDashboard drill-through affordances. A drillable KPI card / summary row reads as
   clickable (pointer + lift + a chevron that brightens on hover) without inline-style smells. Keyboard focus
   is visible for accessibility (the elements carry role="button" + tabindex="0"). */
.cv-drill-card {
    cursor: pointer;
    transition: box-shadow 120ms ease, transform 120ms ease;
}

.cv-drill-card:hover {
    /* SOL-123: Fluent hover — border emphasis + a subtle lift, not the Material elevation-6 bounce. */
    box-shadow: var(--mud-elevation-2);
    border-color: var(--mud-palette-primary);
}

.cv-drill-row {
    cursor: pointer;
    border-radius: var(--mud-default-borderradius);
    transition: background-color 120ms ease;
}

.cv-drill-row:hover {
    background-color: var(--mud-palette-action-default-hover);
}

.cv-drill-card:focus-visible,
.cv-drill-row:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.cv-drill-chevron {
    opacity: 0.5;
    transition: opacity 120ms ease;
    vertical-align: middle;
}

.cv-drill-card:hover .cv-drill-chevron,
.cv-drill-row:hover .cv-drill-chevron {
    opacity: 1;
}

/* ── Signals shared presentation ─────────────────────────────────────────────
   Single source for Signals title/body typography so the feed card and the
   article (detail) view read as the same publication. Root cause of the
   reported font mismatch: the feed card hand-rolled its title weight/line-height
   inline (font-weight:600;line-height:1.3) while the article rendered its body
   through a `.ql-editor`/`.signal-body` div that had NO rule anywhere in the
   served stylesheets (fonts.css / MudBlazor.min.css / app.css) — the editor
   Quill CSS this class name implies is not loaded, so the body fell back to the
   bare default cascade. The two surfaces therefore diverged in family-inheritance
   and weight. These classes give both an explicit, intentional baseline tied to
   the Mud theme typography (Roboto) and lift the inline-style smells. */

/* Article body — the canonical reference. Explicitly inherits the Mud theme
   font instead of relying on the undefined .ql-editor class, and gives the raw
   MarkupString HTML readable body sizing/leading. */
.signal-body {
    font-family: var(--mud-typography-body1-family, var(--mud-typography-default-family));
    font-size: 1rem;
    line-height: 1.6;
    color: var(--mud-palette-text-primary);
}

.signal-body p {
    margin-block: 0 1em;
}

.signal-body p:last-child {
    margin-block-end: 0;
}

/* Signal Body WYSIWYG editor (SOL-22) — Quill snow theme host. As of SOL-22 the Quill
   `snow` stylesheet IS loaded (lib/quill/quill.snow.css, referenced in index.html), so the
   `.ql-editor` class the read-side comment above referred to is now defined. This wrapper just
   gives the editing surface a usable authoring height and aligns its rounded border with the
   Mud Outlined inputs around it on the Content tab. */
.signal-body-editor .ql-container {
    min-height: 220px;
    font-family: var(--mud-typography-body1-family, var(--mud-typography-default-family));
    font-size: 1rem;
    border-bottom-left-radius: var(--mud-default-borderradius);
    border-bottom-right-radius: var(--mud-default-borderradius);
}

.signal-body-editor .ql-toolbar {
    border-top-left-radius: var(--mud-default-borderradius);
    border-top-right-radius: var(--mud-default-borderradius);
}

/* Body validation (SOL-23) — when the Body fails required/max-length, tint the editor chrome
   error-red to match the inline error message, mirroring how a MudTextField shows an error border. */
.signal-body-editor--error .ql-toolbar,
.signal-body-editor--error .ql-container {
    border-color: var(--mud-palette-error);
}

/* Editor footer row: inline error on the left, live character counter on the right. Matches the
   spacing/size of MudBlazor's own helper-text + counter row so the Quill field reads like a Mud input. */
.signal-body-footer {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-top: 4px;
    min-height: 1.25rem;
}

.signal-body-error {
    color: var(--mud-palette-error);
}

.signal-body-counter {
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    margin-left: auto;
}

.signal-body-counter--error {
    color: var(--mud-palette-error);
    font-weight: 500;
}

/* Feed card — same family/weight vocabulary as the article, just scaled for the
   card. Title weight + leading now match the article's heading treatment rather
   than an ad-hoc inline 600. */
.signal-card__title {
    font-weight: 500;
    line-height: 1.3;
}

/* 2-line excerpt clamp, lifted off the inline -webkit-box style smell. */
.signal-card__excerpt {
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

/* Muted card metadata — excerpt, published date, view count + icon.
   Previously these used Color="Color.Secondary", which resolves to the MudBlazor
   Secondary brand-accent slot. Our theme never sets Secondary, so it fell back to
   the built-in default magenta (#ff4081) and painted all body/meta text pink.
   Bind explicitly to the muted secondary-text token instead. (SOL-27/SOL-29) */
.signal-card__meta,
.signal-card__meta .mud-icon-root {
    color: var(--mud-palette-text-secondary);
}

/* ── Signals accessibility (SOL-29) ──────────────────────────────────────────
   Feed cards used to be a <div> with @onclick: not focusable, not announced,
   no Enter/Space. The card surface is now a native <button> (Enter+Space
   activate natively, announced as "button"), reset to look like the bare card
   and given a visible keyboard focus ring. Mouse users still get no outline via
   :focus-visible. */
.signal-card-button {
    appearance: none;
    -webkit-appearance: none;
    background: none;
    border: none;
    margin: 0;
    padding: 0;
    width: 100%;
    display: block;
    text-align: left;
    font: inherit;
    color: inherit;
    cursor: pointer;
    border-radius: var(--mud-default-borderradius, 4px);
}

.signal-card-button:focus-visible {
    outline: 3px solid var(--mud-palette-primary, #594ae2);
    outline-offset: 2px;
}

/* Type filter rail: stack radios one-per-line so short labels ("Safety",
   "Event") stop wrapping two-to-a-row and reading as an accidental grid. */
.signal-type-filter .mud-radio {
    display: flex;
    margin-right: 0;
}

/* Category/type chips: 11px white-on-anything was too small and failed AA on
   light colors. Bump to a readable 12px minimum (foreground contrast is derived
   in SignalChipColors). The hairline border delineates pale chips from the white
   card surface. */
.signal-chip.mud-chip {
    height: 22px;
    font-size: 12px;
    border: 1px solid rgba(0, 0, 0, 0.12);
}

/* ── Account / sign-in shell (login redesign) ────────────────────────────────
   A two-pane sign-in experience shared by every Identity/Account page. A brand
   hero pane (decorative, generic, hidden below md) sits beside the form pane, so
   Login and the simpler account pages (Register, ForgotPassword, 2FA, reset, …)
   all render their form in one clean, centred Fluent card. Theme-aware via Mud
   palette vars: the brand gradient derives from the primary accent token — never
   a hardcoded brand hex — so it reads correctly in both light and dark modes. */
.account-shell {
    display: flex;
    min-height: 100vh;
    width: 100%;
}

/* Brand hero pane — decorative and generic across all account pages. */
.account-brand {
    position: relative;
    flex: 1 1 46%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 32px;
    padding: 56px 56px 40px;
    overflow: hidden;
    color: #fff;
    background: linear-gradient(160deg, var(--mud-palette-primary) 0%, var(--mud-palette-primary-darken) 100%);
}

/* Contrast floor + soft corner highlight, so white text clears AA over the
   accent in both palettes (the dark-mode primary is a lighter blue). */
.account-brand::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(120% 90% at 100% 0%, rgba(255, 255, 255, 0.16), transparent 55%),
        linear-gradient(180deg, rgba(0, 0, 0, 0.06), rgba(0, 0, 0, 0.30));
    pointer-events: none;
}

.account-brand > * {
    position: relative;
    z-index: 1;
}

.account-brand__logo {
    display: flex;
    align-items: center;
    gap: 14px;
}

.account-brand__logo img {
    filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.25));
}

.account-brand__wordmark {
    font-size: 26px;
    font-weight: 300;
    letter-spacing: 0.4rem;
    user-select: none;
}

.account-brand__headline {
    margin: 0 0 16px;
    font-size: clamp(1.9rem, 2.4vw, 2.6rem);
    font-weight: 600;
    line-height: 1.15;
    max-width: 16ch;
}

.account-brand__tagline {
    margin: 0;
    font-size: 1.02rem;
    line-height: 1.6;
    max-width: 46ch;
    opacity: 0.9;
}

.account-brand__features {
    list-style: none;
    margin: 28px 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.account-brand__features li {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 0.98rem;
    opacity: 0.95;
}

.account-brand__features .mud-icon-root {
    color: #fff;
    opacity: 0.9;
}

.account-brand__footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: 0.78rem;
    letter-spacing: 0.2px;
    opacity: 0.7;
}

.account-brand__footer-sep {
    opacity: 0.5;
}

.account-brand__footer-link,
.account-brand__footer-link:hover,
.account-brand__footer-link:focus {
    color: inherit;
    text-decoration: none;
}

.account-brand__footer-link:hover {
    text-decoration: underline;
}

/* About page — 'on this page' anchor nav row. */
.about-toc {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}

/* Form pane — holds the account page body in a centred card. */
.account-form {
    flex: 1 1 54%;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background-color: var(--mud-palette-background);
}

.account-form__topbar {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 12px 20px;
}

.account-form__brand-compact {
    display: none;
    align-items: center;
}

.account-form__body {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px 24px 56px;
}

.account-card {
    width: 100%;
    max-width: 420px;
    background-color: var(--mud-palette-surface);
}

/* Login (and other account pages) header block. */
.account-card__header {
    margin-bottom: 28px;
}

.account-card__title {
    font-weight: 600;
    margin-bottom: 4px;
}

/* Right-aligned "forgot password" aux row under the password field. */
.account-card__aux {
    display: flex;
    justify-content: flex-end;
    margin: 6px 0 20px;
}

/* "or" separator between the primary CTA and the secondary links. */
.account-card__divider {
    display: flex;
    align-items: center;
    margin: 20px 0 16px;
}

/* Container the commented-out external-login buttons will eventually live in;
   transparent so an empty container leaves no visible card while OFF (D-D). */
.account-card__external {
    background: transparent;
}

/* Below md the brand pane collapses and the compact logo appears in the form
   top bar, so mobile/tablet users still see the mark. */
@media (max-width: 959.98px) {
    .account-brand {
        display: none;
    }

    .account-form__brand-compact {
        display: flex;
    }
}