/* QPulse ships Open Iconic locally; importing it here makes every oi-* menu and action icon render. */
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');

/* ============================================================================
   QPulse — executive dashboard styles.
   QPulse authoring rules:
   - RAW shared tokens only (qbm-theme.css loads first): --surface, --surface-alt,
     --text-*, --accent, --success/--warning/--danger/--info, --border, --space-*,
     --radius-*, --shadow-*, --focus-ring. No legacy --qs-* bridge.
   - Logical properties (inline-start/end) everywhere so Arabic/Farsi RTL needs
     no mirrored overrides.
   - Every interactive element defines default / hover / focus-visible / active /
     disabled; every data region has loading / empty / error styles.
   ========================================================================== */

/* ---- App-level token decisions -------------------------------------------- */
/* Light mode keeps the chart-family indigo while dark mode uses its accessible
   lighter companion so labels, focus rings, and selected controls remain legible. */
:root,
:root[data-theme="light"] {
    --accent: #4f46e5;
    --accent-strong: #4338ca;
    /* Aging heat ramp (between the shared info/warning/danger stops). */
    --qp-amber: #f59e0b;
}

:root[data-theme="dark"] {
    --accent: #818cf8;
    --accent-strong: #a5b4fc;
    /* The dark accent is a LIGHT indigo, so the shared white ink inherited from
       qbm-theme reads at only 2.76:1 on it. Anything filled with --accent (the
       skip link, the startup mark, a selected dropdown item) needs dark ink:
       #10122e gives 6.12:1 on #818cf8 and 8.3:1 on the lighter --accent-strong. */
    --accent-contrast: #10122e;
    --qp-amber: #f59e0b;
}

html,
body {
    margin: 0;
    padding: 0;
    font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
    background: var(--surface);
    color: var(--text-primary);
    font-size: var(--font-size-base, 0.95rem);
}

/* KPI figures line up because every numeral occupies the same width. */
.qp-kpi-value,
.qp-delta,
.qp-alert-amount,
.qp-aging-amount,
.qp-table td.num,
.qp-table th.num {
    font-variant-numeric: tabular-nums;
}

/* Keyboard users always get the shared focus ring; mouse clicks stay quiet. */
:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
    border-radius: var(--radius-sm);
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ---- Startup splash (index.html renders this before Blazor boots) ---------- */
.qp-startup {
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-3);
    color: var(--text-secondary);
}

.qp-startup-mark {
    width: 64px;
    height: 64px;
    border-radius: 16px;
    box-shadow: var(--shadow-lg);
}

.qp-startup-pulse {
    stroke-dasharray: 130;
    stroke-dashoffset: 130;
    animation: qp-pulse-draw 1.6s ease-in-out infinite;
}

@keyframes qp-pulse-draw {
    60% { stroke-dashoffset: 0; }
    100% { stroke-dashoffset: -130; }
}

.qp-startup-title {
    font-size: var(--font-size-xl, 1.25rem);
    font-weight: 700;
    color: var(--text-heading);
}

.qp-startup-hint {
    font-size: var(--font-size-sm, 0.875rem);
}

/* ---- Shell states ---------------------------------------------------------- */
.qs-loading {
    min-height: 40vh;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
}

.qs-error {
    margin: var(--space-6) auto;
    max-width: 34rem;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-5);
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-inline-start: 3px solid var(--danger);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    color: var(--text-primary);
}

/* Shared small action button (used by error states, custom range apply, etc.). */
.qs-button {
    align-self: flex-start;
    min-height: 44px;
    padding: 0 var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--btn-radius, 12px);
    background: var(--surface-alt);
    color: var(--text-primary);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, transform 80ms ease;
}

.qs-button:hover:not(:disabled) {
    border-color: var(--accent);
    color: var(--accent);
}

.qs-button:active:not(:disabled) {
    transform: translateY(1px);
}

.qs-button:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

/* ---- Page scaffolding ------------------------------------------------------ */
.content {
    padding: var(--space-4) var(--space-4) var(--space-8);
    /* A wider executive canvas keeps charts analytical rather than thumbnail-sized on management displays. */
    max-width: 1600px;
    margin-inline: auto;
    box-sizing: border-box;
    width: 100%;
}

/* Reserve room for the phone tab bar so the last card is never hidden behind it. */
.qp-has-tabbar {
    padding-bottom: calc(var(--space-8) + 64px + env(safe-area-inset-bottom, 0px));
}

.qp-page-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-block: var(--space-2) var(--space-4);
}

.qp-kicker {
    margin: 0 0 2px;
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent);
}

.qp-page-title h1 {
    margin: 0;
    font-size: var(--font-size-2xl, 1.5rem);
    line-height: 1.2;
    color: var(--text-heading);
}

.qp-page-subtitle {
    margin: var(--space-1) 0 0;
    color: var(--text-secondary);
    font-size: var(--font-size-sm, 0.875rem);
}

.qp-header-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

/* "As of 18/07 14:32 · auto-refresh 5m" status line. */
.qp-asof {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
}

.qp-asof .oi {
    font-size: 0.7rem;
}

/* Section grid: two columns on desktop, stacked on phones. */
.qp-grid-2 {
    display: grid;
    /* Medium screens stack sooner so each visual retains decision-grade plotting room. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 460px), 1fr));
    gap: var(--space-4);
    align-items: start;
}

/* ---- Toolbar (period + location + refresh) --------------------------------- */
.qp-toolbar {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.qp-toolbar-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.qp-period {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-width: 0;
    flex: 1 1 auto;
}

.qp-period-chips {
    display: flex;
    gap: var(--space-2);
    overflow-x: auto;
    padding-block: 2px;
    scrollbar-width: none;
}

.qp-period-chips::-webkit-scrollbar {
    display: none;
}

.qp-chip {
    flex: 0 0 auto;
    min-height: 44px;
    padding: 0 var(--space-3);
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface-alt);
    color: var(--text-secondary);
    font: inherit;
    font-size: var(--font-size-sm, 0.875rem);
    font-weight: 600;
    cursor: pointer;
    transition: color 120ms ease, border-color 120ms ease, background-color 120ms ease;
}

.qp-chip:hover:not(:disabled):not(.active) {
    color: var(--text-primary);
    border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
}

.qp-chip.active {
    background: color-mix(in srgb, var(--accent) 16%, var(--surface-alt));
    border-color: var(--accent);
    /* --accent on its own 16% tint measures 4.47:1 in dark. --accent-strong is the
       lighter companion in dark and the deeper one in light, so it lifts both. */
    color: var(--accent-strong);
}

.qp-chip:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

.qp-period-tools {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.qp-compare {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-sm, 0.875rem);
    color: var(--text-secondary);
}

.qp-select,
.qp-input {
    min-height: 44px;
    padding: 0 var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--field-radius, 12px);
    background: var(--surface-alt);
    color: var(--text-primary);
    font: inherit;
    font-size: var(--font-size-sm, 0.875rem);
}

.qp-select:hover:not(:disabled),
.qp-input:hover:not(:disabled) {
    border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
}

.qp-select:focus-visible,
.qp-input:focus-visible {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--field-focus-ring, color-mix(in srgb, var(--accent) 28%, transparent));
}

.qp-select:disabled,
.qp-input:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

.qp-custom-range {
    display: flex;
    align-items: flex-end;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.qp-custom-range label {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--text-secondary);
}

/* ---- KPI wall -------------------------------------------------------------- */
.qp-kpi-wall {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 168px), 1fr));
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

/* The decision strip gives CEOs one calm, high-signal row before the full KPI wall. */
.qp-decision-strip {
    margin-bottom: var(--space-4);
    padding: var(--space-4);
    border: 1px solid color-mix(in srgb, var(--accent) 24%, var(--border));
    border-radius: var(--radius-lg, 16px);
    background:
        linear-gradient(135deg, color-mix(in srgb, var(--accent) 8%, transparent), transparent 48%),
        var(--surface-alt);
    box-shadow: var(--shadow-card);
}

.qp-decision-header {
    display: flex;
    align-items: end;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}

.qp-decision-header h2 {
    margin: 0;
    color: var(--text-heading);
    font-size: var(--font-size-lg, 1.125rem);
}

.qp-decision-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
    gap: var(--space-2);
}

.qp-decision-item {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-2);
    min-height: 68px;
    padding-block: var(--space-2);
    padding-inline-start: var(--space-3);
    padding-inline-end: calc(var(--space-3) + 32px);
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--surface) 48%, var(--surface-alt));
    cursor: default;
}

.qp-decision-item > span:not(.qp-status-dot) {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.qp-decision-item small,
.qp-decision-item em {
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
    font-style: normal;
}

.qp-decision-item strong {
    color: var(--text-heading);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

.qp-status-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    box-shadow: 0 0 0 4px color-mix(in srgb, currentColor 14%, transparent);
}

.qp-decision-item.success .qp-status-dot { color: var(--success); background: var(--success); }
.qp-decision-item.warning .qp-status-dot { color: var(--warning); background: var(--warning); }
.qp-decision-item.danger .qp-status-dot { color: var(--danger); background: var(--danger); }
/* Neutral results remain visible without implying that a zero amount met a management target. */
.qp-decision-item.neutral .qp-status-dot { color: var(--text-secondary); background: var(--text-secondary); }

/* Decision help is a separate top-corner action rather than a glyph attached to its label. */
.qp-decision-tooltip {
    position: absolute;
    inset-block-start: var(--space-2);
    inset-inline-end: var(--space-2);
}

@media (max-width: 520px) {
    .qp-decision-header {
        align-items: start;
        flex-direction: column;
    }
}

/* A separate shell keeps the share button out of the optional full-card link. */
.qp-kpi-shell {
    position: relative;
    min-width: 0;
    height: 100%;
}

.qp-kpi-shell > .qp-kpi {
    box-sizing: border-box;
    height: 100%;
}

.qp-kpi-shell.has-actions > .qp-kpi {
    padding-inline-end: calc(var(--space-4) + 36px);
}

.qp-kpi-shell.has-help > .qp-kpi {
    padding-inline-end: calc(var(--space-4) + 70px);
}

/* KPI actions are independent controls and therefore never alter the label or value flow. */
.qp-kpi-actions {
    position: absolute;
    inset-block-start: var(--space-2);
    inset-inline-end: var(--space-2);
    display: flex;
    align-items: center;
    gap: 2px;
    z-index: 2;
}

.qp-kpi-actions .qp-icon-button,
.qp-kpi-actions .qp-info-tooltip > summary {
    width: 32px;
    height: 32px;
}

.qp-kpi-share {
    background: color-mix(in srgb, var(--surface-alt) 88%, transparent);
}

/* The shared .qbm-kpi-card supplies surface, radius, and the tone accent rail;
   these rules add the QPulse internals (delta row, sparkline, states). */
.qp-kpi {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-height: 118px;
    padding: var(--space-3) var(--space-4);
    text-decoration: none;
    color: var(--text-primary);
}

.qp-kpi-label {
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--text-secondary);
}

/* The icon-only tooltip uses native details for click/keyboard support and an immediate hover overlay. */
.qp-info-tooltip {
    position: relative;
    z-index: 8;
}

.qp-info-tooltip[open] {
    z-index: 20;
}

.qp-info-tooltip > summary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    list-style: none;
    border: 1px solid transparent;
    border-radius: var(--radius-sm, 8px);
    background: color-mix(in srgb, var(--info) 9%, transparent);
    color: var(--info);
    cursor: help;
    transition: color 120ms ease, background-color 120ms ease, border-color 120ms ease;
}

.qp-info-tooltip > summary::-webkit-details-marker {
    display: none;
}

.qp-info-tooltip > summary::marker {
    content: "";
}

.qp-info-tooltip > summary:hover,
.qp-info-tooltip > summary:focus-visible,
.qp-info-tooltip[open] > summary {
    color: var(--text-heading);
    background: color-mix(in srgb, var(--info) 16%, var(--surface-alt));
    border-color: color-mix(in srgb, var(--info) 40%, var(--border));
    outline: none;
}

.qp-info-tooltip > summary:focus-visible {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--info) 22%, transparent);
}

.qp-info-tooltip-panel {
    position: absolute;
    inset-block-start: calc(100% + 6px);
    inset-inline-end: 0;
    display: none;
    width: min(280px, calc(100vw - 32px));
    padding: var(--space-3);
    border: 1px solid color-mix(in srgb, var(--info) 30%, var(--border));
    border-radius: var(--radius-md, 12px);
    background: var(--surface-alt);
    box-shadow: var(--shadow-elevated, 0 12px 32px rgba(15, 23, 42, 0.18));
    color: var(--text-primary);
    font-size: var(--font-size-sm, 0.875rem);
    font-style: normal;
    font-weight: 400;
    line-height: 1.45;
    text-align: start;
}

/* Hover reveals the overlay without a click; an open details element keeps it visible after a click. */
.qp-info-tooltip:hover > .qp-info-tooltip-panel,
.qp-info-tooltip[open] > .qp-info-tooltip-panel {
    display: block;
}

/* Help overlays may extend beyond a chart edge without changing the chart's dimensions. */
.qp-chart-card.has-help,
.qp-chart-card.has-help .qp-table-wrap {
    overflow: visible;
}

.qp-table-tooltip-cell {
    width: 40px;
    padding-inline-start: 0 !important;
    text-align: center !important;
}

.qp-kpi-value {
    font-size: var(--font-size-xl, 1.25rem);
    font-weight: 700;
    color: var(--text-heading);
    line-height: 1.15;
    overflow-wrap: anywhere;
}

.qp-kpi-meta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 20px;
    flex-wrap: wrap;
}

.qp-kpi-hint {
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
}

.qp-kpi-locked {
    color: var(--text-secondary);
}

a.qp-kpi-link {
    cursor: pointer;
    transition: transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease;
}

a.qp-kpi-link:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

a.qp-kpi-link:active {
    transform: translateY(0);
}

.qp-kpi .qp-sparkline {
    margin-top: auto;
}

/* ---- Delta chip ------------------------------------------------------------ */
.qp-delta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 700;
    line-height: 1.4;
}

.qp-delta-arrow {
    font-size: 0.6rem;
}

.qp-delta.positive {
    color: var(--success);
    background: color-mix(in srgb, var(--success) 14%, transparent);
}

.qp-delta.negative {
    color: var(--danger);
    background: color-mix(in srgb, var(--danger) 14%, transparent);
}

.qp-delta.neutral {
    color: var(--text-secondary);
    background: color-mix(in srgb, var(--text-secondary) 12%, transparent);
}

/* ---- Sparkline ------------------------------------------------------------- */
.qp-sparkline {
    width: 100%;
    height: 36px;
    display: block;
}

.qp-sparkline-line {
    fill: none;
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
}

.qp-sparkline.tone-accent .qp-sparkline-line { stroke: var(--accent); }
.qp-sparkline.tone-success .qp-sparkline-line { stroke: var(--success); }
.qp-sparkline.tone-danger .qp-sparkline-line { stroke: var(--danger); }
.qp-sparkline.tone-neutral .qp-sparkline-line { stroke: var(--text-secondary); }

.qp-sparkline-fill {
    opacity: 0.12;
}

.qp-sparkline.tone-accent .qp-sparkline-fill { fill: var(--accent); }
.qp-sparkline.tone-success .qp-sparkline-fill { fill: var(--success); }
.qp-sparkline.tone-danger .qp-sparkline-fill { fill: var(--danger); }
.qp-sparkline.tone-neutral .qp-sparkline-fill { fill: var(--text-secondary); }

/* ---- Cards ----------------------------------------------------------------- */
.qp-card {
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg, 16px);
    box-shadow: var(--shadow-card);
    overflow: hidden;
    margin-bottom: var(--space-4);
}

/* Cards with icon-triggered explanations allow the overlay to escape the rounded card boundary. */
.qp-card-with-help {
    overflow: visible;
}

.qp-card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-4) 0;
}

.qp-card-heading h2 {
    margin: 0;
    font-size: var(--font-size-lg, 1.125rem);
    color: var(--text-heading);
}

.qp-card-subtitle {
    margin: 2px 0 0;
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--text-secondary);
}

.qp-card-actions {
    display: flex;
    align-items: center;
    gap: var(--space-1);
}

.qp-card-body {
    padding: var(--space-4);
    min-height: 96px;
}

/* Chart cards use a QPulse-only analytical stage instead of a plain white plotting rectangle. */
.qp-chart-card {
    min-width: 0;
    border-color: color-mix(in srgb, var(--accent) 22%, var(--border));
}

.qp-chart-card .qp-card-body {
    min-width: 0;
}

.qp-chart-stage {
    position: relative;
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
    overflow: hidden;
    padding: clamp(0.35rem, 1vw, 0.75rem);
    border: 1px solid color-mix(in srgb, var(--accent) 14%, var(--border));
    border-radius: var(--radius-md, 12px);
    background:
        radial-gradient(circle at 92% 8%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 28%),
        linear-gradient(180deg, color-mix(in srgb, var(--surface) 72%, var(--surface-alt)), var(--surface-alt));
}

/* Telerik's generated chart root must follow the card width instead of its intrinsic SVG width. */
.qp-chart-stage .k-chart,
.qp-chart-stage > * {
    width: 100% !important;
    min-width: 0;
}

/* Wide financial reports keep the chart and exact figures visible together instead of forcing a mode choice. */
.qp-chart-table-split {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(320px, 0.85fr);
    gap: var(--space-4);
    align-items: start;
}

/* The report side scrolls independently when a long custom period contains many monthly rows. */
.qp-chart-companion-table {
    max-height: 380px;
    overflow: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 12px);
}

/* The bank-account reveal reads as a deliberate disclosure control rather than another table row. */
.qp-list-reveal {
    display: flex;
    justify-content: flex-end;
    padding-top: var(--space-3);
}

.qp-more-button {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 40px;
    padding: 0.45rem 0.85rem;
    border: 1px solid color-mix(in srgb, var(--accent) 34%, var(--border));
    border-radius: 999px;
    background: color-mix(in srgb, var(--accent) 8%, var(--surface-alt));
    color: var(--accent);
    font: inherit;
    font-size: var(--font-size-sm, 0.875rem);
    font-weight: 750;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, transform 120ms ease;
}

.qp-more-button:hover {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 13%, var(--surface-alt));
    transform: translateY(-1px);
}

.qp-more-button:focus-visible {
    outline: 3px solid color-mix(in srgb, var(--accent) 28%, transparent);
    outline-offset: 2px;
}

.qp-more-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.75rem;
    height: 1.45rem;
    padding-inline: 0.4rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--accent) 16%, transparent);
    font-size: var(--font-size-xs, 0.75rem);
    font-variant-numeric: tabular-nums;
}

.qp-icon-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm, 8px);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    transition: color 120ms ease, background-color 120ms ease, border-color 120ms ease;
}

.qp-icon-button:hover:not(:disabled) {
    color: var(--text-primary);
    background: color-mix(in srgb, var(--text-secondary) 10%, transparent);
}

.qp-icon-button.active {
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    border-color: color-mix(in srgb, var(--accent) 35%, transparent);
}

.qp-icon-button:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* ---- Data tables ----------------------------------------------------------- */
.qp-table-wrap {
    overflow-x: auto;
}

.qp-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--font-size-sm, 0.875rem);
}

.qp-table th,
.qp-table td {
    padding: var(--space-2) var(--space-3);
    text-align: start;
    border-bottom: 1px solid var(--border);
}

.qp-table th {
    color: var(--text-secondary);
    font-weight: 600;
    font-size: var(--font-size-xs, 0.75rem);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    white-space: nowrap;
}

.qp-table th.num,
.qp-table td.num {
    text-align: end;
}

.qp-table tbody tr:hover {
    background: color-mix(in srgb, var(--accent) 6%, transparent);
}

.qp-table tbody tr:last-child td {
    border-bottom: none;
}

/* Ranked-list share bar behind the numbers (top products/customers). */
.qp-share-cell {
    display: grid;
    grid-template-columns: minmax(64px, 1fr) auto;
    align-items: center;
    gap: 0.55rem;
}

.qp-share-bar {
    position: relative;
    height: 6px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--text-secondary) 14%, transparent);
    overflow: hidden;
    min-width: 64px;
}

.qp-share-bar > span {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    border-radius: inherit;
    background: var(--accent);
}

.qp-share-value {
    min-width: 3.5rem;
    text-align: end;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

/* Delivery-only exposure stays compact because most companies never render this conditional card. */
.qp-delivery-exposure {
    border-inline-start: 4px solid var(--warning);
}

.qp-delivery-exposure-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-3);
    margin: 0;
}

.qp-delivery-exposure-grid > div {
    padding: var(--space-3);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--warning) 7%, var(--surface));
}

.qp-delivery-exposure-grid dt {
    color: var(--text-secondary);
    font-size: 0.82rem;
}

.qp-delivery-exposure-grid dd {
    margin: 0.35rem 0 0;
    color: var(--text-primary);
    font-size: 1.15rem;
    font-weight: 750;
    font-variant-numeric: tabular-nums;
}

@media (max-width: 720px) {
    .qp-delivery-exposure-grid {
        grid-template-columns: 1fr;
    }
}

/* ---- Aging distribution ---------------------------------------------------- */
.qp-aging {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.qp-aging-bar {
    display: flex;
    height: 12px;
    border-radius: 999px;
    overflow: hidden;
    background: color-mix(in srgb, var(--text-secondary) 10%, transparent);
}

.qp-aging-seg { display: block; height: 100%; }
.qp-aging-seg.seg-current { background: var(--success); }
.qp-aging-seg.seg-b30 { background: var(--info); }
.qp-aging-seg.seg-b60 { background: var(--qp-amber); }
.qp-aging-seg.seg-b90 { background: var(--warning); }
.qp-aging-seg.seg-over90 { background: var(--danger); }
.qp-aging-seg.seg-none { background: color-mix(in srgb, var(--text-secondary) 14%, transparent); }

.qp-aging-legend {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--space-1) var(--space-3);
}

.qp-aging-legend li {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--font-size-xs, 0.75rem);
    color: var(--text-secondary);
}

.qp-aging-dot {
    width: 10px;
    height: 10px;
    border-radius: 999px;
    flex: 0 0 auto;
}

.qp-aging-dot.seg-current { background: var(--success); }
.qp-aging-dot.seg-b30 { background: var(--info); }
.qp-aging-dot.seg-b60 { background: var(--qp-amber); }
.qp-aging-dot.seg-b90 { background: var(--warning); }
.qp-aging-dot.seg-over90 { background: var(--danger); }

.qp-aging-amount {
    margin-inline-start: auto;
    color: var(--text-primary);
    font-weight: 600;
}

/* ---- Full counterparty exposure list --------------------------------------- */
/* The complete customer/vendor list opens inside the aging card. It is bounded and scrolls
   on its own so "show everyone" never turns the dashboard into an endless page. */
.qp-exposure-panel[hidden] {
    display: none;
}

.qp-exposure-panel {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--border);
}

.qp-exposure-tools {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.qp-exposure-search {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex: 1 1 180px;
    min-width: 0;
    min-height: 44px;
    padding-inline: var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 8px);
    background: var(--surface-alt);
    color: var(--text-secondary);
}

.qp-exposure-search:focus-within {
    border-color: var(--accent);
    outline: 3px solid color-mix(in srgb, var(--accent) 24%, transparent);
    outline-offset: 1px;
}

.qp-exposure-search input {
    flex: 1 1 auto;
    min-width: 0;
    border: 0;
    background: transparent;
    color: var(--text-primary);
    font: inherit;
    font-size: var(--font-size-sm, 0.875rem);
}

.qp-exposure-search input:focus {
    outline: none;
}

.qp-exposure-sort select {
    min-height: 44px;
    padding-inline: var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 8px);
    background: var(--surface-alt);
    color: var(--text-primary);
    font: inherit;
    font-size: var(--font-size-sm, 0.875rem);
}

.qp-exposure-filters {
    display: flex;
    gap: var(--space-2);
    overflow-x: auto;
    padding-block: 2px;
    scrollbar-width: none;
}

.qp-exposure-filters::-webkit-scrollbar {
    display: none;
}

.qp-exposure-summary {
    margin: 0;
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
    font-variant-numeric: tabular-nums;
}

/* A fixed height is what keeps a several-thousand-row list from flooding the page. */
.qp-exposure-scroll {
    max-height: 24rem;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 8px);
}

.qp-exposure-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--surface);
}

.qp-exposure-table td {
    font-variant-numeric: tabular-nums;
}

/* Virtualization needs a predictable row height, so counterparty rows never wrap. */
.qp-exposure-table tbody td {
    white-space: nowrap;
}

.qp-exposure-partner-cell {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.qp-exposure-name {
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 22ch;
}

/* The oldest band a counterparty sits in, using the same colors as the aging bar above. */
.qp-exposure-band {
    flex: 0 0 auto;
    padding-inline: 0.4rem;
    border-radius: 999px;
    font-size: var(--font-size-xs, 0.75rem);
    line-height: 1.5;
    color: var(--text-primary);
}

.qp-exposure-band.seg-current { background: color-mix(in srgb, var(--success) 20%, transparent); }
.qp-exposure-band.seg-b30 { background: color-mix(in srgb, var(--info) 20%, transparent); }
.qp-exposure-band.seg-b60 { background: color-mix(in srgb, var(--qp-amber) 22%, transparent); }
.qp-exposure-band.seg-b90 { background: color-mix(in srgb, var(--warning) 22%, transparent); }
.qp-exposure-band.seg-over90 { background: color-mix(in srgb, var(--danger) 22%, transparent); }

.qp-exposure-note {
    margin: 0;
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
}

/* ---- Sub-job project tree --------------------------------------------------- */
/* The job tree reuses the bounded scrolling list above and adds only the indentation,
   the expander, and the sub-job count badge. */
.qp-jobtree {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.qp-jobtree-table .qp-exposure-name {
    max-width: 26ch;
}

.qp-jobtree-indent {
    flex: 0 0 auto;
    display: inline-block;
}

.qp-jobtree-toggle {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm, 4px);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
}

.qp-jobtree-toggle:hover {
    color: var(--text-primary);
    background: color-mix(in srgb, var(--accent) 12%, transparent);
}

.qp-jobtree-toggle:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
    outline-offset: 1px;
}

/* A placeholder keeps leaf names aligned with their expandable siblings. */
.qp-jobtree-toggle.placeholder {
    cursor: default;
    background: transparent;
}

.qp-jobtree-count {
    flex: 0 0 auto;
    min-width: 1.4rem;
    padding-inline: 0.35rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--text-secondary) 16%, transparent);
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
    font-variant-numeric: tabular-nums;
    text-align: center;
}

/* ---- Alerts / needs attention ---------------------------------------------- */
.qp-alert-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.qp-alert {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-inline-start-width: 3px;
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--surface) 55%, var(--surface-alt));
}

.qp-alert.warning { border-inline-start-color: var(--warning); }
.qp-alert.danger { border-inline-start-color: var(--danger); }
.qp-alert.info { border-inline-start-color: var(--info); }

.qp-alert-icon { flex: 0 0 auto; }
.qp-alert.warning .qp-alert-icon { color: var(--warning); }
.qp-alert.danger .qp-alert-icon { color: var(--danger); }
.qp-alert.info .qp-alert-icon { color: var(--info); }

.qp-alert-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.qp-alert-text small {
    color: var(--text-secondary);
}

.qp-alert-amount {
    margin-inline-start: auto;
    font-weight: 700;
    color: var(--text-heading);
    white-space: nowrap;
}

.qp-allclear {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    color: var(--text-secondary);
}

.qp-allclear .oi {
    color: var(--success);
    font-size: 1.4rem;
}

.qp-allclear strong { color: var(--text-heading); }
.qp-allclear p { margin: 2px 0 0; font-size: var(--font-size-sm, 0.875rem); }

/* ---- Error + empty states -------------------------------------------------- */
.qp-alert-with-action {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.qp-error-detail {
    display: block;
    color: var(--text-secondary);
    font-size: var(--font-size-sm, 0.875rem);
    margin-top: 2px;
}

.qp-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-6) var(--space-4);
    text-align: center;
    color: var(--text-secondary);
}

.qp-empty-state.compact { padding: var(--space-4); }

.qp-empty-state-icon {
    font-size: 1.6rem;
    color: color-mix(in srgb, var(--text-secondary) 60%, transparent);
}

.qp-empty-state strong { color: var(--text-heading); }
.qp-empty-text { margin: 0; font-size: var(--font-size-sm, 0.875rem); max-width: 32ch; }

/* ---- Skeletons -------------------------------------------------------------- */
.qp-skeleton {
    display: inline-block;
    border-radius: var(--radius-sm, 8px);
    background: linear-gradient(
        90deg,
        color-mix(in srgb, var(--text-secondary) 12%, transparent) 25%,
        color-mix(in srgb, var(--text-secondary) 22%, transparent) 50%,
        color-mix(in srgb, var(--text-secondary) 12%, transparent) 75%);
    background-size: 200% 100%;
    animation: qp-shimmer 1.4s ease-in-out infinite;
}

@keyframes qp-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

.qp-skeleton-group {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.qp-skeleton-line { height: 12px; width: 100%; }
.qp-skeleton-line.w40 { width: 40%; }
.qp-skeleton-line.w60 { width: 60%; }
.qp-skeleton-line.w70 { width: 70%; }
.qp-skeleton-line.w80 { width: 80%; }
.qp-skeleton-label { height: 10px; width: 56%; }
.qp-skeleton-value { height: 22px; width: 72%; }

.qp-skeleton-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 12px);
}

/* ---- Phone bottom tab bar ---------------------------------------------------- */
.qp-tabbar {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 40;
    display: flex;
    justify-content: space-around;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2) calc(var(--space-1) + env(safe-area-inset-bottom, 0px));
    background: color-mix(in srgb, var(--surface-alt) 92%, transparent);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--border);
}

.qp-tab {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    min-height: 52px;
    justify-content: center;
    border-radius: var(--radius-md, 12px);
    color: var(--text-secondary);
    text-decoration: none;
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 600;
    transition: color 120ms ease, background-color 120ms ease;
}

.qp-tab:hover { color: var(--text-primary); }

.qp-tab.active {
    color: var(--accent);
    background: color-mix(in srgb, var(--accent) 12%, transparent);
}

.qp-tab .oi { font-size: 1rem; }

/* ---- QPulse-exclusive executive insight surfaces ------------------------- */
.qp-scope-chip,
.qp-queue-count {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 36px;
    padding-inline: var(--space-3);
    border: 1px solid var(--border);
    border-radius: 999px;
    background: color-mix(in srgb, var(--accent) 7%, var(--surface-alt));
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 600;
}

.qp-scope-note {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin: 0;
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
}

.qp-scope-note .oi {
    flex: 0 0 auto;
    color: var(--info);
    margin-block-start: 2px;
}

.qp-eyebrow {
    margin: 0 0 var(--space-1);
    color: var(--accent);
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Operations is a compact mobile hub rather than an extra sixth bottom tab. */
.qp-operations-hero {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-5);
    margin-bottom: var(--space-4);
    padding: clamp(var(--space-4), 4vw, var(--space-6));
    overflow: hidden;
    border: 1px solid color-mix(in srgb, var(--accent) 28%, var(--border));
    border-radius: var(--radius-lg, 16px);
    background:
        radial-gradient(circle at 88% 14%, color-mix(in srgb, var(--accent) 24%, transparent), transparent 34%),
        linear-gradient(135deg, color-mix(in srgb, var(--accent) 11%, var(--surface-alt)), var(--surface-alt));
    box-shadow: var(--shadow-card);
}

.qp-operations-hero h2 {
    margin: 0;
    color: var(--text-heading);
    font-size: clamp(1.25rem, 3vw, 2rem);
    line-height: 1.15;
}

.qp-operations-hero p:not(.qp-eyebrow) {
    max-width: 58ch;
    margin: var(--space-2) 0 0;
    color: var(--text-secondary);
}

.qp-operations-hero > .oi {
    flex: 0 0 auto;
    color: var(--accent);
    font-size: clamp(3rem, 8vw, 6rem);
    opacity: 0.22;
}

.qp-operation-links {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-4);
    margin-bottom: var(--space-4);
}

.qp-operation-link {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--space-3);
    min-height: 190px;
    padding: var(--space-5);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg, 16px);
    background: var(--surface-alt);
    box-shadow: var(--shadow-card);
    color: var(--text-primary);
    text-decoration: none;
    transition: transform 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}

.qp-operation-link:hover {
    transform: translateY(-3px);
    border-color: color-mix(in srgb, var(--accent) 52%, var(--border));
    box-shadow: var(--shadow-lg);
}

.qp-operation-link:active { transform: translateY(-1px); }

.qp-operation-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: 14px;
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    color: var(--accent);
    font-size: 1.35rem;
}

.qp-operation-link.purchasing .qp-operation-icon {
    background: color-mix(in srgb, var(--warning) 14%, transparent);
    color: var(--warning);
}

.qp-operation-link.jobs .qp-operation-icon {
    background: color-mix(in srgb, var(--success) 14%, transparent);
    color: var(--success);
}

.qp-operation-copy {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.qp-operation-copy strong {
    color: var(--text-heading);
    font-size: var(--font-size-lg, 1.125rem);
}

/* The headline figure reads as a KPI value so the tile summarizes, not just links, its domain. */
.qp-operation-value {
    font-size: var(--font-size-xl, 1.5rem) !important;
    font-variant-numeric: tabular-nums;
    color: var(--accent);
}

.qp-operation-copy span {
    color: var(--text-secondary);
    font-size: var(--font-size-sm, 0.875rem);
    line-height: 1.55;
}

.qp-operation-copy small {
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
}

.qp-operation-action {
    grid-column: 1 / -1;
    align-self: end;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    color: var(--accent);
    font-size: var(--font-size-sm, 0.875rem);
    font-weight: 700;
}

html[dir="rtl"] .qp-operation-action .oi,
html[dir="rtl"] .qp-queue-link .oi {
    transform: scaleX(-1);
}

.qp-readonly-note {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4);
    border: 1px dashed color-mix(in srgb, var(--info) 42%, var(--border));
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--info) 6%, var(--surface-alt));
}

.qp-readonly-note > .oi {
    flex: 0 0 auto;
    margin-block-start: 2px;
    color: var(--info);
    font-size: 1.15rem;
}

.qp-readonly-note strong { color: var(--text-heading); }
.qp-readonly-note p { margin: var(--space-1) 0 0; color: var(--text-secondary); font-size: var(--font-size-sm, 0.875rem); }

/* The two decision maps share an accessible, dependency-free SVG coordinate system. */
.qp-capital-hero,
.qp-commitment-hero,
.qp-job-hero {
    border-color: color-mix(in srgb, var(--accent) 24%, var(--border));
    background:
        linear-gradient(145deg, color-mix(in srgb, var(--accent) 4%, transparent), transparent 44%),
        var(--surface-alt);
}

.qp-capital-hero .qp-card-header,
.qp-job-hero .qp-card-header {
    align-items: flex-start;
}

.qp-risk-legend {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-3);
    flex-wrap: wrap;
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
}

.qp-risk-legend span,
.qp-band-key {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.qp-risk-legend i,
.qp-band-key i {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 999px;
    background: currentColor;
}

.qp-risk-legend .healthy,
.qp-band-key.healthy { color: var(--success); }
.qp-risk-legend .watch,
.qp-band-key.watch { color: var(--warning); }
.qp-risk-legend .trapped,
.qp-band-key.trapped,
.qp-risk-legend .loss { color: var(--danger); }
.qp-risk-legend .integrity,
.qp-band-key.integrity { color: var(--info); }
.qp-risk-legend .overbudget { color: var(--warning); }
.qp-risk-legend .unclassified,
.qp-band-key.unclassified { color: var(--text-secondary); }

.qp-capital-map-wrap {
    width: 100%;
    overflow-x: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--surface) 45%, var(--surface-alt));
}

.qp-capital-map {
    display: block;
    width: 100%;
    min-width: 620px;
    height: auto;
    font-family: "Inter", "Segoe UI", system-ui, sans-serif;
}

.qp-map-zone { stroke: none; }
.qp-map-zone-healthy { fill: color-mix(in srgb, var(--success) 8%, transparent); }
.qp-map-zone-watch { fill: color-mix(in srgb, var(--warning) 7%, transparent); }
.qp-map-zone-trapped,
.qp-map-zone-loss { fill: color-mix(in srgb, var(--danger) 8%, transparent); }
.qp-map-zone-overbudget { fill: color-mix(in srgb, var(--warning) 12%, transparent); }
/* Neutral guide bands describe chart position only; authoritative risk remains on each bubble. */
.qp-map-zone-neutral-a { fill: color-mix(in srgb, var(--text-secondary) 5%, transparent); }
.qp-map-zone-neutral-b { fill: color-mix(in srgb, var(--text-secondary) 10%, transparent); }
.qp-map-axis { stroke: var(--text-secondary); stroke-width: 1.5; }
.qp-map-guide { stroke: color-mix(in srgb, var(--text-secondary) 35%, transparent); stroke-width: 1; stroke-dasharray: 5 6; }
.qp-map-label { fill: var(--text-secondary); font-size: 13px; font-weight: 700; }
.qp-map-tick { fill: var(--text-secondary); font-size: 11px; }
.qp-capital-point { cursor: help; }
.qp-capital-point circle { stroke-width: 2; fill-opacity: 0.72; transition: fill-opacity 120ms ease, stroke-width 120ms ease; }
.qp-capital-point:hover circle,
.qp-capital-point:focus circle { fill-opacity: 0.96; stroke-width: 4; }
.qp-capital-point:focus { outline: none; }
.qp-capital-point.healthy circle { fill: var(--success); stroke: color-mix(in srgb, var(--success) 72%, #000); }
.qp-capital-point.watch circle { fill: var(--warning); stroke: color-mix(in srgb, var(--warning) 72%, #000); }
.qp-capital-point.trapped circle,
.qp-capital-point.loss circle { fill: var(--danger); stroke: color-mix(in srgb, var(--danger) 72%, #000); }
.qp-capital-point.integrity circle { fill: var(--info); stroke: color-mix(in srgb, var(--info) 72%, #000); }
.qp-capital-point.overbudget circle { fill: var(--warning); stroke: color-mix(in srgb, var(--warning) 72%, #000); }
.qp-capital-point.unclassified circle { fill: var(--text-secondary); stroke: var(--text-heading); }

.qp-insight-grid { margin-bottom: 0; }

.qp-band-stack,
.qp-commitment-stack {
    display: flex;
    width: 100%;
    height: 18px;
    overflow: hidden;
    border-radius: 999px;
    background: color-mix(in srgb, var(--text-secondary) 12%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--border) 75%, transparent);
}

.qp-band-stack > span,
.qp-commitment-stack > span {
    display: block;
    min-width: 2px;
    height: 100%;
}

.qp-band-stack .healthy { background: var(--success); }
.qp-band-stack .watch { background: var(--warning); }
.qp-band-stack .trapped { background: var(--danger); }
.qp-band-stack .integrity { background: var(--info); }
.qp-band-stack .unclassified { background: var(--text-secondary); }

.qp-band-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    list-style: none;
    margin: var(--space-4) 0 0;
    padding: 0;
}

.qp-band-list li {
    display: grid;
    grid-template-columns: minmax(100px, 1fr) auto;
    gap: 2px var(--space-3);
    align-items: center;
    padding-block: var(--space-2);
    border-bottom: 1px solid var(--border);
}

.qp-band-list li:last-child { border-bottom: 0; }
.qp-band-list strong { text-align: end; color: var(--text-heading); font-variant-numeric: tabular-nums; }
.qp-band-list small { grid-column: 1 / -1; color: var(--text-secondary); }

.qp-risk-table td small,
.qp-job-table td small {
    display: block;
    margin-block-start: 2px;
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
}

.qp-risk-chip,
.qp-age-chip {
    display: inline-flex;
    align-items: center;
    min-height: 26px;
    padding-inline: 9px;
    border-radius: 999px;
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 700;
    white-space: nowrap;
}

.qp-risk-chip.healthy { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); }
.qp-risk-chip.watch { color: var(--warning); background: color-mix(in srgb, var(--warning) 12%, transparent); }
.qp-risk-chip.trapped,
.qp-risk-chip.loss { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); }
.qp-risk-chip.integrity { color: var(--info); background: color-mix(in srgb, var(--info) 12%, transparent); }
.qp-risk-chip.overbudget { color: var(--warning); background: color-mix(in srgb, var(--warning) 12%, transparent); }
.qp-risk-chip.unclassified { color: var(--text-secondary); background: color-mix(in srgb, var(--text-secondary) 12%, transparent); }

/* Category rails combine portfolio concentration with within-category risk in one visual. */
.qp-category-exposure-list,
.qp-concentration-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    list-style: none;
    margin: 0;
    padding: 0;
}

.qp-category-exposure-list li,
.qp-concentration-list li {
    display: grid;
    grid-template-columns: 28px minmax(140px, 1.2fr) minmax(180px, 2fr) minmax(110px, auto);
    align-items: center;
    gap: var(--space-3);
    padding-block: var(--space-2);
    border-bottom: 1px solid var(--border);
}

.qp-category-exposure-list li:last-child,
.qp-concentration-list li:last-child { border-bottom: 0; }

.qp-category-rank,
.qp-concentration-rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background: color-mix(in srgb, var(--accent) 11%, transparent);
    color: var(--accent);
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 800;
}

.qp-category-copy,
.qp-category-values,
.qp-concentration-copy {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.qp-category-copy strong,
.qp-concentration-copy strong { overflow: hidden; color: var(--text-heading); text-overflow: ellipsis; white-space: nowrap; }
.qp-category-copy small,
.qp-category-values small,
.qp-concentration-copy small { color: var(--text-secondary); font-size: var(--font-size-xs, 0.75rem); }
.qp-category-values { align-items: flex-end; font-variant-numeric: tabular-nums; }
.qp-category-values strong { color: var(--text-heading); }

.qp-category-track,
.qp-concentration-track,
.qp-age-track {
    position: relative;
    display: block;
    height: 10px;
    overflow: hidden;
    border-radius: 999px;
    background: color-mix(in srgb, var(--text-secondary) 11%, transparent);
}

.qp-category-track > i,
.qp-concentration-track > i,
.qp-age-track > i {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    display: block;
    border-radius: inherit;
    background: var(--accent);
}

.qp-category-track > i > b {
    position: absolute;
    inset-block: 0;
    inset-inline-end: 0;
    display: block;
    border-radius: inherit;
    background: var(--danger);
}

/* Commitment age uses warmening stages without implying contractual due status. */
.qp-commitment-stack .age-1 { background: var(--success); }
.qp-commitment-stack .age-2 { background: var(--info); }
.qp-commitment-stack .age-3 { background: var(--warning); }
.qp-commitment-stack .age-4 { background: var(--danger); }
.qp-commitment-stack .age-5 { background: var(--text-secondary); }

.qp-age-ladder {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    list-style: none;
    margin: var(--space-4) 0 0;
    padding: 0;
}

.qp-age-ladder li {
    display: grid;
    grid-template-columns: 34px minmax(132px, 1fr) minmax(180px, 2fr) auto;
    align-items: center;
    gap: var(--space-3);
    min-height: 54px;
    padding: var(--space-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 12px);
}

.qp-age-step {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    /* The step sits on the status fills (success / info / warning / danger), which
       are light enough that white ink reads at only 1.9-3.8:1. Dark ink clears
       4.5:1 on all four in both themes. */
    color: #0b1220;
    font-weight: 800;
}

.qp-age-ladder .age-1 .qp-age-step,
.qp-age-ladder .age-1 .qp-age-track i { background: var(--success); }
.qp-age-ladder .age-2 .qp-age-step,
.qp-age-ladder .age-2 .qp-age-track i { background: var(--info); }
.qp-age-ladder .age-3 .qp-age-step,
.qp-age-ladder .age-3 .qp-age-track i { background: var(--warning); }
.qp-age-ladder .age-4 .qp-age-step,
.qp-age-ladder .age-4 .qp-age-track i { background: var(--danger); }
/* AgeBandOrder falls back to 5 for an unrecognized band code, but the ladder
   defined tones only up to 4 — that step rendered with no fill at all. It uses the
   same neutral as the commitment stack, inked with the surface colour so it stays
   legible whichever way --text-secondary flips between themes. */
.qp-age-ladder .age-5 .qp-age-step,
.qp-age-ladder .age-5 .qp-age-track i { background: var(--text-secondary); }
.qp-age-ladder .age-5 .qp-age-step { color: var(--surface-alt); }
.qp-age-ladder .age-5 .qp-age-step,
.qp-age-ladder .age-5 .qp-age-track i { background: var(--text-secondary); }

.qp-age-copy { display: flex; flex-direction: column; }
.qp-age-copy strong { color: var(--text-heading); }
.qp-age-copy small { color: var(--text-secondary); font-size: var(--font-size-xs, 0.75rem); }
.qp-age-amount { color: var(--text-heading); text-align: end; font-variant-numeric: tabular-nums; }
.qp-age-chip.age-1 { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); }
.qp-age-chip.age-2 { color: var(--info); background: color-mix(in srgb, var(--info) 12%, transparent); }
.qp-age-chip.age-3 { color: var(--warning); background: color-mix(in srgb, var(--warning) 12%, transparent); }
.qp-age-chip.age-4 { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); }
.qp-age-chip.age-5 { color: var(--text-secondary); background: color-mix(in srgb, var(--text-secondary) 12%, transparent); }
.qp-concentration-track > i { background: linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent) 48%, var(--info))); }
.qp-concentration-share { color: var(--text-heading); text-align: end; font-variant-numeric: tabular-nums; }

/* The attention queue is a ranked decision surface, not a transaction grid. */
.qp-attention-card { border-color: color-mix(in srgb, var(--warning) 30%, var(--border)); }
.qp-attention-clear { min-height: 160px; justify-content: center; }
.qp-decision-queue { display: flex; flex-direction: column; gap: var(--space-3); list-style: none; margin: 0; padding: 0; }
.qp-decision-queue > li {
    display: grid;
    grid-template-columns: 34px minmax(92px, auto) minmax(220px, 1fr) minmax(120px, auto) auto;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-inline-start-width: 4px;
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--surface) 45%, var(--surface-alt));
}

.qp-decision-queue > li.severity-critical { border-inline-start-color: var(--danger); }
.qp-decision-queue > li.severity-high { border-inline-start-color: var(--warning); }
.qp-decision-queue > li.severity-notice { border-inline-start-color: var(--info); }

.qp-queue-rank {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--text-secondary) 10%, transparent);
    color: var(--text-heading);
    font-size: var(--font-size-sm, 0.875rem);
    font-weight: 800;
}

.qp-queue-rank > .oi { color: var(--accent); font-size: 0.95rem; }
.qp-queue-rank > small { margin-block-start: 1px; color: var(--text-secondary); font-size: 0.55rem; line-height: 1; }

.qp-queue-severity {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 800;
    white-space: nowrap;
}

.severity-critical .qp-queue-severity { color: var(--danger); }
.severity-high .qp-queue-severity { color: var(--warning); }
.severity-notice .qp-queue-severity { color: var(--info); }
.qp-queue-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.qp-queue-copy strong { color: var(--text-heading); }
.qp-queue-copy small { color: var(--text-secondary); font-size: var(--font-size-xs, 0.75rem); line-height: 1.45; }
.qp-queue-section { color: var(--accent); font-size: 0.68rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; }
.qp-queue-impact { display: flex; flex-direction: column; align-items: flex-end; color: var(--text-secondary); font-size: var(--font-size-xs, 0.75rem); }
.qp-queue-impact strong { color: var(--text-heading); font-size: var(--font-size-base, 0.95rem); font-variant-numeric: tabular-nums; }
.qp-queue-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: 40px;
    padding-inline: var(--space-3);
    border: 1px solid color-mix(in srgb, var(--accent) 38%, var(--border));
    border-radius: var(--btn-radius, 12px);
    background: color-mix(in srgb, var(--accent) 8%, transparent);
    color: var(--accent);
    font-size: var(--font-size-sm, 0.875rem);
    font-weight: 700;
    text-decoration: none;
}
.qp-queue-link:hover { background: color-mix(in srgb, var(--accent) 15%, transparent); }

.qp-queue-actions {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-2);
}

/* Reminders are reversible local preferences; scheduled/due color never replaces signal severity. */
.qp-reminder-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 36px;
    padding-inline: var(--space-2);
    border: 1px solid var(--border);
    border-radius: var(--btn-radius, 12px);
    background: transparent;
    color: var(--text-secondary);
    font: inherit;
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 700;
    cursor: pointer;
}

.qp-reminder-button:hover { border-color: var(--accent); color: var(--accent); }
.qp-reminder-button.scheduled { border-color: color-mix(in srgb, var(--info) 40%, var(--border)); color: var(--info); }
.qp-reminder-button.due {
    border-color: color-mix(in srgb, var(--warning) 55%, var(--border));
    background: color-mix(in srgb, var(--warning) 10%, transparent);
    color: var(--warning);
}

/* Due reminders are visible page alerts and point back to the unchanged ranked queue. */
.qp-reminder-due-banner {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    margin-bottom: var(--space-4);
    padding: var(--space-3) var(--space-4);
    border: 1px solid color-mix(in srgb, var(--warning) 45%, var(--border));
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--warning) 8%, var(--surface-alt));
    color: var(--text-secondary);
}

.qp-reminder-due-banner > .oi,
.qp-reminder-due-banner strong { color: var(--warning); }

/* Threshold editing is a compact, optional preference panel on the Attention page. */
.qp-threshold-card { margin-bottom: var(--space-4); }
.qp-threshold-card details > summary {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-4);
    cursor: pointer;
    list-style: none;
}

.qp-threshold-card details > summary::-webkit-details-marker { display: none; }
.qp-threshold-summary-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 12px;
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    color: var(--accent);
    font-size: 1.05rem;
}

.qp-threshold-summary-copy { display: flex; flex-direction: column; min-width: 0; }
.qp-threshold-summary-copy strong { color: var(--text-heading); }
.qp-threshold-summary-copy small { color: var(--text-secondary); line-height: 1.4; }
.qp-threshold-count {
    padding: 5px 9px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--accent) 8%, transparent);
    color: var(--accent);
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 700;
    white-space: nowrap;
}

.qp-threshold-card summary > .oi-chevron-bottom { color: var(--text-secondary); transition: transform 120ms ease; }
.qp-threshold-card details[open] summary > .oi-chevron-bottom { transform: rotate(180deg); }
.qp-threshold-body { padding: 0 var(--space-4) var(--space-4); border-top: 1px solid var(--border); }
.qp-threshold-guidance {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin: var(--space-3) 0;
    color: var(--text-secondary);
    font-size: var(--font-size-sm, 0.875rem);
}

.qp-threshold-guidance > .oi { margin-block-start: 2px; color: var(--info); }
.qp-threshold-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
    gap: var(--space-3);
}

.qp-threshold-grid label { display: flex; flex-direction: column; gap: 5px; }
.qp-threshold-grid label > span {
    /* Reserve three title lines so long localized labels cannot push one input below its row peers. */
    display: flex;
    align-items: flex-end;
    min-height: 3.9em;
    color: var(--text-heading);
    font-size: var(--font-size-sm, 0.875rem);
    font-weight: 700;
    line-height: 1.3;
}
.qp-threshold-grid label > small { color: var(--text-secondary); font-size: var(--font-size-xs, 0.75rem); line-height: 1.35; }
.qp-threshold-grid input,
.qp-threshold-grid select {
    min-height: 42px;
    box-sizing: border-box;
    width: 100%;
    padding-inline: var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 8px);
    background: var(--surface);
    color: var(--text-primary);
    font: inherit;
}

.qp-threshold-grid input:hover,
.qp-threshold-grid select:hover { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); }
.qp-threshold-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    flex-wrap: wrap;
    margin-block-start: var(--space-4);
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
}

.qp-threshold-save { display: inline-flex; align-items: center; gap: var(--space-2); }
.qp-threshold-actions > span { display: inline-flex; align-items: center; gap: var(--space-2); }

/* Job pressure tiles separate realized loss from budget burn exposure. */
.qp-pressure-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3);
}

.qp-pressure-grid > div {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 3px var(--space-2);
    padding: var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--surface) 50%, var(--surface-alt));
}

.qp-pressure-grid > div > .oi { grid-row: 1 / span 3; margin-block-start: 4px; font-size: 1.2rem; }
.qp-pressure-grid .loss > .oi { color: var(--danger); }
.qp-pressure-grid .overbudget > .oi { color: var(--warning); }
.qp-pressure-grid small,
.qp-pressure-grid span { color: var(--text-secondary); font-size: var(--font-size-xs, 0.75rem); }
.qp-pressure-grid strong { color: var(--text-heading); font-size: var(--font-size-lg, 1.125rem); font-variant-numeric: tabular-nums; }

.qp-partial-note {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
    padding: var(--space-3) var(--space-4);
    border: 1px solid color-mix(in srgb, var(--info) 35%, var(--border));
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--info) 7%, var(--surface-alt));
    color: var(--text-secondary);
    font-size: var(--font-size-sm, 0.875rem);
}

.qp-partial-note .oi { flex: 0 0 auto; margin-block-start: 2px; color: var(--info); }

/* One consolidated indicator replaces scanning every card for its own unavailable state. */
.qp-completeness {
    position: relative;
    display: inline-block;
    z-index: 8;
}

.qp-completeness[open] { z-index: 20; }

.qp-completeness > summary {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 36px;
    padding-inline: var(--space-3);
    border: 1px solid var(--border);
    border-radius: 999px;
    background: color-mix(in srgb, var(--accent) 7%, var(--surface-alt));
    color: var(--text-secondary);
    font-size: var(--font-size-sm, 0.875rem);
    cursor: pointer;
    list-style: none;
    white-space: nowrap;
}

.qp-completeness > summary::-webkit-details-marker { display: none; }
.qp-completeness > summary::marker { content: ""; }

.qp-completeness.complete > summary { color: var(--success); }
.qp-completeness.partial > summary { color: var(--warning); }

.qp-completeness > summary > .oi-chevron-bottom {
    font-size: 0.7em;
    transition: transform 120ms ease;
}

.qp-completeness[open] > summary > .oi-chevron-bottom { transform: rotate(180deg); }

.qp-completeness-panel {
    position: absolute;
    inset-block-start: calc(100% + 6px);
    inset-inline-end: 0;
    display: none;
    flex-direction: column;
    gap: var(--space-2);
    width: min(320px, calc(100vw - 32px));
    margin: 0;
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 12px);
    background: var(--surface-alt);
    box-shadow: var(--shadow-elevated, 0 12px 32px rgba(15, 23, 42, 0.18));
    list-style: none;
}

.qp-completeness[open] > .qp-completeness-panel { display: flex; }

.qp-completeness-panel li {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--space-2);
    color: var(--text-primary);
    font-size: var(--font-size-sm, 0.875rem);
}

.qp-completeness-panel li.available > .oi { color: var(--success); }
.qp-completeness-panel li.unavailable > .oi { color: var(--warning); }
.qp-completeness-panel li small { flex-basis: 100%; color: var(--text-secondary); }

/* Finance decision bridge composes four authoritative domains without pretending to forecast cash. */
.qp-working-capital-bridge {
    border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
    background:
        radial-gradient(circle at 90% 0%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 35%),
        var(--surface-alt);
}

/* The rolling cash outlook is visually prominent because liquidity is a first-order management decision. */
.qp-cash-outlook {
    border-color: color-mix(in srgb, var(--success) 32%, var(--border));
    background:
        radial-gradient(circle at 88% 4%, color-mix(in srgb, var(--success) 10%, transparent), transparent 34%),
        var(--surface-alt);
}

.qp-cash-outlook .qp-card-heading h2 {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}

.qp-cash-outlook .qp-card-heading h2 > .oi {
    color: var(--success);
    font-size: 1rem;
}

/* Six bounded figures summarize the due-date schedule before the manager enters either chart. */
.qp-cash-outlook-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
    gap: var(--space-3);
}

.qp-cash-outlook-kpi {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    min-height: 88px;
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-block-start-width: 3px;
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--surface) 52%, var(--surface-alt));
}

.qp-cash-outlook-kpi small {
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
    font-weight: 700;
}

.qp-cash-outlook-kpi strong {
    color: var(--text-heading);
    font-size: clamp(1rem, 2vw, 1.35rem);
    font-variant-numeric: tabular-nums;
}

.qp-cash-outlook-kpi > span {
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
}

.qp-cash-outlook-kpi.neutral { border-block-start-color: var(--text-secondary); }
.qp-cash-outlook-kpi.positive { border-block-start-color: var(--success); }
.qp-cash-outlook-kpi.warning { border-block-start-color: var(--warning); }
.qp-cash-outlook-kpi.danger {
    border-block-start-color: var(--danger);
    background: color-mix(in srgb, var(--danger) 7%, var(--surface-alt));
}
.qp-cash-outlook-kpi.danger strong { color: var(--danger); }

/* A projected negative point remains visible in-page and does not depend on opening the alert list. */
.qp-cash-alert {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-4);
    padding: var(--space-3);
    border: 1px solid color-mix(in srgb, var(--danger) 55%, var(--border));
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--danger) 9%, var(--surface-alt));
}

.qp-cash-alert > .oi {
    color: var(--danger);
    font-size: 1.25rem;
}

.qp-cash-alert > span {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.qp-cash-alert strong { color: var(--text-heading); }
.qp-cash-alert small { color: var(--text-secondary); line-height: 1.4; }
.qp-cash-alert em {
    color: var(--danger);
    font-style: normal;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

/* Forecast-basis notes disclose conservative assumptions without competing with the alert severity. */
.qp-cash-basis-note {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    margin: var(--space-3) 0 0;
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
    line-height: 1.45;
}

.qp-cash-basis-note > .oi {
    flex: 0 0 auto;
    margin-block-start: 2px;
    color: var(--info);
}

.qp-cash-basis-note-standalone {
    margin: calc(-1 * var(--space-1)) 0 var(--space-4);
    padding: 0 var(--space-1);
}

/* Cash cards retain equal decision weight while their own chart/table controls remain independent. */
.qp-cash-planning-grid > .qp-card {
    height: 100%;
}

/* Plain-language financial-health tiles translate existing ratios without adding a second accounting engine. */
.qp-financial-health { border-color: color-mix(in srgb, var(--info) 28%, var(--border)); }
.qp-financial-health .qp-card-heading h2 {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}

.qp-financial-health .qp-card-heading h2 > .oi { color: var(--info); font-size: 1rem; }
.qp-health-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
    gap: var(--space-3);
}

.qp-health-metric {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--space-3);
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-block-start-width: 3px;
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--surface) 50%, var(--surface-alt));
}

.qp-health-metric.positive { border-block-start-color: var(--success); }
.qp-health-metric.warning { border-block-start-color: var(--warning); }
.qp-health-metric.danger { border-block-start-color: var(--danger); }
.qp-health-metric.neutral { border-block-start-color: var(--text-secondary); }
.qp-health-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 11px;
    background: color-mix(in srgb, var(--accent) 9%, transparent);
    color: var(--accent);
}

.qp-health-metric.warning .qp-health-icon { color: var(--warning); background: color-mix(in srgb, var(--warning) 10%, transparent); }
.qp-health-metric.danger .qp-health-icon { color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, transparent); }
.qp-health-metric.positive .qp-health-icon { color: var(--success); background: color-mix(in srgb, var(--success) 10%, transparent); }
.qp-health-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.qp-health-copy small { color: var(--text-secondary); font-weight: 700; }
.qp-health-copy strong { color: var(--text-heading); font-size: var(--font-size-xl, 1.25rem); font-variant-numeric: tabular-nums; }
.qp-health-copy > span { color: var(--text-secondary); font-size: var(--font-size-xs, 0.75rem); line-height: 1.4; }

.qp-bridge-equation {
    direction: ltr;
    display: grid;
    grid-template-columns: minmax(110px, 1fr) auto minmax(110px, 1fr) auto minmax(110px, 1fr) auto minmax(130px, 1fr) auto minmax(155px, 1.2fr);
    align-items: stretch;
    gap: var(--space-2);
}

.qp-bridge-term,
.qp-bridge-result {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--space-1);
    min-height: 88px;
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-md, 12px);
    background: color-mix(in srgb, var(--surface) 52%, var(--surface-alt));
    text-align: center;
}

.qp-bridge-term small,
.qp-bridge-result small {
    color: var(--text-secondary);
    font-size: var(--font-size-xs, 0.75rem);
    line-height: 1.35;
}

.qp-bridge-term strong,
.qp-bridge-result strong {
    color: var(--text-heading);
    font-size: clamp(0.95rem, 1.6vw, 1.2rem);
    font-variant-numeric: tabular-nums;
}

.qp-bridge-term.positive { border-block-start: 3px solid var(--success); }
.qp-bridge-term.negative { border-block-start: 3px solid var(--warning); }
.qp-bridge-result {
    border-width: 2px;
    box-shadow: var(--shadow-card);
}
.qp-bridge-result.positive { border-color: color-mix(in srgb, var(--success) 62%, var(--border)); background: color-mix(in srgb, var(--success) 8%, var(--surface-alt)); }
.qp-bridge-result.danger { border-color: color-mix(in srgb, var(--danger) 62%, var(--border)); background: color-mix(in srgb, var(--danger) 8%, var(--surface-alt)); }
.qp-bridge-result.positive strong { color: var(--success); }
.qp-bridge-result.danger strong { color: var(--danger); }

.qp-bridge-operator {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    color: var(--text-secondary);
    font-size: 1.25rem;
    font-weight: 800;
}

.qp-bridge-operator.equals { color: var(--accent); }

/* Independent pressure signals reuse the receivables-aging bar and legend language. */
.qp-pressure-aging .qp-pressure-seg { min-width: 8px; }
.qp-pressure-aging .qp-pressure-seg.danger,
.qp-pressure-aging .qp-pressure-dot.danger { background: var(--danger); }
.qp-pressure-aging .qp-pressure-seg.warning,
.qp-pressure-aging .qp-pressure-dot.warning { background: var(--warning); }
.qp-pressure-aging .qp-pressure-seg.amber,
.qp-pressure-aging .qp-pressure-dot.amber { background: var(--qp-amber); }
.qp-pressure-aging .qp-pressure-seg.slate,
.qp-pressure-aging .qp-pressure-dot.slate { background: var(--text-secondary); }
.qp-pressure-aging-legend { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.qp-pressure-aging-legend li { align-items: flex-start; }
.qp-pressure-aging-name {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.qp-pressure-aging-name strong {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-heading);
}
.qp-pressure-aging-name strong > .oi { color: var(--text-secondary); font-size: 0.9rem; }
.qp-pressure-aging-name small { color: var(--text-secondary); line-height: 1.4; }

/* Custom metric tiles use the same independent corner action as the reusable KPI component. */
.qp-indicator-tile {
    position: relative;
    padding-inline-end: calc(var(--space-3) + 36px);
}

.qp-pressure-grid > div.qp-indicator-tile {
    padding-inline-end: calc(var(--space-4) + 36px);
}

.qp-indicator-tooltip {
    position: absolute;
    inset-block-start: 6px;
    inset-inline-end: 6px;
}

.qp-indicator-tooltip > summary {
    width: 28px;
    height: 28px;
}

/* Row and legend help remains a distinct control and never becomes a suffix on the indicator label. */
.qp-pressure-tooltip,
.qp-legend-tooltip {
    flex: 0 0 auto;
}

.qp-queue-tooltip {
    align-self: flex-end;
}

@media (max-width: 900px) {
    .qp-operation-links { grid-template-columns: 1fr; }
    .qp-operation-link { min-height: 150px; }
    .qp-decision-queue > li { grid-template-columns: 34px minmax(80px, auto) minmax(0, 1fr) auto; }
    .qp-queue-impact { grid-column: 3; align-items: flex-start; }
    .qp-queue-actions { grid-column: 4; grid-row: 1 / span 2; }
    .qp-bridge-equation { grid-template-columns: minmax(120px, 1fr) auto minmax(120px, 1fr); }
    .qp-bridge-result { grid-column: 1 / -1; }
    .qp-chart-table-split { grid-template-columns: 1fr; }
}

@media (max-width: 680px) {
    .qp-operations-hero > .oi { display: none; }
    .qp-capital-hero .qp-card-header,
    .qp-job-hero .qp-card-header { flex-direction: column; }
    .qp-risk-legend { justify-content: flex-start; }
    .qp-category-exposure-list li,
    .qp-concentration-list li { grid-template-columns: 28px minmax(0, 1fr) auto; }
    .qp-category-track,
    .qp-concentration-track { grid-column: 2 / -1; }
    .qp-age-ladder li { grid-template-columns: 34px minmax(0, 1fr) auto; }
    .qp-age-track { grid-column: 2 / -1; }
    .qp-decision-queue > li { grid-template-columns: 32px minmax(0, 1fr); align-items: start; }
    .qp-queue-severity { justify-self: end; }
    .qp-queue-copy,
    .qp-queue-impact,
    .qp-queue-actions { grid-column: 2; }
    .qp-queue-impact { align-items: flex-start; }
    .qp-queue-actions { grid-row: auto; justify-self: start; flex-direction: row; flex-wrap: wrap; }
    .qp-pressure-grid { grid-template-columns: 1fr; }
    .qp-bridge-equation { grid-template-columns: 1fr; }
    .qp-bridge-operator { min-height: 20px; }
    .qp-cash-alert { grid-template-columns: auto minmax(0, 1fr); }
    .qp-cash-alert em { grid-column: 2; }
    /* A single-column phone layout does not need cross-column title-height alignment. */
    .qp-threshold-grid label > span { min-height: 0; }
    .qp-threshold-card details > summary { grid-template-columns: auto minmax(0, 1fr) auto; }
    .qp-threshold-count { grid-column: 2; justify-self: start; }
    .qp-threshold-card summary > .oi-chevron-bottom { grid-column: 3; grid-row: 1 / span 2; }
}

@media (max-width: 430px) {
    .qp-tabbar { gap: 0; padding-inline: 2px; }
    .qp-tab { min-width: 0; padding-inline: 2px; font-size: 0.66rem; }
    .qp-tab-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .qp-operation-link { padding: var(--space-4); }
    .qp-category-values { align-items: flex-start; grid-column: 2 / -1; }
}

/* Desktop: the sidebar owns navigation; the tab bar disappears. */
@media (min-width: 841px) {
    .qp-tabbar { display: none; }
    .qp-has-tabbar { padding-bottom: var(--space-8); }
}

/* ---- Blazor error UI (hidden until the runtime raises it) ------------------- */
#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    inset-inline: 0;
    z-index: 100;
    padding: var(--space-3) var(--space-6) var(--space-3) var(--space-4);
    background: var(--warning);
    color: #1f1300;
    font-weight: 600;
    box-shadow: var(--shadow-lg);
}

#blazor-error-ui .reload {
    color: inherit;
    text-decoration: underline;
    margin-inline-start: var(--space-2);
}

#blazor-error-ui .dismiss {
    position: absolute;
    inset-inline-end: var(--space-3);
    top: 50%;
    transform: translateY(-50%);
    cursor: pointer;
    color: inherit;
    text-decoration: none;
    font-weight: 700;
}

/* ---- Print ------------------------------------------------------------------ */
@media print {
    .qp-tabbar,
    .sidebar,
    .qbm-topbar,
    .qp-card-actions,
    .qp-kpi-actions,
    .qp-header-actions,
    .qp-info-tooltip,
    .qp-completeness,
    .qp-period,
    .qp-compare,
    .qp-reminder-due-banner,
    .mobile-nav-backdrop {
        display: none !important;
    }

    /* Board-pack pages read on paper, so honor the light-theme palette regardless of the active screen theme. */
    :root {
        color-scheme: light;
    }

    body,
    .page,
    main,
    article.content {
        background: #fff !important;
        color: #0f172a !important;
    }

    .qp-card {
        box-shadow: none;
        break-inside: avoid;
        border-color: #cbd5e1 !important;
        background: #fff !important;
    }

    /* Long tables and ranked lists may legitimately span more than one page. */
    .qp-attention-card,
    .qp-table-wrap {
        break-inside: auto;
    }

    /* A wide side-by-side chart/table layout collapses to a readable single column on paper. */
    .qp-chart-table-split {
        display: block;
    }

    .qp-chart-table-split .qp-chart-stage {
        margin-block-end: var(--space-3);
    }

    a[href] {
        color: inherit;
        text-decoration: none;
    }
}

/* ============================================================================
   TELERIK THEME ADAPTATION
   ----------------------------------------------------------------------------
   Telerik 4.5.0's bundled theme (kendo-theme-default) is hard-coded LIGHT and
   ships no dark palette or CSS custom properties, so its controls ignore the
   QPulse tokens entirely. Measured on the real DOM/SVG in dark mode before this
   block existed:

     .k-picker-solid   background #f5f5f5, text #424242  -> a light-grey period
                                                            selector on the dark shell
     chart axis text   fill #424242                      -> invisible
     chart axis lines  stroke #000                       -> invisible
     chart grid lines  stroke rgba(0,0,0,.08)            -> invisible

   The Telerik sheet is loaded BEFORE app.css (see index.html) so these rules win
   on equal specificity without !important.
   ========================================================================== */

/* ---- Controls (period selector and any future picker) --------------------- */

.k-input,
.k-picker,
.k-input-solid,
.k-picker-solid,
.k-dropdownlist,
.k-combobox {
    border-color: var(--border-strong, var(--border));
    color: var(--text-primary);
    background-color: var(--surface-alt);
    background-image: none;
}

.k-input-inner,
.k-input-value-text {
    color: var(--text-primary);
    background: transparent;
}

.k-input:hover,
.k-picker:hover,
.k-input-solid:hover,
.k-picker-solid:hover,
.k-picker-solid.k-hover {
    border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
    background-color: color-mix(in srgb, var(--accent) 8%, var(--surface-alt));
}

.k-input:focus-within,
.k-picker:focus-within {
    border-color: var(--accent);
    box-shadow: var(--focus-ring);
    outline: none;
}

.k-input .k-input-button,
.k-picker .k-input-button,
.k-input .k-icon,
.k-picker .k-icon,
.k-input .k-svg-icon,
.k-picker .k-svg-icon {
    color: var(--text-secondary);
    background: transparent;
    border-color: transparent;
}

.k-button-solid-base {
    border-color: var(--border-strong, var(--border));
    color: var(--text-primary);
    background-color: color-mix(in srgb, var(--text-primary) 6%, transparent);
    background-image: none;
}

.k-button-solid-base:hover,
.k-button-solid-base.k-hover {
    color: var(--text-primary);
    background-color: color-mix(in srgb, var(--accent) 14%, transparent);
    background-image: none;
}

.k-disabled {
    opacity: 0.55;
    filter: none;
}

/* Dropdown popups render into a body-level container, outside any .qp-* ancestor,
   so these selectors are deliberately un-scoped. */
.k-popup,
.k-list,
.k-list-container,
.k-calendar,
.k-tooltip {
    border-color: var(--border);
    color: var(--text-primary);
    background-color: var(--surface-alt);
}

.k-popup {
    box-shadow: var(--shadow-base);
}

.k-list-item,
.k-list-optionlabel {
    color: var(--text-primary);
}

.k-list-item:hover,
.k-list-item.k-hover,
.k-list-optionlabel:hover {
    color: var(--text-primary);
    background-color: color-mix(in srgb, var(--accent) 14%, transparent);
}

.k-list-item.k-selected,
.k-list-item.k-selected:hover {
    color: var(--accent-contrast, #fff);
    background-color: var(--accent);
}

.k-nodata,
.k-list-group-item {
    color: var(--text-secondary);
    background-color: transparent;
}

/* ---- Charts ---------------------------------------------------------------
   Chart SVG colours do NOT come from CSS on the SVG. On every render
   telerik-blazor.js injects hidden probe elements (.k-var--*), reads each one's
   computed background-color, bakes the values into the SVG, then removes them.
   Overriding those probes is therefore the only way to reach grid lines and
   axis lines.

   Because the probe is read once per render, a per-theme probe value goes stale
   after a live theme toggle. So anything baked into the SVG uses ONE
   theme-neutral translucent grey that reads on both light and dark, while chart
   TEXT is themed through CSS `fill`, which beats the baked fill attribute and
   updates live.
   ------------------------------------------------------------------------- */

.k-var--background {
    background-color: transparent;
}

.k-var--normal-text-color {
    background-color: rgb(129, 145, 178);
}

.k-var--chart-major-lines {
    background-color: rgba(129, 145, 178, 0.34);
}

.k-var--chart-minor-lines {
    background-color: rgba(129, 145, 178, 0.16);
}

.k-var--chart-inactive {
    background-color: rgba(129, 145, 178, 0.45);
}

.k-var--chart-crosshair-background {
    background-color: rgba(129, 145, 178, 0.55);
}

/* The stage behind the SVG owns the surface, so the chart itself stays clear and
   follows the theme live instead of baking a background colour. */
.k-chart {
    background-color: transparent;
}

/* CSS beats the `fill` attribute Kendo writes on each <text>, so labels follow
   the theme without waiting for a re-render. */
.k-chart text {
    fill: var(--text-secondary) !important;
}

.k-chart .k-chart-tooltip,
.k-chart-tooltip {
    color: var(--text-primary);
    background-color: var(--surface-alt);
}

@media print {
    /* A dark-mode session must not print near-white labels onto white paper. */
    .k-chart text {
        fill: #000 !important;
    }
}

/* Kendo bakes a hard #000 outline around the plot area (pre-existing: a black box
   on white in light mode, invisible in dark). CSS beats the presentation
   attribute, and targeting the literal value leaves the series stroke — which
   carries the QBM chart palette — untouched. */
.k-chart path[stroke="#000"] {
    stroke: rgba(129, 145, 178, 0.34);
}
