html, body {
    height: 100%;
}

app {
    display: block;
    height: 100%;
}

.header-logo {
    flex-shrink: 0;
    background-color: currentColor;
    -webkit-mask: url('../images/Logo.svg');
    mask: url('../images/Logo.svg');
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    width: 100px;
    height: 24px;
}

#blazor-error-ui {
    background: inherit;
    bottom: 0;
    display: none;
    position: fixed;
    width: 100%;
    height: 100%;
    z-index: 100001;
}

.info-card {
    position: relative;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: 0.5rem;
    padding: 1rem;
}

.info-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* Fixed header height so every card lines up across the strip. Button cards (Patient/Prescriber/Drug)
       get a 36px header driven by the DxButton, while button-less cards (Case Status, PBM / Pharmacy) get a
       taller ~40px title-only header. That 4px difference left the button cards' content — and, because the
       column is a flex column, the whole card body — sitting 4px lower, so the top borders read as
       misaligned. Pinning a single 40px header height equalizes every card body, so all tops (and first data
       rows) line up. */
    height: 2.5rem;
    margin-bottom: 0.75rem;
}

.info-card-title {
    font-size: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    /* Keep the title on one line so it fits the fixed-height header (no wrap/clip on narrower cards). */
    white-space: nowrap;
}

/* The left side of the header: the title plus any TitleContent (e.g. Case Status indicators) sitting right
   next to it. The header itself is space-between, so this group stays left while HeaderContent (the Edit
   button) sits at the right. The gap only shows when there is TitleContent. */
.info-card-title-group {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.info-card-grid {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: 0.5rem;
    row-gap: 0.5rem;
    height: 12.5rem;
    overflow-y: auto;
    padding-right: 0.5rem;
    /* Keep the rows at their natural spacing pinned to the top. Without this, when the card is taller than
       its content (e.g. the splitter dragged far down, or a short card like Case Status), the grid's default
       align-content spreads the rows to fill the height and the line spacing visibly stretches. */
    align-content: start;
}

.info-card-grid > div {
    display: grid;
    grid-template-columns: subgrid;
    grid-column: 1 / -1;
    align-items: baseline;
}

.info-card-label {
    font-size: 0.875rem;
    font-weight: 600;
    white-space: nowrap;
}

.info-card-label::after {
    content: ":";
}

.info-card-value {
    color: var(--bs-body-color);
    font-size: 1rem;
    line-height: 1.4;
    min-height: 1.4rem;
}

.info-card-address {
    white-space: pre-line;
}

/* PatientInformationCard "Edit Patient" popup: stacked rows of fields, each field a label above its editor. */
.info-card-edit-form {
    display: flex;
    flex-direction: column;
    row-gap: 0.75rem;
}

.info-card-edit-row {
    display: flex;
    column-gap: 0.75rem;
}

.info-card-edit-field {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    /* Let fields shrink so the editors never overflow the row. */
    min-width: 0;
    row-gap: 0.25rem;
}

.info-card-edit-label {
    font-size: 0.875rem;
    font-weight: 600;
}

.info-card-edit-form .dxbl-text-edit,
.info-card-edit-form .dxbl-date-edit {
    width: 100%;
}

@media (max-width: 767.98px) {
    .info-card-grid {
        grid-template-columns: 1fr;
    }
}

.review-document-drop-zone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1.5rem;
    margin-bottom: 0.5rem;
    border: 2px dashed var(--bs-border-color, #adb5bd);
    border-radius: 0.5rem;
    color: var(--bs-secondary-color, #6c757d);
    text-align: center;
    cursor: pointer;
    transition: border-color 0.15s ease-in-out, background-color 0.15s ease-in-out;
}

.review-document-drop-zone-icon {
    font-size: 1.75rem;
}

.review-document-drop-zone-dragover {
    border-style: solid;
    border-color: var(--bs-primary, #0d6efd);
    background-color: var(--bs-primary-bg-subtle, rgba(13, 110, 253, 0.08));
    color: var(--bs-primary, #0d6efd);
}

/* Read-only plain-text editor (StaticTextPropertyEditor): normal, legible body text instead of the
   muted/gray read-only input style. Used by the "record is locked" dialog message. */
.static-text-editor {
    color: var(--bs-body-color);
    white-space: pre-wrap;
    line-height: 1.4;
    padding-top: 0.25rem;
}

/* ===== Read-only form editors: normal-contrast text + read-only indicator (system-wide) =====
   Non-editable XAF Property Editors render as *disabled* (.dxbl-disabled + input[disabled]); the
   theme then paints their text with --dxbl-text-edit-disabled-color (#a8a9a8 — a low-contrast gray
   that is hard to read). XAF already unsets the disabled *opacity*, so only the text color needs
   changing. We repoint that color at --dxbl-body-color, i.e. the same text color an editable field
   uses (theme-aware: dark in light themes, light in dark themes).

   Because the text is now full-contrast, a left accent bar marks a field as read-only. It is drawn
   with an inset box-shadow (not border-left) so the field's rounded corners are preserved, and uses
   the brand purple #5f368d rather than red to avoid clashing with DevExpress's red validation
   styling. No theme exposes a usable accent CSS variable on the editor, so the color is fixed.

   Scoped to a form-layout control cell's direct editor (".dxbl-fl-ctrl > ...") so it covers detail-
   form fields everywhere — text edits, combo boxes / dropdowns, date-time edits, spin edits — while
   leaving disabled toolbar/ribbon editors (and the Rich Text editor's own toolbar) in their native
   muted style. The Rich Text editor itself is not a .dxbl-text-edit, so it is unaffected. */
.dxbl-fl-ctrl > .dxbl-text-edit.dxbl-disabled {
    --dxbl-text-edit-disabled-color: var(--dxbl-body-color);
    box-shadow: inset 3px 0 0 0 #5f368d;
}

/* Hide the now-non-functional editor buttons (spin up/down, date-picker, dropdown) on read-only
   fields; the input (flex-grow: 1) then fills the freed width. Editable fields keep their buttons
   because they are not .dxbl-disabled, and toolbar/ribbon editors are excluded by the .dxbl-fl-ctrl >
   scope. .dxbl-spin-btns is listed separately because the spin button group does not carry the
   generic .dxbl-btn-group class. */
.dxbl-fl-ctrl > .dxbl-text-edit.dxbl-disabled .dxbl-btn-group,
.dxbl-fl-ctrl > .dxbl-text-edit.dxbl-disabled .dxbl-spin-btns {
    display: none;
}

/* ===== Letter (ReviewLetter) detail popup =====
   Scoped to this view via the .letter-detail-root marker (CustomCSSClassName on the layout root) matched
   on the XAF popup with :has(). The markers are set in Model.xafml (ReviewLetter_DetailView layout). */

/* Make the letter popup fill the full viewport (it is otherwise a fixed-width, centered 800px dialog). */
.xafPopup:has(.letter-detail-root) {
    height: 100vh !important;
    max-height: 100vh !important;
    width: 100vw !important;
    max-width: 100vw !important;
    left: 0 !important;
    margin: 0 !important;
}

/* Left column: fixed width. Right column: grows to fill the remaining width. */
.letter-fields-col {
    flex: 0 0 250px !important;
    max-width: 250px !important;
}

.letter-data-col {
    flex: 1 1 auto !important;
    min-width: 0 !important;
}

/* Grow the Letter Data rich text editor to fill the tall popup (leaves room for the header, footer,
   field label and the collapsed Change History bar). */
.letter-data-col .xaf-richedit {
    min-height: calc(100vh - 15rem) !important;
}

/* LETTER-CHECKBOX-CLIP — inline pictures (the request forms' checkboxes) shown whole in every rich text editor.
   The DevExpress Blazor RichEdit draws an inline picture in a span placed a pixel or two above its row
   (a negative top: -1.2 px and -2.5 px on the forms) inside div.dxreRow, which clips with overflow: hidden — so each
   checkbox lost its top edge. Rows holding an inline picture, at any depth (a hyperlink or underline on the picture
   wraps it in extra spans), still clip, but only 4 px outside their box: enough for that offset, while a picture taller
   than an exact line height stays clipped as before rather than painting over the rows above it. A browser without
   overflow-clip-margin (older Safari) clips at the box edge, as it did before. The document (and the fax PDF made
   from it) is unchanged. */
.dxreRow:has(img.dxrePic) {
    overflow: clip;
    overflow-clip-margin: 4px;
}

/* The "Send" action (ReviewLetterSendController, below the Edit Letter button) uses the DevExpress
   "Actions_Send" image — a blue paper plane. On the blue Primary button that is blue-on-blue and nearly
   invisible, so recolor it to a solid white silhouette: brightness(0) flattens the glyph to black, invert(1)
   turns that white, and alpha is preserved — yielding a clean white paper plane. Scoped by the icon's src,
   so only the Send button is affected. */
.xaf-toolbar-item-icon[src*="Actions_Send"] {
    filter: brightness(0) invert(1);
}

/* ===== Incoming Fax (IncomingFax) detail — DRAFT, modeled on the ReviewLetter popup layout =====
   Fields stacked in a fixed-width column on the left, the received fax PDF filling the right and the rest of
   the view. Markers set in Model.xafml (IncomingFax_DetailView layout): fax-detail-root / fax-body-row /
   fax-fields-col / fax-data-col. Like the letter, the fax detail opens as a modal popup (IncomingFax is
   [ModalDetailView]) that is sized to the full viewport below — these rules make the body a full-height
   two-column row and stretch the PDF to fill. */

/* Full-screen the fax popup (IncomingFax is [ModalDetailView], so it opens as a centered dialog); mirrors the
   .xafPopup:has(.letter-detail-root) rule above. */
.xafPopup:has(.fax-detail-root) {
    height: 100vh !important;
    max-height: 100vh !important;
    width: 100vw !important;
    max-width: 100vw !important;
    left: 0 !important;
    margin: 0 !important;
}

/* Stretch the view root and the body row to the full height of the popup so the right PDF column can fill. */
.fax-detail-root,
.fax-detail-root > .dxbl-fl,
.fax-detail-root .dxbl-fl-group-items {
    height: 100%;
}

.fax-body-row {
    height: 100%;
    align-items: stretch !important;
}

/* Left column: fixed width. Right column: grows to fill the remaining width. */
.fax-fields-col {
    flex: 0 0 320px !important;
    max-width: 320px !important;
}

/* Right column: give it a DEFINITE height (the full-screen popup minus its title bar + footer) rather than a
   flex/min-height chain. The DevExpress PDF viewer sizes itself to height:100% of its container, and height:100%
   resolves to nothing when the container's own height is indefinite — so the viewer collapsed. A concrete
   calc(100vh - …) height gives it something to fill. */
.fax-data-col {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    height: calc(100vh - 9rem) !important;
    display: flex !important;
    flex-direction: column !important;
}

/* Force the XAF layout-item / control-cell wrappers between the column and the viewer to fill that height, so
   the viewer has a definite parent height to fill. Descendant selectors (not '>') so this holds whether the
   fax-data-col marker lands on the layout item itself or a wrapper around it. */
.fax-data-col .dxbl-fl-item,
.fax-data-col .dxbl-fl-ctrl {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}

.fax-data-col .dxbl-fl-ctrl > *,
.fax-data-col .dxbl-pdf-viewer {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
}

/* ===== Clinical Review Criteria Version detail — fields left, source PDF right =====
   Same two-column-with-PDF shape as the Incoming Fax popup above. The version is [FullScreenModalDetailView],
   so FullScreenModalController already sizes the popup to the viewport (no .xafPopup:has() rule needed here —
   that is the only difference from the fax block). These rules make the body a full-height two-column row and
   stretch the PDF viewer to fill. Markers set in Model.xafml (ClinicalReviewCriteriaVersion_DetailView layout):
   crc-version-detail-root / crc-version-body-row / crc-version-fields-col / crc-version-data-col. */

/* Stretch the view root and the body row to the full height of the popup so the right PDF column can fill. */
.crc-version-detail-root,
.crc-version-detail-root > .dxbl-fl,
.crc-version-detail-root .dxbl-fl-group-items {
    height: 100%;
}

.crc-version-body-row {
    height: 100%;
    align-items: stretch !important;
}

/* Left column: fixed width. Right column: grows to fill the remaining width. */
.crc-version-fields-col {
    flex: 0 0 320px !important;
    max-width: 320px !important;
}

/* Right column: give it a DEFINITE height (the full-screen popup minus its title bar + footer) rather than a
   flex/min-height chain — the DevExpress PDF viewer sizes to height:100% of its container, which resolves to
   nothing when the container's own height is indefinite. Same fix as .fax-data-col. */
.crc-version-data-col {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    height: calc(100vh - 9rem) !important;
    display: flex !important;
    flex-direction: column !important;
}

/* Force the XAF layout-item / control-cell wrappers between the column and the viewer to fill that height, so
   the viewer has a definite parent height to fill. */
.crc-version-data-col .dxbl-fl-item,
.crc-version-data-col .dxbl-fl-ctrl {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}

.crc-version-data-col .dxbl-fl-ctrl > *,
.crc-version-data-col .dxbl-pdf-viewer {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
}

/* ===== Letter Template detail — fields left, DOCX Rich Text editor right =====
   Same two-column shape as the Criteria Version popup above, but the right column holds the Rich Text editor
   (the inherited Template) instead of a PDF viewer. LetterTemplate is [FullScreenModalDetailView], so
   FullScreenModalController already sizes the popup to the viewport (no .xafPopup:has() rule needed). These rules
   make the body a full-height two-column row and stretch the editor to fill. Markers set in Model.xafml
   (LetterTemplate_DetailView layout): lettertemplate-detail-root / -body-row / -fields-col / -data-col. */

/* Stretch the view root and the body row to the full height of the popup so the right editor column can fill. */
.lettertemplate-detail-root,
.lettertemplate-detail-root > .dxbl-fl,
.lettertemplate-detail-root .dxbl-fl-group-items {
    height: 100%;
}

.lettertemplate-body-row {
    height: 100%;
    align-items: stretch !important;
}

/* Left column: fixed width. Right column: grows to fill the remaining width. */
.lettertemplate-fields-col {
    flex: 0 0 320px !important;
    max-width: 320px !important;
}

/* Right column: give it a DEFINITE height (the full-screen popup minus its title bar + footer) rather than a
   flex/min-height chain — the DevExpress Rich Text editor sizes to height:100% of its container, which resolves
   to nothing when the container's own height is indefinite. Same fix as .crc-version-data-col / .fax-data-col. */
.lettertemplate-data-col {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    height: calc(100vh - 9rem) !important;
    display: flex !important;
    flex-direction: column !important;
}

/* Force the XAF layout-item / control-cell wrappers between the column and the editor to fill that height, so
   the editor has a definite parent height to fill. */
.lettertemplate-data-col .dxbl-fl-item,
.lettertemplate-data-col .dxbl-fl-ctrl {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}

.lettertemplate-data-col .dxbl-fl-ctrl > *,
.lettertemplate-data-col .xaf-richedit {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
}

/* ===== Review Call (ReviewCall) detail popup — two modes =====
   NEW calls ("+ Out" / the grid's New action) are logged live while staff are on the phone, so that form must
   NOT block the Review behind it: it becomes a docked, click-through panel in the lower-right corner. EXISTING
   calls (opened from the timeline or a grid row) are just being read back, so they stay a standard centered
   modal. XAF shows both as the same modal popup (TargetWindow.NewModalWindow + [ModalDetailView]) and exposes
   no "modeless popup" switch, so the docked variant is done purely in CSS.
   Two markers, both matched with :has() (the same idiom as the letter popup above):
   - .reviewcall-detail-root — the view itself (CustomCSSClassName on the layout root, set in Model.xafml);
     scopes the rules shared by both modes (hidden title bar, popup width).
   - .reviewcall-docked — emitted by ReviewCallHeaderCard.razor only when the popup opened for a NEW call
     (latched at first render so a Save that keeps the popup open can't recenter it); scopes the dock rules.

   Three pieces make the docked variant behave like a panel rather than a modal:
   1. DevExpress renders a backdrop (.dxbl-modal-back — a fixed, full-viewport div, rgba(0,0,0,.4),
      pointer-events auto) that both dims the page and swallows every click. Neutralize it (transparent +
      pointer-events:none) so the Review stays bright and clickable. Scoped through the .dxbl-modal wrapper
      that contains our marker, so only THIS popup's backdrop is touched — the account / theme-settings
      popups keep theirs.
   2. The overlay layers above the page (.dxbl-modal-root, .dxbl-popup-cell — both fixed, full-viewport) get
      pointer-events:none so clicks fall through to the Review; the card itself re-enables pointer-events.
   3. The card (.xafPopup) is pinned to the bottom-right corner as a fixed-width box (NOT the full-width bottom
      bar it used to be), with a thick, high-contrast accent outline so it reads as a distinct floating panel
      over the case. The form's native two-column layout fits the ~600px width; nothing in the Review reflows,
      and the body scrolls if a tall case (e.g. the Other Name field for an "Other" recipient) exceeds the cap. */
.dxbl-modal:has(.reviewcall-docked) .dxbl-modal-back {
    background: transparent !important;
    pointer-events: none !important;
}

.dxbl-modal-root:has(.reviewcall-docked),
.dxbl-popup-cell:has(.reviewcall-docked) {
    pointer-events: none !important;
}

.dxbl-modal-root:has(.reviewcall-docked) .xafPopup {
    pointer-events: auto !important;
    position: fixed !important;
    left: auto !important;
    right: 24px !important;
    bottom: 24px !important;
    top: auto !important;
    width: 600px !important;
    max-width: 92vw !important;
    height: auto !important;
    max-height: 80vh !important;
    min-height: 0 !important;
    margin: 0 !important;
    transform: none !important;
    border-radius: 10px !important;
    /* Very visible box outline: a thick accent border plus a contrasting ring and a deep drop shadow. */
    border: 4px solid var(--dxbl-btn-primary-bg) !important;
    box-shadow: 0 0 0 2px #ffffff, 0 12px 32px rgba(0, 0, 0, 0.45) !important;
}

.dxbl-modal-root:has(.reviewcall-docked) .xafPopup > .dxbl-modal-content {
    max-height: 80vh !important;
}

/* Centered variant (existing call): the standard modal keeps its backdrop and centering; just narrow it from
   XAF's default ~800px to the ~600px the call form's two-column layout was designed for (matching the docked
   panel and the note / timeline-item popups below). */
.xafPopup:has(.reviewcall-detail-root):not(:has(.reviewcall-docked)) {
    width: 600px !important;
    max-width: 90vw !important;
}

/* Hide the popup's own title bar (the "Review Call / Outgoing Call" caption and the close "X"). The panel's
   heading is the ReviewCallHeaderCard inside the form (Direction + Call Date), and the footer's Save / Cancel
   close it — so the window chrome is redundant. Scoped to this popup via the .reviewcall-detail-root marker. */
.xafPopup:has(.reviewcall-detail-root) .dxbl-popup-header {
    display: none !important;
}

/* Review detail popup header: the "Case {number}" caption only repeats the case number the Timeline card
   header now shows, and its ~72px bar is dead vertical space. Lift the whole header out of flow (absolute,
   top-right) so the form body slides up to reclaim the space, and hide just the caption — while KEEPING the
   close "X" floating in the corner. The header's native flex layout is left intact (only the caption is
   removed and the button is pushed to the right) so the tool button keeps its size; switching the header to
   a block layout collapses the button to 0×0. Scoped via the .review-detail-root marker (CustomCSSClassName
   on the layout root); the modal content is position:relative, so the absolute header anchors to it. */
.xafPopup:has(.review-detail-root) .dxbl-popup-header {
    position: absolute !important;
    top: 0;
    right: 0;
    left: auto;
    z-index: 30;
    display: flex !important;
    width: auto;
    min-height: 0 !important;
    height: auto !important;
    padding: 4px !important;
    border: none !important;
    background: transparent !important;
    box-shadow: none !important;
}
.xafPopup:has(.review-detail-root) .dxbl-popup-header .view-caption-root {
    display: none !important;
}
.xafPopup:has(.review-detail-root) .dxbl-popup-header .dxbl-modal-header-default {
    justify-content: flex-end;
    min-height: 0;
    padding: 0;
    width: auto;
}

/* Clinical Review full-screen modal: hide the popup's OWN caption bar (the BO_Task icon + "Criteria
   Evaluation" type name + object-summary the DetailView renders top-left). The panel now carries its own
   Policy / Section / Item header, so that chrome is redundant. Same idiom as .review-detail-root above:
   lift the header out of flow (absolute, top-right) and hide just the caption, KEEPING the close "X"
   floating in the corner. Scoped via the .crit-modal-root marker (CustomCSSClassName on the layout root). */
.xafPopup:has(.crit-modal-root) .dxbl-popup-header {
    position: absolute !important;
    top: 0;
    right: 0;
    left: auto;
    z-index: 40;
    display: flex !important;
    width: auto;
    min-height: 0 !important;
    height: auto !important;
    padding: 4px !important;
    border: none !important;
    background: transparent !important;
    box-shadow: none !important;
}
.xafPopup:has(.crit-modal-root) .dxbl-popup-header .view-caption-root {
    display: none !important;
}
.xafPopup:has(.crit-modal-root) .dxbl-popup-header .dxbl-modal-header-default {
    justify-content: flex-end;
    min-height: 0;
    padding: 0;
    width: auto;
}

/* Panel heading: Direction + Call Date (ReviewCallHeaderCard.razor), styled to read as the form's title now
   that the popup's own header is hidden. */
.reviewcall-header {
    padding: 6px 4px 10px;
    font-size: 1.15rem;
    line-height: 1.3;
    color: var(--dxbl-body-color);
    border-bottom: 1px solid rgba(128, 128, 128, 0.35);
    margin-bottom: 10px;
}
.reviewcall-header-title {
    font-weight: 700;
}
.reviewcall-header-date {
    font-weight: 500;
    opacity: 0.75;
}

/* Result radio group (ReviewCallResultRadioEditor.razor) and the Timeline Item Status radio group
   (ReviewTimelineItemStatusRadioEditor.razor): the radios laid out in a row, each radio next to its label,
   with comfortable spacing. */
.reviewcall-result-radio,
.reviewtimelineitem-status-radio {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
    align-items: center;
    padding-top: 4px;
}

.reviewcall-result-radio-item,
.reviewtimelineitem-status-radio-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    cursor: pointer;
}

.reviewcall-result-radio-item input,
.reviewtimelineitem-status-radio-item input {
    cursor: pointer;
}

/* ===== Review Note (ReviewNote) / Timeline Item (ReviewTimelineItem) detail popups =====
   Scoped to these views via the .reviewnote-detail-root / .reviewtimelineitem-detail-root markers
   (CustomCSSClassName on the layout root, set in Model.xafml) matched on the XAF popup with :has() — the
   same idiom as the letter/call popups above. The two popups share the same shape (read-only Created On /
   Created By header row over a dominant memo), so they share these rules.
   The default XAF modal is a fixed-width ~800px centered dialog; narrow it to ~600px (a midpoint that keeps
   the form compact without cramping the memo). The two read-only header labels sit in a horizontal row;
   the memo below is grown to fill the remaining popup body so it dominates the form. */
.xafPopup:has(.reviewnote-detail-root),
.xafPopup:has(.reviewtimelineitem-detail-root),
.xafPopup:has(.reviewdocument-detail-root) {
    width: 600px !important;
    max-width: 90vw !important;
}

/* ===== Generate Letter / Send Letter / Record Locked confirmation popups =====
   Scoped via the .generate-letter-root / .send-letter-root / .record-locked-root markers (CustomCSSClassName
   on each view's layout root, set in Model.xafml) matched on the XAF popup with :has() — same idiom as the
   note/timeline popups above. The default XAF modal is a fixed-width ~800px centered dialog; halve it to 400px. */
.xafPopup:has(.generate-letter-root),
.xafPopup:has(.send-letter-root),
.xafPopup:has(.record-locked-root) {
    width: 400px !important;
    max-width: 90vw !important;
}

.reviewnote-detail-root .dxbl-memo,
.reviewnote-detail-root textarea,
.reviewtimelineitem-detail-root .dxbl-memo,
.reviewtimelineitem-detail-root textarea {
    min-height: 220px !important;
}

/* Header: hide the object caption (the free-text preview under the view caption) — a free-text preview is
   noise as a popup title — and promote the remaining view caption to title weight/size
   (the values the object caption line had) so the header still reads as a title. */
.xafPopup:has(.reviewnote-detail-root) .xaf-object-caption,
.xafPopup:has(.reviewtimelineitem-detail-root) .xaf-object-caption {
    display: none;
}
.xafPopup:has(.reviewnote-detail-root) .xaf-view-caption-sm,
.xafPopup:has(.reviewtimelineitem-detail-root) .xaf-view-caption-sm {
    font-size: 0.875rem;
    font-weight: 600;
}

/* Created On / Created By read-only labels: match the value text's vertical metrics to the field
   caption's (6px vertical padding + 20px line-height, vs the editor's default 4px/1.4) so the label
   and its value share the same baseline. Scoped to form usage (.dxbl-fl-ctrl >) — the dialog-message
   uses of .static-text-editor keep their own spacing. */
.dxbl-fl-ctrl > .static-text-editor {
    padding: 6px 0;
    line-height: 20px;
}

/* Footer: pull the "Change History" button out of the right-aligned Save/Cancel cluster to the lower-left
   corner. The footer toolbar is a flexbox of per-action button groups; order:-1 moves the Change History
   group first and margin-right:auto pushes the rest to the right edge. */
.xafPopup:has(.reviewnote-detail-root) .dxbl-modal-footer .dxbl-btn-group:has(button[data-action-name="Change History"]),
.xafPopup:has(.reviewtimelineitem-detail-root) .dxbl-modal-footer .dxbl-btn-group:has(button[data-action-name="Change History"]) {
    order: -1;
    margin-right: auto;
}

/* ===== Letter Template detail: full-height Template editor =====
   The Letter Template DetailView is shown in the main content area (not a popup), and its Template
   Rich Text editor (.xaf-richedit) defaults to a fixed 600px height, leaving the lower viewport
   empty. Grow it to fill down to ~the viewport bottom. The 280px offset is the editor's distance
   from the viewport top (app header + ribbon + tab bar + the Name field above it); it stays constant
   as the window resizes, so the editor height tracks the viewport. Scoped to .main-content so the
   ReviewLetter popup's editor (sized by .letter-data-col above) is unaffected. */
.main-content .xaf-richedit {
    height: calc(100vh - 280px) !important;
}

/* ===== Popup close ("X") button: bolder, accent-colored icon (system-wide) =====
   The close button in an XAF popup header (.dxbl-popup-header-button — the only header button) renders
   the dx-dismiss "X" as a thin SVG icon (16x16 viewBox, a single fill-only path that follows currentColor).
   Set the color to the theme accent and add a matching stroke: the fill follows currentColor, the stroke
   thickens the strokes (~2px at this size), and a small size bump makes it a bolder, more obvious affordance.
   The accent is --dxbl-btn-primary-bg (the theme's primary/accent color). It is redefined per theme, so it
   tracks the theme switcher; the more obvious --bs-primary / --dxbl-primary are not exposed in these themes. */
.xafPopup .dxbl-popup-header-button svg.dxbl-image {
    width: 22px;
    height: 22px;
    color: var(--dxbl-btn-primary-bg);
    stroke: currentColor;
    stroke-width: 1.5px;
}

/* ===== Review "Timeline" tab: custom feed (CaseTimelineCard.razor) =====
   Date-grouped activity feed replacing the sparse XAF grid. Capped at ~540px so it reads like a
   feed rather than filling the full tab width; the tab content is a column flexbox so width + align-self
   work (flex-basis would size height instead).
   Color note: use --bs-body-color (Bootstrap, auto-flips light/dark) for text, --bs-border-color for
   lines, matching the pattern used by the other information cards in this view. */
.case-timeline {
    width: 100%;
    max-width: 540px;
    padding: 0.5rem 0;
}

.case-timeline-empty {
    font-size: 1rem;
    color: var(--bs-body-color);
    opacity: 0.55;
    padding: 1rem 0;
}

/* Date group header: label + hairline rule */
.ct-date-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 1rem 0 0.5rem;
}
.ct-date-header:first-child {
    margin-top: 0;
}
.ct-date-label {
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bs-body-color);
    opacity: 0.5;
    white-space: nowrap;
}
.ct-date-line {
    flex: 1;
    height: 1px;
    background: var(--bs-border-color, rgba(128,128,128,0.2));
}

/* Each event row */
.ct-row {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    margin-bottom: 0.65rem;
}

/* Icon column — alignment box for the colored Tabler indicator glyph (.case-ind*, defined below). The glyph
   itself is the SAME one shown in the Cases list "Type" column / Case Status card, mapped in one place
   (CaseTimelineEntry.IndicatorParts), so the timeline rows match those views. */
.ct-icon {
    width: 28px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 4px;
}
/* Render the timeline glyph a touch larger than the grid's 18px so it reads at row scale. */
.timeline-card .ct-icon .case-ind::before {
    font-size: 20px;
}

/* Text content */
.ct-body {
    flex: 1;
    padding-top: 5px;
}
.ct-action {
    font-size: 1rem;
    font-weight: 600;
    color: var(--bs-body-color);
}
.ct-detail {
    font-size: 1rem;
    color: var(--bs-body-color);
    opacity: 0.6;
}
/* The "Note" label in a Note row is a click target that opens that note's detail popup. Deliberately NOT
   styled as a link — same font/color as the other action labels; only the cursor (and hover dim) hint at it.
   Only the word is the target, not the note text. */
.ct-action-link {
    cursor: pointer;
}
.ct-action-link:hover {
    opacity: 0.8;
}
/* Wrapper around every row's action + detail text. Clamps the secondary text to three lines (with a trailing
   "…") so any long free-text entry — a Note, a Contacted comment, etc. — can't blow out the timeline card. This
   is the default for all rows. -webkit-box + -webkit-line-clamp is the cross-browser ellipsis-after-N-lines
   idiom. */
.ct-text {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
}
.ct-meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 3px;
}
.ct-time {
    font-size: 0.8rem;
    color: var(--bs-body-color);
    opacity: 0.45;
}
/* The user a timeline row is attributed to (CaseTimelineEntry.CreatedBy), shown after the time. Same muted
   treatment as the time so the meta line reads as one quiet strip under the row's action text. */
.ct-user {
    font-size: 0.8rem;
    color: var(--bs-body-color);
    opacity: 0.45;
}

/* Status badges */
.ct-badge {
    font-size: 0.75rem;
    font-weight: 600;
    padding: 1px 7px;
    border-radius: 4px;
    letter-spacing: 0.03em;
}
.ct-badge-attn   { background: #FAECE7; color: #993C1D; }
.ct-badge-wait   { background: #FAEEDA; color: #854F0B; }
.ct-badge-closed { background: #EAF3DE; color: #3B6D11; }
.ct-badge-note   { background: rgba(128,128,128,0.12); color: var(--bs-body-color); }

/* ===== Review detail: Timeline card docked as a full-height left sidebar =====
   The Timeline feed lives as a card in the "TimelineColumn" LayoutGroup (CustomCSSClassName
   "review-timeline-col"), the left column of the horizontal ContentRow group in Model.xafml. Everything
   else — the five-card info strip and the CaseTabs tab group — stacks in the "review-main-col" column to
   its right, so the sidebar runs the full form height. XAF renders the row's columns as equal Bootstrap
   cols, so these rules set the real split: fixed ~1/5 sidebar, main column flex-grows to fill the rest.
   min-width keeps the feed legible on narrow viewports. */
.review-timeline-col {
    /* 25% narrower than the original 20% split (0.20 × 0.75 = 0.15). */
    flex: 0 0 15% !important;
    max-width: 15% !important;
    min-width: 220px;
}

.review-main-col {
    flex: 1 1 0 !important;
    max-width: none !important;
    min-width: 0 !important;
}

/* ===== Review detail: horizontal splitter between the card strip and the tab group =====
   XAF Blazor has no native splitter view item (the WinForms Layout Control's Splitter/Separator items
   are not available in Blazor projects, and the model SplitLayout node only governs the List-View +
   Detail-View master/detail split), so the split is built here in CSS plus wwwroot/js/reviewSplitter.js.
   MainColumn renders as a single wrapping `.dxbl-row`; turning it into a non-wrapping flex COLUMN stacks
   its three children — the card strip (.review-cards-pane), the drag handle (.review-split-divider), and
   the tab group (.review-tabs-pane) — vertically. The top pane keeps its natural height (the handle sets
   an explicit height while dragging); the bottom pane flex-grows to fill the remaining form height so the
   tabs run to the bottom instead of floating under the cards. */
.review-main-col > .dxbl-row {
    flex-direction: column !important;
    flex-wrap: nowrap !important;
    height: 100%;
    align-items: stretch;
}

.review-cards-pane {
    flex: 0 0 auto !important;
    min-height: 0;
}

/* Anchor the card bottoms to the splitter (WinForms "anchor bottom") while keeping the tops pinned in a
   row. Every card is the same height because every card's data grid is the same height, so their tops line
   up (top pinned) AND their bottoms line up. That shared grid height is driven by the --cards-grid-h
   variable, which reviewSplitter.js grows/shrinks as the divider is dragged — so the bottoms track the
   divider down/up. Unset (un-dragged), it falls back to the original ~12.5rem strip. The base
   .info-card-grid rule keeps overflow-y:auto, so a card with more rows than fit just scrolls. */
.review-cards-pane .info-card-grid {
    height: var(--cards-grid-h, 12.5rem);
}

/* The bottom pane below the card strip is itself a horizontal row: a fixed-width actions panel on the
   left beside the tab group on the right. It takes the slot the tab group used to occupy directly, so it
   flex-grows to fill the height remaining under the cards + splitter; making it a flex COLUMN lets its
   inner .dxbl-row stretch to that full height, and the two panes stretch to match each other. */
.review-bottom-row {
    flex: 1 1 0 !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}

.review-bottom-row > .dxbl-row {
    flex: 1 1 auto !important;
    flex-wrap: nowrap !important;
    min-height: 0 !important;
    align-items: stretch;
}

/* Fixed-width left column hosting the custom actions card (CaseActionsCard). Sized so the longest caption
   ("Deny - Req. Not Met") fits on one line with its icon plus a little overhead; scrolls internally only if
   the whole stack is taller than the pane. */
.review-actions-panel {
    flex: 0 0 auto !important;
    width: 12.5rem;
    min-width: 0 !important;
    overflow: auto;
}

/* The actions card body: three groups (Add New / Update State / Case Status) stacked down the panel. */
.actions-panel-card {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    padding: 0.25rem 0.15rem;
}

/* Wrap so buttons flow onto rows: full-width buttons each take their own row; a run of half-width buttons
   (the In/Out calls) pairs up two-per-row. */
.actions-group {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}

.actions-group-title {
    flex: 0 0 100%;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--dxbl-text-muted, #6c757d);
}

/* One themed DxButton (Secondary) per row — colors come from the XAF theme so the panel follows light/dark
   mode (like the cards' "Edit" button). Layout only here: full panel width, caption + .case-btn ::before
   glyph left-aligned rather than DxButton's default centering. */
.actions-btn.dxbl-btn {
    flex: 1 1 100%;
    min-width: 0;
    justify-content: flex-start;
    text-align: left;
}

/* Half-width buttons pair two-per-row (In / Out). 50% minus half the row gap so both fit one line. */
.actions-btn-half.dxbl-btn {
    flex: 1 1 calc(50% - 0.15rem);
}

.review-tabs-pane {
    /* Fill whatever width/height remains beside the actions panel and below the cards + handle; scroll
       internally when a tab's content is larger than the pane so the page itself does not grow. min-width:0
       lets the tab group shrink below its content width inside the horizontal bottom row. */
    flex: 1 1 0 !important;
    min-width: 0 !important;
    min-height: 0 !important;
    overflow: auto;
}

.review-split-divider {
    flex: 0 0 auto !important;
}

.review-split-handle {
    height: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: row-resize;
    touch-action: none;
}

.review-split-grip {
    width: 48px;
    height: 4px;
    border-radius: 2px;
    background: var(--dxbl-border-color, #ced4da);
    transition: background-color 0.12s ease-in-out;
}

.review-split-handle:hover .review-split-grip {
    background: var(--dxbl-btn-primary-bg, #6c757d);
}

/* The card fills the column; its feed scrolls internally so a long history does not stretch the page.
   Drop the feed's wide-tab 540px cap so it fills the narrow card width instead. */
.timeline-card {
    display: flex;
    flex-direction: column;
    /* Extend the card down to the bottom of the form. The min-height is applied to the card itself (not its
       layout column) because height:100% does not resolve through XAF's form-layout wrappers — the card would
       stay at its content height inside a taller column. Driving the card's own min-height makes it grow; its
       column then grows to contain it and the main column stretches to match (align-items:stretch on the row).
       The Review DetailView opens as a full-height popup (100vh), and its card strip starts at the very top of
       the modal body (~4px in — there is NO app header/ribbon inside the popup). So the only chrome to clear is
       the form's bottom footer bar (.dxbl-modal-footer, ~67px) plus that small top inset and a hair of gap —
       ~80px total — so the card bottom lands just above the footer rather than short of it (leaving whitespace)
       or underneath it. */
    min-height: calc(100vh - 80px);
}

.timeline-card .case-timeline {
    max-width: none;
    /* Fill the card's remaining height below the header and scroll internally when the history is long.
       min-height:0 lets this flex child shrink below its content size so overflow-y actually scrolls
       instead of pushing the card taller. */
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* ===== Merge-field picker popup (LetterTemplate "Insert Field") =====
   The custom Insert-Merge-Field popup (MergeFieldPicker.razor). Lay each group's fields out in two
   left-aligned columns for legibility, and cap the body height so a long list scrolls inside the popup
   instead of running off-screen. Class names come from the component's own markup. */
/* Size the popup card itself (DxPopup's Width param renders no unit and is ignored; the popup otherwise
   runs full-width in "adaptivity" mode). CssClass="merge-field-popup" lands on the .dxbl-popup root. */
.dxbl-popup.merge-field-popup {
    width: 720px !important;
}
.merge-field-picker {
    /* Fill the sized card; the two 1fr columns then get a definite width instead of expanding to the viewport. */
    width: 100%;
    max-height: 70vh;
    overflow-y: auto;
}
.merge-field-picker .merge-field-group-title {
    font-weight: 600;
    opacity: 0.65;
    margin: 12px 0 4px;
}
/* Two columns filled COLUMN-major (down column 1 alphabetically, then down column 2) — CSS multi-column does
   this and balances the halves automatically per group. (A CSS grid fills row-major, which read top-to-bottom
   per column looks unsorted.) The fields arrive already sorted alphabetically from MergeFieldCatalog. */
.merge-field-picker .merge-field-group {
    column-count: 2;
    column-gap: 24px;
}
/* DxButton (link) renders its own <button>; make each a left-aligned block that flows in the columns and
   never splits across a column break. */
.merge-field-picker .merge-field-item {
    display: block;
    width: 100%;
    text-align: left;
    justify-content: flex-start;
    break-inside: avoid;
}

/* ── Case status / type indicator icons ────────────────────────────────────────────────────────────────
   The Cases List View "Status" and "Type" columns (and the Case Status card) show colored Tabler icons.
   Because the grid renders a cell's value as plain text, the icon is NOT the cell value — it is drawn by a
   CSS class applied to the cell: ReviewListIconTooltipController stamps the per-row class onto the grid cell
   (Review.Case_StatusIndicatorClass / Case_TypeIndicatorClass), and the Case Status card puts the same class
   on a <span>. Glyphs are from @tabler/icons-webfont 3.24.0 (full woff2 bundled locally below — a later build
   step could subset it to just the glyphs used here). Each state's color is baked into its rule. */
@font-face {
    font-family: 'tabler-icons';
    font-style: normal;
    font-weight: 400;
    font-display: block;
    src: url('fonts/tabler-icons.woff2') format('woff2');
}
.case-ind::before {
    font-family: 'tabler-icons';
    font-weight: normal;
    font-style: normal;
    font-size: 18px;
    line-height: 1;
    display: inline-block;
    vertical-align: -0.18em;
    -webkit-font-smoothing: antialiased;
    text-rendering: auto;
}
/* Center the glyph in the narrow grid indicator cells. */
.case-ind { text-align: center; }
/* Status indicators (glyph + color per Case_CurrentStatus). */
.case-ind-contacted::before { content: "\ea5e"; color: #1D9E75; } /* check — green        (Contacted)  */
.case-ind-attn::before     { content: "\ea05"; color: #BA7517; } /* alert-circle — amber (Needs Attn) */
.case-ind-alert::before    { content: "\ed07"; color: #E24B4A; } /* bell-ringing — red   (Alert)     */
.case-ind-error::before    { content: "\ea06"; color: #E24B4A; } /* alert-triangle — red (ERROR)     */
.case-ind-closed::before   { content: "\eaf2"; color: #888780; } /* minus — gray      (Closed)       */
/* Type indicators (glyph + color per most-recent timeline event). */
.case-ind-new::before              { content: "\f6d7"; color: #D4AF37; } /* sparkles — gold     (New Case)            */
.case-ind-approved::before         { content: "\eb3c"; color: #1D9E75; } /* thumb-up — green    (Approved)            */
.case-ind-denied::before           { content: "\eb3b"; color: #E24B4A; } /* thumb-down — red    (Denied)             */
.case-ind-duplicate::before        { content: "\ebd4"; color: #E24B4A; } /* forbid-2 — red      (Duplicate)           */
.case-ind-fax::before              { content: "\ea9d"; color: #378ADD; } /* file-download — blue (Received Fax)       */
.case-ind-call-in::before          { content: "\eb06"; color: #1D9E75; } /* phone-incoming — green (Incoming Call)    */
.case-ind-call-out-ok::before      { content: "\eb07"; color: #1D9E75; } /* phone-outgoing — green (Outgoing success) */
.case-ind-call-out-noanswer::before{ content: "\ec07"; color: #E24B4A; } /* phone-x — red       (Outgoing no answer)  */
.case-ind-voicemail-out::before    { content: "\f85e"; color: #1D9E75; } /* message-share — green (Outgoing voicemail) */
.case-ind-voicemail-in::before     { content: "\f85f"; color: #1D9E75; } /* message-down — green  (Incoming voicemail) */
.case-ind-sent::before             { content: "\eb1e"; color: #0F6E56; } /* send — green        (Sent letter/fax)     */
.case-ind-attach::before           { content: "\eb02"; color: #854F0B; } /* paperclip — amber   (Attachment)          */
.case-ind-status::before           { content: "\eb13"; color: #185FA5; } /* refresh — blue      (Status changed)      */
.case-ind-reopen::before           { content: "\f6d7"; color: #D4AF37; } /* sparkles — gold     (Reopened — matches Created/New) */
.case-ind-note::before             { content: "\eb6d"; color: #A855F7; } /* note (paper) — purple (Note)              */

/* Review case-decision buttons (ReviewCaseActionsController, "Actions" tab) — reuse the Timeline's Tabler
   glyphs so a button and the timeline row it produces share one icon. The .case-btn-* class is applied to the
   rendered toolbar button; ::before stamps the glyph before the caption, matching the .case-ind-* codepoints. */
.case-btn::before {
    font-family: 'tabler-icons';
    font-weight: normal;
    font-style: normal;
    font-size: 16px;
    line-height: 1;
    display: inline-block;
    vertical-align: -0.15em;
    margin-right: 0.4em;
    -webkit-font-smoothing: antialiased;
    text-rendering: auto;
}
.case-btn-approved::before { content: "\eb3c"; color: #1D9E75; } /* thumb-up — green  (Approve)  */
.case-btn-denied::before   { content: "\eb3b"; color: #E24B4A; } /* thumb-down — red  (Deny)     */
.case-btn-reauth::before   { content: "\f6d7"; color: #D4AF37; } /* sparkles — gold   (ReAuth)   */
.case-btn-reopen::before   { content: "\f6d7"; color: #D4AF37; } /* sparkles — gold   (Reopen — matches Created/New) */
/* (No .case-btn-duplicate here — marking a duplicate moved off the Actions card to the Potential Duplicates grid
   toolbar; that button's glyph is the .dxbl-toolbar-btn[data-action-name="Mark as Duplicate"] rule below.) */
/* 2nd-row status buttons (ReviewStatusItemActionsController) — each glyph matches the .case-ind-* status
   indicator it sets: check/Contacted, alert-circle/Needs Attn, bell-ringing/Alert. */
.case-btn-contacted::before { content: "\ea5e"; color: #1D9E75; } /* check — green        (Contacted)  */
.case-btn-attn::before     { content: "\ea05"; color: #BA7517; } /* alert-circle — amber (Needs Attn) */
.case-btn-alert::before    { content: "\ed07"; color: #E24B4A; } /* bell-ringing — red   (Alert)     */
/* "Log Call" buttons (ReviewCallActionsController, "Actions" tab) — amber phone glyphs. */
.case-btn-call-out::before { content: "\eb07"; color: #BA7517; } /* phone-outgoing — amber (Log Outgoing Call) */
.case-btn-call-in::before  { content: "\eb06"; color: #BA7517; } /* phone-incoming — amber (Log Incoming Call) */
/* "Note" button in the same "Add New" group — matches the .case-ind-note timeline glyph (purple paper note). */
.case-btn-note::before     { content: "\eb6d"; color: #A855F7; } /* note (paper) — purple (New Note) */
/* "Document" button in the same "Add New" group — matches the .case-ind-attach timeline glyph (amber paperclip). */
.case-btn-doc::before      { content: "\eb02"; color: #854F0B; } /* paperclip — amber (New Document) */
/* "RFI" quick button in the same "Add New" group (Review_GenerateRfiController) — the send/outgoing-letter glyph
   (matches the .case-ind-sent timeline glyph), blue to read as an outbound fax being generated. */
.case-btn-rfi::before      { content: "\eb1e"; color: #378ADD; } /* send — blue (Generate RFI fax) */

/* Potential Duplicates grid — the leading caption-less marker cell on the current case's row reads "This Case"
   in red (Review_PotentialDuplicatesMarkerController stamps this class on that data cell, and on the Reason cell
   of the same row). Same red as the Deny/Duplicate glyphs; !important beats the grid's default cell color token. */
.dup-current-marker { color: #E24B4A !important; font-weight: 600; }

/* PA-INTAKE: the Intake form's Same Person grid pins the open case as its top row ("This case" in Case #);
   Review_IntakeMatchesController stamps this class on that data row so it reads as the reference line, not a match. */
.intake-current-row > td { background-color: rgba(55, 138, 221, 0.12) !important; font-weight: 600; }

/* PA-INTAKE r2: the import form's "Import a claim file" step (ImportFile_DetailView) — a light panel so the file picker
   and its Import button read as the one thing to do on the page, kept to a readable width. */
.import-step { max-width: 720px; background-color: rgba(55, 138, 221, 0.06); border-radius: 6px; padding: 0.5rem 0.75rem; }

/* "Mark as Duplicate" button on the Potential Duplicates grid toolbar (Review_PotentialDuplicatesActionsController).
   It is a plain XAF toolbar SimpleAction (no .case-btn class hook), so the glyph is stamped via the data-action-name
   attribute — the SAME Tabler "forbid-2" glyph (red) as the Duplicate state indicator (.case-ind-duplicate),
   spaced before the caption. */
.dxbl-toolbar-btn[data-action-name="Mark as Duplicate"]::before {
    content: "\ebd4"; /* forbid-2 */
    font-family: 'tabler-icons';
    font-weight: normal;
    font-style: normal;
    font-size: 15px;
    line-height: 1;
    display: inline-block;
    vertical-align: -0.15em;
    margin-right: 0.4em;
    color: #E24B4A;
    -webkit-font-smoothing: antialiased;
    text-rendering: auto;
}

/* Idle auto-logoff warning overlay (idleLogoff.js / IdleLogoffController — HIPAA automatic logoff).
   Built in plain DOM so it appears even when the Blazor circuit is busy. Theme-aware via --dxbl-*
   tokens (empty --bs-* vars in this app; see the read-only-editor CSS note). z-index sits above the
   XAF loading splash so the countdown is never occluded. */
.idle-logoff-overlay {
    position: fixed;
    inset: 0;
    z-index: 20000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.45);
}
.idle-logoff-box {
    min-width: 20rem;
    max-width: 90vw;
    padding: 1.5rem 1.75rem;
    border-radius: 0.5rem;
    background: var(--dxbl-body-bg, #fff);
    color: var(--dxbl-body-color, #212529);
    box-shadow: 0 0.5rem 2rem rgba(0, 0, 0, 0.35);
    text-align: center;
}
.idle-logoff-title {
    font-size: 1.15rem;
    font-weight: 600;
    margin-bottom: 0.5rem;
}
.idle-logoff-message {
    margin-bottom: 1.25rem;
    line-height: 1.4;
}
.idle-logoff-count {
    font-weight: 700;
    color: var(--dxbl-btn-primary-bg, #0d6efd);
}
.idle-logoff-stay {
    min-width: 10rem;
}

/* ============================================================================
   Clinical Criteria tab (ClinicalCriteriaCard / CriteriaQuestionnaire)
   A schema-driven prior-auth questionnaire with a live engine recommendation.
   Theme-agnostic: the DevExpress theme sets the real text/background COLOR on
   body (light-on-dark in dark theme, dark-on-light in light theme) but does NOT
   expose its --dxbl-* custom properties at arbitrary content nodes, so we must
   INHERIT color rather than hardcode it. Secondary text uses opacity on the
   inherited color; separators use a neutral translucent gray; the status chips
   and Yes/No toggles are solid pills that read on either background. See the
   read-only-editor note in memory for where --dxbl-* vars DO apply.
   ============================================================================ */
.crit-root {
    padding: 0.75rem 1rem 1.5rem;
    overflow-y: auto;
    height: 100%;
    /* Inherit the theme's body color — do NOT hardcode (would vanish in dark theme). */
}

/* Start panel (no evaluation yet) */
.crit-start { display: flex; flex-direction: column; gap: 0.75rem; max-width: 40rem; }
.crit-start-title { font-size: 1.1rem; font-weight: 600; }
.crit-start-row { display: flex; align-items: center; gap: 0.75rem; }
.crit-label {
    font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.03em;
    color: inherit; opacity: 0.65; font-weight: 600;
}
.crit-note { color: inherit; opacity: 0.7; font-style: italic; }
.crit-error { color: #e5534b; opacity: 1; font-style: normal; }
/* LOGIC S5 - stale/invalid schema pin notice (CriteriaEvaluationPanel / BasicInfoCard). */
.crit-stale { color: #b7791f; opacity: 1; font-style: normal; display: flex; flex-direction: column; gap: .5rem; }
.crit-stale-confirm { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
/* Solid readable pill like the other chips (.crit-chip sets color:#fff, so the background must be dark enough). */
.crit-chip.crit-chip-stale { background: #b7791f; color: #fff; }

/* Header: policy identity + module selector */
.crit-header {
    display: flex; justify-content: space-between; align-items: flex-start;
    gap: 1rem; margin-bottom: 0.75rem; flex-wrap: wrap;
}
.crit-policy-name { font-size: 1.05rem; font-weight: 600; }
.crit-policy-meta { font-size: 0.8rem; opacity: 0.65; }
.crit-header-module { display: flex; align-items: center; gap: 0.5rem; }

/* Verdict banner */
.crit-verdict {
    display: flex; justify-content: space-between; align-items: center;
    padding: 0.6rem 1rem; border-radius: 0.4rem; margin-bottom: 0.75rem;
    border-left: 4px solid transparent;
}
.crit-verdict-main { display: flex; align-items: baseline; gap: 0.75rem; }
.crit-verdict-word { font-size: 1.25rem; font-weight: 700; letter-spacing: 0.02em; }
.crit-verdict-drug { font-size: 1.05rem; font-weight: 600; }
.crit-verdict-sub { font-size: 0.9rem; opacity: 0.85; }
.crit-verdict-tag { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.7; }
/* Tint backgrounds are translucent so they darken/lighten with the theme; the
   word colors are picked to read on both the pale (light theme) and the muted
   (dark theme) tint. */
.crit-approve { background: rgba(25, 135, 84, 0.18); border-left-color: #2ea86f; }
.crit-approve .crit-verdict-word { color: #2ea86f; }
.crit-deny { background: rgba(220, 53, 69, 0.18); border-left-color: #e5534b; }
.crit-deny .crit-verdict-word { color: #e5534b; }
.crit-pend { background: rgba(128, 128, 128, 0.18); border-left-color: #9aa0a6; }
.crit-pend .crit-verdict-word { color: #9aa0a6; }

/* Blocking list */
.crit-blocking {
    border: 1px solid rgba(128, 128, 128, 0.3); border-radius: 0.4rem;
    padding: 0.5rem 0.75rem; margin-bottom: 1rem; background: rgba(128, 128, 128, 0.08);
}
.crit-blocking-head { font-weight: 600; font-size: 0.85rem; margin-bottom: 0.25rem; }
.crit-blocking-list { margin: 0; padding-left: 1.1rem; font-size: 0.85rem; }
.crit-blocking-list li { margin: 0.15rem 0; }

/* Criterion rows (top-level, numbered) */
.crit-questions { display: flex; flex-direction: column; gap: 0.5rem; }
.crit-criterion { display: flex; gap: 0.6rem; align-items: flex-start; }
.crit-criterion-no {
    flex: 0 0 2rem; text-align: right; font-weight: 700; font-size: 0.85rem;
    opacity: 0.55; padding-top: 0.35rem;
}
.crit-criterion-body { flex: 1 1 auto; min-width: 0; }

/* Groups */
.crit-group {
    border: 1px solid rgba(128, 128, 128, 0.3); border-radius: 0.4rem;
    padding: 0.4rem 0.6rem; margin: 0.25rem 0;
}
.crit-op-any { border-left: 3px solid #4a90e2; }
.crit-group-head { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; margin-bottom: 0.3rem; }
.crit-group-label { font-size: 0.82rem; font-weight: 600; }
.crit-group-body { display: flex; flex-direction: column; gap: 0.15rem; }

/* AND / OR connectors shown between a group's clauses, so the boolean structure reads at a glance. */
.crit-connector {
    font-size: 0.66rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: #868e96; padding: 0.05rem 0; user-select: none;
}
.crit-connector-any, .crit-connector-atleast { color: #4a90e2; }
.crit-na .crit-connector { color: #adb5bd; }
/* UI-4 X1 — the module's top-level combinator, styled like a group heading over the numbered criteria. */
.crit-root-head { font-size: 0.82rem; font-weight: 600; margin: 0 0 0.35rem 2.6rem; }
.crit-root-connector { margin-left: 2.6rem; }

/* Conditional ("if–then") node */
.crit-conditional { border-left: 3px solid #b26bd0; }
.crit-cond-arm { display: flex; align-items: flex-start; gap: 0.5rem; }
.crit-cond-tag {
    flex: 0 0 auto; margin-top: 0.3rem; font-size: 0.66rem; font-weight: 700; letter-spacing: 0.03em;
    text-transform: uppercase; color: #b26bd0; min-width: 2.4rem;
}
.crit-cond-node { flex: 1 1 auto; min-width: 0; }
.crit-cond-waived { font-size: 0.78rem; font-style: italic; opacity: 0.7; padding: 0.15rem 0 0.15rem 2.9rem; }

/* Questions */
.crit-question { padding: 0.25rem 0; }
.crit-q-row { display: flex; align-items: center; gap: 0.6rem; }
.crit-q-prompt { flex: 1 1 auto; font-size: 0.85rem; line-height: 1.3; }
.crit-q-input { flex: 0 0 auto; }
.crit-q-doc { margin: 0.3rem 0 0.2rem 5.5rem; }

/* Lookup with an image: the source PDF table shown exactly as printed, above the pickers.
   White backing so the (white) table render stays legible in dark theme; bounded height so it
   never dominates the questionnaire. */
/* B3.7 module-level table artifacts (concomitant / reference tables shown as printed; the reviewer reads them). */
.crit-tables { margin: 0.85rem 0 0.4rem 0; padding-top: 0.6rem; border-top: 1px dashed rgba(128, 128, 128, 0.4); }
.crit-tables-head { font-size: 0.78rem; font-weight: 600; opacity: 0.8; margin-bottom: 0.5rem; }
/* HOLDS-1: the reviewer confirmation under an unbound policy table. */
.crit-table-confirm { display: flex; align-items: center; gap: 0.4rem; margin-top: 0.4rem; font-size: 0.85rem; font-weight: 600; }
.crit-table-artifact { margin: 0 0 0.7rem 0; }
.crit-table-prompt { font-size: 0.8rem; font-weight: 600; margin-bottom: 0.3rem; }
/* LOGIC S7 - CCE tables as their printed rows (CriteriaTableRows), module notes (CriteriaPolicyNotes) and the
   hold reasons under the verdict bar (CriteriaHoldReasons). Theme tokens, so light and dark both read. */
.crit-table-rows { border-collapse: collapse; width: 100%; font-size: 0.8rem; margin: 0.2rem 0 0.4rem 0; }
.crit-table-rows td {
    border: 1px solid var(--bs-border-color, rgba(128, 128, 128, 0.45)); padding: 0.25rem 0.45rem;
    vertical-align: top; color: var(--bs-body-color); white-space: pre-wrap;
}
.crit-notes, .crit-hold { margin: 0.55rem 0; padding: 0.45rem 0.65rem; border-radius: 0.3rem; font-size: 0.8rem; }
.crit-notes { border: 1px solid var(--bs-border-color, rgba(128, 128, 128, 0.4)); color: var(--bs-body-color); }
.crit-hold { border: 1px solid #b7791f; background: rgba(183, 121, 31, 0.1); color: var(--bs-body-color); }
.crit-notes-head, .crit-hold-head { font-weight: 600; margin-bottom: 0.25rem; }
.crit-hold-head { color: #b7791f; }
.crit-notes-list, .crit-hold-list { margin: 0; padding-left: 1.1rem; }
/* PA-UI-2026-10-23-01 - why the engine says Deny / Pending (CriteriaVerdictReasons): collapsed under the verdict bar,
   copyable. Theme tokens (light + dark). */
.crit-reasons { margin: 0 0 0.55rem; padding: 0.35rem 0.65rem; border-radius: 0.3rem; font-size: 0.8rem;
    border: 1px solid var(--bs-border-color, rgba(128, 128, 128, 0.4)); color: var(--bs-body-color); }
.crit-reasons-summary { cursor: pointer; font-weight: 600; }
.crit-reasons-tag { margin-left: 0.4rem; font-weight: 400; font-size: 0.7rem; text-transform: uppercase;
    letter-spacing: 0.04em; opacity: 0.7; }
.crit-reasons-body { margin-top: 0.35rem; }
.crit-reasons-head { font-weight: 600; margin: 0.35rem 0 0.2rem; }
.crit-reasons-list { margin: 0; padding-left: 1.1rem; }
.crit-reasons-list li { margin: 0.15rem 0; }
.crit-reasons-actions { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.4rem; }
.crit-reasons-copy { font-size: 0.75rem; padding: 0.1rem 0.6rem; border-radius: 0.25rem; cursor: pointer;
    border: 1px solid var(--bs-border-color, rgba(128, 128, 128, 0.5)); background: transparent; color: var(--bs-body-color); }
.crit-reasons-copy:focus-visible { outline: 2px solid var(--bs-primary, #0d6efd); outline-offset: 2px; }
.crit-reasons-copy-failed { color: #e5534b; }
/* UI-5 D3 - the reviewer-entered approval length (CriteriaApprovalLengthInput). Theme tokens (light + dark). */
.crit-length { margin: 0.55rem 0; padding: 0.45rem 0.65rem; border-radius: 0.3rem; font-size: 0.8rem;
    border: 1px solid var(--bs-border-color, rgba(128, 128, 128, 0.4)); color: var(--bs-body-color); }
.crit-length-head { font-weight: 600; margin-bottom: 0.25rem; }
.crit-length-hint { margin: 0 0 0.35rem; padding-left: 1.1rem; opacity: 0.85; }
.crit-length-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.crit-length-note { margin-top: 0.3rem; opacity: 0.75; }
.crit-length-disabled .crit-length-head, .crit-length-disabled .crit-length-hint { opacity: 0.6; }
/* UI-2 - one logical policy table across its pages (CriteriaTableGroupViewer): the selected page large with its page
   label, a thumbnail strip (ARIA tablist) when it spans pages, Prev/Next in the lightbox. Theme tokens (light + dark). */
.crit-tgv-main { display: flex; flex-direction: column; align-items: flex-start; gap: 0.25rem; }
.crit-tgv-open { padding: 0; border: 0; background: none; cursor: zoom-in; max-width: 100%; }
.crit-tgv-open:focus-visible, .crit-tgv-thumb:focus-visible, .crit-tgv-nav:focus-visible {
    outline: 2px solid var(--bs-primary, #0d6efd); outline-offset: 2px;
}
.crit-tgv-caption { font-size: 0.75rem; opacity: 0.8; color: var(--bs-body-color); }
.crit-tgv-strip { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.4rem; }
.crit-tgv-thumb {
    display: flex; flex-direction: column; align-items: center; gap: 0.15rem; padding: 0.2rem;
    border: 1px solid var(--bs-border-color, rgba(128, 128, 128, 0.45)); border-radius: 0.3rem;
    background: var(--bs-body-bg, transparent); color: var(--bs-body-color); cursor: pointer;
}
.crit-tgv-thumb img { width: 64px; height: 48px; object-fit: cover; object-position: top; background: #fff; border-radius: 0.2rem; }
.crit-tgv-thumb[aria-selected="true"] { border: 2px solid var(--bs-primary, #0d6efd); background: var(--bs-primary-bg-subtle, rgba(13, 110, 253, 0.08)); }
.crit-tgv-thumb-no { font-size: 0.7rem; }
/* BI-4c - the page tabs of a rows table split over pages (one tab per printed page; the selected page's rows below). */
.crit-tgv-pagetab {
    padding: 0.15rem 0.6rem; font-size: 0.8rem; cursor: pointer; border-radius: 0.3rem;
    border: 1px solid var(--bs-border-color, rgba(128, 128, 128, 0.45));
    background: var(--bs-body-bg, transparent); color: var(--bs-body-color);
}
.crit-tgv-pagetab[aria-selected="true"] { border: 2px solid var(--bs-primary, #0d6efd); background: var(--bs-primary-bg-subtle, rgba(13, 110, 253, 0.08)); font-weight: 600; }
.crit-tgv-pagetab:focus-visible { outline: 2px solid var(--bs-primary, #0d6efd); outline-offset: 2px; }
.crit-tgv-pagepanel[hidden] { display: none; }
.crit-tgv-zoom { display: flex; flex-direction: column; align-items: center; gap: 0.35rem; }
.crit-tgv-zoom:focus-visible { outline: 2px solid var(--bs-primary, #0d6efd); outline-offset: 2px; }
.crit-tgv-zoom-popup .crit-tgv-caption { margin: 0 auto; }
.crit-tgv-nav {
    padding: 0.3rem 0.8rem; border: 1px solid var(--bs-border-color, rgba(128, 128, 128, 0.45)); border-radius: 0.3rem;
    background: var(--bs-body-bg, transparent); color: var(--bs-body-color); cursor: pointer;
}
.crit-tgv-nav:disabled { opacity: 0.4; cursor: default; }

.crit-lookup-table { margin: 0.45rem 0 0.55rem 0; }
.crit-lookup-table-img {
    max-width: 100%; max-height: 360px; height: auto; display: block;
    border: 1px solid rgba(128, 128, 128, 0.45); border-radius: 0.3rem; background: #fff;
    cursor: zoom-in;
}
.crit-lookup-hint {
    font-size: 0.72rem; opacity: 0.6; margin-top: 0.25rem; cursor: zoom-in;
    user-select: none;
}
/* B3.9 — a policy table shown INLINE under the criterion that cites it (not the module footer). Inset with a left
   rule so it reads as belonging to that criterion. */
.crit-node-tables { margin: 0.3rem 0 0.5rem 0.4rem; padding-left: 0.7rem; border-left: 2px solid rgba(128, 128, 128, 0.35); }
.crit-node-tables .crit-table-prompt { font-size: 0.78rem; font-weight: 600; opacity: 0.85; margin-bottom: 0.25rem; }
/* R2 — click-to-enlarge zoom: a nested DxPopup (crit-tgv-zoom-popup) sized for the tall multi-page tables; its body
   scrolls. The image is shown at a readable width on white. */
.crit-tgv-zoom-popup .crit-lightbox-img {
    max-width: 100%; width: auto; height: auto; display: block; margin: 0 auto;
    background: #fff; border-radius: 0.25rem;
}
.crit-lookup-dims { display: flex; flex-direction: column; gap: 0.4rem; margin: 0.25rem 0 0.2rem 0; }
.crit-lookup-dim { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.crit-lookup-dim-label { font-size: 0.82rem; min-width: 12rem; flex: 0 0 auto; }
.crit-lookup-out { font-size: 0.82rem; margin-top: 0.35rem; font-weight: 600; }
.crit-lookup-out-met { color: #198754; }
.crit-lookup-out-no { color: #c0392b; }

/* State chips — solid pills with white text, so they read on any background. */
.crit-chip {
    flex: 0 0 auto; font-size: 0.68rem; font-weight: 600; text-transform: uppercase;
    letter-spacing: 0.02em; padding: 0.1rem 0.4rem; border-radius: 0.8rem; white-space: nowrap;
    min-width: 4.5rem; text-align: center; color: #fff;
}
.crit-chip.met { background: #198754; }
.crit-chip.notmet { background: #c0392b; }
.crit-chip.pending { background: #6c757d; }
/* UI-4 W1 — a conditional's IF answered so the requirement is waived: neutral, never a red failure. */
.crit-chip.waived { background: transparent; color: var(--bs-body-color); border: 1px solid rgba(134, 142, 150, 0.7); }
/* NA — a non-decisive branch (losing arm of a satisfied ONE-OF / N-of-M, or a waived
   conditional). Hollow dashed pill + muted text, so it never reads as a red failure. */
.crit-chip.na {
    background: transparent; color: #868e96;
    border: 1px dashed rgba(134, 142, 150, 0.6);
}
.crit-na.crit-op-any,
.crit-na.crit-conditional { border-left-color: rgba(128, 128, 128, 0.3); }
.crit-na .crit-group-label,
.crit-na .crit-q-prompt,
.crit-na .crit-cond-tag { color: #868e96; }
/* Grey out an already-answered toggle on an NA row so the whole branch reads muted. */
.crit-na .crit-opt.is-on-yes,
.crit-na .crit-opt.is-on-no { background: #868e96; color: #fff; }

/* Yes/No toggle — inactive options inherit the theme (transparent + inherited
   color); the selected option is a solid green/red pill. */
.crit-yesno { display: inline-flex; border: 1px solid rgba(128, 128, 128, 0.45); border-radius: 0.3rem; overflow: hidden; }
.crit-opt {
    border: none; background: transparent; color: inherit;
    padding: 0.2rem 0.7rem; font-size: 0.8rem; cursor: pointer; min-width: 3rem;
}
.crit-opt + .crit-opt { border-left: 1px solid rgba(128, 128, 128, 0.45); }
.crit-opt:disabled { cursor: default; opacity: 0.6; }
.crit-opt.is-on-yes { background: #198754; color: #fff; }
.crit-opt.is-on-no { background: #c0392b; color: #fff; }

/* ============================================================================
   Clinical Review full-screen modal (CriteriaEvaluation_DetailView)
   Two columns: the questionnaire panel (left) and the attachment PDF viewer
   (right), mirroring the crc-version split. The launcher (.crit-launch) is the
   compact summary + button on the Review "Clinical Criteria" tab.
   ============================================================================ */

/* Stretch the view root + body row to the full popup height so both columns fill. */
.crit-modal-root,
.crit-modal-root > .dxbl-fl,
.crit-modal-root .dxbl-fl-group-items {
    height: 100%;
}
.crit-modal-body-row {
    height: 100%;
    align-items: stretch !important;
    gap: 0.5rem;
}

/* Left column: the questionnaire, ~46% width. Give it a definite height so the
   panel's own overflow-y scroll (.crit-root) resolves. */
.crit-modal-left-col {
    flex: 0 0 46% !important;
    max-width: 46% !important;
    min-width: 0 !important;
    height: calc(100vh - 9rem) !important;
    display: flex !important;
    flex-direction: column !important;
}
/* Left column inner: the questionnaire component fills the column height. */
.crit-modal-left-col .dxbl-fl-item,
.crit-modal-left-col .dxbl-fl-ctrl {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}
.crit-modal-left-col .dxbl-fl-ctrl > * {
    flex: 1 1 auto !important;
    min-height: 0 !important;
}

/* Right column: a vertical stack — the attachment picker (natural height) above the PDF viewer (fills). The
   right column is a LayoutGroup, so its internal group wrappers must also become full-height flex columns. */
.crit-modal-right-col {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    height: calc(100vh - 9rem) !important;
    display: flex !important;
    flex-direction: column !important;
    min-height: 0 !important;
}
.crit-modal-right-col > *,
.crit-modal-right-col .dxbl-fl-group,
.crit-modal-right-col .dxbl-fl-group-items {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}

/* AttachmentSelector hosts the picker bar + the PDF viewer in one component. The crit-pdf-viewer-col fill rules
   below make the .dxbl-pdf-viewer resolve to a definite height; inside the component the bar is fixed and the
   viewer fills the remaining space. */
.crit-attach-host { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.crit-attach-host > .crit-attach-bar { flex: 0 0 auto; }
.crit-attach-host > .crit-attach-viewer { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* The DevExpress PDF viewer's root is .dxbrv-wrapper; without an explicit size it collapses to ~1px in a flex
   parent. Stretch it (and its viewbox) to fill the column so the document renders. */
.crit-attach-host > .crit-attach-viewer > * { flex: 1 1 auto; min-height: 0; min-width: 0; width: 100%; }
.crit-attach-viewer .dxbrv-wrapper { width: 100%; height: 100%; }
.crit-attach-bar { display: flex; align-items: center; gap: 0.6rem; padding: 0 0.25rem 0.6rem; }

/* PDF viewer item fills the rest; mirror the crc-version rules so the DevExpress PDF viewer (height:100%)
   resolves against a definite height. */
.crit-pdf-viewer-col {
    flex: 1 1 auto !important;
    height: auto !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}
.crit-pdf-viewer-col .dxbl-fl-item,
.crit-pdf-viewer-col .dxbl-fl-ctrl {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}
.crit-pdf-viewer-col .dxbl-fl-ctrl > *,
.crit-pdf-viewer-col .dxbl-pdf-viewer {
    flex: 1 1 auto !important;
    height: 100% !important;
    min-height: 0 !important;
}

/* Header controls row inside the left panel (policy + module pickers). */
.crit-header-controls { display: flex; gap: 1rem; flex-wrap: wrap; }
.crit-header-field { display: flex; flex-direction: column; gap: 0.15rem; }
/* Read-only value shown in place of a header selector (classification is set on the Basic Info tab, not here). */
.crit-header-value { font-size: 0.95rem; font-weight: 500; padding: 0.15rem 0; min-height: 1.4rem; }

/* Classification header strip: Policy (+ effective date) / Section / Item. Rendered as a FULL-WIDTH row above
   both modal columns (CriteriaEvaluationHeader), so it spans the questionnaire and the PDF viewer. Replaces the
   removed popup caption. */
.crit-topbar {
    display: flex; flex-wrap: wrap; gap: 1.75rem;
    padding: 0.15rem 0.25rem 0.7rem; margin-bottom: 0.15rem;
    border-bottom: 1px solid rgba(128, 128, 128, 0.3);
}
.crit-header-eff { opacity: 0.6; font-weight: 400; font-size: 0.82rem; margin-left: 0.5rem; white-space: nowrap; }

/* The header's own layout row: natural height (so the two-column body fills the rest), full bleed, aligned to
   the modal's content padding. The border-bottom is the divider between the header and the content below. */
.crit-modal-header-row { flex: 0 0 auto !important; }
.crit-modal-header-row .dxbl-fl-ctrl,
.crit-modal-header-row .dxbl-fl-ctrl > * { padding: 0 !important; margin: 0 !important; }
.crit-topbar-full { padding: 0.5rem 1rem 0.7rem; margin-bottom: 0; }

/* Pin the engine-recommendation bar to the top of the scrolling questionnaire (the left panel, .crit-root, is
   the scroll container) so the Approve/Deny/Pend verdict is always visible. The tint backgrounds are
   translucent (theme-agnostic), so the sticky bar needs an OPAQUE base underneath or scrolled content shows
   through — layer the tint over the panel surface colour (Canvas fallback adapts to light/dark). */
.crit-modal-left { --crit-surface: var(--dxbl-popup-bg, var(--dxbl-panel-bg, var(--dxbl-body-bg, Canvas))); }
/* Dock the verdict flush to the top of the scrolling panel: the panel's own top padding is dropped (below) and
   the bar carries no top margin, so no band is left above the (opaque) bar for scrolled content to peek through. */
.crit-root.crit-modal-left { padding-top: 0; }
.crit-modal-left .crit-verdict {
    position: sticky; top: 0; z-index: 6;
    margin-top: 0;
}
.crit-modal-left .crit-approve { background: linear-gradient(rgba(25, 135, 84, 0.18), rgba(25, 135, 84, 0.18)), var(--crit-surface); }
.crit-modal-left .crit-deny    { background: linear-gradient(rgba(220, 53, 69, 0.18), rgba(220, 53, 69, 0.18)), var(--crit-surface); }
.crit-modal-left .crit-pend    { background: linear-gradient(rgba(128, 128, 128, 0.18), rgba(128, 128, 128, 0.18)), var(--crit-surface); }

/* Launcher on the Review "Clinical Review" tab */
.crit-launch { padding: 1rem 1.25rem; display: flex; flex-direction: column; gap: 0.75rem; max-width: 36rem; }
.crit-launch-title { font-size: 1.1rem; font-weight: 600; }
.crit-launch-summary { display: flex; flex-direction: column; gap: 0.4rem; }
.crit-launch-row { display: flex; align-items: center; gap: 0.6rem; }
.crit-launch-row > .crit-label { min-width: 8rem; }
.crit-launch-months { opacity: 0.75; font-size: 0.85rem; }

/* Clinical Review tab: the case's two adjudications side by side — Evaluation left, Quantity Limit right. The
   tab hosts two panels rather than one, so it needs the full width the launcher otherwise caps. Each panel is a
   bordered column that keeps its Open button at the bottom, so the two line up however tall their summaries run.
   Below ~60rem the pair stacks rather than squeezing two dropdown-width columns into a narrow pane. */
.crit-launch:has(.crit-launch-slots) { max-width: none; }
.crit-launch-row-policy { display: flex; align-items: center; gap: 0.6rem; }
.crit-launch-row-policy > .crit-label { min-width: 8rem; }
.crit-launch-slots { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; max-width: 72rem; }
@media (max-width: 60rem) { .crit-launch-slots { grid-template-columns: minmax(0, 1fr); } }
.crit-launch-slot {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 0.9rem 1rem;
    border: 1px solid var(--crit-border, rgba(128, 128, 128, 0.35));
    border-radius: 0.4rem;
}
.crit-launch-slot > .dxbl-btn { margin-top: auto; align-self: flex-start; }
.crit-launch-slot-title { font-weight: 600; }

/* Basic Info tab: the Policy > Section > Item classification picker (stacked fields), repeated per slot. */
.crit-basic-picker { display: flex; flex-direction: column; gap: 0.6rem; }

/* Basic Info tab: sub-section heading above each picker group (Clinical Criteria / Request Form). */
.crit-basic-section-label {
    font-weight: 600;
    margin: 0.9rem 0 0.4rem;
    opacity: 0.8;
}
.crit-basic-section-label:first-of-type { margin-top: 0; }

/* Basic Info tab: the two classification slots side by side under the (full-width) Policy picker — Evaluation
   left, Quantity Limit right, in the same bordered boxes the Clinical Review tab uses for the pair. Same
   stacking break as there, so two 22rem dropdown columns never get squeezed into a narrow pane. */
.crit-launch:has(.crit-basic-slots) { max-width: none; }
/* Lifting the card's width cap (above) is only so the two slot boxes fit side by side — the card's own pickers
   (Policy, Request Form) keep the width they had, rather than stretching across the freed space. */
.crit-launch > .crit-basic-picker { max-width: 36rem; }
.crit-basic-slots { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; max-width: 72rem; }
@media (max-width: 60rem) { .crit-basic-slots { grid-template-columns: minmax(0, 1fr); } }
.crit-basic-slot {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.9rem 1rem;
    border: 1px solid var(--crit-border, rgba(128, 128, 128, 0.35));
    border-radius: 0.4rem;
}

/* Basic Info tab: the per-slot heading (Evaluation / Quantity Limit) at the top of each box. */
.crit-basic-slot-label { font-weight: 600; font-size: 0.9rem; opacity: 0.75; }

/* Basic Info tab: body of the "this will reset saved answers" confirmation. */
.crit-confirm-body { padding: 0.5rem 0.25rem; line-height: 1.45; }

/* ── Client list: the expanded row showing a client's plans ──────────────────────────────────────────────
   Rendered by Editors/ClientPlansDetailRow.razor into the DxGrid detail row (see
   PBMClient_PlansMasterDetailController). Inset from the master row so the nesting reads at a glance, and the
   nested grid is stripped of the chrome that only makes sense on a top-level list. */
.client-plans-detail { padding: 0.5rem 0.75rem 0.75rem 2.5rem; }
.client-plans-empty { opacity: 0.7; font-style: italic; padding: 0.35rem 0; }
/* Plan rows are click-to-open, so show the affordance. */
.client-plans-grid .dxbl-grid-table > tbody > tr { cursor: pointer; }
