/* ==========================================================================
   1. Design tokens
   Colors sourced from the Reliance Figma file (VP4Jhg5BCCizR0xWbiukuA):
   sidebar/nav navy + white sidebar bg from the Settings/Organization/
   Dashboard frames, auth blue + branding-panel gradient from the
   Login - Officer frame.
   ========================================================================== */
:root {
    --brand-navy: #1E3A8A;
    --black: #000000;
    --brand-blue: #15349d;
    --brand-blue-light: #2563EB;
    --brand-blue-dark: #0f2570;
    --muted-blue-1: #6a79af;
    --muted-blue-2: #7680a3;
    --muted-blue-3: #7983a2;
    --field-label: #404d78;
    --icon-grey: #71717a;
    --border: #dedee0;
    --page-bg: #fafafa;
    --sidebar-bg: #ffffff;
    --nav-active-bg: #e5eaf0;
    --nav-group-label: #94a3b8;
    --white-text: #fcfcfc;
    --branding-gradient-start: #435ab4;
    --branding-gradient-end: #061d5c;
    --red-50: #fef2f2;
    --red-500: #ef4444;
    --doc-select-checked: #2563EB;
    --doc-select-badge: #FF383C;
    --dashboard-stat-red: #b91c1c;
    --dashboard-stat-blue: #414D78;
}

/* ==========================================================================
   2. Base / reset
   ========================================================================== */
html, body { overflow-x: hidden; }
body {
    font-family: 'Inter', Arial, sans-serif;
    background: var(--page-bg);
    margin: 0;
    color: #18181b;
    font-size: 14px;
}

/* ==========================================================================
   3. Authenticated app shell
   ========================================================================== */
.app-shell { display: flex; height: 100vh; overflow: hidden; }

.sidebar {
    width: 225px;
    height: 100%;
    flex-shrink: 0;
    background: var(--sidebar-bg);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
}
.sidebar-brand {
    display: flex; align-items: center; gap: 10px;
    padding: 18px;
}
.sidebar-brand img { height: 46px; }
.sidebar-nav {
    padding: 11px; flex: 1; overflow-y: auto;
    scrollbar-width: none; -ms-overflow-style: none;
}
.sidebar-nav::-webkit-scrollbar { display: none; }
.sidebar-nav-label {
    text-transform: uppercase;
    font-size: 14px;
    font-weight: 400;
    letter-spacing: .05em;
    color: var(--nav-group-label);
    padding: 0 11px;
    margin: 18px 0 8px;
}
.sidebar-nav-label:first-child { margin-top: 6px; }
.sidebar-nav .nav-item {
    display: flex; align-items: center; gap: 11px;
    padding: 9px 11px; border-radius: 8px;
    color: var(--brand-navy); font-size: 14px; font-weight: 500;
    text-decoration: none;
}
.sidebar-nav .nav-item i { width: 16px; text-align: center; font-size: 14px; }
.sidebar-nav .nav-item { transition: background-color 0.15s ease; }
.sidebar-nav .nav-item:not(.active):not(.disabled):hover { background: #F5F7F9; }
.sidebar-nav .nav-item.active { background:#e9f1fa; }
.sidebar-nav .nav-item.disabled {
    color: #b6bbd6;
    cursor: default;
    pointer-events: none;
}
.sidebar-nav button.nav-item {
    width: 100%; background: none; border: none; cursor: pointer;
    font-family: inherit; text-align: left;
}
.nav-subnav { display: flex; flex-direction: column; gap: 2px; margin-top: 2px; }
.nav-subnav .nav-item-sub { padding-left: 34px; font-size: 14px; }
/* Delegations count. margin-left:auto rather than a spacer element - .nav-item
   is already a flex row, so the badge pushes itself to the far edge and the
   label keeps its natural gap from the icon. Only rendered when non-zero, so
   there is no empty-pill state to style. */
.nav-badge {
    margin-left: auto;
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 20px; height: 20px; padding: 0 6px;
    border-radius: 10px;
    background: var(--brand-blue-light); color: #fff;
    font-size: 11px; font-weight: 600; line-height: 1;
}
.sidebar-footer { padding: 11px; border-top: 1px solid var(--border); }
.sidebar-footer .nav-item {
    display: flex; align-items: center; gap: 11px;
    width: 100%; padding: 9px 11px; border: none; border-radius: 8px;
    background: none; cursor: pointer;
    color: var(--brand-navy); font-size: 14px; font-weight: 500;
    font-family: inherit; text-align: left;
    transition: background-color 0.15s ease;
}
.sidebar-footer .nav-item:not(.disabled):hover { background: #F5F7F9; }

.loading-container{
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
}

.main-area { flex: 1; min-width: 0; height: 100%; overflow-y: auto; }
.topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    background: #fff;
    border-bottom: 1px solid var(--border);
    padding: 18px 24px;
    font-size: 14px;
    color: var(--nav-group-label);
    /* The New-quotation/avatar/hamburger actions must never drop below the
       greeting onto a second line, at any viewport width - but the markup
       also carries Bootstrap's .flex-wrap utility (wrap !important) for
       other pages' topbar_actions content, which lets the row itself break
       in two whenever the identity block's preferred width doesn't fit
       alongside the actions. !important beats the utility class regardless
       of breakpoint. The identity block (.topbar-identity: min-width:0,
       flex:1 1 auto) absorbs the squeeze instead - its own greeting text
       wraps onto a second line internally rather than the row splitting.
       align-items also overrides Bootstrap's align-items-center utility:
       centering against a now-possibly-2-line identity block would push
       the actions off-center relative to the greeting's first line: top-
       aligning keeps them level with it regardless of how many lines the
       greeting wraps to. */
    flex-wrap: nowrap !important;
    align-items: flex-start !important;
}
/* Vertically centers just the greeting block within the topbar's height
   (the actions side - avatar/New Quotation button/hamburger - is usually
   taller, which otherwise leaves the single-line greeting pinned to the
   top with empty space below it). Scoped to this one flex item via
   align-self rather than changing .topbar's align-items: when the greeting
   wraps to 2 lines and becomes the tallest sibling, centering a block
   against its own full height is a no-op, so the actions stay level with
   its first line exactly as before - the invariant above still holds. */
.topbar-identity { align-self: center; }
.topbar strong { color: #18181b; }

/* Notification bell + panel (design_html/Notifications Panel.html) */
.nf { position: relative; display: flex; }
.nf-bell {
    position: relative; display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border: 1px solid var(--border); border-radius: 10px;
    background: #fff; color: #27272a; cursor: pointer;
}
.nf-bell:hover, .nf-bell[aria-expanded="true"] { background: #f4f5f7; }
.nf-bell[aria-expanded="true"] { border-color: #cdd0d8; }
.nf-bell:active { background: #ebedf1; }
.nf-bell svg, .nf-bell img { display: block; }
.nf-badge {
    position: absolute; top: -5px; right: -5px;
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
    border: 2px solid #fff; background: #dc2626; font-size: 10.5px; font-weight: 700;
    color: #fff; line-height: 1;
}
/* Higher specificity than .nf-badge's own display:inline-flex, so the
   [hidden] attribute (toggled server-side via the poll's OOB badge swap)
   reliably hides it at zero unread rather than losing to the class rule. */
.nf-badge[hidden] { display: none; }
/* .nf-pop sizing/visuals only - position/visibility are Bootstrap's own
   .dropdown-menu, not the mockup's absolute-positioned popover. */
.nf-pop {
    width: 400px; max-width: calc(100vw - 32px);
    border-radius: 14px; overflow: hidden; padding: 0;
    box-shadow: 0 2px 8px rgba(0,0,0,.06), 0 -6px 12px rgba(0,0,0,.03), 0 14px 28px rgba(0,0,0,.08);
}
.nf-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 24px 12px; }
.nf-head__title { display: flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 600; }
.nf-new { display: inline-flex; align-items: center; height: 20px; padding: 0 7px; border-radius: 10px; background: #dbeafe; font-size: 11.5px; font-weight: 600; color: #1d4ed8; }
.nf-readall { height: 28px; padding: 0 8px; border: none; border-radius: 7px; background: transparent; font-size: 12.5px; font-weight: 600; color: #1d4ed8; cursor: pointer; }
.nf-readall:hover { background: #eff6ff; }

.nf-jobs { display: flex; flex-direction: column; gap: 8px; padding: 4px 12px 8px; }
.nf-job { display: grid; grid-template-columns: 32px minmax(0,1fr) auto; column-gap: 12px; align-items: center; padding: 12px; border-radius: 10px; background: #eff6ff; transition: background 150ms ease; text-decoration: none; }
.nf-job:hover { background: #dbeafe; }
.nf-job__spin { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; background: #fff; color: #1d4ed8; }
.nf-job__spin svg { display: block; animation: nf-spin 800ms linear infinite; }
.nf-job__title { font-size: 13.5px; font-weight: 600; line-height: 1.4; color: #1e3a8a; }
.nf-job__id { margin-top: 2px; font-size: 12.5px; line-height: 1.45; color: #1d4ed8; font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@keyframes nf-spin { to { transform: rotate(360deg); } }

.nf-list { display: flex; flex-direction: column; gap: 8px; max-height: 460px; overflow-y: auto; margin: 0; padding: 0 12px 12px; list-style: none; }
.nf-item { padding: 0; border-radius: 10px; }
.nf-item-link {
    display: block; width: 100%; padding: 12px; border: none; background: none;
    text-align: left; border-radius: 10px; cursor: pointer; transition: background 150ms ease;
    font-family: inherit;
}
.nf-item-link:hover { background: #fafafb; }
.nf-item-link:active { background: #f4f4f5; }
.nf-item__title { font-size: 13.5px; font-weight: 500; line-height: 1.4; color: #18181b; text-wrap: pretty; }
.nf-item--unread .nf-item__title { font-weight: 600; }
.nf-item__id { margin-top: 2px; font-size: 12.5px; line-height: 1.45; color: #64748b; font-variant-numeric: tabular-nums; }
.nf-item__meta { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.nf-item__time { font-size: 11.5px; color: #94a3b8; }

.nf-tag { display: inline-flex; align-items: center; gap: 5px; height: 20px; padding: 0 8px; border-radius: 10px; font-size: 11px; font-weight: 600; }
.nf-tag::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.nf-tag--sent { background: #dcfce7; color: #15803d; }
.nf-tag--failed, .nf-tag--revoked { background: #fee2e2; color: #b91c1c; }
.nf-tag--delegation { background: #dbeafe; color: #1d4ed8; }

.nf-empty { padding: 36px 20px; text-align: center; font-size: 13.5px; color: #71717a; }

.content-area { padding: 24px 24px;}
.content-area-detail { margin: 0 auto; width: 100%; }

/* Opt-in sticky variant for a detail page's own breadcrumb+actions row (see
   quotation_detail.html) - stays visible beneath the already-sticky .topbar
   as the page scrolls. top tracks --topbar-h (set by a ResizeObserver in
   reliance.js) rather than a fixed value, since .topbar's own height isn't
   constant - a long officer name wraps its greeting to a second line (see
   .topbar-identity above). The 77px fallback matches .topbar's usual
   single-line height for the instant before that JS runs on first paint. */
.page-sticky-header {
    position: sticky;
    top: var(--topbar-h, 77px);
    z-index: 10;
    background: var(--page-bg);
    padding: 12px ;
}

.employee-list-name{
    font-weight: 500;
    color: #18181b;
}

.employee-list-role{
    color: #6C727E;
    font-size: 12px;
}
/* Sub-text under a name next to an avatar (Quotations/Cover notes' officer
   column, Settings) - pinned to 12px rather than Bootstrap's relative
   .small (0.875em of the base font-size), matching .employee-list-role
   above. */
.officer-identity .small,
.settings-identity .small,
.settings-report-body .small {
    font-size: 12px;
}
/* ==========================================================================
   4. Pre-auth split-screen layout
   ========================================================================== */
.auth-shell { display: flex; min-height: 100vh; }
.auth-branding-panel {
    flex: 1 1 42%;
    max-width: 460px;
    background: linear-gradient(160deg, var(--branding-gradient-start), var(--branding-gradient-end));
    color: #fff;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 48px;
    position: relative;
    overflow: hidden;
}
.auth-branding-panel::before,
.auth-branding-panel::after {
    content: "";
    position: absolute;
    border-radius: 50%;
    filter: blur(40px);
    opacity: .55;
}
.auth-branding-panel::before {
    width: 320px; height: 320px;
    background: #44baff;
    top: -80px; right: -100px;
}
.auth-branding-panel::after {
    width: 260px; height: 260px;
    background: #455dc9;
    bottom: 60px; right: -60px;
}
.auth-branding-panel .auth-wordmark {
    position: relative;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.15;
    margin: 0;
}
.auth-branding-panel .auth-wordmark .brokers { display: block; color: var(--muted-blue-3); }
.auth-branding-panel .auth-tagline {
    position: relative;
    color: var(--muted-blue-2);
    font-size: 14px;
    margin: 10px 0 0;
}
.auth-form-panel {
    flex: 1 1 58%;
    background: #fff;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 48px;
}
/* Fluid instead of a fixed 90px - same clamp() pattern as .topbar-greeting/
   .mobile-stat-card .stat-tile-label: shrinks smoothly down to a legible
   floor on a narrow phone's auth-form-panel (padding 32px 24px below
   768px) rather than needing its own breakpoint, and is already at the
   original 90px by normal desktop widths. */
.auth-form-panel .auth-logo { height: clamp(56px, 18vw, 90px); margin-bottom: clamp(20px, 6vw, 32px); }
.auth-card { max-width: 393px; width: 100%; }
.auth-heading { color: var(--brand-blue); font-weight: 600; font-size: 14px; margin: 0 0 4px; }
.auth-subheading { color: var(--muted-blue-1); font-size: 14px; margin: 0 0 24px; }
.auth-form-panel .form-label { color: var(--field-label); font-weight: 400; font-size: 14px; margin-bottom: 12px; }

/* Segmented OTP digit boxes. Each box is flex:1 1 0 with a max-width cap
   (not a fixed width/height) so all 6 shrink together to fit the
   container on a narrow phone instead of overflowing it - the auth card's
   mobile padding (see .auth-form-panel below) leaves less room than the
   6 boxes' combined fixed 45px width + gaps needed. aspect-ratio keeps
   each box square at whatever width it lands on, so this also just
   reproduces the original fixed 45x45px look unchanged on desktop, where
   there's enough room for every box to reach its cap. */
.otp-boxes { display: flex; align-items: center; gap: 8px; }
.otp-box {
    flex: 1 1 0;
    max-width: 45px;
    aspect-ratio: 1;
    text-align: center;
    font-size: 14px;
    border: 1px solid var(--border);
    border-radius: 12px;
}
.otp-box:focus { border-color: var(--brand-blue); box-shadow: 0 0 0 3px rgba(21, 52, 157, 0.15); outline: none; }
.otp-dash { color: var(--muted-blue-1); font-size: 14px; padding: 0 2px; }

/* ==========================================================================
   5. Shared components
   ========================================================================== */
.card {
    border: 1px solid #F1F5F9;
    border-radius: 12px;
}
/* The currently-active master excel file's card (Maintain excel calculator
   page) - same blue as its "Currently in use" badge, so the active file is
   obviously distinct from the history list below it. */
.master-excel-active-card {
    border: 1px solid #0485F7;
}
.org-tabs { display: flex; gap: 24px; border-bottom: 1px solid var(--border); }
.org-tab {
    padding: 10px 2px; font-size: 14px; font-weight: 500; color: black;
    text-decoration: none; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.org-tab:hover { color: var(--brand-navy); }
.org-tab.active { border-bottom-color: #0485F7; font-weight: 600; }
.section-heading { color: #18181b; font-weight: 600; font-size: 16px; margin-bottom: 8px; }
.section-subheading { color: #64748B; font-size: 14px; }
/* Quotation Details card (partials/_quotation_details_summary.html) - a
   muted divider under each column heading only, not between every row;
   label/value pairs are plain inline text (not a table), compactly spaced,
   with the value in a muted color so it reads as secondary to the label. */
.quotation-details-card {
    /* Figma spec: 16px radius, 1px colors/slate/100 border - overrides the
       shared .card's 12px/var(--border) look, which other cards keep as-is. */
    border-radius: 16px;
    border-color: #f1f5f9;
    background: #fff;
}
.quotation-details-card .section-heading {
    /* Figma "Quotation Details" text layer uses the "Body base medium" style
       (dimensions/font/text-base 16px / dimensions/leading/text-base 24px,
       weight 500) - scoped here rather than changed on .section-heading
       itself, which is shared by other cards' bold 700 headings. */
    line-height: 24px;
    margin-bottom: 16px;
    font-size: 14px;
    color:#0485F7 ;
}
/* "View more"/"View less" toggle - plain text button (no border/fill),
   matching the Figma reference's muted link treatment rather than any of
   the app's bordered .btn-reliance* variants. */
.card-toggle-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
    border: none;
    background: none;
    padding: 0;
    font-size: 14px;
    font-weight: 400;
    color: var(--icon-grey);
}
.card-toggle-link:hover { color: #18181b; }
.card-toggle-link i { font-size: 12px; }
.quotation-details-card h3 {
    /* Figma "Vehicle and policy details" / "Cover and Benefits" text layers:
       Inter, weight 600 (Semi Bold), 14px, line-height 18.75px. Stays scoped
       to .quotation-details-card - h3 is a generic tag used elsewhere on the
       page, unlike .detail-row/.detail-label/.detail-value below, which are
       specific to this card and don't need the same scoping. */
    font-size: 14px;
    font-weight: 600;
    line-height: 18.75px;
    border-bottom: 1px solid var(--border);
    padding-bottom: 6px;
    margin-bottom: 12px;
}
.detail-row {
    margin-bottom: 12px;
    font-size: 14px; /* Figma dimensions/font/text-sm */
    line-height: 20px; /* Figma dimensions/leading/text-sm */
}
.detail-label { font-weight: 400; }
.detail-value { color: var(--icon-grey); }
/* Collapsed state (.quotation-details-card without .is-expanded, toggled by
   "View more"/"View less" in reliance.js): Vehicle and policy details takes
   the full card width instead of its normal 4-column slice, and its rows
   flow left-to-right in one line (wrapping if the card is too narrow)
   instead of stacking - Cover and Benefits is hidden either way, so there's
   no reason to leave the row squeezed into a third of the card. Expanded
   reverts to plain Bootstrap col-md-4 + the stacked .detail-row default
   above - nothing to override there, .is-expanded only exists to gate this
   collapsed-only rule. */
.quotation-details-card:not(.is-expanded) #quotation-vehicle-details {
    flex: 0 0 100%;
    max-width: 100%;
}
.quotation-details-card:not(.is-expanded) #quotation-vehicle-details .detail-rows {
    display: flex;
    flex-wrap: wrap;
    column-gap: 32px;
    row-gap: 8px;
}
.quotation-details-card:not(.is-expanded) #quotation-vehicle-details .detail-row {
    margin-bottom: 0;
}
.btn-reliance {
    background-color: var(--brand-navy);
    border-color: #0486f700; color: #fff;
    border-radius: 8px; padding: 8px 18px; font-size: 14px; font-weight: 500;
}
.btn-reliance:hover { background: var(--brand-blue-dark); border-color: var(--brand-blue-dark); color: #fff; transition: 30ms;}
/* Bootstrap dims disabled buttons to 65% opacity by default - skip that here
   since these buttons are disabled only for the duration of an in-flight
   hx-disabled-elt request, and the spinner already communicates "busy". */
.btn-reliance:disabled {
    opacity: 1;
    color: var(--icon-grey);
    background: #e5eaf0;
}
/* Every modal's primary action gets the brighter brand-blue-light instead of
   .btn-reliance's own navy - scoped to .modal rather than changed globally,
   since other .btn-reliance buttons (page-level Save/Add actions) keep navy.
   Doesn't touch .btn-danger (warning/delete modals' red primary action) -
   different class entirely, so those are unaffected by design. :not(:disabled)
   keeps this from out-specificity-tying .btn-reliance:disabled above (same
   0,2,0 specificity) and painting a disabled button blue instead of grey. */
.modal .btn-reliance:not(:disabled) {
    background-color: var(--brand-blue-light);
    border-color: var(--brand-blue-light);
}
/* :not(:disabled) above outranks the plain .btn-reliance:hover rule's
   specificity, which would otherwise freeze a modal button at brand-blue-light
   with no hover feedback - restate the same darken-on-hover here instead. */
.modal .btn-reliance:not(:disabled):hover {
    background-color: var(--brand-blue-dark);
    border-color: var(--brand-blue-dark);
}
/* Same brand-blue-light swap as the .modal rule above, for page-level
   primary actions outside a modal (Login/Verify OTP/forced password change,
   Excel Test's and the real Quotation form's "Generate Quotations", Cover
   notes' "Policy issued" trigger) - add alongside btn-reliance wherever a
   navy primary button is being migrated to the new blue. */
.btn-reliance-primary:not(:disabled) {
    background-color: var(--brand-blue-light);
    border-color: var(--brand-blue-light);
}
.btn-reliance-primary:not(:disabled):hover {
    background-color: var(--brand-blue-dark);
    border-color: var(--brand-blue-dark);
}
/* Reusable base for CSS-mask icons (see the Send button in
   templates/partials/_quotation_bank_quote_form.html and friends):
   each caller sets mask-image/-webkit-mask-image inline to the specific SVG.
   Uses currentColor by default so the icon follows the button's text color
   without a separate override. */
.icon-mask {
    display: inline-block;
    width: 16px;
    height: 16px;
    background-color: currentColor;
    vertical-align: middle;
    flex-shrink: 0;
    mask-repeat: no-repeat;
    mask-size: contain;
    mask-position: center;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    -webkit-mask-position: center;
}
.form-label {
    font-size: 14px; font-weight: 400; color: #18181b; margin-bottom: 6px;
}
.form-control {
    border: 0.5px solid #D3D6E0; border-radius: 12px; font-size: 14px; color: #414D78; max-width: 300px;
}
/* Textareas opt out of the 300px cap above. That width is right for the
   single-line inputs the two-up form rows are built around, but it squeezes a
   multi-line box into a column narrower than the text it holds. Fields inside
   .field-row-body keep the cap (higher specificity wins): that form's whole
   point is a uniform 300px value column. */
textarea.form-control { max-width: none; }
/* Auth forms (login, etc.) are single-column and sized to .auth-card, so the
   300px cap above - built for two-up form rows - would leave inputs
   narrower than the full-width (w-100) submit button below them. The
   password field's own wrapper carries a matching 300px cap (see
   .password-field below) that needs uncapping here too. */
.auth-card .form-control,
.auth-card .password-field { max-width: none; }
.form-control:focus { border-color: var(--brand-blue); box-shadow: 0 0 0 3px rgba(21, 52, 157, 0.15); }
/* Chrome/Safari paint an autofilled field with a pale blue wash via an internal
   box-shadow that `background` can't override - repaint it to the neutral grey
   used for a filled field. The 5000s transition is the standard trick to stop
   the native colour flashing first. */
.form-control:-webkit-autofill,
.form-control:-webkit-autofill:hover,
.form-control:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 1000px #F3F4F6 inset;
    -webkit-text-fill-color: #414D78;
    caret-color: #414D78;
    transition: background-color 5000s ease-in-out 0s;
}

/* Gap between stacked sub-sections within one merged card (e.g. User
   profile / Additional Details / Email signature on officers/form.html) -
   plain spacing instead of an <hr> divider, which read as visual clutter
   between sections that already have their own headings. No matching
   Bootstrap spacer utility goes this large (mt-5 tops out at 48px, which
   this happens to match exactly). */
.form-section-gap {
    margin-top: 48px;
}

/* Short numeric/time fields (reminder day, nearing-expiry window bounds):
   .form-control's 300px cap is sized for text, which leaves a 1-2 digit box
   looking mostly empty. Goes on the field's wrapper, not the input. */
.form-field-narrow {
    max-width: 9rem;
}

/* Two-up form fields: with inputs capped at max-width 300px, Bootstrap's
   .row/.col-md-6 split leaves a wide empty gap between the pair. This keeps
   them side by side with a fixed 32px gutter (16px row-gap once they wrap on
   narrow screens). Applied to the field row wrapper in place of .row. */
.form-row-2col {
    display: flex;
    flex-wrap: wrap;
    gap: 16px 32px;
    margin: 0;
}
.form-row-2col > [class*="col-"] {
    flex: 0 1 300px;
    max-width: 300px;
    min-width: 0;
    padding: 0;
}
/* Money columns: put .amount-cell on both the <th> and the <td> so the header sits
   over the digits. The type below is the Figma spec for numeric values (Inter Bold,
   paragraph-s); it is scoped to the <td> so headers keep their own table type.
   tabular-nums stays on top of it - Inter's proportional figures make a
   right-aligned column look ragged without it. */
.amount-cell {
    text-align: right; white-space: nowrap;
}
td.amount-cell {
    font-family: inherit;
    font-weight: 700;
    font-size: 14px;
    line-height: 20px;
    letter-spacing: 0;
    vertical-align: middle;
    font-variant-numeric: tabular-nums;
    color: #2563EB;
}

.icon-button{
    display: inline-flex;
    justify-content: center;
    align-items: center;
    gap: 4px;
}

/* ==========================================================================
   6. Dropzone widget
   ========================================================================== */
.dropzone {
    border: 2px dashed var(--border);
    border-radius: 8px;
    padding: 24px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    cursor: pointer;
    color: var(--nav-group-label);
    font-size: 14px;
    background: #fff;
    transition: border-color .15s, background-color .15s;
}
/* Cover note per-document attachment grid only - a hard height (not just a
   floor) so every box in the grid stays the same size regardless of how
   many pills it holds, with overflow:hidden as a quiet safety net (no
   scrollbar) for the rare case content exceeds it. Scoped here rather than
   on the shared .dropzone above, which other single-file upload zones
   elsewhere in the app also use and shouldn't be constrained like this. */
.dropzone-fixed-height {
    height: 210px;
    overflow: hidden;
}
.dropzone.dragover { border-color: var(--brand-blue); background: rgba(21, 52, 157, 0.05); }
.dropzone.is-invalid { border-color: #dc3545; }
.dropzone .dropzone-icon { font-size: 14px; color: var(--nav-group-label); margin-bottom: 4px; }
.dropzone .dropzone-browse { color: var(--brand-blue); font-weight: 600; text-decoration: underline; }
.dropzone .dropzone-filename { font-weight: 600; color: #18181b; font-size: 14px; }
.dropzone-attachments {
    min-height: 60px;
    width: 100%;
}
.dropzone input[type="file"] { display: none; }

/* Framed preview of a saved email signature image - the Settings page's own
   card and the admin Add/Edit Employee page's Email signature card. */
.signature-preview {
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 16px;
    background: #fff;
    overflow-x: auto;
}
.signature-preview img { max-width: 100%; height: auto; }

/* ==========================================================================
   8. HTMX utility
   ========================================================================== */
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator { display: inline-block; }
.htmx-request.htmx-indicator { display: inline-block; }

/* ==========================================================================
   10. Additional form controls (quotation form's outline button, selects,
   checkboxes)
   ========================================================================== */
/* 8px radius / 6px-12px padding per the Figma spec recorded in
   docs/design-notes/new-quotation-figma-notes.md - this was a pill before,
   which never matched the design on any screen using it. */
.btn-reliance-outline {
    background: #fff; border: 1px solid var(--border); color: #18181b;
    border-radius: 8px; padding: 6px 12px; font-size: 14px; font-weight: 500;
}
.btn-reliance-outline:disabled{
    border-color: var(--border); color: var(--icon-grey);
}
.btn-reliance-outline:disabled img { opacity: 0.5; }

.btn-reliance-outline:hover { background: #f8f9fa; border-color: var(--border); color: #18181b; }
/* The cover note reminder's "Send email" action (Nearing Expiry list row and
   the workspace's nearing-expiry banner) - #EA580C matches the orange
   already used for the nearing-expiry accent, see
   static/img/NearingExpiry-orange.svg and .expiry-dot-nearing. */
.btn-reliance-reminder {
    background: #EA580C; border-color: #EA580C; color: #fff;
    border-radius: 10px; padding: 8px 18px; font-size: 14px; font-weight: 500;
}
.btn-reliance-reminder:hover { background: #C2410C; border-color: #C2410C; color: #fff; }
/* Same shape as .btn-reliance-outline (Delete task, next to Save this
   task/Send to email to bank) but in red, since it's a destructive action. */
.btn-reliance-outline-danger {
    background: #fff; border: 1px solid var(--border); color: #dc3545;
    border-radius: 8px; padding: 6px 12px; font-size: 14px; font-weight: 500;
}
.btn-reliance-outline-danger:hover { background: #f8f9fa; border-color: var(--border); color: #dc3545; }
/* Bootstrap's .btn-outline-secondary (e.g. the modal "Cancel" buttons) ships
   with Bootstrap's default border-radius; match the 8px used across the
   .btn-reliance* family. */
.btn-outline-secondary { border-radius: 8px; }
/* Topbar "New Motor Quotation" button - dedicated one-off style, not part of
   the .btn-reliance* family. Only ever visible at >=768px (d-md-inline-flex
   in base.html), so sizes scale fluidly across that desktop/tablet range
   rather than all the way down to phone widths - same clamp() approach as
   .topbar-greeting / .mobile-stat-card .stat-tile-label. */
.btn-new-quotation {
    background: radial-gradient(ellipse at 2% 10%, #243EB0 0%, #0F1A4A 100%);
    color: #FCFCFD;
    font-family: 'Inter', sans-serif;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.15;
    letter-spacing: 0;
    border: none;
    border-radius: clamp(10px, 1.2vw, 12px);
    padding: clamp(8px, 1.4vw, 12px) clamp(10px, 1.6vw, 12px);
}
.btn-new-quotation:hover{
    background: radial-gradient(ellipse at 2% 10%, #1D2D60 0%, #061D5C 100%);
    color: #FCFCFD;
}
.form-select {
    border: 0.5px solid #D3D6E0; border-radius: 12px; font-size: 14px; color: #18181b; max-width: 300px;
}
.form-select:focus { border-color: var(--brand-blue); box-shadow: 0 0 0 3px rgba(21, 52, 157, 0.15); }
.form-select option[value=""] { color: var(--icon-grey); }
.form-select:has(option[value=""]:checked) { color: var(--icon-grey); }
.form-check-input { border-color: #DEDEE0; border-radius: 6px; }
.form-check-input[type="radio"] { border-radius: 50%; }
.form-check-input:checked { background-color: var(--doc-select-checked); border-color: var(--doc-select-checked); }
.form-check-input:focus { border-color: var(--doc-select-checked); box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15); }
#required-document-table .form-check-input:disabled { opacity: 1; }
/* Bootstrap's checked fill (--doc-select-checked, blue) reads as "already
   active/editable" - wrong signal for a disabled checkbox the officer can't
   touch until they click Edit. Gray it specifically for the disabled+checked
   case so the row's edit-locked state is visually obvious at a glance. */
#required-document-table .form-check-input:disabled:checked {
    background-color: var(--icon-grey);
    border-color: var(--icon-grey);
}

/* Personal/Corporate header text ("Required for personal/corporate
   quotations") is long enough that an auto-layout <table> (inside
   .table-responsive, which scrolls rather than compresses columns) just
   gives the <th> however much width its unwrapped content needs, ignoring a
   plain width/max-width on the cell itself. Constraining an inner
   inline-block span instead forces the wrap the <br> asks for, which in turn
   caps how wide the column can grow - left-aligning both header and
   checkbox then keeps the two columns, and the checkboxes inside them, as
   close together as that width allows. */
.required-document-category-label {
    display: inline-block;
    width: 150px;
    white-space: normal;
    font-weight: 500;
}
.required-document-category-cell { text-align: left; }
/* #required-document-table, not just the class: every non-action column in
   a .mobile-card-table gets a 64px padding-right "gutter" from the shared
   `.mobile-card-table ... td:not(.table-action-col)` rule further down,
   whose :not() chain outranks a single class here - a plain
   .required-document-category-cell--personal { padding-right: ... } was
   silently losing to it. The id makes sure this one wins instead. */
#required-document-table .required-document-category-cell--personal { padding-right: 32px; }
#required-document-table .required-document-category-cell--corporate { padding-left: 4px; }

/* --------------------------------------------------------------------------
   Custom select - progressive enhancement of every <select class="form-select">
   by initCustomSelects() in reliance.js. The native <select> stays in the DOM
   and still holds the value / submits / resets; this is a styled listbox
   layered over it, because a native <option> popup can't be styled (its row
   padding, spacing, and corner radius are all OS-drawn). With reliance.js
   blocked the native select just shows through unchanged.
   -------------------------------------------------------------------------- */
.rs-select { position: relative; width: 100%; max-width: 300px; }
.field-row-body .rs-select { max-width: 300px; }

/* Native control kept for form submission + reset(), taken out of sight and
   the tab order - the trigger button stands in for it. Not display:none so a
   <label for> click still lands somewhere (reliance.js forwards that focus to
   the trigger). */
.rs-select-native {
    position: absolute; width: 1px; height: 1px;
    opacity: 0; pointer-events: none; margin: 0;
}
/* Bootstrap's own .form-select:disabled resets opacity to 1 (undoing the
   browser's default dimming so its own disabled look applies instead) - same
   specificity as the rule above, so a disabled select loses the opacity:0
   hide and its native chevron peeks through at this element's 1x1px corner.
   Re-declaring it here wins the tie: this rule and Bootstrap's are equally
   specific, and this one loads after Bootstrap's stylesheet. */
.rs-select-native:disabled { opacity: 0; }

.rs-select-trigger {
    display: flex; align-items: center; width: 100%;
    text-align: left;
}
.rs-select-trigger > .rs-select-label {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rs-select-trigger.rs-placeholder > .rs-select-label { color: var(--icon-grey); }
.rs-select[data-open="true"] .rs-select-trigger {
    border-color: var(--brand-blue);
    box-shadow: 0 0 0 3px rgba(21, 52, 157, 0.15);
}

.rs-select-menu {
    position: absolute; left: 0; right: 0; top: calc(100% + 6px);
    z-index: 1080;                       /* above Bootstrap modals (1055) */
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 16px;
    box-shadow: 0 12px 32px rgba(16, 24, 40, 0.12);
    padding: 8px;
    max-height: 288px; overflow-y: auto;
    /* left:0/right:0 ties the menu to the trigger's own width, which for a
       narrow trigger (e.g. the 2-letter vehicle_number_prefix select, wrapped
       at max-width:100px in _quotation_form.html) wraps option text like
       "Remove Selection" into a near-unreadable column. min-width lets the
       menu overflow past a narrow trigger's right edge instead. */
    min-width: 180px;
}
.rs-select-menu--up { top: auto; bottom: calc(100% + 6px); }

/* Non-selectable prompt at the top of the menu, in place of Django's
   "---------" blank option (see placeholderTextFor() in reliance.js). */
.rs-select-heading {
    padding: 12px 16px 8px;
    font-size: 14px;
    color: #71717A;
}

.rs-select-optgroup {
    padding: 8px 12px 4px; font-size: 14px; font-weight: 600;
    color: var(--icon-grey); text-transform: uppercase; letter-spacing: .02em;
}
.rs-select-option {
    padding: 8px 8px; border-radius: 10px; font-size: 14px;
    color: #18181b; cursor: pointer; user-select: none;
}
.rs-select-option[aria-selected="true"] { font-weight: 600; }
.rs-select-option.is-active,
.rs-select-option:hover { background: #EFF6FF; color: var(--brand-blue); }
.rs-select-option.is-active { color: #2563EB; }
.rs-select-option.rs-placeholder { color: var(--icon-grey); }
.rs-select-option[aria-disabled="true"] { opacity: .5; cursor: default; }
.rs-select-option[aria-disabled="true"]:hover { background: transparent; color: #18181b; }

/* ==========================================================================
   11. Read-only form field rows (partials/_readonly_field_row.html) - shared
   by quotation/cover note detail views and, now, officer/cluster read-only
   pages
   ========================================================================== */
.field-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
    padding: 14px 0;
    border-bottom: 1px solid var(--border);
}
.field-row:last-child { border-bottom: none; }
.field-row-label {
    width: 280px;
    flex-shrink: 0;
    font-size: 14px;
    font-weight: 500;
    color: #18181b;
    white-space: nowrap;
}
.field-row-label--indented {
    padding-left: 24px;
}
.required-marker {
    color: #dc3545 !important;
    margin-left: 2px;
}
.field-row-body {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    flex: 1;
    min-width: 0;
}
.field-row-body .form-control,
.field-row-body .form-select {
    max-width: 300px;
}
.field-group {
    display: flex;
    align-items: center;
    gap: 10px;
}
.field-group-label {
    font-size: 14px;
    color: #18181b;
    white-space: nowrap;
}
.field-suffix {
    font-size: 14px;
    color: var(--nav-group-label);
    white-space: nowrap;
}
/* Own line under the input - .field-row-body is a wrapping flex row. */
.field-row-body .field-error { flex-basis: 100%; margin-top: -6px; }
.field-row-body .field-error:empty { display: none; }
.rs-select:has(.rs-select-native.is-invalid) .rs-select-trigger { border-color: var(--bs-form-invalid-border-color, #dc3545); }

/* partials/_detail_field_row.html - plain label/value pairs for fully
   read-only pages (officer/cluster "View"). Own label/value colors rather
   than reusing .field-row-label (dark, meant for editable-form labels) -
   here the label is the muted side and the value is what should read. */
.detail-field-row {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 0;
}
.detail-field-label {
    width: 160px;
    flex-shrink: 0;
    font-size: 14px;
    color: var(--icon-grey);
}
.detail-field-value {
    font-size: 14px;
    font-weight: 700;
    color: #18181b;
}
.detail-field-suffix {
    font-weight: 500;
    color: var(--icon-grey);
}
@media (max-width: 575.98px) {
    .detail-field-row { flex-direction: column; gap: 4px; }
    .detail-field-label { width: 100%; }
}

/* ==========================================================================
   12. Insurer-request recipient chips
   ========================================================================== */
/* white-space:nowrap - same reason as .status-pill: without it, a chip in
   a narrow/unconstrained container (e.g. a long typed email in a compose
   modal) wraps its text inside the flex box and border-radius:999px turns
   it into a circle. The chip just grows wider instead; .mail-to-chips'
   own flex-wrap already wraps multiple chips onto new lines as needed. */
.chip {
    background: #F3F4F6;
    color: #353535;;
    border-radius: 999px;
    padding: 4px 12px;
    font-size: 14px;
    white-space: nowrap;
}
.chip-remove {
    background: none;
    border: none;
    color: var(--brand-navy);
    line-height: 1;
    padding: 0 4px;
    cursor: pointer;
}
/* Cover note attachment chips (PDF pills) - neutral grey, darkening on hover
   for the interactive ones (<a>/<button> that open the document). */
.chip-file { background: #EBEBEC; color: #2e2e2e; height: 26px; line-height: 1; }
.chip-file .chip-file-link { color: inherit; text-decoration: none; }
.chip-file .chip-file-link:hover { text-decoration: underline; }

/* Recipient chips in the Email center whose send to that address bounced. */
.chip-failed { background: #FEE2E2; color: #991B1B; }

.mail-chip {
    background: transparent;
    border: 1px solid #1D63AE;
    color: #1D63AE;
}
.mail-chip .chip-remove {
    color: #1D63AE;
}
/* The cover note preview chip is a <button> (it opens a panel, it does not
   navigate), so undo the border and font the UA gives buttons - .chip was
   written for anchors and spans and sets neither. */
button.chip { border: none; font-family: inherit; cursor: pointer; }
button.chip:hover { background: rgba(4, 133, 247, 0.2); }
button.chip:focus-visible { outline: 2px solid var(--brand-blue); outline-offset: 1px; }
/* Two classes so this beats button.chip:hover above for the PDF preview chips;
   .mail-chip keeps its own transparent/bordered treatment. */
.chip.chip-file:not(.mail-chip):hover { background: #D9D9D9; }
.chip-file .chip-remove { color: #1d63ae; }
.bcc-indicator {
    flex-shrink: 0;
    font-size: 14px;
    color: var(--nav-group-label);
    padding-top: 4px;
}

/* ==========================================================================
   13. Gmail-style compose layout for the send-email modals (insurer
   request, bank quote, cover note)

   Bootstrap's .modal-dialog-scrollable already turns .modal-content into a
   fixed-height flex column with .modal-body as the one scrolling element -
   rather than fight that with a 4-region header/body/footer split,
   .mail-sticky-top/.mail-sticky-bottom are sticky-positioned first/last
   children *inside* .modal-body (.mail-modal-body strips its default
   padding so their opaque backgrounds reach the modal's edges; everything
   between them - greeting text, locked table(s), closing text - is normal
   .mail-scroll-region content that scrolls underneath/above them).
   ========================================================================== */
.mail-modal-title {
    font-size: 14px;
    font-weight: 600;
    color: #18181b;
    margin: 0;
}
.mail-modal-header {
    background: #F1F5F9;
}
/* Fixed size rather than .modal-dialog-scrollable's default grow-to-a-cap-
   then-scroll behavior (max-height) - the modal shouldn't visibly resize as
   greeting/table/closing content varies between quotations, so this is a
   real height, and .mail-scroll-region scrolls inside it either way. */
.mail-modal-dialog .modal-content {
    height: 80vh;
}
/* Wide, Gmail-compose-style width instead of Bootstrap's modal-lg cap
   (800px) - these modals are meant to feel like a full compose window, not
   a narrow dialog. 80vw rather than 90vw leaves a comfortable gutter on
   both sides, matching Gmail's own compose window instead of stretching
   near edge-to-edge. */
.mail-modal-dialog {
    max-width: 80vw;
}
.mail-modal-body {
    padding: 0;
    display: flex;
    flex-direction: column;
    /* Every Gmail-style compose modal (cover note, bank quote, insurer
       request) shares this container - 14px keeps labels/values/body text
       consistent across all of them rather than inheriting whatever
       ancestor size happens to apply. */
    font-size: 14px;
}
/* The form fills the modal body so .mail-scroll-region's flex-grow can push
   .mail-sticky-bottom to the true bottom even when the compose content is
   shorter than the modal (without this the sticky footer settles mid-modal,
   wherever the short content happens to end). */
.mail-modal-body > form {
    display: flex;
    flex-direction: column;
    flex: 1 0 auto;
    min-height: 0;
}
.mail-sticky-top {
    position: sticky;
    top: 0;
    z-index: 2;
    background: #ffffff;
    padding: 16px 24px 0;
    flex-shrink: 0;
}
.mail-to-row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding-bottom: 12px;
}
.mail-to-label,
.mail-subject-label {
    flex-shrink: 0;
    padding-top: 4px;
}
.mail-to-chips {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    min-width: 0;
}
.mail-subject-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 0;
}
.mail-subject-row .mail-editable {
    flex: 1;
    width: auto;
}
.mail-divider {
    border: none;
    border-top: 1px solid #c7c7cc;
    margin: 0;
}
/* The divider between To and Subject sits *inside* .mail-sticky-top, which
   has 24px of horizontal padding - -24px cancels that out so it bleeds
   edge-to-edge, matching the other divider (between Subject and the scroll
   region), which is a sibling of .mail-sticky-top with no padded ancestor
   and is already edge-to-edge at the base margin:0 above. */
.mail-sticky-top .mail-divider,
/* Same padded-row bleed in the combined send wizard's email card. */
.send-all-mail-rows .mail-divider {
    margin: 0 -24px;
}
/* Recipient email field on the bank-quote/cover-note send modals - blends
   in like plain text until focused, matching the rest of the compose UI. */
.mail-to-input {
    flex: 1 1 160px;
    min-width: 120px;
    border: none;
    background: transparent;
    padding: 4px 0;
    font: inherit;
    color: inherit;
}
.mail-to-input:focus {
    outline: none;
}
/* Browser autofill paints its own background (often a blue/lavender tint)
   via an internal box-shadow that the background property above can't
   override - this repaints it to match the field's normal transparent
   look instead. The absurdly long transition delay is the standard trick
   to stop that repaint from briefly flashing the native color first. */
.mail-to-input:-webkit-autofill,
.mail-to-input:-webkit-autofill:hover,
.mail-to-input:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 1000px #ffffff inset;
    -webkit-text-fill-color: inherit;
    transition: background-color 5000s ease-in-out 0s;
}
.mail-scroll-region {
    padding: 16px 24px;
    flex: 1 1 auto;
}
.mail-sticky-bottom {
    position: sticky;
    bottom: 0;
    z-index: 2;
    background: #F1F5F9;
    border-top: 1px solid var(--border);
    padding: 8px 24px;
    flex-shrink: 0;
    display: flex;
    /* flex-start rather than center - if the toolbar wraps onto a second
       row (see .trix-button-row above), the Send button should sit level
       with its first row, not centered against the whole wrapped block. */
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}
/* The email card in the send wizard's email steps
   (_cover_note_send_all_step.html): To/Subject/body in their own bordered
   panel with a title bar. */
.wizard-mail-card {
    /* Right-only inset past the step's own 32px padding, so it visibly
       doesn't span the full available width - left edge stays flush with
       the heading/stepper/footer buttons above and below it. */
    margin-right: 8px;
    border: 1px solid #dedee0;
    border-radius: 8px;
    overflow: hidden;
    background: #fff;
}
.wizard-mail-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background: #F1F5F9;
    padding: 12px 16px;
    font-weight: 600;
    color: #18181b;
}
/* Attachments list sits inside the same .wizard-mail-card as the rest of the
   message, split off by a muted divider that's inset (not edge-to-edge like
   .mail-divider elsewhere in this form). */
.wizard-mail-card-divider { border: none; border-top: 1px solid #dedee0; margin: 0 24px; }
.wizard-mail-card-attachments { padding: 16px 24px; }
/* The send wizard gets a taller dialog than the reminder modal, since its
   content (the dropzone grid, the email card) is denser. */
.mail-modal-dialog:has(.wizard-sticky-header) .modal-content { height: 92vh; }
/* The send wizard's stepper stays pinned to the top of the scrollable
   step content (#cover-note-email-modal-body) while the rest (dropzones,
   the email card) scrolls underneath - a plain white backdrop so scrolled
   content doesn't show through. */
.wizard-sticky-header {
    position: sticky;
    top: 0;
    z-index: 2;
    background: #fff;
    padding: 24px 32px 16px;
}
/* Combined "Send to bank and insurer" wizard
   (partials/_cover_note_send_all_*.html), per the Reliance Portal mockup:
   numbered stepper, step panel, and a footer bar pinned to the bottom. */
.send-all-header { align-items: flex-start; padding: 20px 24px 16px; }
/* .mail-modal-title, a size up for the wizard. */
.send-all-title { font-size: 16px; }
.send-all-ref { font-size: 13px; color: #71717a; margin-top: 2px; }
/* Fill the modal body so the footer sits at the bottom on short steps. */
.send-all-step,
.send-all-form,
.send-all-review { display: flex; flex-direction: column; flex: 1 0 auto; }
/* Sticky/background come from .wizard-sticky-header, which also gives the
   dialog the wizard's 92vh height. */
.send-all-stepper-bar { padding: 16px 24px; border-bottom: 1px solid var(--border); }
.send-all-stepper { display: flex; gap: 12px; list-style: none; margin: 0; padding: 0; }
.send-all-stepper-item { display: flex; align-items: center; gap: 10px; flex: 1 1 0; min-width: 0; }
.send-all-stepper-item:last-child { flex: 0 0 auto; }
/* Connector line after every step but the last. */
.send-all-stepper-item:not(:last-child)::after {
    content: '';
    flex: 1;
    height: 2px;
    min-width: 12px;
    background: #e2e4e9;
    border-radius: 1px;
}
.send-all-stepper-done:not(:last-child)::after { background: #16a34a; }
.send-all-stepper-circle {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 600;
    background: #fff;
    color: #71717a;
    box-shadow: inset 0 0 0 1.5px #d4d7de;
}
.send-all-stepper-current .send-all-stepper-circle { background: #1e2b4d; color: #fff; box-shadow: none; }
.send-all-stepper-done .send-all-stepper-circle { background: #16a34a; color: #fff; box-shadow: none; }
.send-all-stepper-text { display: flex; flex-direction: column; line-height: 1.25; white-space: nowrap; }
.send-all-stepper-kicker { font-size: 11px; color: #71717a; }
.send-all-stepper-label { font-size: 13px; font-weight: 500; color: #71717a; }
.send-all-stepper-current .send-all-stepper-label { color: #18181b; font-weight: 600; }
.send-all-stepper-done .send-all-stepper-label { color: #3f3f46; }
.send-all-panel { padding: 24px; flex: 1 0 auto; }
.send-all-progress { display: flex; align-items: center; gap: 10px; font-size: 13px; color: #52525b; white-space: nowrap; }
.send-all-progress-track { width: 120px; height: 6px; border-radius: 3px; background: #e2e4e9; overflow: hidden; }
.send-all-progress-fill { height: 100%; background: #16a34a; transition: width 200ms ease; }
.send-all-mail-rows { padding: 12px 24px 0; }
.send-all-summary-card { border: 1px solid var(--border); border-radius: 12px; padding: 16px; }
.send-all-summary-icon {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: #f1f5f9;
    color: #334155;
}
.send-all-summary-grid {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 6px 16px;
    margin: 14px 0 0;
    font-size: 13.5px;
}
.send-all-summary-grid dt { font-weight: 400; color: #71717a; }
.send-all-summary-grid dd { margin: 0; color: #18181b; overflow-wrap: anywhere; }
/* Attach documents: one titled group per email (_cover_note_attachments.html). */
.attach-group-title { font-size: 14px; font-weight: 600; color: #18181b; margin-bottom: 12px; }
.send-all-footer {
    position: sticky;
    bottom: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 12px 24px;
    background: #fff;
    border-top: 1px solid var(--border);
}
.send-all-footer-note { font-size: 13px; color: #71717a; }
@media (max-width: 767.98px) {
    .send-all-stepper-text { display: none; }
    .send-all-stepper-current .send-all-stepper-text { display: flex; }
}
/* Subject/greeting/closing text always looks like plain text, clickable to
   edit with no border/tag distinguishing it from the locked table(s) around
   it - there's no read-only variant of these fields anywhere in the app, so
   there's nothing to visually distinguish. */
.mail-editable {
    display: block;
    width: 100%;
    border: none;
    background: transparent;
    padding: 0;
    margin: 0;
    resize: none;
    /* Height is managed by reliance.js's autosizeMailEditable (shown.bs.modal
       + a delegated input listener) for the greeting/closing <textarea>s that
       share this class - hidden overflow avoids a scrollbar flashing before
       each resize. Irrelevant to the single-line subject <input> that also
       uses this class, but harmless there. */
    overflow-y: hidden;
    font: inherit;
    color: inherit;
    white-space: pre-line;
}
.mail-editable:focus {
    outline: none;
}

/* Small pill badge (e.g. quotation list's "Draft saved" indicator) -
   white-space:nowrap for the same reason as .status-pill/.chip:
   unprotected contexts would otherwise let the pill's text wrap and its
   border-radius:999px render as a circle. */
.verify-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border: 1px solid var(--brand-blue);
    border-radius: 999px;
    padding: 4px 14px;
    font-size: 14px;
    font-weight: 500;
    background: transparent;
    color: var(--brand-blue);
    white-space: nowrap;
}

/* Pale-green success pill (e.g. "Quotation requested") - lighter fill than
   Bootstrap's bg-success, matching the confirmation-state pills elsewhere.
   white-space:nowrap - same reason as .status-pill/.chip/.verify-pill: most
   usages of this pill are in fully unprotected contexts (no
   .table-responsive, no card), so this is the only thing stopping its text
   from wrapping and its border-radius:999px rendering as a circle. */
.status-pill-success {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border-radius: 999px;
    padding: 4px 14px;
    font-size: 14px;
    font-weight: 500;
    background: #e3f6e8;
    color: #1a7f3c;
    white-space: nowrap;
}

/* Quotation detail's floating premium-selection bar (see
   _quotation_selection_bar.html) - centred over the content area, i.e.
   offset by the 225px sidebar, which is off-canvas below 768px. */
.selection-bar {
    position: fixed;
    bottom: 20px;
    left: calc(50% + 112.5px);
    transform: translateX(-50%);
    z-index: 1030;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
    width: max-content;
    max-width: calc(100vw - 225px - 48px);
    padding: 10px 12px 10px 16px;
    background: #1e2b4d;
    border-radius: 14px;
    box-shadow: 0 16px 36px rgba(15, 23, 42, 0.32), 0 2px 8px rgba(15, 23, 42, 0.14);
    color: #fff;
}
.selection-bar:not(.d-none) { animation: selection-bar-rise 160ms ease-out; }
@keyframes selection-bar-rise {
    from { opacity: 0; transform: translate(-50%, 8px); }
    to { opacity: 1; transform: translate(-50%, 0); }
}
.selection-bar-summary {
    display: flex; flex-direction: column; gap: 1px;
    padding-right: 12px; border-right: 1px solid rgba(255, 255, 255, 0.18);
    line-height: 1.3;
}
.selection-bar-total { font-size: 13.5px; font-weight: 600; }
.selection-bar-split { font-size: 12px; color: #cbd5e6; }
.selection-bar-warn { font-size: 12px; font-weight: 500; color: #fca5a5; }
.selection-bar-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
/* A group button is hidden (not disabled) when its group has nothing ticked -
   beats Bootstrap's !important d-inline-flex, and drops the now-empty
   wrapper so it doesn't leave a double gap. */
.selection-bar [hidden] { display: none !important; }
.selection-bar-actions > :has(> [data-selection-action][hidden]) { display: none !important; }
/* Buttons on the dark bar: translucent white outline for the group actions,
   solid white for Send to bank, plain text for Clear. */
.selection-bar .btn-reliance,
.selection-bar .btn-reliance-outline,
.selection-bar .selection-bar-clear { height: 36px; padding: 0 14px; border-radius: 8px; font-size: 13.5px; font-weight: 600; line-height: 1; }
.selection-bar .btn-reliance-outline { border: 1px solid rgba(255, 255, 255, 0.6); background: rgba(255, 255, 255, 0.14); color: #fff; }
.selection-bar .btn-reliance-outline:hover { border-color: rgba(255, 255, 255, 0.85); background: rgba(255, 255, 255, 0.22); color: #fff; }
.selection-bar .btn-reliance { border: none; background: #fff; color: #1e2b4d; }
.selection-bar .btn-reliance:hover { background: #e8edf7; color: #1e2b4d; }
.selection-bar .btn-reliance:active { background: #d6dff0; color: #1e2b4d; }
.selection-bar .selection-bar-clear { padding: 0 12px; border: none; background: transparent; font-weight: 500; color: #cbd5e6; }
.selection-bar .selection-bar-clear:hover { background: rgba(255, 255, 255, 0.1); color: #fff; }
/* Send to bank's sent/sending/failed states render text in place of the
   button - keep it legible on the dark background. */
.selection-bar #bank-quote-action .text-success { color: #86efac !important; }
.selection-bar #bank-quote-action .text-muted { color: #cbd5e6 !important; }
.icon-mask-14 { width: 14px; height: 14px; }
/* Room below the cards so the bar never covers the last row. */
#calculate-premium-pane { padding-bottom: 96px; }
/* Short one-word labels ("Request", "Verify", "Bank") - phones only. */
.selection-bar-short { display: none; }
@media (max-width: 767px) {
    /* Phones: the bar docks to the bottom edge like a bottom navigation -
       count on the left, then the actions as equal-width icon-over-label
       tabs, then Clear. The full labels stay in the DOM, visually hidden,
       so each button keeps its accessible name; show/hide of the group
       buttons is unchanged (reliance.js), and the remaining tabs share the
       freed width. */
    .selection-bar {
        left: 0;
        right: 0;
        bottom: 0;
        transform: none;
        width: auto;
        max-width: none;
        animation: none;
        flex-wrap: nowrap;
        gap: 8px;
        min-height: 72px;
        padding: 8px 8px calc(8px + env(safe-area-inset-bottom)) 16px;
        border-radius: 16px 16px 0 0;
    }
    .selection-bar-split { display: none; }
    .selection-bar-summary { flex-shrink: 0; }
    .selection-bar-actions { flex: 1; flex-wrap: nowrap; gap: 6px; min-width: 0; }
    .selection-bar-actions > div { flex: 1; min-width: 0; }
    .selection-bar #bank-quote-action form { width: 100%; }
    .selection-bar .btn-reliance,
    .selection-bar .btn-reliance-outline {
        flex-direction: column;
        gap: 4px !important; /* beats the buttons' own .gap-2 */
        width: 100%;
        height: 56px;
        padding: 0 4px;
        justify-content: center;
        border-radius: 10px;
    }
    .selection-bar .icon-mask { width: 18px; height: 18px; }
    .selection-bar-short { display: block; font-size: 11.5px; font-weight: 600; line-height: 1; }
    .selection-bar .selection-bar-clear { flex-shrink: 0; height: 56px; padding: 0 8px; }
    .selection-bar-label {
        position: absolute !important;
        width: 1px; height: 1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
    }
    /* Sent / sending states replace the bank button with text - drop the
       secondary address detail so it fits beside the count. */
    .selection-bar #bank-quote-action .text-muted { display: none; }
    #calculate-premium-pane { padding-bottom: 96px; }
}
/* Excel premium revert button + hover tooltip (reference design): shown,
   light blue, only while the amount differs from the excel figure; hidden
   when there's nothing to revert. */
.premium-revert-wrap { position: relative; display: flex; align-items: center; flex-shrink: 0; }
.premium-revert {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    min-width: 32px;
    padding: 0;
    border: none;
    border-radius: 12px;
    background: #e9f2ff;
    color: var(--brand-blue-light); /* arrow is stroke="currentColor" */
    cursor: pointer;
    transition: background 120ms ease, color 120ms ease;
}
.premium-revert svg { display: block; }
.premium-revert:hover:not(:disabled) { background: #d7e7fe; }
.premium-revert:active:not(:disabled) { background: #c4dcfd; }
/* Nothing to revert (figure matches excel, or the row is locked) - hide the
   button rather than show an inert one. visibility, not display, so its
   32px slot stays and the premium field doesn't resize as it toggles,
   keeping every row's field the same width. reliance.js (syncPremiumRevert)
   owns the disabled state. */
.premium-revert:disabled { visibility: hidden; }
.premium-revert-tip {
    position: absolute;
    bottom: 38px;
    right: -6px;
    z-index: 20;
    display: none;
    white-space: nowrap;
    background: #18181b;
    color: var(--white-text);
    font-size: 11.5px;
    font-weight: 500;
    border-radius: 8px;
    padding: 6px 9px;
    pointer-events: none;
    box-shadow: 0 6px 16px rgba(15, 23, 42, 0.22);
}
.premium-revert-wrap:hover .premium-revert:not(:disabled) + .premium-revert-tip { display: block; }
/* Premium cards (manual + excel) - laid out like the reference design: no
   card padding, so the header, "Select all" strip, column headers and row
   separators all run the full width of the card. Every strip and cell uses
   the same 12px side inset, which is what lines the checkboxes up. */
/* "Last saved: …" at the right end of the quotation tabs (reference design). */
.premium-last-saved { font-size: 12px; color: #a1a1aa; white-space: nowrap; }
.premium-card { padding: 0; overflow: hidden; }
.premium-card-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    column-gap: 10px;
    row-gap: 4px;
    padding: 13px 12px;
    border-bottom: 1px solid var(--border);
}
.premium-select-all {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 40px;
    padding: 8px 12px;
    background: #fcfcfc; /* a shade lighter than --page-bg */
    border-bottom: 1px solid var(--border);
    font-weight: 500;
}
.premium-card-footer { padding: 12px; border-top: 1px solid var(--border); }
.premium-card .table-responsive { margin: 0; }

.table-premium-grid { margin: 0; }
.table-premium-grid th,
.table-premium-grid td { padding: 0 12px; border-color: var(--border); }
.table-premium-grid thead th {
    padding-top: 8px;
    padding-bottom: 7px;
    vertical-align: bottom;
    font-size: 13px;
    font-weight: 700;
    line-height: 1.3;
    color: #18181b;
    border-bottom: 1px solid var(--border);
}
/* height is a minimum on table cells - the vertical padding lets a row grow
   with room to spare when a premium error shows under the input. */
.table-premium-grid tbody td { height: 56px; padding-top: 8px; padding-bottom: 8px; }
.table-premium-grid tbody tr:last-child td { border-bottom: none; }
.table-premium-grid .premium-empty { height: auto; padding: 28px 12px; text-align: center; color: var(--nav-group-label); }
.premium-company { font-weight: 500; }
/* Inputs fill their column, as in the reference - lifts .form-control's 300px cap. */
.table-premium-grid .form-control { max-width: none; }
/* Email matches the premium field's box (38px high, same padding/radius/type)
   - it renders as .form-control-sm, which is otherwise shorter. */
.table-premium-grid input[type=email].form-control {
    height: 38px;
    padding: 0 12px;
    font-size: 14px;
    border-radius: 12px;
}

.premium-cell { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.premium-amount { display: flex; align-items: center; gap: 6px; }
/* LKR sits inside the input's box, as in the reference: the wrapper draws
   the .form-control border/focus ring and holds a borderless input plus the
   suffix, so LKR can't drift outside the box (the input alone is capped at
   .form-control's 300px max-width, narrower than a wide column). */
.premium-field {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    min-width: 0;
    height: 38px;
    padding: 0 12px;
    background: #fff;
    border: 0.5px solid #D3D6E0;
    border-radius: 12px;
}
.premium-field:focus-within { border-color: var(--brand-blue); box-shadow: 0 0 0 3px rgba(21, 52, 157, 0.15); }
.premium-field .form-control {
    flex: 1;
    min-width: 0;
    max-width: none;
    padding: 0;
    border: none;
    border-radius: 0; /* the wrapper is the rounded box; a radius here clips the text selection */
    background: transparent;
    box-shadow: none;
    font-variant-numeric: tabular-nums;
}
.premium-field .field-suffix { flex-shrink: 0; font-size: 12px; }
/* Confirmed (Received/Verified) - read-only until the switch is turned off. */
.premium-field.is-locked { background: #f7f8fa; border-color: #f0f1f4; }
.premium-field.is-locked .form-control { color: var(--icon-grey); cursor: default; }
/* A ticked row with no premium when Send to bank was clicked. */
.premium-field.is-invalid { border-color: var(--red-500); }
.premium-field.is-invalid:focus-within { border-color: var(--red-500); box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15); }
.premium-error { color: var(--red-500); font-size: 12px; line-height: 1.3; }

/* Shared switch control - 40x24 track, grey off / blue on, white thumb. The
   flex row replaces Bootstrap's .form-switch left padding / negative input
   margin, and the explicit border-radius undoes section 7's global 6px
   .form-check-input radius, which would otherwise square off the track. */
.switch-control { display: flex; align-items: center; gap: 10px; min-height: 24px; padding-left: 0; }
.switch-control .form-check-input {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2.6' fill='%23fff'/%3e%3c/svg%3e");
    flex-shrink: 0;
    width: 40px;
    height: 24px;
    margin: 0;
    float: none;
    border: none;
    border-radius: 12px;
    background-color: #e4e4e7;
    cursor: pointer;
    transition: background-color 150ms ease, background-position 150ms ease;
}
.switch-control .form-check-input:checked {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2.6' fill='%23fff'/%3e%3c/svg%3e");
    background-color: #006fee;
}
.switch-control .form-check-input:focus { box-shadow: 0 0 0 3px rgba(0, 111, 238, 0.2); }
.switch-control .form-check-input:disabled { opacity: 0.5; cursor: not-allowed; }

/* Received/Verified switch - the label greys out while off. */
.premium-confirm .form-check-label {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12.5px;
    font-weight: 500;
    color: #71717a;
    white-space: nowrap;
    cursor: pointer;
}
.premium-confirm .form-check-input:checked ~ .form-check-label { color: #18181b; }
.premium-confirm .form-check-input:disabled ~ .form-check-label { opacity: 0.5; cursor: not-allowed; }
.premium-switch-lock { flex-shrink: 0; }

/* Short columns (checkbox, status pill, switch) are fixed to their content;
   company, premium and email have no width, so the fixed layout shares the
   rest of the card equally between them. Fixed layout (not auto) keeps both
   cards' columns lined up. Applies at every width: on narrow screens the
   table keeps its columns and the card's .table-responsive wrapper scrolls
   it horizontally (no stacked mobile-card layout here). The extra .table
   outranks section 21's `.table-responsive .table { min-width: 640px }`,
   which would otherwise squeeze the three shared columns on a phone. */
.table-premium-grid { table-layout: fixed; }
.table-responsive .table.table-premium-grid { min-width: 760px; }
.table-premium-grid .premium-col-check { width: 40px; }
.table-premium-grid .premium-col-status { width: 180px; }  /* "Verification sent" pill */
.table-premium-grid .premium-col-confirm { width: 170px; } /* switch + "Not verified" + lock */
.table-premium-grid th:first-child,
.table-premium-grid td:first-child { padding-right: 0; }
/* Phones: give the input columns real widths instead of an equal share of
   the 760px floor. Amount fits a 7-digit figure ("1,234,567.00 LKR", ~150px
   field) plus the excel card's 32px revert button; email fits a typical
   insurer address. The fixed layout grows the table to the column sum, and
   .table-responsive scrolls it. */
@media (max-width: 767px) {
    .table-premium-grid .premium-col-name { width: 150px; }
    .table-premium-grid .premium-col-amount { width: 212px; }
    .table-premium-grid .premium-col-email { width: 240px; }
}

/* ==========================================================================
   14. Quotation management page
   ========================================================================== */
/* Fluid across the full viewport range (same clamp() approach as
   .btn-new-quotation) rather than a fixed 18px with a separate mobile
   override - shrinks smoothly down to a legible floor instead of jumping
   at a breakpoint. */
.topbar-greeting { font-size: 18px; font-weight: 500; color: var(--brand-blue-light); margin: 0; }

/* Shared breadcrumb trail - partials/_breadcrumbs.html. Used on every detail,
   form and sub-list page so the trail looks identical throughout the app. */
.page-crumbs-list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 16px;
}
.page-crumbs { flex-shrink: 0; }
.page-crumbs-item { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
.page-crumbs-item + .page-crumbs-item::before {
    content: "\203A";
    color: var(--icon-grey);
    font-weight: 400;
}
.page-crumbs-list a { color: #18181B; font-weight: 500; text-decoration: none; }
.page-crumbs-list a:hover { text-decoration: underline; }
/* Two-step trail (parent + current only): mute the parent link */
.page-crumbs-item:first-child:nth-last-child(2) a { color: #4B5563; font-weight: 400; }
.page-crumbs-current { color: #18181B; font-weight: 600; }
/* Matches the list-page header icon size (25px); recoloured from the SVG's
   own navy fill to the muted grey via a CSS mask (accent pages pass their
   own background-color inline). */
.page-crumbs-icon {
    display: inline-block;
    width: 25px;
    height: 25px;
    flex: 0 0 25px;
    background-color: #4B5563;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: contain;
            mask-size: contain;
}
.page-crumbs-desc { margin-top: 0; }

.main-page-header-title {
    font-size: 16px;
    font-weight: 700;
    color: var(--brand-navy);
    margin: 0;
}

.page-header-icon {
    width: 40px; height: 40px;
    border-radius: 10px;
    /* background: var(--nav-active-bg); */
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}
.page-header-icon img { width: 20px; height: 20px; }
.page-header-icon i { font-size: 14px; color: var(--brand-blue); }

.stat-tile {
    display: flex; align-items: center; gap: 12px;
    min-width: 240px;
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 14px 20px;
    background: var(--sidebar-bg);
    border: 1px solid var(--border);
}
.stat-tile-icon {
    flex-shrink: 0;
    width: 22px; height: 22px;
    display: flex; align-items: center; justify-content: center;
}
.stat-tile-icon img { width: 100%; height: 100%; }
.stat-tile-label { font-size: 14px; font-weight: 500; color: #18181b; white-space: nowrap; }
.stat-tile-value {
    font-size: 14px; line-height: 1; font-weight: 700;
    color: var(--tile-accent, var(--brand-blue));
    margin-left: auto; padding-left: 16px;
    font-variant-numeric: tabular-nums;
}

/* Chart.js's responsive resize needs a positioned ancestor with an explicit
   height once maintainAspectRatio is off (see templates/dashboards/partials/
   _dashboard_content.html) - without this, every HTMX swap that recreates
   the dashboard's charts settles on a stale width/height ratio and the
   canvas renders squashed or stretched. */
.dashboard-chart-wrapper { position: relative; height: 260px; }

/* Dashboard stat card - title+icon row, big value, muted description
   underneath (dashboards/partials/_stat_card.html). Distinct from
   .stat-tile above, which is the single-row icon+label+value tile the
   Quotations/Cover notes list-page headers use. */
.dashboard-stat-card {
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 16px;
    background: var(--sidebar-bg);
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
    height: 100%;
    min-height: 142px;
}
.dashboard-stat-card-header { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.dashboard-stat-card-title { font-size: 14px; font-weight: 500; color: #18181b; }
.dashboard-stat-card-icon {
    flex-shrink: 0;
    width: 22px; height: 22px;
    display: flex; align-items: center; justify-content: center;
}
.dashboard-stat-card-icon img { width: 100%; height: 100%; }
/* Sizing override on top of shared .icon-mask (16px default -> fill 22px wrapper). */
.dashboard-stat-card-icon-mask {
    width: 100%; height: 100%;
}
.dashboard-stat-card-value {
    font-size: 3rem; line-height: 1; font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.dashboard-stat-card-description { color: #64748B; font-size: 13px; }

.filter-pill {
    display: inline-flex; align-items: center; gap: 6px;
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 2px 12px;
    font-size: 14px;
    font-weight: 500;
    color: #18181B;
    background: #fff;
    cursor: pointer;
    margin: 0;
    user-select: none;
}
.filter-pill:hover { background: #fff; }
.filter-pill i { display: none; }
.filter-pill:has(input:checked) {
    background: white;
    border-color: #2563EB;
    color: #2563EB;
    font-weight: 600;
}
.filter-pill:has(input:checked) i { display: inline; }
.filter-pill:has(input:focus-visible) {
    outline: 2px solid #2563EB;
    outline-offset: 1px;
}
/* Subtle vertical rule dividing the date-range pills from the status/action
   pills in the list filter rows (Quotations, Cover Notes). */
/* The count on a state pill (Delegations). Inherits the pill's own colour rather
   than setting one, so it greys with the label and turns blue when the pill is
   checked - no second component to keep in step. Not .filter-chip-badge: that is
   the dashboard dropdown's solid blue circle, far too heavy inside a white
   pill. */
.filter-pill-count { opacity: .55; font-variant-numeric: tabular-nums; }
.filter-separator {
    align-self: stretch;
    flex-shrink: 0;
    width: 1px;
    margin: 2px 4px;
    background: var(--border);
    border: 0;
}

/* Multi-select "Filter by cluster/branch" chip dropdowns (dashboards) -
   same pill look as .filter-pill, plus a small count badge once at least
   one option is checked. */
.filter-chip-btn {
    display: inline-flex; align-items: center; gap: 6px;
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 3px 12px;
    font-size: 13px;
    font-weight: 500;
    color: #18181B;
    background: #fff;
}
.filter-chip-btn:hover { background: #f8f9fa; }
.filter-chip-badge {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--brand-blue-light);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    padding: 0 4px;
}
.filter-chip-menu { min-width: 220px; max-height: 280px; overflow-y: auto; }
.filter-chip-option {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 8px;
    border-radius: 6px;
    font-size: 13px;
    cursor: pointer;
    margin: 0;
}
.filter-chip-option:hover { background: #f8f9fa; }

/* white-space:nowrap matters everywhere, not just in the mobile-card-table
   context: without it, a pill in any unconstrained/narrow cell wraps its
   text inside the flex box, and border-radius:999px on the now-tall/narrow
   result renders as a circle instead of a pill. There's no context in this
   app where a status pill is meant to wrap. */
.status-pill {
    display: inline-flex; align-items: center;
    border-radius: 999px;
    padding: 2px 12px;
    font-size: 14px;
    font-size: 14px;
    font-weight: 500;
    white-space: nowrap;
}
.status-pill-sent {
    background: #0485F717;
    color: #184FFC; 
}
.status-pill-draft { background: #F3F4F6; color: #374151; }
/* Amber: one of the two mails is still outstanding - deliberately distinct from
   both the neutral draft pill and the blue "fully sent" one. */
.status-pill-pending { background: rgba(191, 128, 20, 0.12); color: #8a5a0b; }
/* Teal: sent quotation that's progressed to cover-note stage - distinct
   from the plain "sent" blue pill so officers can tell the two apart in the
   quotation list without opening each row. */
.status-pill-covernote { background: rgb(230, 243, 249); color: #1278AB; }

/* Cover note's own draft/sent pills - kept separate from
   .status-pill-draft/.status-pill-sent (which read as quotation states) so
   the two objects' status pills can diverge without one styling the other. */
.status-pill-cn-draft { background: rgba(218, 199, 169, 0.15); border: 1px solid var(--border); color: #9B8C6E; }
.status-pill-cn-sent { background: rgba(245, 165, 36, 0.15); color: #CA8A04; }
/* The Email center's two send outcomes, for the window between the officer
   clicking Send and the worker finishing (cover_notes.tasks). Blue for
   in-flight - the one colour still free in the cover-note range, and far
   enough from -cn-sent's amber and -cn-draft's beige to be read across the
   two tiles at a glance; it borrows .status-pill-sent's hue rather than
   introducing a fourth. Red reuses .chip-failed's pair exactly, since that is
   already this app's "this email did not go out" colour and the two appear on
   the same screen (see _cover_note_email_log.html). */
.status-pill-cn-pending { background: rgba(4, 133, 247, 0.10); color: #184FFC; }
.status-pill-cn-failed { background: #FEE2E2; color: #991B1B; }
/* Never attempted - neutral grey, as in the send wizard's mockup. */
.status-pill-cn-not-sent { background: #F4F4F5; color: #52525B; }

/* Nearing Expiry / Expired list pages: a small dot + text under the status
   pill showing how many days remain or have passed. Amber matches
   .status-pill-pending's color; red is new to the palette. */
.expiry-dot { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; }
.expiry-dot::before { content: ''; width: 6px; height: 6px; border-radius: 50%; display: inline-block; }
.expiry-dot-nearing { color: #8a5a0b; }
.expiry-dot-nearing::before { background: #bf8014; }
.expiry-dot-expired { color: #b3261e; }
.expiry-dot-expired::before { background: #b3261e; }

/* ==========================================================================
   17. Quotation workspace top tabs
   ========================================================================== */
.quotation-tabs {
    display: flex;
    gap: 24px;
    border-bottom: 1px solid var(--border);
}
.quotation-tabs .nav-link {
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    padding: 10px 2px;
    margin-bottom: -1px;
    font-size: 14px;
    font-weight: 500;
    color: black;
    background: none;
}
.quotation-tabs .nav-link:hover { color: var(--brand-navy); border-color: transparent; }
.quotation-tabs .nav-link.active {
    color: black;
    font-weight: 600;
    border-bottom-color: #0485F7;
    background: none;
}
.quotation-tabs .nav-link.disabled { color: var(--nav-group-label); opacity: .55; cursor: default; }

/* Plain text-styled action buttons (e.g. "Select All") used alongside a
   section heading where a bordered button would be too heavy. */
.link-action {
    background: none;
    border: none;
    padding: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--brand-blue);
}
.link-action:hover { text-decoration: underline; }

.table thead th{
    font-weight: 500;
    font-size: 14px;
    padding-bottom: 14px;
}

.table tbody td{
    font-size: 14px;
}

/* Bootstrap's .table sets width:100%, which pins the table to its container
   and leaves .table-responsive nothing to scroll - on a narrow viewport this
   crushes columns (e.g. the Officer column's avatar+name) below their
   content's natural size instead of triggering horizontal scroll. A
   min-width gives the table a floor so .table-responsive can do its job. */
.table-responsive .table {
    min-width: 640px;
}

/* Admin list tables (clusters, officers, insurers, banks, quotations, cover
   notes): pack the content columns to the left with a fixed 64px gutter
   instead of Bootstrap's width:100% spreading them across the card; the row
   actions column absorbs the slack and stays pinned to the right edge.
   Desktop only - below md each row becomes a card (.mobile-card-table). The
   premium data grids (--premium) keep their full-width multi-column layout.

   The actions column is identified by .table-action-col on its <th> and <td>,
   not by :last-child. Position is the wrong signal: the empty-state row
   (<td colspan> "No employees yet") is also a last child, and a future table
   whose last column isn't an action column would silently inherit the pinning.
   .table-action-col sits alongside .row-action-cell / .mobile-card-action-cell
   rather than replacing either - those two drive different <768px card layouts
   and aren't interchangeable. */
@media (min-width: 768px) {
    /* width:1% + nowrap collapses each content column to its single-line
       natural width so the group packs left; a very wide table (many columns)
       overflows into .table-responsive's horizontal scroll rather than
       spreading. [colspan] excludes the full-width empty-state row, which
       should stay centred rather than being packed and nowrapped. */
    .mobile-card-table:not(.mobile-card-table--premium) th:not(.table-action-col),
    .mobile-card-table:not(.mobile-card-table--premium) td:not(.table-action-col):not([colspan]) {
        width: 1%;
        white-space: nowrap;
        padding-right: 64px;
    }
    /* Actions column takes the remaining width and pins right. width:auto
       beats the inline width:1% the action <td>s still carry.

       It also sticks to the right edge of .table-responsive's scroll box. The
       nowrap above means a table with several long text columns (the officer
       list's Email + Branch + "Report to") outgrows the card and overflows
       into horizontal scroll - without this the View/Edit controls are the
       first thing pushed out of reach, since they're last in the row. Sticky
       keeps them on screen at any scroll offset.

       The <th> needs this too, not just the <td>: left transparent and
       scrolling, the header cell lets the other column labels slide through
       the strip directly above the pinned buttons.

       The opaque background and z-index are both required: table cells are
       transparent by default (Bootstrap sets --bs-table-bg: transparent), so
       the scrolled content columns would otherwise show through underneath.
       #fff matches the .card these tables sit in - no zebra striping or row
       hover to account for on .mobile-card-table. */
    .mobile-card-table:not(.mobile-card-table--premium) th.table-action-col,
    .mobile-card-table:not(.mobile-card-table--premium) td.table-action-col {
        width: auto !important;
        text-align: right;
        position: sticky;
        right: 0;
        z-index: 1;
        background: #fff;
        padding-left: 20px;
    }
}

/* Insurer-premiums table (excel-covered insurers, FR13/FR17/FR18) - navy
   header + zebra-striped rows, scoped to this table only so it doesn't
   affect the plain Bootstrap tables used elsewhere (quotation list,
   insurer/officer admin lists). */
.table-premiums {
    border-radius: 8px;
    overflow: hidden;
}
.table-premiums thead th {
    color: #18181b;
    font-weight: 600;
    font-size: 14px;
    padding: 10px 14px;
    border: none;
}
.table-premiums tbody td { padding: 12px 14px; border-color: var(--border); }
.table-premiums tbody tr:nth-child(even) { background: #f8f9fb; }

/* Cover note action in the sent-quotation workspace: a row shows either
   "Generate cover note" or "Open cover note" depending on whether that insurer
   already has one, so both are sized to the wider label to keep the column's
   right edge straight down the table. */
.cover-note-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 168px;
}
/* Generate + Upload: two fixed 168px slots (matching .cover-note-action's
   min-width), so Generate sits in the same place on every row whether or not
   Upload is offered. inline-grid keeps the pair against the cell's right edge
   (the cell is .text-end). On mobile the row is a card: the two stay side by
   side, sharing the width rather than wrapping, and an empty Upload slot
   takes no space. */
.cover-note-actions {
    display: inline-grid;
    grid-template-columns: repeat(2, 168px);
    gap: 8px;
    text-align: left;
}
@media (max-width: 767px) {
    .cover-note-actions { display: flex; }
    .cover-note-actions > * { flex: 1 1 0; min-width: 0; }
    .cover-note-actions > :empty { display: none; }
    .cover-note-actions .cover-note-action { width: 100%; min-width: 0; }
}

/* ==========================================================================
   18. Email center - one recipient chip per email, per event card
   ========================================================================== */
/* Avatar for recipients with no insurer logo (bank/manual-request sends).
   Icon reflects that one recipient's own outcome - envelope for sent/pending,
   an alert glyph on the failed red pair (matches .chip-failed, the chip this
   avatar sits inside) - rather than a blank gradient fill that read the same
   whether the send worked or not. */
.chip-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--brand-navy);
    flex-shrink: 0;
}
.chip-avatar i {
    color: #fff;
    font-size: 10px;
    line-height: 1;
}
.chip-avatar-failed { background: #FEE2E2; }
.chip-avatar-failed i { color: #991B1B; }

/* Email center's "Email log" card - bespoke timeline look, deliberately
   distinct from the status-pill-cn and chip-avatar styles above: an
   approved mockup for this one card, not a retrofit of the app's existing
   chip/pill language. */
.email-log { max-width: 100%; background: #fff; border: 1px solid #f0f1f4; border-radius: 14px; padding: 20px 24px; margin-top: 24px; }
.email-log__head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.email-log__title { margin: 0; font-size: 16px; font-weight: 600; color: #18181b; }
.email-log__desc { margin: 4px 0 0; font-size: 13.5px; color: #64748b; }
.email-log__count { font-size: 12.5px; font-weight: 500; color: #71717a; }
.email-log__list { list-style: none; margin: 16px 0 0; padding: 0; max-height: 420px; overflow-y: auto; }

.log-item { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; column-gap: 14px; }
.log-item__rail { display: flex; flex-direction: column; align-items: center; }
.log-item__rail::after { content: ""; flex: 1; width: 1.5px; min-height: 12px; background: #e8eaee; }
.log-item:last-child .log-item__rail::after { background: transparent; }
.log-item__icon { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0; }
.log-item__icon svg { display: block; width: 14px; height: 14px; }
.log-item__icon .spinner-border { width: 14px; height: 14px; border-width: 2px; }
.log-item--sent .log-item__icon { background: #dcfce7; color: #15803d; }
.log-item--failed .log-item__icon { background: #fee2e2; color: #b91c1c; }
.log-item--retried .log-item__icon { background: #fef3c7; color: #b45309; }
/* Grey/blue, not in the original mockup (it had no pending state) - chosen to
   match .status-pill-cn-pending's existing "in-flight" blue elsewhere on this
   same page, rather than inventing a second meaning for blue. */
.log-item--pending .log-item__icon { background: rgba(4, 133, 247, 0.12); color: #184FFC; }

.log-item__body { min-width: 0; padding: 4px 0 18px; }
.log-item__title { font-size: 14px; font-weight: 600; color: #18181b; }
.log-item__meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 3px; font-size: 12.5px; color: #71717a; }
.log-item__sep { width: 3px; height: 3px; border-radius: 50%; background: #a1a1aa; }
.log-item__reason { font-weight: 500; color: #b91c1c; }
.log-item__time { padding-top: 5px; font-size: 12.5px; color: #71717a; white-space: nowrap; font-variant-numeric: tabular-nums; }

.email-log__empty { margin-top: 14px; padding: 22px 16px; border-radius: 12px; background: #f9fafb; font-size: 13.5px; color: #71717a; text-align: center; }

/* ==========================================================================
   18b. Cover note PDF preview panel
   ========================================================================== */
/* The height has to be an explicit length: .modal-body has no height of its own,
   so a percentage here collapses the frame to nothing and the panel looks empty
   even though the PDF loaded. Paired with .modal-body.p-0 on the panel so the
   browser's PDF viewer fills it edge to edge. */
.cover-note-pdf-frame {
    display: block;
    width: 100%;
    height: 78vh;
    border: 0;
    background: var(--page-bg);
}

/* ==========================================================================
   19. Toasts
   ========================================================================== */
.toast-custom {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 14px 16px;
    border-radius: 14px;
    border: 1px solid var(--border);
    background: #ffffff;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
    width: 460px;
    max-width: 100%;
}
.toast-custom .toast-icon {
    flex-shrink: 0;
    margin-top: 1px;
    font-size: 22px;
    line-height: 1;
    color: var(--toast-accent);
}
.toast-custom .toast-content { flex: 1; min-width: 0; }
.toast-custom .toast-title { font-size: 14px; font-weight: 700; color: var(--toast-accent); }
.toast-custom .toast-description { margin: 2px 0 0; font-size: 13px; color: #52525B; }
.toast-custom .toast-action {
    flex-shrink: 0;
    align-self: center;
    border: none;
    border-radius: 8px;
    padding: 6px 16px;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    background: var(--toast-action-bg);
    color: var(--toast-action-text);
}
.toast-custom .toast-action:hover { filter: brightness(0.96); }
/* Plain dismiss on a toast with no action - muted, not the colored pill. */
.toast-custom .toast-close {
    flex-shrink: 0;
    align-self: center;
    border: none;
    background: transparent;
    padding: 6px 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--icon-grey);
}
.toast-custom .toast-close:hover { color: var(--brand-navy); }

/* Per-type color pair: accent (icon + title) and a softer tint for the
   action button, matching .status-pill-success's existing green and the
   app's --red-500/--dashboard-stat-red for danger. */
.toast-custom.toast-success {
    --toast-accent: #1a7f3c;
    --toast-action-bg: #86efac;
    --toast-action-text: #14532d;
}
.toast-custom.toast-danger {
    --toast-accent: #b91c1c;
    --toast-action-bg: #fecaca;
    --toast-action-text: #7f1d1d;
}
/* Disabled look while the htmx Retry button's request is in flight. */
.toast-custom .toast-action.htmx-request { opacity: 0.7; pointer-events: none; }

/* Slide in from the right, riding Bootstrap's own .showing/.show toggle -
   toast.js adds/removes these classes on show/hide and reads this element's
   own transition duration, so no JS changes are needed to animate it. */
#toast-container .toast {
    transform: translateX(0);
    transition: transform 0.2s ease-out, opacity 0.2s ease-out;
}
#toast-container .toast.showing {
    transform: translateX(110%);
    opacity: 0;
}

/* ==========================================================================
   20. Quotation sent-status timeline
   ========================================================================== */
.qt-timeline { list-style: none; margin: 0; padding: 0; }
.qt-timeline-step { position: relative; display: flex; gap: 12px; padding-top: 4px; padding-bottom: 4px; }
.qt-timeline-step:last-child { padding-bottom: 0; }

/* Connecting line: drawn on every step except the last, from below its dot
   down to the next dot. Positioned using the dot's own fixed size/margin
   so it lines up regardless of how tall each step's content is. */
.qt-timeline-step:not(:last-child)::before {
    content: '';
    position: absolute;
    left: 7px;
    /* Gap below this step's dot: padding-top(4) + margin-top(6) + dot(16) + 8px gap */
    top: 34px;
    /* Stop ~8px short of the next step's dot (which sits 10px below this box) */
    bottom: -2px;
    width: 2px;
    background: #CBD5E1;
}
.qt-timeline-step.qt-timeline-step-done:not(:last-child)::before { background: #CBD5E1; }

.qt-timeline-dot {
    flex: 0 0 16px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    /* Centre the 16px dot on the title's 28px line box (line-height 2 x 14px) */
    margin-top: 6px;
    z-index: 1;
}
.qt-timeline-dot-done { background: #0485F7; }
.qt-timeline-dot-pending { background: #fff; border: 2px solid var(--border); }

.qt-timeline-title { font-weight: 500; font-size: 14px; color: #334155; }
.qt-timeline-title-pending { color: var(--nav-group-label); font-weight: 500; }
.qt-timeline-meta { color: var(--nav-group-label); font-size: 14px;}
.qt-timeline-meta-text {line-height: 2;}

/* ==========================================================================
   21. Responsive breakpoints
   ========================================================================== */
.mobile-nav-toggle {
    background: none;
    border: none;
    padding: 6px;
    margin-right: 4px;
    font-size: 14px;
    color: var(--brand-navy);
    line-height: 1;
}
.sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 1039;
}
.sidebar-backdrop.is-open { display: block; }

.mobile-icon-btn {
    width: 34px; height: 34px;
    border-radius: 10%;
    border: 1px solid var(--border);
    background: #fff;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
}

@media (max-width: 767px) {
    /* Sidebar becomes an off-canvas drawer instead of a flex column - taking it
       out of flow with position:fixed means .main-area (still flex:1) naturally
       reclaims the full width without any change needed on that side. */
    .sidebar {
        position: fixed;
        top: 0;
        left: 0;
        height: 100vh;
        height: 100dvh;
        z-index: 1040;
        transform: translateX(-100%);
        transition: transform .2s ease;
        box-shadow: 2px 0 12px rgba(0, 0, 0, 0.15);
    }
    .sidebar.is-open { transform: translateX(0); }

    .topbar { padding: 12px 16px; }
    /* .content-area { padding: 16px; } */

    /* .topbar's flex-wrap:nowrap (see base rule above) keeps the row itself
       from splitting; the identity block still needs min-width:0/flex:1 1
       auto so it's the one that absorbs the squeeze and shrinks, rather
       than forcing the row wider than the viewport. .topbar-greeting's
       font-size (base rule) already shrinks fluidly as the viewport
       narrows, and if an officer's name is still too wide even at the
       clamped-down min size, only the greeting text wraps onto a second
       line - the actions stay on the first. align-items overrides its own
       Bootstrap align-items-center utility for the same reason .topbar's
       was overridden above: once the greeting wraps to 2 lines, centering
       the avatar against that taller block drifts it away from the first
       line - top-aligning keeps it level with the text. */
    .topbar-identity { min-width: 0; flex: 1 1 auto; align-items: flex-start !important; }
    /* Same self-centering trick as .topbar-identity's align-self in the base
       rule, one level down: the 36px avatar is usually taller than the
       single-line greeting, which otherwise sits pinned to the top of the
       row instead of centered against it. Scoped to just the greeting (not
       the avatar) so the 2-line-wrap case above is unaffected - once
       wrapped, the greeting becomes the taller sibling and centering it
       against its own height is a no-op, so the avatar still lines up with
       its first line as intended. */
    .topbar-greeting { align-self: center; }

    /* Split-screen auth layout (login/OTP/password screens) stacks instead of
       crushing both panels side by side. */
    .auth-shell { flex-direction: column; }
    .auth-branding-panel { flex: 0 0 auto; max-width: none; padding: 32px 24px; }
    .auth-form-panel { padding: 32px 24px; }

    /* Field-row forms (quotation/officer/organization/insurer) stack the label
       above the input instead of reserving a fixed 280px label column. */
    .field-row { flex-direction: column; align-items: flex-start; gap: 6px; }
    .field-row-label { width: 100%; }
    .field-row-body .form-control,
    .field-row-body .form-select { max-width: none; width: 100%; }
}

@media (max-width: 576px) {
    .btn-reliance, .btn-reliance-outline, .btn-reliance-reminder { padding: 7px 14px; font-size: 14px; }
    /* Send wizard - the desktop padding used throughout .wizard-* stacks up
       and leaves very little usable width on a phone screen; tighten it here
       rather than at every rule's own declaration, same as this block already
       does for button padding. */
    .wizard-sticky-header { padding: 16px 16px 12px; }
    .wizard-mail-card-divider { margin: 0 12px; }
    .wizard-mail-card-attachments { padding: 12px; }
    .wizard-mail-card { margin-right: 4px; }
}

/* ==========================================================================
   22. Document tracking selection (quotation form)
   ========================================================================== */

/* .badge (defined later in this file) sets its own background-color/color
   for the generic light-blue badge look - same specificity as a single
   class, so it would win by source order alone. .badge.document-important-badge
   here (matching the badge's actual "badge document-important-badge" class
   list) makes this win regardless of where either rule sits in the file. */
.badge.document-important-badge {
    position: absolute;
    top: 16px;
    right: 16px;
    background-color: var(--doc-select-badge);
    color: #fff;
    border-radius: 999px;
    padding: 4px 14px;
    font-size: 12px;
    font-weight: 600;
}

.document-select-divider {
    border: none;
    border-top: 2px solid var(--border);
    margin: 16px 0;
}

.document-usage-option {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.document-usage-description {
    margin-left: 24px;
}

.document-checklist-row {
    display: flex;
    align-items: center;
    gap: 4px;
    width: fit-content;
    margin-left: -8px;
    padding: 4px 8px;
    border-radius: 8px;
}
.document-checklist-row:hover {
    background: var(--nav-active-bg);
}
.document-checklist-remove {
    background: none;
    border: none;
    color: var(--icon-grey);
    visibility: hidden;
    padding: 2px 6px;
    border-radius: 4px;
    line-height: 1;
}
.document-checklist-row:hover .document-checklist-remove {
    visibility: visible;
}

.document-edit-modal-footer {
    border-top: none;
    justify-content: flex-start;
}
.document-edit-modal-footer .btn-reliance {
    border-radius: 8px;
    padding: 6px 12px;
}

.document-edit-modal-header {
    border-bottom: none;
}

/* ==========================================================================
   22. Mobile row-card table pattern
   Ported from the signed-off prototype in design-previews/mobile-list-redesign/,
   first built for Quotations, then generalized into two reusable recipes so
   every list table in the app can opt in via a class on the <table> itself:

     .mobile-card-table--idstatus  id / status-or-label / trailing (3 columns)
       - Quotations, Cover note list, and the three cover-note expiry pages.
       - Trailing is either an officer avatar (paired with a single-action
         stretched-link row - see .row-action-cell below) or 1-2 visible
         action icons (.mobile-card-action-icons) for tables with no avatar.

     .mobile-card-table--identity  primary identity / trailing (2 columns)
       - Officers, Insurers, Organizations (clusters + banks) - tables with
         no separate id/status pair, just a name (or avatar+name) cell.
       - Officers is single-action (stretched link, like Quotations);
         Insurers/Clusters/Banks are two-action (.mobile-card-action-icons).

   Mark the cell that should sit in the recipe's flexible middle/primary
   track with .mobile-card-primary. Both recipes share the same row/column
   mechanics, tap-target handling, and header-collapse pattern below.
   ========================================================================== */
.mobile-page-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 12px;
}
.mobile-page-header-title { display: flex; align-items: center; gap: 10px; }
.mobile-page-header-title h1 { font-size: 14px; font-weight: 700; color: var(--brand-blue); margin: 0; }
.mobile-page-header-actions { display: flex; align-items: center; gap: 8px; }
.mobile-filters-trigger {
    display: inline-flex; align-items: center; gap: 6px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 10%;
    padding: 7px 12px;
    font-size: 14px;
    font-weight: 500;
    color: #18181b;
}
.mobile-filters-trigger .mobile-filters-badge {
    background: var(--brand-blue);
    color: #fff;
    border-radius: 10%;
    font-size: 14px;
    font-weight: 700;
    padding: 1px 7px;
    display: none;
}
.mobile-filters-trigger .mobile-filters-badge.is-visible { display: inline-block; }
/* The stat tile is reused as-is (partials/_stat_tile.html) but needs to
   span the mobile page's width here, instead of its default min-width:240px
   shrink-to-fit sizing meant for sitting beside the desktop header. */
.mobile-stat-card { margin-bottom: 16px; }
.mobile-stat-card .stat-tile { width: 100%; min-width: 0; }
/* Same shrink-then-wrap treatment as .topbar-greeting - .stat-tile-label's
   content is normally a short fixed string ("Total Quotations sent" etc.),
   not user data, so this isn't a live bug today, but it sits in the same
   narrowing flex row shape, so it gets the same defensive scaling rather
   than staying a latent nowrap trap for a longer future label or a 320px
   device. Scoped to .mobile-stat-card only - the desktop stat tile keeps
   its fixed 14px. */
.mobile-stat-card .stat-tile-label { font-size: 14px; white-space: normal; }
/* Baseline (all widths) so wrapping two existing action controls (e.g.
   View link + Delete form/button) in this div doesn't change their current
   side-by-side desktop layout - mobile-only rules below turn them into
   compact icon circles. */
.mobile-card-action-icons { display: inline-flex; align-items: center; gap: 6px; }

/* Shared app-wide pagination bar (templates/partials/_pagination.html) - a
   pill-bordered segmented control replacing Bootstrap's default square
   .pagination look. Previous/Next are icon(+label)/icon-only chevrons;
   page-number pills sit between them, the current page filled solid. */
.pagination-pills {
    /* background: #fff; */
    /* border: 1px solid var(--border); */
    /* border-radius: 999px; */
    padding: 4px;
    gap: 0.5rem;
}
.pagination-pills .page-item .page-link {
    border: none;
    background: #fff; 
    border: 1px solid var(--border);
    border-radius: 5px;
    min-width: 32px;
    height: 32px;
    padding: 0 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-size: 14px;
    font-weight: 500;
    color: var(--field-label);
    background: transparent;
}
.pagination-pills .page-item .page-link:hover { background: var(--nav-active-bg); color: var(--brand-navy); }
.pagination-pills .page-item.active .page-link {
    background: var(--brand-blue-light);
    color: #fff;
}
.pagination-pills .page-item.disabled .page-link { color: var(--nav-group-label); opacity: .6; }
.pagination-pills .page-link-prev,
.pagination-pills .page-link-next { padding: 0 14px; }
.pagination-goto-input { width: 170px; border-radius: 5px; }
/* Prevents the Results/Go-to group from overflowing past the card's right
   edge on narrow-but-not-mobile widths (below the 767px breakpoint where
   they're hidden outright) - lets it drop below Previous/page-numbers/Next
   instead, and lets its own contents wrap rather than break mid-word. */
.pagination-bar { flex-wrap: wrap; row-gap: 0.5rem; }
.pagination-meta { flex-wrap: wrap; }


@media (max-width: 767px) {
    /* Compact header replaces each page's desktop header block (icon+title+
       subtitle+stat tile row + inline filter-pill row) - toggled via
       d-flex/d-none d-md-* pairs on the two header blocks in each list
       template. Shared by every page that has a filter-pill form to
       collapse (Quotations + the four Cover Notes pages); toggled by
       [data-filters-toggle] buttons wired to a specific panel via
       data-filters-panel (see reliance.js). */
    .mobile-filters-panel {
        display: none;
        margin-bottom: 16px;
    }
    .mobile-filters-panel div{
        margin-bottom: 12px;
    }
    .mobile-filters-panel.is-open { display: block; }

    /* section 21's `.table-responsive .table { min-width: 640px }` exists to
       stop OTHER tables' columns being crushed narrower than their content -
       a table with its own real mobile layout below doesn't need that
       escape hatch, and left at 640px the grid columns resolve against a
       table wider than the viewport, pushing everything off-screen. Matches
       section 21's own two-class specificity (.table-responsive .table) so
       source order (this comes later) decides it, rather than losing to it
       outright the way a single-class `.mobile-card-table` selector would. */
    .table-responsive .mobile-card-table { min-width: 0; }

    /* Below this point each recipe gets its own floor back (see the
       "Freeze + scale" block after the row-card rules): the screenshot the
       floor width was tuned against is the most compact this layout should
       ever get - narrower viewports must not wrap/squeeze any further, they
       scale the whole thing down instead (see below). Same two-class
       specificity + source-order technique as the reset above.
       --idstatus/--wide-id: 360/400px left only ~110px of actual text width
       for the trailing officer name after the id+status columns and the
       avatar - fine for a short 2-word name, but a longer 3-word one (e.g.
       "Sathindu Geethika Perera") didn't have room to wrap at word
       boundaries and broke mid-word instead ("Sathind"/"u"). 430/470px
       leaves enough width for a realistic full name to wrap two words per
       line. */
    .table-responsive .mobile-card-table--identity { min-width: 375px; }
    .table-responsive .mobile-card-table--idstatus { min-width: 430px; }
    .table-responsive .mobile-card-table--idstatus.mobile-card-table--wide-id { min-width: 470px; }
    .table-responsive .mobile-card-table--banks { min-width: 260px; }
    .table-responsive .mobile-card-table--premium { min-width: 370px; }

    /* Row-card layout: two grid recipes (id/status/trailing vs. identity/
       trailing - see section comment above), sharing the same mechanics.
       Secondary columns are dropped via d-none d-md-table-cell in each
       template rather than crushed. */
    .mobile-card-table thead tr,
    .mobile-card-table tbody tr {
        display: grid;
        align-items: center;
        column-gap: 14px;
        position: relative;
    }
    /* Row separators: each row's own cells are stripped of their border
       below (.mobile-card-table tbody td { border: none }) since the grid
       layout breaks real table-row semantics, so without this, adjacent
       cards run straight into each other with only cell padding between
       them. Scoped to tbody only - thead is a single label row, not a list
       of cards, so it doesn't need one; last row skips it so the card
       doesn't end on a stray line sitting against the pagination below it. */
    .mobile-card-table tbody tr {
        padding: 4px 0;
        border-bottom: 1px solid var(--border);
    }
    .mobile-card-table tbody tr:last-child {
        border-bottom: none;
    }
    /* Status is a fixed 180px, not auto/max-content - each <tr> is its own
       independent grid container (see display:grid above), so a
       content-sized track resolves separately per row instead of sharing
       one column boundary across the whole table the way a real <table>
       would. Two rows with different status text ("Quotation Sent" vs.
       "Quotation Drafted") would then start their officer column at two
       different x-positions, which is exactly the misalignment a table's
       columns are supposed to prevent. 180px comfortably fits the longest
       status label in either table ("Cover Note Generated" / "Insurer mail
       pending") without wrapping/clipping, and - being a fixed length
       instead of content-based - is identical on every row regardless of
       that row's own text, so the officer column after it lines up too.
       The officer column keeps the leftover space (1fr), so its content
       sits right after the status column with no gap, and has room to wrap
       a long name instead of needing to truncate it. */
    .mobile-card-table--idstatus thead tr,
    .mobile-card-table--idstatus tbody tr { grid-template-columns: 40px 180px 1fr; }
    .mobile-card-table--identity thead tr,
    .mobile-card-table--identity tbody tr { grid-template-columns: 2fr 2fr 1fr; }

    .mobile-card-table--banks thead tr,
    .mobile-card-table--banks tbody tr { grid-template-columns: 1fr auto }
    /* Cover notes' id column holds a formatted reference like
       "CN-2026-000058", not a short number like Quotations' - the default
       40px track wraps it across 4 lines. Opt into a wider one with
       .mobile-card-table--wide-id alongside --idstatus. */
    .mobile-card-table--idstatus.mobile-card-table--wide-id thead tr,
    .mobile-card-table--idstatus.mobile-card-table--wide-id tbody tr { grid-template-columns: 84px 180px 1fr; }

    /* Customer name (Quotations list, Cover notes list, and the three expiry
       tables): its own full-width line below the id/status/officer line
       rather than a 4th track, which the 3-track recipes above have no room
       for. The explicit placement is what keeps the line above intact -
       an explicitly-placed grid item is taken out of auto-placement, so the
       cells around it still flow into tracks 1-3 of row 1 exactly as they did
       before this column existed. Left as an auto item it would instead take
       track 3 and push the officer column onto a row of its own.

       Placed by class rather than nth-child because the cells *after* it sit
       at different positions per table - status is the 3rd cell on Quotations
       but the 4th on Cover notes (the desktop-only "Quotation" cell stays in
       the DOM between them) - so a positional rule would need a different
       variant per table for no gain.

       The <th> is hidden: thead here is a single strip of labels above a list
       of cards, so a full-width label under it reads as a stray row rather
       than a column heading. The name needs no label in card form, same as
       the officer name beside it. */
    .mobile-card-table td.customer-cell { grid-column: 1 / -1; grid-row: 2; }
    .mobile-card-table th.customer-cell { display: none; }

    /* --expiry (Cover notes' three expiry-kind tables - nearing/expired/
       policy-issued - only, scoped past --wide-id since that class is
       shared with the main Cover Notes list, which has a different column
       at this same DOM position): the trailing column's 1fr track is
       otherwise blank on all three (either an invisible full-row tap
       target or 1-2 action icons that don't fill the whole track), so
       "Sent to" (bank branch) now renders there too instead of staying
       desktop-only. td:nth-child(5) is safe here because
       .mobile-card-table--expiry is only ever this table - "Sent to" is
       always its 5th cell regardless of expiry_kind (both the customer-name
       cell and the display:none "Created at" cell before it stay in the DOM
       and count, so neither shifts this). Nearing's action icons (.mobile-card-action-cell)
       stack below the bank chip in the same column instead of auto-flowing
       to a new row starting back at column 1; expired/policy-issued's
       row-action-cell needs no rule since display:contents (see below)
       takes it out of grid flow entirely. */
    .mobile-card-table--expiry td:nth-child(5),
    .mobile-card-table--expiry th:nth-child(5) { grid-column: 3; grid-row: 1; }
    .mobile-card-table--expiry td.mobile-card-action-cell { grid-column: 4; grid-row: 1; }

    /* --premium: name / amount / (optional extra field) / status+action -
       name and amount share the top line, everything else drops to its own
       full-width line below rather than being squeezed into extra columns.
       Shared by two tables with a different cell count each:
       _quotation_sent_workspace.html always renders exactly 3 cells
       (company name, amount, status+action); _quotation_premium_table.html
       renders 3 or 4 depending on has_excel_verification_sent (adds a
       contact-email cell before the trailing action). nth-child(n+3) below
       matches "everything from the 3rd cell on" in both cases, and grid
       auto-placement (no explicit grid-row past row 1) flows each of those
       cells onto its own subsequent row in DOM order regardless of how
       many there are - one recipe covers both tables without knowing which
       one it's in. */
    .mobile-card-table--premium thead tr,
    .mobile-card-table--premium tbody tr {
        grid-template-columns: 1fr auto;
        row-gap: 6px;
    }
    .mobile-card-table--premium td:nth-child(1),
    .mobile-card-table--premium th:nth-child(1) { grid-column: 1; grid-row: 1; }
    .mobile-card-table--premium td:nth-child(2),
    .mobile-card-table--premium th:nth-child(2) { grid-column: 2; grid-row: 1; }
    /* text-align:left !important overrides these cells' own Bootstrap
       .text-end (right-aligned on desktop, where each is still a narrow
       shrink-to-fit column) - once spanning the full row width here,
       right-aligning would leave a growing gap on the left as the row gets
       wider, the same class of bug fixed for Quotations' officer column
       above. Harmless on cells that don't carry .text-end (e.g. the
       contact-email cell) since there's nothing to override. */
    .mobile-card-table--premium td:nth-child(n+3),
    .mobile-card-table--premium th:nth-child(n+3) { grid-column: 1 / -1; text-align: left !important; }

    .mobile-card-table thead th,
    .mobile-card-table tbody td {
        display: block;
        border: none;
        padding: 8px 0;
        /* Grid items default to min-width:auto (their content's min-content
           size) - same root cause as the classic flexbox text-overflow bug.
           A nowrap status pill's full width would otherwise force its 1fr
           track (and the whole row) wider than the viewport regardless of
           the 1fr; this lets the track actually shrink to fit. */
        min-width: 0;
    }
    .mobile-card-table thead th:last-child { display: none; }
    .mobile-card-table thead th.mobile-card-trailing-label { text-align: left; white-space: nowrap; }
    /* Left-aligned (not flex-end) - the officer column is now a 1fr track
       (see grid-template-columns above), so pinning its content to the far
       right would put the gap it was closing right back, just inside this
       cell instead of before it. */
    .mobile-card-table .officer-cell { justify-content: flex-start; }
    /* Shown in full, wrapping onto a second line for a long name instead of
       being cut off with an ellipsis - matches the Employees list's
       identity column. min-width:0 lets the flex item actually shrink
       below its text's unbroken width so wrapping kicks in, the same class
       of fix as the status-pill/greeting cases above. The recipe's floor
       width (see .mobile-card-table--idstatus min-width above) is sized to
       give a realistic 2-3-word name room to wrap at spaces; overflow-wrap
       is a fallback only - it prefers a normal word-boundary break and
       only splits a single word as a last resort, for a name long/unlucky
       enough to still not fit. */
    .mobile-card-table .officer-identity { min-width: 0; overflow-wrap: break-word; }
    /* Cover notes' expiry-kind tables pack a status pill and an expiry-dot/
       chip side by side in the same cell - fine with room to spare on
       desktop, but cramped once that cell shrinks to fit a phone's status
       column, so stack them instead of squeezing both onto one line.
       !important: the cell also carries Bootstrap's .align-items-center
       utility, which would otherwise win over align-items:flex-start. */
    .mobile-card-table .status-with-meta { flex-direction: column; align-items: flex-start !important; gap: 4px; }

    /* Single-action rows: the action link/button is stretched to an
       invisible full-row tap target instead of a visible button - same
       interaction the prototype's whole-row <a> gave, adapted to a real
       <table> that HTMX still targets by id for filtering/pagination. */
    .mobile-card-table .row-action-cell { display: contents; }
    /* Strip the control's own chrome (background/border/padding) once it's
       stretched to cover the whole row - left in place, its opaque white
       .btn-reliance-outline background paints over the row's real content
       (id, status pill, avatar) since it sits later in paint order. */
    .mobile-card-table .row-action-cell a,
    .mobile-card-table .row-action-cell button {
        position: absolute;
        inset: 0;
        background: transparent;
        border: none;
        padding: 0;
    }
    .mobile-card-table .row-action-label { display: none; }

    /* Two-action rows (Insurers/Clusters/Banks delete, Nearing-expiry's
       Send email): two small always-visible icon buttons instead of a
       whole-row tap target, which only makes sense with exactly one action.
       The cell's own `style="width: 1%"` (desktop shrink-to-fit column)
       still applies once it's a real grid item rather than display:contents
       like .row-action-cell - override it back to fitting its 66px track. */
    .mobile-card-table td.mobile-card-action-cell { width: auto !important; }
    .mobile-card-action-icons {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: 6px;
    }
    .mobile-card-action-icons .mobile-card-action-label { display: none; }
    .mobile-card-action-icons a,
    .mobile-card-action-icons button {
        width: 30px; height: 30px;
        border-radius: 10%;
        display: flex; align-items: center; justify-content: center;
        padding: 0;
        background: #fff;
        border: 1px solid var(--border);
    }

    /* Pagination: drop the low-value "Results X-Y of Z" text and the "go to
       page" input on a narrow screen; Previous/page-numbers/Next stay as
       they are (same HTMX wiring), just without the extra chrome around them.
       !important: the goto-form also carries Bootstrap's .d-flex utility,
       which sets display:flex !important and would otherwise win. */
    .pagination-result-count,
    .pagination-goto-form {
        display: none !important;
    }


    /* Freeze + scale: the min-width floors above stop each recipe's grid
       from wrapping/squeezing past its tuned reference width, but that
       alone would just push the row wider than a narrower viewport and
       force .table-responsive to scroll. Scaling the whole card (table +
       pagination together, so they shrink as one unit and stay aligned)
       down to fit avoids that - `zoom` (not `transform: scale`) is used
       because it shrinks the element's footprint in normal flow along with
       its visual size, so nothing overlaps or leaves a gap below it.
       `calc(100vw / <reference>px)` is 1 at the reference width and drops
       proportionally below it; `min(1, …)` stops it from scaling *up* past
       1 on wider viewports, where the fluid grid above already has room to
       breathe unscaled. `:has()` scopes each rule to cards that actually
       contain that recipe, so this can't affect unrelated `.card` usage,
       and needs no template changes.
       Quotations and Cover notes render their pagination as a sibling after
       the card (not inside it, unlike Officers/Insurers/Clusters/Banks) -
       the adjacent-sibling rules below give that sibling the same scale so
       it shrinks in lockstep with the table above it. */
    .card:has(.mobile-card-table--identity) { zoom: min(1, calc(100vw / 375px)); }
    .card:has(.mobile-card-table--banks) { zoom: min(1, calc(100vw / 260px)); }
    .card:has(.mobile-card-table--premium) { zoom: min(1, calc(100vw / 370px)); }
    .card:has(.mobile-card-table--idstatus) { zoom: min(1, calc(100vw / 430px)); }
    .card:has(.mobile-card-table--idstatus) + .d-flex.justify-content-between.align-items-center.mt-3 {
        zoom: min(1, calc(100vw / 430px));
    }
    .card:has(.mobile-card-table--idstatus.mobile-card-table--wide-id) { zoom: min(1, calc(100vw / 470px)); }
    .card:has(.mobile-card-table--idstatus.mobile-card-table--wide-id) + .d-flex.justify-content-between.align-items-center.mt-3 {
        zoom: min(1, calc(100vw / 470px));
    }
}

/* All modals center vertically by default - equivalent to Bootstrap's
   .modal-dialog-centered, applied globally so individual modal templates
   don't each need the class added by hand. */
.modal-dialog {
    display: flex;
    align-items: center;
    min-height: calc(100% - 1rem);
}

@media (min-width: 576px) {
    .modal-dialog {
        min-height: calc(100% - 3.5rem);
    }
}

/* Small confirmation / blocked-action modals (delete, deactivate, OTP,
   reassign, excel upload) - shared centered layout injected into
   .modal-content: 44px status circle, a short title and body copy. */
.confirm-modal h5 {
    font-size: 14px;
    font-weight: 500;
}
.confirm-modal p {
    font-size: 14px;
    font-weight: 400;
}
/* Plain Bootstrap buttons (btn-outline-secondary, btn-danger - Cancel/Keep
   editing/Discard, etc.) default to Bootstrap's 1rem (16px), one size up
   from .btn-reliance's own 14px - this keeps every button in a confirm-modal
   the same size regardless of which class rendered it. */
.confirm-modal .btn {
    font-size: 14px;
}
/* Deliberate, fixed 32px gap between a modal's last field and its Save/
   Cancel row - set here rather than left to whatever margin the field
   happens to carry, since a <fieldset> (border-0/p-0/m-0, wrapping the
   fields in every one of these modals) blocks margin collapse in Chromium,
   so two adjacent mb-3/mt-3 utility margins stack instead of merging. Pair
   with mb-0 on the field immediately before it so this is the only margin
   contributing to the gap. */
.modal-form-actions {
    margin-top: 32px;
}

/* Reassign's quotation/cover-note list can grow long - scroll just the
   list instead of letting the whole modal overflow the page. */
.confirm-modal-task-list {
    max-height: 240px;
    overflow-y: auto;
}

.alert {
    border-radius: 16px;
    padding: 12px 16px;
    font-size: 14px;
    line-height: 1.5;
}

.alert-info {
    --bs-alert-color: #2563EB;
    --bs-alert-bg: #EFF6FF;
    --bs-alert-border-color: transparent;
    --bs-alert-link-color: #2563EB;
    border: none;
}

.alert-success {
    --bs-alert-color: #067647;
    --bs-alert-bg: #e2faec;
    --bs-alert-border-color: transparent;
    --bs-alert-link-color: #067647;
    border: none;
}

.alert-danger {
    --bs-alert-color: #a91212;        /* red-500 */
    --bs-alert-bg: #FEF2F2;           /* red-50 */
    --bs-alert-border-color: transparent;
    --bs-alert-link-color: #f78888;
    border: 1px solid #ffc0c0;
}

/* Badge - small inline count / flag / label chip. The base is the neutral
   blue; the -success / -danger / -warning / -muted modifiers recolour it.
   Self-contained: no Bootstrap .bg-* utility needed, and it fully overrides
   Bootstrap's own .badge. (Pill-shaped status indicators are .status-pill.) */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border-radius: 4px;
    padding: 2px 8px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    color: #2563EB;
    background-color: #EFF6FF;
}
.badge-success { color: #0f8338; background-color: #d3edde; }
.badge-danger  { color: #B42318; background-color: #FEF3F2; }
.badge-warning { color: #B54708; background-color: #FFFAEB; }
.badge-muted   { color: #52525B; background-color: #F4F4F5; }
/* Same purple as .status-pill-delegated - this is the one other place a
   delegation gets flagged, so the deactivation modal's row type badges
   reuse it rather than inventing a second "this is a delegation" colour. */
.badge-delegated { color: #4d3486; background-color: rgba(51, 20, 191, 0.12); }

/* Initials placeholder inside partials/_circle_image.html, shown once a
   person has no uploaded profile picture (background/text colour come from
   the template via the avatar templatetags - deterministic per name). */
.circle-image-initials {
    font-weight: 600;
    line-height: 1;
    user-select: none;
}

/* Opt-in border for one specific circle-image (pass extra_class=
   "circle-image-bordered" - see _circle_image.html / _profile_image_field.html)
   - avatars are borderless by default everywhere else; the Add/Edit Employee
   page's own profile-picture upload circle looked bare without one. */
.circle-image-bordered {
    border: 1px solid var(--border);
}

/* ==========================================================================
   23. Settings page (authentication/profile.html)
   ========================================================================== */
/* "People reporting to you" - three across on desktop, collapsing to one. */
.settings-reports-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
}
@media (max-width: 991.98px) { .settings-reports-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 575.98px) { .settings-reports-grid { grid-template-columns: minmax(0, 1fr); } }
.settings-report {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: #F9FAFB;
}
.settings-report-body { min-width: 0; }
.settings-report-name { font-size: 14 px; }

/* ==========================================================================
   24. Help page (help/help.html)
   ========================================================================== */
.help-contact-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
}
/* Email support sizes to its own content rather than splitting the row
   evenly with Phone support - flex-basis is just a starting point, not a
   floor, so it still shrinks on narrow viewports instead of overflowing. */
.help-contact-card--compact { flex: 0 1 260px; }
.help-contact-card--grow { flex: 1 1 260px; }
.help-contact-icon { font-size: 24px; color: var(--brand-blue-light); }
.help-grid-2 { display: grid; grid-template-columns: minmax(0, 1.75fr) minmax(0, 1fr); gap: 20px; }
@media (max-width: 900px) { .help-grid-2 { grid-template-columns: minmax(0, 1fr); } }

.faq-row { border-radius: 10px; background: #F9FAFB; overflow: hidden; }
.faq-head {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 14px 16px; cursor: pointer;
}
.faq-head:hover { background: #F4F5F7; }
.faq-question { font-size: 14px; color: #18181B; }
/* Bootstrap's own collapse toggle sets aria-expanded, so the chevron flip
   needs no JS - see help_view/help.html for the collapse markup. */
.faq-head[aria-expanded="true"] .faq-chevron { transform: rotate(180deg); }
.faq-chevron { transition: transform 140ms ease; color: #71717A; }
.faq-answer { margin: 0; padding: 0 16px 14px; font-size: 14px; line-height: 1.6; color: #52525B; }
.help-faq-empty { padding: 26px 4px; font-size: 14px; color: #71717A; }

.help-demo-thumb { width: 100%; aspect-ratio: 16 / 10; border-radius: 12px; background: #F4F5F7; }
.help-demo-link {
    display: inline-flex; align-items: center; gap: 9px; font-size: 14px; font-weight: 600;
    text-decoration: none; color: #18181B;
}
.help-demo-link:hover { color: var(--brand-blue-light); }
.help-demo-play {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 24px; border-radius: 6px; background: #FF0000; color: #fff; flex-shrink: 0;
}

/* ==========================================================================
   25. Password change modal (Settings) and the password visibility toggle
   ========================================================================== */
/* Two steps share one dialog under the shell-in-page modal pattern (the shell
   lives in templates/authentication/profile.html), so the width has to be set
   here rather than by each returned partial. The form step needs room for the
   two-up new/confirm row: 2 x the 300px .form-control cap + .form-row-2col's
   32px gutter + .p-4's 2 x 24px = 680px, which is also what makes the single
   current-password field read as half-width, per the design. The OTP step is
   narrower, and marks itself so :has() can pick it up on the way back out. */
#passwordChangeModal .modal-dialog { max-width: 680px; }
#passwordChangeModal .modal-dialog:has([data-modal-narrow]) { max-width: 460px; }

/* Rounded-square lock badge, top-left of the form step. */
.password-change-icon {
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--field-label);
}

/* Eye toggle, positioned inside the input's right edge (see
   templates/partials/_password_field.html and the delegated
   [data-password-toggle] handler in reliance.js). The 300px cap moves from the
   input to this wrapper: left on the input, the wrapper would stretch to the
   column's full width and park the button well clear of the field's edge. */
.password-field {
    position: relative;
    display: block;
    width: 100%;
    max-width: 300px;
}
.password-field .form-control {
    width: 100%;
    max-width: none;   /* the wrapper above now carries the cap */
    padding-right: 40px;
}
.password-toggle {
    position: absolute;
    top: 50%;
    right: 12px;
    transform: translateY(-50%);
    background: none;
    border: 0;
    padding: 0;
    line-height: 1;
    color: var(--icon-grey);
}
.password-toggle:hover { color: var(--field-label); }

.password-change-form-fieldset {
    margin-bottom: 25px;
}

/*
==========================================================================
   25. Delegation of authority (DOA) workflow
========================================================================== 
*/

/* The delegation detail summary: one row of labelled fields, each sized to its
   own content and packed left with a generous gap - deliberately not an even-
   column grid, where a short "Status" would claim the same width as an avatar
   plus a full name.

   Three things keep that row inside .card-body. Without them it could only ever
   grow: a plain `display:flex` row with a fixed 5rem gap spends 320px on the
   four gaps before any content, so it ran past the card on a laptop with the
   sidebar open, long before phone widths. .main-area sets overflow-y:auto,
   which makes the x-axis compute to auto rather than visible, so the symptom
   was an inner horizontal scrollbar instead of a visible break.

   1. flex-wrap - fields drop to the next line instead of widening the row.
      row-gap is much smaller than column-gap on purpose: 5rem between stacked
      rows would read as unrelated blocks rather than one summary.
   2. clamp()'d column-gap - holds 5rem on wide screens and eases toward 1.5rem
      as the viewport narrows, so the row stays on one line longer before it has
      to wrap. Below ~600px the 4vw term falls under the floor and it settles at
      1.5rem, so no media query is needed.
   3. min-width:0 + overflow-wrap - a flex item defaults to min-width:auto and so
      refuses to shrink below its longest unbroken word, which forced the
      overflow for a long officer name even when there was room to compress.
      Same fix as .mobile-card-table .officer-identity above, on the same
      .officer-cell / .officer-identity markup; the avatar beside it is already
      flex-shrink:0 via partials/_circle_image.html. */
.details-card-grid {
    display: flex;
    flex-wrap: wrap;
    column-gap: clamp(1.5rem, 6vw, 5rem);
    row-gap: 20px;
    padding: 12px 0;
}

.details-card-grid-item {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
}

.details-card-grid-item .officer-identity { min-width: 0; overflow-wrap: break-word; }

.status-pill-delegated {
    background: rgba(51, 20, 191, 0.12); color: #4d3486; 
}

.delegation-disabled-row { opacity: 0.5; pointer-events: none; }

.delegated-task-desc {
    font-size: 14px;
    font-weight: 600;
    color:var(--brand-blue-light);
    line-height: 1.5;
}

.delegated-task-desc-container {
    display: flex;
    flex-direction: column;
}

/* Coverage state on the delegated-out table (see
   delegations/partials/_delegated_out_table.html): its own full-width line
   below the record/status/action line in card form, rather than a 4th track
   that .mobile-card-table--idstatus has no room for. Identical mechanism and
   reasoning to .customer-cell in section 22 - explicit placement keeps the
   line above intact, since an explicitly-placed grid item is taken out of
   auto-placement. Unlike .customer-cell the <th> is not hidden: this cell
   carries two different pill labels rather than a bare name, so the label
   above it is doing work. Inside the same media query as the recipe it
   belongs to.

   The <th> is hidden exactly as .customer-cell's is, and for the same reason:
   thead here is a single strip of labels above a list of cards, so a
   full-width label under it reads as a stray row. Nothing is lost - the cell's
   two pill labels ("Being covered" / "Returned to you") already name
   themselves. */
@media (max-width: 767px) {
    .mobile-card-table td.coverage-cell { grid-column: 1 / -1; grid-row: 2; }
    .mobile-card-table th.coverage-cell { display: none; }
}

/* "Currently covered for you" strip above the delegated-out table - one card
   per live hand-over of this officer's work. See
   delegations/partials/_coverage_summary.html.

   auto-fill/minmax rather than a fixed column count because a hand-over takes
   an officer's whole open queue, so the realistic case is one or two cards: a
   hard 3-up grid would strand a lone card at a third of the width.

   Tinted #EFF6FF, the same "this belongs to someone else" blue .alert-info and
   .ownership-select-scope already use, so the strip can't be mistaken for an
   ordinary white card and scrolled past. */
.coverage-summary {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 16px;
}

.coverage-summary-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 16px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: #fdfdfd;
}

.coverage-summary-meta { font-size: 14px; line-height: 2; }

/* Keeps the "May raise quotations in your name" chip at its text width rather
   than stretched across the card by the flex column. */
.coverage-summary-card .badge { align-self: flex-start; }

/* The dashboard pane variant: the strip sits inside a tab above its own table,
   so it gives up the standalone page's vertical breathing room. */
.coverage-summary-compact { gap: 12px; }
.coverage-summary-compact .coverage-summary-card { padding: 12px; }

/* ==========================================================================
   26. Circular image crop modal (Cropper.js) - partials/_profile_image_field.html
   ========================================================================== */
.crop-modal-image-wrap {
    max-height: 60vh;
    display: flex;
    justify-content: center;
}
.crop-modal-image-wrap img { max-width: 100%; display: block; }

/* Cropper.js's documented round-crop-box recipe: .cropper-view-box clips the
   live preview to a circle, .cropper-face (the draggable overlay) needs the
   same radius so its hit-area matches what's visually kept. The default
   square outline on .cropper-view-box would otherwise poke out past the
   circle, hence outline:0. */
.cropper-view-box,
.cropper-face {
    border-radius: 50%;
}
.cropper-view-box {
    outline: 0;
}

/* ==========================================================================
   Bank quote "Prepare break down for customer" popup
   ========================================================================== */
.breakdown-title { font-size: 1rem; font-weight: 600; color: #3b82f6; margin-bottom: 0.25rem; }
.breakdown-wrap { display: flex; gap: 0.5rem; align-items: stretch; }
.breakdown-scroll { flex: 1 1 auto; overflow-x: auto; }
.breakdown-table { width: 100%; border-collapse: collapse; }
.breakdown-table th,
.breakdown-table td { padding: 1rem; border: 1px solid #e4e4e7; font-size: 0.875rem; text-align: left; white-space: nowrap; }
.breakdown-table th { font-weight: 500; }
.breakdown-table th:has(.breakdown-input),
.breakdown-table td:has(.breakdown-input) { padding: 0; min-width: 9rem; }
.breakdown-input { width: 100%; padding: 1rem; border: 0; background: transparent; font: inherit; }
.breakdown-input:focus { outline: 2px solid #3b82f6; outline-offset: -2px; }
.breakdown-add-col { flex: 0 0 auto; width: 2rem; border: 0; border-radius: 0.5rem; background: #f4f4f5; color: #52525b; }
.breakdown-add-col:hover:not(:disabled) { background: #e4e4e7; }
.breakdown-add-col:disabled { opacity: 0.5; cursor: not-allowed; }

/* ==========================================================================
   27. Quotation ownership selector (on_behalf_of pills, quotation form)
   Replaces the old "Create as" dropdown with clickable pills inside a card
   tinted the same blue already used for "this belongs to someone else"
   context elsewhere in the app (.alert-info / _delegation_banner.html), so
   it can't be mistaken for an ordinary white card and skipped past. Pill
   recipe mirrors .filter-pill (dashboards) - same :has(input:checked) /
   :has(input:focus-visible) technique, reused rather than duplicated blind.
   ========================================================================== */
.ownership-select-scope {
    background: #EFF6FF;
    border-color: rgba(37, 99, 235, 0.25);
}

.ownership-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 8px 16px;
    font-size: 14px;
    font-weight: 500;
    color: #18181b;
    cursor: pointer;
    user-select: none;
}
.ownership-pill:has(input:checked) {
    border-color: var(--doc-select-checked);
    color: var(--doc-select-checked);
    font-weight: 600;
}
.ownership-pill:has(input:focus-visible) {
    outline: 2px solid var(--doc-select-checked);
    outline-offset: 1px;
}
