/* EMS global utilities and icon set. Loaded after ems-tokens.css. */

/* Layout helpers usable on any page. */
.ems-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ems-space-3);
}

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

/* Doubled class beats the DemoSection scoped margin, which loads later in the bundle. */
.ems-grid-2.ems-grid-2 > .ems-demo {
    margin-bottom: 0;
}

.ems-grid-2.ems-grid-2 + .ems-demo,
.ems-grid-2.ems-grid-2 + .ems-grid-2 {
    margin-top: var(--ems-space-5);
}

/* KPI rows: 4 -> 2 columns, never an orphaned 3 + 1. */
.ems-grid-4 {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--ems-space-4);
}

.ems-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: min(220px, 100%);
}

.ems-field > label {
    color: var(--ems-text);
    font-size: 0.8rem;
    font-weight: 500;
}

.ems-muted {
    color: var(--ems-text-subtle);
    font-size: 0.85rem;
}

code {
    padding: 1px 5px;
    background: var(--ems-surface-subtle);
    border: 1px solid var(--ems-border);
    border-radius: var(--ems-radius-sm);
    color: var(--ems-text);
    font-size: 0.8em;
}

/* Icons: SVG masks take the current text colour, so they work in both themes. */
.ems-icon {
    display: inline-block;
    flex: none;
    width: 16px;
    height: 16px;
    background-color: currentColor;
    -webkit-mask: var(--ems-icon) center / contain no-repeat;
    mask: var(--ems-icon) center / contain no-repeat;
}

.ems-icon-home { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 10.5 12 3l9 7.5V21h-6v-6H9v6H3z'/%3E%3C/svg%3E"); }
.ems-icon-palette { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Cpath d='M12 3a9 9 0 1 0 0 18c1.1 0 2-.9 2-2 0-.5-.2-1-.5-1.3-.3-.4-.5-.8-.5-1.3 0-1.1.9-2 2-2h2.4A4.6 4.6 0 0 0 21 9.8C21 6 17 3 12 3z'/%3E%3Ccircle cx='7.5' cy='11' r='1'/%3E%3Ccircle cx='10' cy='7' r='1'/%3E%3Ccircle cx='15' cy='7' r='1'/%3E%3C/svg%3E"); }
.ems-icon-cursor { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M5 3l14 8-6 2-2 6z'/%3E%3C/svg%3E"); }
.ems-icon-edit { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M4 20h4L19 9l-4-4L4 16z'/%3E%3C/svg%3E"); }
.ems-icon-form { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='4' y='3' width='16' height='18' rx='2'/%3E%3Cpath d='M8 8h8M8 12h8M8 16h5'/%3E%3C/svg%3E"); }
.ems-icon-grid { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='3' y='4' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M3 15h18M9 4v16'/%3E%3C/svg%3E"); }
.ems-icon-tree { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='3' y='3' width='6' height='5' rx='1'/%3E%3Crect x='14' y='10' width='7' height='4' rx='1'/%3E%3Crect x='14' y='17' width='7' height='4' rx='1'/%3E%3Cpath d='M6 8v11h8M6 12h8'/%3E%3C/svg%3E"); }
.ems-icon-calendar { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18M8 3v4M16 3v4'/%3E%3C/svg%3E"); }
.ems-icon-chart { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M4 20V10M10 20V4M16 20v-8M22 20H2'/%3E%3C/svg%3E"); }
.ems-icon-menu { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M4 6h16M4 12h16M4 18h16'/%3E%3C/svg%3E"); }
.ems-icon-layers { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M12 3 2 8l10 5 10-5zM2 13l10 5 10-5'/%3E%3C/svg%3E"); }
.ems-icon-layout { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='3' y='3' width='18' height='18' rx='2'/%3E%3Cpath d='M3 9h18M9 9v12'/%3E%3C/svg%3E"); }
.ems-icon-ticket { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M3 7h18v3a2 2 0 0 0 0 4v3H3v-3a2 2 0 0 0 0-4z'/%3E%3Cpath d='M14 7v10' stroke-dasharray='2 2'/%3E%3C/svg%3E"); }
.ems-icon-users { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Ccircle cx='9' cy='8' r='4'/%3E%3Cpath d='M2 21c0-4 3-6 7-6s7 2 7 6M16 4a4 4 0 0 1 0 8M22 21c0-3-1.5-5-4-5.7'/%3E%3C/svg%3E"); }
.ems-icon-building { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='4' y='3' width='16' height='18' rx='1'/%3E%3Cpath d='M9 7h1M14 7h1M9 11h1M14 11h1M9 15h1M14 15h1M10 21v-3h4v3'/%3E%3C/svg%3E"); }
.ems-icon-money { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='2' y='6' width='20' height='12' rx='2'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E"); }
.ems-icon-plus { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E"); }
.ems-icon-download { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 4v11M7 10l5 5 5-5M4 20h16'/%3E%3C/svg%3E"); }
.ems-icon-trash { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M4 7h16M9 7V4h6v3M6 7l1 14h10l1-14'/%3E%3C/svg%3E"); }
.ems-icon-mail { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='2'/%3E%3Cpath d='m3 7 9 6 9-6'/%3E%3C/svg%3E"); }
.ems-icon-pin { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Cpath d='M12 21s7-6.2 7-12a7 7 0 0 0-14 0c0 5.8 7 12 7 12z'/%3E%3Ccircle cx='12' cy='9' r='2.5'/%3E%3C/svg%3E"); }
.ems-icon-sun { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M2 12h2M20 12h2M5 5l1.5 1.5M17.5 17.5 19 19M5 19l1.5-1.5M17.5 6.5 19 5'/%3E%3C/svg%3E"); }
.ems-icon-moon { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M20 14.5A8 8 0 0 1 9.5 4 8 8 0 1 0 20 14.5z'/%3E%3C/svg%3E"); }
.ems-icon-check { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12 5 5 9-10'/%3E%3C/svg%3E"); }
.ems-icon-search { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-4-4'/%3E%3C/svg%3E"); }
.ems-icon-chevron { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); }
.ems-icon-sidebar { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='3' y='4' width='18' height='16' rx='2'/%3E%3Cpath d='M9 4v16'/%3E%3C/svg%3E"); }
.ems-icon-help { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M9.5 9.5a2.5 2.5 0 0 1 4.8 1c0 1.7-2.3 2-2.3 3.5M12 17.5v.01'/%3E%3C/svg%3E"); }
.ems-icon-bell { --ems-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M6 9a6 6 0 0 1 12 0c0 6 2.5 7.5 2.5 7.5h-17S6 15 6 9zM10 20a2 2 0 0 0 4 0'/%3E%3C/svg%3E"); }

@media (max-width: 1100px) {
    .ems-grid-4 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 600px) {
    .ems-grid-4 {
        gap: var(--ems-space-3);
    }
}

/* Form field grid: fields fill the row and wrap evenly instead of keeping fixed widths. */
.ems-fields {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
    gap: var(--ems-space-4) var(--ems-space-5);
    align-items: start;
}

.ems-fields > .ems-field {
    min-width: 0;
}

.ems-field-wide {
    grid-column: span 2;
}

.ems-field-full {
    grid-column: 1 / -1;
}

@media (max-width: 600px) {
    .ems-field-wide {
        grid-column: 1 / -1;
    }
}

/* Wide content (tables, matrices) scrolls inside its card rather than widening the page. */
.ems-scroll-x {
    max-width: 100%;
    overflow-x: auto;
}

/* Avatar used by the sidebar, header and user menu. */
.ems-ds-avatar {
    display: grid;
    flex: none;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--ems-data-2);
    color: #FFFFFF;
    font-size: 0.72rem;
    font-weight: 700;
}

.ems-ds-avatar.ems-avatar-lg {
    width: 44px;
    height: 44px;
    font-size: 0.9rem;
}

/* Header menus (DxFlyout renders at <body>): no inner padding, our content supplies it. */
.ems-menu-flyout .dxbl-flyout-body,
.ems-menu-flyout .dxbl-popup-body {
    padding: 0;
}

/* Empty and not-found states. */
.ems-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--ems-space-2);
    padding: var(--ems-space-6);
    color: var(--ems-text-subtle);
    text-align: center;
}

.ems-empty strong,
.ems-empty h1 {
    margin: 0;
    color: var(--ems-text);
    font-size: 1.1rem;
    font-weight: 600;
}

.ems-empty p {
    margin: 0;
}

.ems-empty a {
    color: var(--ems-accent-text);
    font-weight: 500;
}

/* Blazor unhandled-error bar (rendered in App.razor). */
#blazor-error-ui {
    position: fixed;
    bottom: 0;
    left: 0;
    z-index: 1000;
    display: none;
    box-sizing: border-box;
    width: 100%;
    padding: 0.6rem 1.25rem 0.7rem;
    background: var(--ems-danger-bg);
    color: var(--ems-danger);
    box-shadow: var(--ems-shadow-lg);
    font-family: var(--ems-font-family);
}

#blazor-error-ui .dismiss {
    position: absolute;
    top: 0.5rem;
    right: 0.75rem;
    cursor: pointer;
}

/* DevExpress editors: one even 1px border instead of Fluent's darker, thicker bottom underline.
   Validation colours still win because DevExpress sets them with more specific selectors. */
html .dxbl-text-edit {
    --dxbl-text-edit-underline-color: var(--dxbl-text-edit-border-color);
    --dxbl-text-edit-underline-hovered-color: color-mix(in srgb, var(--ems-text-subtle) 55%, var(--ems-border));
    --dxbl-text-edit-underline-focused-color: var(--ems-accent);
    --dxbl-text-edit-underline-active-color: var(--ems-accent);
    --dxbl-text-edit-underline-focused-height: 1px;
    transition: border-color var(--ems-transition), box-shadow var(--ems-transition);
}

html .dxbl-text-edit:hover:not(:focus-within) {
    border-color: color-mix(in srgb, var(--ems-text-subtle) 55%, var(--ems-border));
}

html .dxbl-text-edit:focus-within {
    border-color: var(--ems-accent);
    box-shadow: var(--ems-focus-ring);
}

/* Top page-load bar (App.razor #ems-progress, driven by ems-shell.js). */
#ems-progress {
    position: fixed;
    inset: 0 0 auto;
    z-index: 3000;
    height: 3px;
    pointer-events: none;
}

#ems-progress > div {
    width: 0;
    height: 100%;
    background: linear-gradient(90deg, var(--ems-accent), color-mix(in srgb, var(--ems-accent) 55%, var(--ems-data-6)));
    box-shadow: 0 0 8px color-mix(in srgb, var(--ems-accent) 60%, transparent);
    opacity: 0;
    transition: width 250ms ease-out, opacity 300ms ease;
}

@media (prefers-reduced-motion: reduce) {
    #ems-progress > div {
        transition: none;
    }
}

/* DevExpress buttons: Fluent renders every Outline/Text variant as neutral grey, which hides their meaning.
   Give each semantic style its own text, border and hover tint; Secondary stays neutral. */
html .dxbl-btn.dxbl-btn-outline-primary,
html .dxbl-btn.dxbl-btn-text-primary { --ems-btn-tone: var(--ems-accent-text); }
html .dxbl-btn.dxbl-btn-outline-success,
html .dxbl-btn.dxbl-btn-text-success { --ems-btn-tone: var(--ems-success); }
html .dxbl-btn.dxbl-btn-outline-warning,
html .dxbl-btn.dxbl-btn-text-warning { --ems-btn-tone: var(--ems-warning); }
html .dxbl-btn.dxbl-btn-outline-danger,
html .dxbl-btn.dxbl-btn-text-danger { --ems-btn-tone: var(--ems-danger); }
html .dxbl-btn.dxbl-btn-outline-info,
html .dxbl-btn.dxbl-btn-text-info { --ems-btn-tone: var(--ems-info); }

html .dxbl-btn:is(.dxbl-btn-outline-primary, .dxbl-btn-outline-success, .dxbl-btn-outline-warning, .dxbl-btn-outline-danger, .dxbl-btn-outline-info) {
    --dxbl-btn-color: var(--ems-btn-tone);
    --dxbl-btn-border-color: color-mix(in srgb, var(--ems-btn-tone) 45%, var(--ems-border));
    --dxbl-btn-hover-color: var(--ems-btn-tone);
    --dxbl-btn-hover-bg: color-mix(in srgb, var(--ems-btn-tone) 10%, transparent);
    --dxbl-btn-hover-border-color: var(--ems-btn-tone);
    --dxbl-btn-active-color: var(--ems-btn-tone);
    --dxbl-btn-active-bg: color-mix(in srgb, var(--ems-btn-tone) 16%, transparent);
}

html .dxbl-btn:is(.dxbl-btn-text-primary, .dxbl-btn-text-success, .dxbl-btn-text-warning, .dxbl-btn-text-danger, .dxbl-btn-text-info) {
    --dxbl-btn-color: var(--ems-btn-tone);
    --dxbl-btn-hover-color: var(--ems-btn-tone);
    --dxbl-btn-hover-bg: color-mix(in srgb, var(--ems-btn-tone) 10%, transparent);
    --dxbl-btn-active-color: var(--ems-btn-tone);
    --dxbl-btn-active-bg: color-mix(in srgb, var(--ems-btn-tone) 16%, transparent);
}

/* Grid popup edit form (rendered at <body>, so it must be global). */
.ems-edit-popup {
    width: min(640px, calc(100vw - 32px)) !important;
    max-width: none !important;
}

/* Boot splash (App.razor #ems-boot). Fades in after 900ms so fast, cached starts never show it. */
.ems-boot-screen {
    position: fixed;
    inset: 0;
    z-index: 3500;
    display: grid;
    place-items: center;
    background: color-mix(in srgb, var(--ems-page-bg) 92%, transparent);
    backdrop-filter: blur(2px);
    font-family: var(--ems-font-family);
    opacity: 0;
    pointer-events: none;
    animation: ems-boot-in 200ms ease-out 900ms forwards;
    transition: opacity 250ms ease;
}

.ems-boot-screen.done {
    opacity: 0 !important;
    animation: none;
    pointer-events: none;
}

.ems-boot-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--ems-space-3);
    color: var(--ems-text);
}

.ems-boot-logo {
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    border-radius: var(--ems-radius-lg);
    background: linear-gradient(135deg, var(--ems-accent), color-mix(in srgb, var(--ems-accent) 60%, var(--ems-data-5)));
    box-shadow: var(--ems-shadow-lg);
    color: #FFFFFF;
    font-size: 1.5rem;
    font-weight: 700;
    animation: ems-boot-pulse 1.4s ease-in-out infinite;
}

.ems-boot-card strong {
    font-size: 1.1rem;
}

.ems-boot-card small {
    color: var(--ems-text-subtle);
}

.ems-boot-track {
    position: relative;
    width: 160px;
    height: 4px;
    overflow: hidden;
    border-radius: 999px;
    background: var(--ems-border);
}

.ems-boot-track span {
    position: absolute;
    inset: 0 auto 0 0;
    width: 40%;
    border-radius: inherit;
    background: var(--ems-accent);
    animation: ems-boot-slide 1.1s ease-in-out infinite;
}

@keyframes ems-boot-in {
    to { opacity: 1; pointer-events: auto; }
}

@keyframes ems-boot-pulse {
    50% { transform: scale(0.94); }
}

@keyframes ems-boot-slide {
    from { transform: translateX(-100%); }
    to { transform: translateX(260%); }
}

/* Charts: shimmer placeholder until DevExpress draws the first frame. */
.dxbl-chart-root.dxbl-chart-first-loading,
.dxbl-pie-chart-root.dxbl-chart-first-loading {
    border-radius: var(--ems-radius);
    background: linear-gradient(90deg, var(--ems-surface-subtle) 25%, color-mix(in srgb, var(--ems-border) 60%, var(--ems-surface-subtle)) 50%, var(--ems-surface-subtle) 75%) 0 0 / 200% 100%;
    animation: ems-shimmer 1.2s linear infinite;
}

@keyframes ems-shimmer {
    to { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
    .ems-boot-logo,
    .ems-boot-track span,
    .dxbl-chart-root.dxbl-chart-first-loading {
        animation: none;
    }

    .ems-boot-screen {
        animation-duration: 1ms;
    }
}
