/* ============================================================================
 * BI — design system for the dashboard & report area
 * ----------------------------------------------------------------------------
 * Tokens map onto the Radzen Material palette (--rz-*) so the BI area reads as
 * part of the same program as the rest of OpexPrime. Every rule is scoped to
 * the `.bi-area` namespace: the DevExpress dashboard, designer and viewer canvases
 * share these pages, and DX is sensitive to stray global CSS.
 *
 * The recurring device is the scope rule — a hairline under every page title,
 * tipped with a short accent segment, carrying the counts that say how much of
 * the catalog you are looking at. It is the one element every BI page shares.
 * ========================================================================== */

/* ---------------------------------------------------------------- tokens -- */
.bi-area {
    /* surfaces */
    --bi-ground: var(--rz-base-100, #f6f7fa);
    --bi-paper: var(--rz-white, #ffffff);
    --bi-sunk: var(--rz-base-200, #e9edf0);

    /* hairlines */
    --bi-line: var(--rz-base-300, #dadfe2);
    --bi-line-soft: var(--rz-base-200, #e9edf0);
    --bi-line-strong: var(--rz-base-400, #c1c9cb);

    /* ink */
    --bi-ink: var(--rz-base-900, #28363c);
    --bi-ink-soft: var(--rz-base-700, #545e61);
    --bi-ink-mute: var(--rz-base-600, #77858b);
    --bi-ink-faint: var(--rz-base-500, #95a4a8);

    /* accent — one blue, the app's primary */
    --bi-accent: var(--rz-primary, #0d6efd);
    --bi-accent-soft: rgba(13, 110, 253, 0.08);
    --bi-accent-line: rgba(13, 110, 253, 0.32);

    /* semantics — darkened off the Radzen pastels so they read on white */
    --bi-star: #b07d1f;
    --bi-good: #3f8a57;
    --bi-warn: #b07d1f;
    --bi-bad: #c64a50;
    --bi-good-soft: rgba(93, 191, 116, 0.16);
    --bi-warn-soft: rgba(250, 193, 82, 0.20);
    --bi-bad-soft: rgba(249, 119, 127, 0.16);

    /* type */
    --bi-font: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    --bi-mono: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;

    /* spacing */
    --bi-s1: 4px;
    --bi-s2: 8px;
    --bi-s3: 12px;
    --bi-s4: 16px;
    --bi-s5: 24px;
    --bi-s6: 32px;
    --bi-s7: 48px;

    /* radii — tight; this is a catalog, not a card wall */
    --bi-r-sm: 3px;
    --bi-r-md: 6px;
    --bi-r-lg: 10px;
    --bi-r-pill: 999px;

    /* motion */
    --bi-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
    --bi-fast: 140ms;
    --bi-slow: 220ms;

    /* elevation — flat at rest, lifts only on intent */
    --bi-lift: 0 1px 2px rgba(40, 54, 60, 0.04), 0 6px 16px rgba(40, 54, 60, 0.08);
}

/* ----------------------------------------------------------------- shell -- */
.bi-area {
    background: var(--bi-ground);
    color: var(--bi-ink);
    font-family: var(--bi-font);
    font-size: 14px;
    line-height: 1.5;
    /* The host article is a column flex container, so growing is what actually fills a short
       page — a percentage min-height resolves against an auto height and does nothing. */
    flex: 1 1 auto;
    min-height: 100%;
    padding: var(--bi-s6) var(--bi-s6) var(--bi-s7);
    box-sizing: border-box;
}

.bi-area *,
.bi-area *::before,
.bi-area *::after {
    box-sizing: border-box;
}

/* Let the BI ground run edge to edge inside the host content area. */
article:has(> .bi-area) {
    padding: 0 !important;
}

.bi-shell {
    max-width: 1440px;
    margin: 0 auto;
}

/* Canvas pages pin themselves to the viewport (minus the layout's 3.5rem topbar) and hand
   every remaining pixel to the DX surface: the head takes its natural height, the canvas
   flexes into the rest, and the page itself never scrolls. */
.bi-area--canvas {
    display: flex;
    flex-direction: column;
    height: calc(100dvh - 3.5rem);
    min-height: 0;
    overflow: hidden;
    padding: var(--bi-s4) var(--bi-s5);
}

/* Canvas pages ignore the catalog's 1440px reading width — the DX surface gets the whole
   viewport, with the area's own padding as the only side margin. */
.bi-area--canvas .bi-shell {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: none;
}

.bi-area--canvas .bi-canvas {
    flex: 1 1 auto;
    min-height: 0;
    height: auto;
}

/* ------------------------------------------------------------- page head -- */
.bi-head {
    margin-bottom: var(--bi-s5);
}

.bi-eyebrow {
    font-family: var(--bi-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--bi-ink-mute);
    margin: 0 0 var(--bi-s2);
}

.bi-title {
    font-size: 30px;
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--bi-ink);
    margin: 0;
}

.bi-lede {
    margin: var(--bi-s3) 0 0;
    color: var(--bi-ink-mute);
    font-size: 14px;
    max-width: 76ch;
}

.bi-lede code {
    font-family: var(--bi-mono);
    font-size: 0.92em;
    background: var(--bi-sunk);
    border-radius: var(--bi-r-sm);
    padding: 1px 5px;
}

/* The scope rule — hairline, accent tick at the left, facts and actions under. */
.bi-rule {
    position: relative;
    margin-top: var(--bi-s5);
    padding-top: var(--bi-s3);
    border-top: 1px solid var(--bi-line);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--bi-s4);
    flex-wrap: wrap;
}

.bi-rule::before {
    content: '';
    position: absolute;
    left: 0;
    top: -1px;
    width: 28px;
    height: 2px;
    background: var(--bi-accent);
}

.bi-facts {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--bi-s1) var(--bi-s4);
    min-height: 30px;
}

.bi-fact {
    font-family: var(--bi-mono);
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--bi-ink-mute);
    white-space: nowrap;
}

.bi-fact b {
    font-weight: 600;
    font-size: 13px;
    color: var(--bi-ink);
    font-variant-numeric: tabular-nums;
}

.bi-fact--accent b {
    color: var(--bi-accent);
}

.bi-fact--star b {
    color: var(--bi-star);
}

.bi-fact--warn b {
    color: var(--bi-warn);
}

.bi-actions {
    display: flex;
    align-items: center;
    gap: var(--bi-s2);
    flex-wrap: wrap;
}

/* Compact head — the canvas pages' single-row variant. The accent tick moves onto the
   bottom hairline so the scope-rule identity survives the collapse. */
.bi-head--compact {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--bi-s4);
    flex-wrap: wrap;
    margin-bottom: var(--bi-s3);
    padding-bottom: var(--bi-s3);
    border-bottom: 1px solid var(--bi-line);
}

.bi-head--compact::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: -1px;
    width: 28px;
    height: 2px;
    background: var(--bi-accent);
}

.bi-head--compact .bi-head__id {
    display: flex;
    align-items: baseline;
    gap: var(--bi-s3);
    min-width: 0;
}

.bi-head--compact .bi-eyebrow {
    margin: 0;
    white-space: nowrap;
}

.bi-head--compact .bi-title {
    font-size: 18px;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bi-head--compact .bi-facts {
    min-height: 0;
}

/* --------------------------------------------------------------- search --- */
/* A native input rather than a Radzen one: filtering has to react per keystroke,
   and RadzenTextBox only raises its value on change. */
.bi-search {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.bi-search__icon {
    position: absolute;
    left: 9px;
    color: var(--bi-ink-faint);
    pointer-events: none;
    line-height: 0;
}

.bi-search input {
    font: inherit;
    font-size: 13px;
    color: var(--bi-ink);
    width: 240px;
    height: 34px;
    padding: 0 30px 0 32px;
    background: var(--bi-paper);
    border: 1px solid var(--bi-line-strong);
    border-radius: var(--bi-r-sm);
    transition: border-color var(--bi-fast) var(--bi-ease), box-shadow var(--bi-fast) var(--bi-ease);
}

.bi-search input::placeholder {
    color: var(--bi-ink-faint);
}

.bi-search input:hover {
    border-color: var(--bi-ink-faint);
}

.bi-search input:focus {
    outline: none;
    border-color: var(--bi-accent);
    box-shadow: 0 0 0 3px var(--bi-accent-soft);
}

.bi-search__clear {
    position: absolute;
    right: 5px;
    appearance: none;
    background: none;
    border: 0;
    padding: 2px;
    line-height: 0;
    border-radius: var(--bi-r-sm);
    color: var(--bi-ink-faint);
    cursor: pointer;
}

.bi-search__clear:hover {
    color: var(--bi-ink);
    background: var(--bi-sunk);
}

/* ---------------------------------------------------------------- panel --- */
.bi-panel {
    background: var(--bi-paper);
    border: 1px solid var(--bi-line);
    border-radius: var(--bi-r-md);
}

.bi-panel + .bi-panel {
    margin-top: var(--bi-s4);
}

.bi-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--bi-s4);
    flex-wrap: wrap;
    padding: var(--bi-s4) var(--bi-s5);
    border-bottom: 1px solid var(--bi-line-soft);
}

.bi-panel__title {
    font-size: 15px;
    font-weight: 600;
    color: var(--bi-ink);
    margin: 0;
}

.bi-panel__hint {
    margin: 2px 0 0;
    font-size: 13px;
    color: var(--bi-ink-mute);
}

.bi-panel__body {
    padding: var(--bi-s5);
}

/* -------------------------------------------------------------- section --- */

.bi-section__title {
    font-family: var(--bi-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bi-ink-mute);
    margin: 0 0 var(--bi-s3);
}

/* ---------------------------------------------------------------- tiles --- */
.bi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--bi-s4);
}

.bi-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--bi-s3);
    background: var(--bi-paper);
    border: 1px solid var(--bi-line);
    border-radius: var(--bi-r-md);
    padding: var(--bi-s4);
    transition: border-color var(--bi-fast) var(--bi-ease),
                box-shadow var(--bi-slow) var(--bi-ease),
                transform var(--bi-slow) var(--bi-ease);
}

.bi-tile:hover {
    border-color: var(--bi-accent-line);
    box-shadow: var(--bi-lift);
    transform: translateY(-2px);
}

.bi-tile:focus-within {
    border-color: var(--bi-accent);
}

.bi-tile__top {
    display: flex;
    align-items: flex-start;
    gap: var(--bi-s3);
}

.bi-tile__mark {
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    border-radius: var(--bi-r-md);
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bi-accent-soft);
    color: var(--bi-accent);
    overflow: hidden;
}

.bi-tile__mark img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.bi-tile__heading {
    min-width: 0;
    flex: 1 1 auto;
}

/* The name is the hit target: its ::after covers the whole tile, so the card
   clicks as one piece while the star button stays independently reachable. */
.bi-tile__name {
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    font: inherit;
    text-align: left;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--bi-ink);
    cursor: pointer;
    overflow-wrap: anywhere;
}

.bi-tile__name::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: var(--bi-r-md);
}

.bi-tile__name:hover {
    color: var(--bi-accent);
}

.bi-tile__name:focus-visible {
    outline: none;
}

.bi-tile__name:focus-visible::after {
    outline: 2px solid var(--bi-accent);
    outline-offset: 2px;
}

.bi-tile__desc {
    margin: 0;
    font-size: 13px;
    color: var(--bi-ink-soft);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.bi-tile__foot {
    margin-top: auto;
    padding-top: var(--bi-s3);
    border-top: 1px solid var(--bi-line-soft);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--bi-s2);
    min-height: 34px;
}

/* Category identity, shown only where cards span categories. */
.bi-tile__cat {
    display: inline-flex;
    align-items: center;
    gap: var(--bi-s2);
    font-size: 12px;
    color: var(--bi-ink-mute);
    min-width: 0;
}

.bi-tile__dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex: 0 0 7px;
}

.bi-tile__open {
    font-family: var(--bi-mono);
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--bi-ink-faint);
    white-space: nowrap;
    transition: color var(--bi-fast) var(--bi-ease);
}

.bi-tile:hover .bi-tile__open {
    color: var(--bi-accent);
}

/* Star sits above the tile-wide hit area. */
.bi-star {
    position: relative;
    z-index: 1;
    appearance: none;
    background: none;
    border: 0;
    padding: var(--bi-s1);
    margin: -4px -4px 0 0;
    line-height: 0;
    border-radius: var(--bi-r-sm);
    color: var(--bi-ink-faint);
    cursor: pointer;
    transition: color var(--bi-fast) var(--bi-ease), background var(--bi-fast) var(--bi-ease);
}

.bi-star:hover {
    background: var(--bi-sunk);
    color: var(--bi-star);
}

.bi-star--on {
    color: var(--bi-star);
}

/* ---------------------------------------------------------------- strip --- */
.bi-strip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    background: var(--bi-paper);
    border: 1px solid var(--bi-line);
    border-radius: var(--bi-r-md);
    overflow: hidden;
}

.bi-strip__cell {
    padding: var(--bi-s4) var(--bi-s5);
    border-right: 1px solid var(--bi-line-soft);
    display: flex;
    flex-direction: column;
    gap: var(--bi-s1);
}

.bi-strip__cell:last-child {
    border-right: 0;
}

.bi-strip__label {
    font-family: var(--bi-mono);
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--bi-ink-mute);
}

.bi-strip__value {
    font-size: 26px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--bi-ink);
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- pills --- */
.bi-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--bi-s1);
    padding: 2px 9px;
    border-radius: var(--bi-r-pill);
    font-family: var(--bi-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.04em;
    white-space: nowrap;
    background: var(--bi-sunk);
    color: var(--bi-ink-soft);
}

.bi-pill--good {
    background: var(--bi-good-soft);
    color: var(--bi-good);
}

.bi-pill--warn {
    background: var(--bi-warn-soft);
    color: var(--bi-warn);
}

.bi-pill--quiet {
    background: transparent;
    border: 1px solid var(--bi-line);
    color: var(--bi-ink-mute);
}

/* Machine-facing identifiers: DbSet names, process ids, context names. */
.bi-ident {
    font-family: var(--bi-mono);
    font-size: 12px;
    color: var(--bi-ink-mute);
}


/* A disclosure that keeps long reference copy out of the way until wanted. */
.bi-disclose {
    border: 1px solid var(--bi-line);
    border-radius: var(--bi-r-md);
    background: var(--bi-paper);
}

.bi-disclose > summary {
    cursor: pointer;
    list-style: none;
    padding: var(--bi-s3) var(--bi-s5);
    font-size: 13px;
    font-weight: 600;
    color: var(--bi-ink-soft);
    display: flex;
    align-items: center;
    gap: var(--bi-s2);
}

.bi-disclose > summary::-webkit-details-marker {
    display: none;
}

.bi-disclose > summary::before {
    content: '';
    width: 0;
    height: 0;
    border-left: 5px solid var(--bi-ink-faint);
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
    transition: transform var(--bi-fast) var(--bi-ease);
}

.bi-disclose[open] > summary::before {
    transform: rotate(90deg);
}

.bi-disclose > summary:hover {
    color: var(--bi-accent);
}

.bi-disclose__body {
    padding: 0 var(--bi-s5) var(--bi-s4);
    border-top: 1px solid var(--bi-line-soft);
    padding-top: var(--bi-s4);
}

.bi-disclose__body p {
    margin: 0 0 var(--bi-s3);
    font-size: 13px;
    color: var(--bi-ink-soft);
    max-width: 92ch;
}

.bi-disclose__body p:last-child {
    margin-bottom: 0;
}

.bi-disclose__body code {
    font-family: var(--bi-mono);
    font-size: 0.92em;
    background: var(--bi-sunk);
    border-radius: var(--bi-r-sm);
    padding: 1px 5px;
}

/* --------------------------------------------------------------- states --- */
.bi-state {
    border: 1px dashed var(--bi-line-strong);
    border-radius: var(--bi-r-md);
    background: var(--bi-paper);
    padding: var(--bi-s7) var(--bi-s5);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--bi-s3);
    text-align: center;
}

.bi-state__icon {
    color: var(--bi-ink-faint);
    line-height: 0;
}

.bi-state--error .bi-state__icon {
    color: var(--bi-bad);
}

.bi-state__title {
    font-size: 16px;
    font-weight: 600;
    color: var(--bi-ink);
    margin: 0;
}

.bi-state__body {
    margin: 0;
    font-size: 13px;
    color: var(--bi-ink-mute);
    max-width: 46ch;
}

/* Skeletons hold the layout while data loads, so nothing jumps on arrival. */
.bi-skel {
    background: linear-gradient(90deg, var(--bi-sunk) 25%, var(--bi-line-soft) 37%, var(--bi-sunk) 63%);
    background-size: 400% 100%;
    animation: bi-shimmer 1.4s ease-in-out infinite;
    border-radius: var(--bi-r-sm);
}

.bi-skel-tile {
    height: 148px;
    border-radius: var(--bi-r-md);
}

.bi-skel-row {
    height: 44px;
    margin-bottom: var(--bi-s2);
}

@keyframes bi-shimmer {
    0% { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

/* --------------------------------------------------------------- canvas --- */
/* Frame around a DevExpress dashboard, designer or viewer surface. */
.bi-canvas {
    background: var(--bi-paper);
    border: 1px solid var(--bi-line);
    border-radius: var(--bi-r-md);
    overflow: hidden;
    min-height: 460px;
}

.bi-canvas .dx-dashboard {
    height: 100%;
    overflow: hidden;
}

/* ------------------------------------------------- Radzen grid alignment -- */
/* Radzen grids stay Radzen grids; these only bring their chrome in line with
   the rest of the BI vocabulary. */
.bi-area .rz-data-grid,
.bi-area .rz-datatable {
    border: 1px solid var(--bi-line);
    border-radius: var(--bi-r-md);
    overflow: hidden;
    background: var(--bi-paper);
}

.bi-area .rz-datatable-thead th {
    font-family: var(--bi-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--bi-ink-mute);
    background: var(--bi-ground);
}

.bi-area .rz-data-row td {
    border-bottom: 1px solid var(--bi-line-soft);
}

.bi-area .rz-data-row:hover td {
    background: var(--bi-ground);
}

/* --------------------------------------------------------------- a11y ----- */
.bi-area :focus-visible {
    outline: 2px solid var(--bi-accent);
    outline-offset: 2px;
}

/* DevExpress draws its own focus affordances; hand its internals back to the browser default
   rather than stamping the BI ring on every toolbar item inside a canvas. */
.bi-canvas :focus-visible {
    outline: revert;
    outline-offset: revert;
}

.bi-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

@media (prefers-reduced-motion: reduce) {
    .bi-area *,
    .bi-area *::before,
    .bi-area *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }

    .bi-tile:hover {
        transform: none;
    }
}

/* -------------------------------------------------------------- responsive */
@media (max-width: 640px) {
    .bi-area {
        padding: var(--bi-s5) var(--bi-s4) var(--bi-s6);
    }

    /* The stacked mobile layout has no fixed topbar offset to subtract, so canvas pages
       fall back to natural page scroll with a vh-sized canvas. */
    .bi-area--canvas {
        height: auto;
        overflow: visible;
    }

    .bi-area--canvas .bi-canvas {
        flex: none;
        height: 78vh;
    }

    .bi-title {
        font-size: 24px;
    }

    .bi-grid {
        grid-template-columns: 1fr;
    }

    .bi-strip__cell {
        border-right: 0;
        border-bottom: 1px solid var(--bi-line-soft);
    }

    .bi-strip__cell:last-child {
        border-bottom: 0;
    }
}
