/* Visual language tokens (Phase 2 Spec F1, 2026-05-28).
   Future per-module restyles consume these via var(--token-name). */
:root {
    /* Color */
    --color-primary:   #052767;          /* deep navy — from sidebar gradient top */
    --color-accent:    #3a0647;          /* deep purple — from sidebar gradient bottom */
    --color-success:   #198754;          /* Bootstrap success */
    --color-danger:    #dc3545;          /* Bootstrap danger */
    --color-warning:   #ffc107;          /* Bootstrap warning */
    --color-bg:        #f8f9fa;          /* page background */
    --color-surface:   #ffffff;          /* card/panel background */
    --color-text:      #212529;          /* body text */
    --color-muted:     #6c757d;          /* secondary text */
    --color-border:    #dee2e6;          /* hairlines, dividers */

    /* Typography */
    --font-family-base: system-ui, -apple-system, "Segoe UI", Roboto,
                        "Helvetica Neue", Arial, sans-serif;

    --text-xs:   12px;
    --text-sm:   13px;
    --text-base: 14px;
    --text-md:   15px;
    --text-lg:   20px;

    --weight-normal:   400;
    --weight-semibold: 600;
    --weight-bold:     700;

    /* Spacing (4-px grid; gaps mirror Bootstrap scale) */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-6: 24px;
    --space-8: 32px;

    /* Radius */
    --radius-sm:   4px;
    --radius-md:   6px;
    --radius-lg:   8px;
    --radius-pill: 9999px;

    /* Shadow */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
    --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* Layout patterns (Phase 2 Spec F2, 2026-05-29).
   Reusable utilities consumed by per-module restyles. */

/* Page hero — gradient header at the top of restyled pages */
.page-hero {
    background: linear-gradient(180deg, var(--color-primary), var(--color-accent));
    color: var(--color-surface);
    padding: var(--space-4) var(--space-6);
    border-radius: var(--radius-md);
    margin-top: var(--space-3);
    margin-bottom: var(--space-4);
}
.page-hero .hero-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: var(--space-4);
}
.page-hero .hero-eyebrow {
    font-size: var(--text-xs);
    opacity: 0.8;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: var(--space-1);
}
.page-hero h1,
.page-hero h2,
.page-hero h3 {
    color: var(--color-surface);
    margin: 0;
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
}
.page-hero .hero-meta {
    font-size: var(--text-sm);
    opacity: 0.8;
    margin-top: var(--space-1);
}
.page-hero .btn-on-hero {
    background: var(--color-surface);
    color: var(--color-primary);
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-md);
    font-weight: var(--weight-bold);
    font-size: var(--text-sm);
    border: 0;
    cursor: pointer;
}
.page-hero .btn-on-hero:hover { opacity: 0.92; }

/* KPI strip — flex container of count cards */
.kpi-strip {
    display: flex;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
}
.kpi-strip .kpi {
    flex: 1;
    background: var(--color-bg);
    padding: var(--space-3);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
}
.kpi-strip .kpi-value {
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    color: var(--color-primary);
    line-height: 1;
}
.kpi-strip .kpi-label {
    font-size: var(--text-xs);
    color: var(--color-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-top: var(--space-1);
}

/* Table card — wraps a data table in a bordered, rounded surface */
.table-card {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    background: var(--color-surface);
    margin-bottom: var(--space-3);
}
.table-card > .table { margin-bottom: 0; }
.table-card > .table > thead > tr > th {
    background: var(--color-bg);
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-muted);
    font-weight: var(--weight-semibold);
    border-bottom: 1px solid var(--color-border);
    padding: var(--space-2) var(--space-3);
}
.table-card > .table > tbody > tr > td {
    padding: var(--space-3);
    font-size: var(--text-sm);
    border-top: 1px solid var(--color-border);
    vertical-align: middle;
}
.table-card > .table > tbody > tr:hover { background: var(--color-bg); }
/* Clickable rows get a clearly-visible (but still soft) hover. Bootstrap paints an opaque white
   background on the CELLS (var(--bs-table-bg)), which covers any <tr> background — so we must tint
   the <td>s, not the <tr>. */
.table-card > .table > tbody > tr.clickable-row > td { transition: background-color .12s ease; }
.table-card > .table > tbody > tr.clickable-row:hover > td { background-color: #e6ebf2; }

/* Row meta — small muted secondary line inside a two-line cell */
.row-meta {
    font-size: var(--text-xs);
    color: var(--color-muted);
    margin-top: var(--space-1);
}

/* Status pills — generic + status-specific modifiers */
.status-pill {
    display: inline-block;
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    padding: 2px var(--space-2);
    border-radius: var(--radius-pill);
    /* uniform 78px when it fits, but shrinks to the cell so a pill can never spill past a
       fixed-layout table's border (min-width wins over max-width, so min() is the right tool). */
    min-width: min(78px, 100%);
    text-align: center;
    line-height: 1.6;
}
.status-pill.status-open      { background: #fff3cd; color: #856404; }   /* warm yellow */
.status-pill.status-progress  { background: #cfe2ff; color: #084298; }   /* info blue */
.status-pill.status-resolved  { background: #e2d4f0; color: #492a8e; }   /* accent purple */
.status-pill.status-closed    { background: #d1e7dd; color: #0f5132; }   /* success green */
.status-pill.status-rejected  { background: #f8d7da; color: #842029; }   /* danger red */
.status-pill.status-archived  { background: #e2e3e5; color: #41464b; }   /* muted gray */
.status-pill.status-active    { background: #d1e7dd; color: #0f5132; }   /* vivid success green */
.status-pill.status-inactive  { background: #f8d7da; color: #842029; }   /* vivid danger red */
.status-pill.status-draft      { background: #e9ecef; color: #495057; }   /* convey draft gray */
.status-pill.status-inpipeline { background: #cfe2ff; color: #084298; }   /* convey routing blue */

/* Ticket priority pills (PriorityPresentation.PillClass) */
.status-pill.priority-low      { background: #e2e3e5; color: #41464b; }   /* muted gray */
.status-pill.priority-medium   { background: #fff3cd; color: #856404; }   /* warm yellow */
.status-pill.priority-high     { background: #f8d7da; color: #842029; }   /* danger red */
.status-pill.status-onhold     { background: #ffe7cc; color: #8a4b0f; }   /* waiting orange */
.status-pill.status-paid       { background: #d1f0e8; color: #0b5d4e; }   /* expense paid - deep teal/green */

/* Generic colored tag pill — single --c hex drives a soft tint + darker text.
   Used for department pills (org-chart hue) and role pills (RolePalette). */
.tag-pill {
    display: inline-block;
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    line-height: 1.6;
    padding: 1px var(--space-2);
    border-radius: var(--radius-pill);
    white-space: nowrap;
    background: color-mix(in srgb, var(--c, #94a3b8) 14%, white);
    color:      color-mix(in srgb, var(--c, #94a3b8) 78%, black);
}
/* Bullet variant: a dot one shade darker than the fill (role pills). */
.tag-pill--dot::before {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    margin-right: 5px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--c, #94a3b8) 72%, black);
    vertical-align: baseline;
}
/* Wrap multiple pills (e.g. several roles) with a small gap. */
.tag-pill-group {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

/* Toolbar pill — restyled button group, replaces ad-hoc Bootstrap toolbars */
.toolbar-pill {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
}
.toolbar-pill .toolbar-btn {
    background: var(--color-bg);
    color: var(--color-text);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
}
.toolbar-pill .toolbar-btn:hover { border-color: var(--color-primary); color: var(--color-primary); }
.toolbar-pill .toolbar-btn.toolbar-btn-active {
    background: var(--color-primary);
    color: var(--color-surface);
    border-color: var(--color-primary);
}
.toolbar-pill .toolbar-btn.toolbar-btn-danger {
    background: var(--color-surface);
    color: var(--color-danger);
    border-color: var(--color-danger);
}
.toolbar-pill .toolbar-btn.toolbar-btn-danger:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* Subsection label — small uppercase muted heading above grids */
.subsection-label {
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    color: var(--color-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin: var(--space-4) 0 var(--space-2) 0;
}

/* Modal section — inner panel inside a modal body (admin actions, support details, etc.) */
.modal-section {
    background: var(--color-bg);
    padding: var(--space-3);
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
}

/* Scoped brand override for primary buttons inside modals (per-module restyle boundary) */
.modal .btn-primary {
    background: var(--color-primary);
    border-color: var(--color-primary);
}
.modal .btn-primary:hover,
.modal .btn-primary:focus {
    background: var(--color-accent);
    border-color: var(--color-accent);
}

/* Soft-tinted secondary destructive buttons (Spec G).
   Used for secondary destructive actions inside an Edit dialog where
   the WHOLE modal is not destructive (the primary action is Save).
   Outside .modal, normal Bootstrap btn-danger/btn-info still apply. */
.modal .btn-danger-soft {
    background: #f8d7da;
    color: #842029;
    border: 1px solid #f5c2c7;
}
.modal .btn-danger-soft:hover {
    background: #f5c2c7;
    color: #842029;
}
.modal .btn-info-soft {
    background: #cff4fc;
    color: #055160;
    border: 1px solid #b6effb;
}
.modal .btn-info-soft:hover {
    background: #b6effb;
    color: #055160;
}

/* Shared cross-cutting UI styles. Linked from Components/App.razor (app.css is not linked here). */

/* Modal backdrop blur — render <div class="modal-overlay"></div> before a manual modal. */
.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, 0.3);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    z-index: 1000;
}

/* Keep manual modals above the overlay (matches the existing per-page rule). */
.modal {
    z-index: 1100;
}

/* Single-click table rows — subtle interactivity cue. */
.clickable-row { cursor: pointer; transition: background-color .12s ease; }
.clickable-row:hover { background-color: #e6ebf2; }

/* Badge count — red pill for unread/active counts on tabs and KPI tiles */
.badge-count { display:inline-flex; align-items:center; justify-content:center; min-width:18px; height:18px;
  padding:0 5px; margin-left:6px; border-radius:9999px; background:#dc3545; color:#fff;
  font-size:11px; font-weight:700; line-height:1; vertical-align:middle; }
.kpi { position:relative; }
.kpi .badge-count { position:absolute; top:8px; right:10px; margin:0; }

/* Modal loading spinner — centered, brand-coloured (Phase 2 Task 7). */
.modal-spinner { display:flex; flex-direction:column; justify-content:center; align-items:center; gap:var(--space-3); padding:var(--space-8) 0; }
.modal-spinner .spinner-border { width:2.5rem; height:2.5rem; color:var(--color-primary); border-width:.28em; }
.modal-spinner-text { color:var(--color-muted); font-size:var(--text-sm); font-weight:var(--weight-semibold); text-align:center; margin:0; }

/* Report cards (Reports page) */
.report-card {
    background: var(--color-surface, #fff);
    border: 1px solid var(--color-border, #e2e8f0);
    border-radius: var(--radius-md, 12px);
    box-shadow: var(--shadow-md, 0 1px 4px rgba(0,0,0,.05));
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
}
.rc-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
.rc-title { font-size: 15px; margin: 0; color: #0f172a; }
.rc-pill { font-size: 10px; font-weight: 800; color: #fff; padding: 3px 9px; border-radius: 999px; white-space: nowrap; }
.rc-pill--share { background: #3a0647; }
.rc-pill--exec  { background: #052767; }
.rc-pill--mgr   { background: #14b8a6; }
.rc-pill--ops   { background: #475569; }
.rc-body { height: 230px; position: relative; }
.rc-desc { font-size: 12.5px; color: #334155; line-height: 1.5; margin-top: 12px; border-top: 1px solid #eef2f7; padding-top: 10px; }

/* Verbatim message box — used for submission-modal guard/error messages. */
.verbatim {
    display: block;
    background: #f6f8fa;
    border-left: 4px solid var(--color-danger, #dc3545);
    border-radius: var(--radius-sm, 4px);
    padding: 10px 14px;
    margin: 4px 0;
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
    font-size: var(--text-sm, 13px);
    white-space: pre-wrap;
    color: var(--color-text, #212529);
}

/* ===== Responsive data tables ===== */
@media (max-width: 600px) {
    .table-card { overflow-x: visible; }
    .table-card > .table { min-width: 0 !important; }
    .table-card > .table thead { display: none; }
    .table-card > .table tbody,
    .table-card > .table tr,
    .table-card > .table td { display: block; width: 100% !important; }
    .table-card > .table tr {
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        margin: 0 0 var(--space-3);
        padding: var(--space-2) var(--space-3);
        background: var(--color-surface);
    }
    .table-card > .table td {
        border: 0;
        padding: var(--space-1) 0;
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: var(--space-3);
        text-align: right;
        min-width: 0;
        /* let long unbreakable values (emails, usernames) wrap instead of overflowing the card */
        overflow-wrap: anywhere;
    }
    .table-card > .table td::before {
        content: attr(data-label);
        font-weight: var(--weight-semibold);
        color: var(--color-muted);
        text-align: left;
        white-space: nowrap;
        flex-shrink: 0;   /* keep the label intact; the value wraps */
    }
    .table-card > .table td:empty { display: none; }
}

/* ===== Wide two-column ticket modal ===== */
.modal-dialog.ticket-modal-wide { max-width: 1200px; width: 96%; }
.ticket-modal-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-6);
    align-items: stretch;
}
.ticket-modal-grid > .ticket-col-right {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
@media (max-width: 800px) {
    .modal-dialog.ticket-modal-wide { max-width: 96%; }
    .ticket-modal-grid { grid-template-columns: 1fr; gap: var(--space-4); }
}

/* ===== Wide convey create/edit modal (single source — do NOT duplicate into scoped css) ===== */
.modal-dialog.convey-modal-wide { max-width: 1100px; width: 96%; }
@media (max-width: 800px) {
    .modal-dialog.convey-modal-wide { max-width: 96%; }
}

/* ===== Wide expense create modal ===== */
.modal-dialog.expense-modal-wide { max-width: 1180px; width: 96%; }
@media (max-width: 800px) {
    .modal-dialog.expense-modal-wide { max-width: 96%; }
}

/* ===== Wide users edit modal ===== */
.modal-dialog.users-modal-wide { max-width: 960px; width: 96%; }
@media (max-width: 800px) {
    .modal-dialog.users-modal-wide { max-width: 96%; }
}

/* ===== Functional-role sections grid (Manage Users edit modal) =====
   Each subsystem cell (.role-subsystem-cell) contains a label + grey box.
   3 columns on wide modal, 2 on medium, 1 on mobile. */
.role-sections-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-3);
    align-items: start;
}
@media (max-width: 700px) {
    .role-sections-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
    .role-sections-grid { grid-template-columns: 1fr; }
}
/* Each cell: label sits directly above its grey box, no extra top margin */
.role-subsystem-cell .subsection-label { margin-top: 0; }

/* ===== Single-scrollbar when a modal is open =====
   These modals are rendered manually (<div class="modal show" style="display:block">)
   WITHOUT Bootstrap's JS, which would normally add .modal-open to <body> and lock
   the background. blazor.bootstrap.css makes <main> a scroll container
   (height:100vh; overflow-x:hidden => overflow-y:auto), so when a tall modal opens
   the page shows TWO vertical scrollbars: the background <main> and the modal itself.
   While any modal is open, lock the background so only the modal scrolls. */
body:has(.modal.show) { overflow: hidden; }
body:has(.modal.show) main { overflow: hidden !important; }

/* ===== Responsive detail modals (leave + procurement + convey) ===== */
/* .custom-modal is used ONLY by the 8 detail modals (3 leave + 3 procurement + 2 convey);
   the create-request modal uses .modal-lg, so it is intentionally unaffected.
   !important is REQUIRED here: each page's scoped CSS (.custom-modal[b-xxx] etc.)
   carries the isolation attribute, raising its specificity at/above these global
   selectors, and App.razor re-links the scoped bundle AFTER shared-ui.css — so
   without !important these overrides silently lose the cascade. (Same reason the
   responsive data-table rules above use width/min-width !important.) */
@media (max-width: 800px) {
    .modal-dialog.custom-modal { max-width: 96% !important; }
    .custom-modal .request-details-container { flex-direction: column !important; }
    /* procurement scopes .details-column to max-width:33% — full-width when stacked */
    .custom-modal .request-details-container > div { max-width: 100% !important; }
}

/* Procurement detail tables → stacked label/value cards on phones.
   Mirrors the data-grid card-collapse pattern; needs data-label on every <td>. */
@media (max-width: 600px) {
    .custom-modal .products-table { table-layout: auto !important; min-width: 0 !important; }
    .custom-modal .products-table thead { display: none !important; }
    .custom-modal .products-table,
    .custom-modal .products-table tbody,
    .custom-modal .products-table tr { display: block !important; width: 100% !important; }
    .custom-modal .products-table tr {
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        margin: 0 0 var(--space-3);
        padding: var(--space-2) var(--space-3);
        background: var(--color-surface);
    }
    .custom-modal .products-table td {
        display: flex !important;
        width: 100% !important;
        border: 0 !important;
        padding: var(--space-1) 0 !important;
        align-items: baseline;
        justify-content: space-between;
        gap: var(--space-3);
        text-align: right !important;
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
    }
    .custom-modal .products-table td::before {
        content: attr(data-label);
        font-weight: var(--weight-semibold);
        color: var(--color-muted);
        text-align: left;
        white-space: nowrap;
        margin-right: var(--space-3);
    }
    .custom-modal .products-table td:empty { display: none !important; }
}

/* ===== Approval / signature "pipeline" tables (detail modals) ==========================
   The Procurement, Expense and Convey detail modals each render a pipeline-of-approvals
   table (# · Stage · Decision · Approver · Date · Message — or the Convey signature
   equivalent). These historically reused .products-table with table-layout:fixed, so every
   column inherited a hard percentage borrowed from the 7-column Products grid: the "#"
   column ballooned to the Products "Title" width (30 %) while the "Message" header wrapped
   letter-by-letter ("Messag e"). .pipeline-table instead sizes each column to its content —
   header cells never wrap, so a column is always at least wide enough to show its header
   cleanly, and the free-text .pipeline-col-flex column (Message) wraps + soaks up the slack
   so the data columns stay compact. Every <td> carries data-label for the phone card-collapse
   below. */
.pipeline-table {
    width: 100%;
    table-layout: auto;          /* content-driven column widths, not fixed percentages */
    border-collapse: collapse;
    margin-top: 1rem;
}
.pipeline-table th,
.pipeline-table td {
    padding: 0.75rem;
    text-align: left;
    vertical-align: middle;
    border: 1px solid #dee2e6;
    white-space: nowrap;         /* each column hugs its content on a single line */
}
.pipeline-table thead th {
    background-color: #f8f9fa;
    font-weight: bold;
    text-align: center;
    white-space: nowrap;         /* header never breaks → it sets the column's minimum width */
}
.pipeline-table tbody tr:nth-child(odd) { background-color: #f9f9f9; }
/* Free-text column (Message): wraps and absorbs the remaining width; its header keeps the
   nowrap rule above, so the "Message" label itself still never breaks. */
.pipeline-table th.pipeline-col-flex { width: 100%; }
.pipeline-table td.pipeline-col-flex {
    width: 100%;
    white-space: normal;
    word-break: break-word;
}

/* Pipeline tables → stacked label/value cards on phones (mirrors the .products-table
   collapse; every <td> has data-label). Not scoped to .custom-modal so it also covers the
   Expense/Convey modals. */
@media (max-width: 600px) {
    .pipeline-table thead { display: none; }
    .pipeline-table,
    .pipeline-table tbody,
    .pipeline-table tr { display: block; width: 100%; }
    .pipeline-table tr {
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        margin: 0 0 var(--space-3);
        padding: var(--space-2) var(--space-3);
        background: var(--color-surface);
    }
    .pipeline-table td {
        display: flex;
        width: 100% !important;
        border: 0;
        padding: var(--space-1) 0;
        align-items: baseline;
        justify-content: space-between;
        gap: var(--space-3);
        text-align: right;
        white-space: normal;
    }
    .pipeline-table td::before {
        content: attr(data-label);
        font-weight: var(--weight-semibold);
        color: var(--color-muted);
        text-align: left;
        white-space: nowrap;
        margin-right: var(--space-3);
    }
    .pipeline-table td:empty { display: none; }
}

/* Procurement CREATE form (CreateProcurementRequestModal) — its product-entry table is an INPUT
   grid (class .entry-products-table, unique to that component; it's a .modal-lg, not .custom-modal).
   On phones collapse each product row into a stacked block: label above, full-width control below,
   so "Unit Price (without VAT)" etc. stop wrapping letter-by-letter in tiny fixed columns.
   !important beats the component's scoped per-column nth-child widths + table-layout:fixed. */
@media (max-width: 600px) {
    .entry-products-table { display: block !important; table-layout: auto !important; width: 100% !important; }
    .entry-products-table thead { display: none !important; }
    .entry-products-table tbody,
    .entry-products-table tr,
    .entry-products-table td { display: block !important; width: 100% !important; }
    .entry-products-table tr {
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        margin: 0 0 var(--space-3);
        padding: var(--space-2) var(--space-3);
        background: var(--color-surface);
    }
    .entry-products-table td {
        border: 0 !important;
        padding: var(--space-2) 0 !important;
        vertical-align: top;
    }
    .entry-products-table td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-weight: var(--weight-semibold);
        color: var(--color-muted);
        font-size: var(--text-xs);
        margin-bottom: var(--space-1);
    }
    /* controls fill the card width */
    .entry-products-table td .form-control,
    .entry-products-table td .unit-price-wrap { width: 100% !important; }
    /* the title field is scoped to 50% — full-width on phones too */
    .request-title-input { width: 100% !important; }
}

/* ===== KPI strip: drop secondary tiles on phones =====
   A .kpi-strip with many tiles (e.g. Ticket Management's 7) crushes on a phone.
   Tag the non-essential tiles .kpi-hide-mobile to keep only the key few visible. */
@media (max-width: 768px) {
    .kpi-hide-mobile { display: none !important; }
}

/* Rendered rich-text ticket content + missing-attachment chip */
.rt-rendered { max-width: 100%; overflow-wrap: break-word; }
.rt-rendered img { max-width: 100%; height: auto; border-radius: 4px; }
.rt-rendered p { margin-bottom: 6px; }
.rt-missing-attachment { display: inline-block; background: #f1f3f5; color: #6c757d; font-size: 12px; padding: 2px 10px; border-radius: 12px; border: 1px dashed #ced4da; }

/* ===== Functional-role description tooltip (the grid's trailing i-icon) =====
   Hover on desktop; tap works too because tabindex=0 makes the span focusable. */
.role-info {
    position: relative;
    display: inline-block;
    margin-left: 8px;
    color: #5b2a86;
    font-weight: 700;
    cursor: help;
    outline: none;
}
.role-info:focus-visible { outline: 2px solid #5b2a86; outline-offset: 2px; border-radius: 3px; }
.role-info::after {
    content: attr(data-tip);
    position: absolute;
    right: 0;
    bottom: 125%;
    width: max-content;
    max-width: 260px;
    background: #2d2a33;
    color: #fff;
    font-size: 12px;
    font-weight: 400;
    line-height: 1.45;
    text-align: left;
    white-space: normal;
    word-break: break-word;
    padding: 6px 10px;
    border-radius: 8px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .12s ease;
    z-index: 50;
}
.role-info:hover::after,
.role-info:focus::after { opacity: 1; }

/* ── GnΩsis wordmark (GnosisBrand.razor): shrink the capital Ω toward lowercase x-height ── */
.omega-lc { font-size: 0.84em; vertical-align: baseline; }

/* Auto-growing wrapping text fields (textarea) — used app-wide so long values
   wrap onto the next line instead of being clipped. Hoisted from the Purchases
   create-modal scoped CSS so every subsystem's free-text fields behave the same. */
.auto-grow {
    field-sizing: content;              /* auto-grow height (Chromium target) */
    min-height: calc(1.5em + 0.75rem);  /* match single-line .form-control height */
    resize: vertical;                   /* manual fallback where field-sizing is unsupported */
    white-space: pre-wrap;              /* wrap text and preserve newlines */
    overflow-wrap: break-word;          /* break long words to prevent overflow */
}
