﻿/* ─────────────────────────────────────────────────────────────
   ELTS ERP — Application Theme
   A refined, token-driven design system.
   Class names are stable; views rely on them unchanged.
   ───────────────────────────────────────────────────────────── */

/* =========== Design tokens =========== */
:root {
    /* Layout */
    --erp-sidebar-w: 264px;
    --erp-sidebar-w-collapsed: 72px;
    --erp-topbar-h: 60px;

    /* Surface / background */
    --erp-bg: #f5f7fb;
    --erp-surface: #ffffff;
    --erp-surface-2: #f7f9fc;
    --erp-surface-3: #eef2f8;
    --erp-border: #e4e8f0;
    --erp-border-strong: #d1d7e3;

    /* Text */
    --erp-text: #0f1a36;
    --erp-text-muted: #667085;
    --erp-text-soft: #98a2b3;

    /* Brand (sidebar) */
    --erp-brand: #0f172a;
    --erp-brand-2: #1e293b;
    --erp-brand-3: #243449;
    --erp-brand-contrast: #e2e8f0;
    --erp-brand-accent: #60a5fa;

    /* Primary */
    --erp-primary: #2563eb;
    --erp-primary-600: #1d4ed8;
    --erp-primary-700: #1e40af;
    --erp-primary-50: #eef4ff;
    --erp-primary-100: #dbe7ff;

    /* Semantic */
    --erp-success: #16a34a;
    --erp-success-50: #ecfdf5;
    --erp-warning: #d97706;
    --erp-warning-50: #fff7ed;
    --erp-danger: #dc2626;
    --erp-danger-50: #fef2f2;
    --erp-info: #0891b2;
    --erp-info-50: #ecfeff;

    /* ELTS gold — the mark's own colour, sampled from branding/elts-solutions.png.
       It lived only inside the login page's local <style> as --auth-gold, so the app
       spoke three unrelated brand voices: gold when signing in, generic blue in the
       shell, navy on printed paper. Promoted here so the identity can be an accent in
       all three. It marks chrome only — a hairline, a glyph — and never a figure: a
       brand colour that lands on a number competes with the semantic colours that say
       whether the number is good or bad. */
    --erp-gold: #c9a227;
    --erp-gold-lite: #e8c766;

    /* Radius */
    --erp-radius-xs: 4px;
    --erp-radius-sm: 8px;
    --erp-radius: 12px;
    --erp-radius-lg: 16px;

    /* Elevation — soft, multi-layer, slightly blue-tinted */
    --erp-shadow-xs: 0 1px 2px rgba(15, 23, 42, 0.04);
    --erp-shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04), 0 1px 3px rgba(15, 23, 42, 0.04);
    --erp-shadow: 0 2px 4px rgba(15, 23, 42, 0.04), 0 4px 12px rgba(15, 23, 42, 0.06);
    --erp-shadow-lg: 0 4px 8px rgba(15, 23, 42, 0.04), 0 12px 32px rgba(15, 23, 42, 0.10);

    /* Rings */
    --erp-ring: 0 0 0 3px rgba(37, 99, 235, 0.18);
    --erp-ring-danger: 0 0 0 3px rgba(220, 38, 38, 0.18);

    /* Motion */
    --erp-ease: cubic-bezier(.3, .7, .3, 1);
    --erp-dur-fast: .12s;
    --erp-dur: .18s;
    --erp-dur-slow: .28s;

    /* Fonts */
    --erp-font-sans: "Inter", "Segoe UI", "IBM Plex Sans Arabic", Tahoma, system-ui, sans-serif;
    --erp-font-arabic: "IBM Plex Sans Arabic", "Noto Naskh Arabic", "Inter", Tahoma, sans-serif;
    --erp-font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Consolas, monospace;
}

html[dir="rtl"] {
    --erp-font-sans: var(--erp-font-arabic);
}

/* =========== Base =========== */
*, *::before, *::after { box-sizing: border-box; }

html, body {
    height: 100%;
    background: var(--erp-bg);
    color: var(--erp-text);
    font-family: var(--erp-font-sans);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

@media (min-width: 1200px) {
    html, body { font-size: 15px; }
}

body { margin: 0; }

a { color: var(--erp-primary); text-decoration: none; transition: color var(--erp-dur-fast) var(--erp-ease); }
a:hover { color: var(--erp-primary-600); }

h1, h2, h3, h4, h5, h6 {
    color: var(--erp-text);
    font-weight: 600;
    letter-spacing: -0.01em;
}

/* Custom scrollbar (subtle) */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--erp-border-strong) transparent;
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
    background: var(--erp-border-strong);
    border-radius: 999px;
    border: 2px solid var(--erp-bg);
}
*::-webkit-scrollbar-thumb:hover { background: var(--erp-text-soft); }

/* Selection */
::selection { background: var(--erp-primary-100); color: var(--erp-primary-700); }

/* Focus visible — global */
:focus-visible {
    outline: none;
    box-shadow: var(--erp-ring);
    border-radius: var(--erp-radius-xs);
}

/* =========== App shell =========== */
.app-shell {
    display: grid;
    grid-template-columns: var(--erp-sidebar-w) 1fr;
    grid-template-rows: var(--erp-topbar-h) 1fr;
    min-height: 100vh;
    transition: grid-template-columns var(--erp-dur) var(--erp-ease);
}

.app-shell.sidebar-collapsed {
    grid-template-columns: var(--erp-sidebar-w-collapsed) 1fr;
}

.app-sidebar {
    grid-row: 1 / span 2;
    background: var(--erp-brand);
    color: var(--erp-brand-contrast);
    border-inline-end: 1px solid rgba(255, 255, 255, 0.04);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    position: sticky;
    top: 0;
    height: 100vh;
    z-index: 30;
}

.app-topbar {
    background: rgba(255, 255, 255, 0.9);
    backdrop-filter: saturate(180%) blur(8px);
    -webkit-backdrop-filter: saturate(180%) blur(8px);
    border-bottom: 1px solid var(--erp-border);
    padding: 0 1.25rem;
    display: flex;
    align-items: center;
    gap: .75rem;
    position: sticky;
    top: 0;
    z-index: 20;
    box-shadow: var(--erp-shadow-xs);
}

.app-main {
    padding: 1.5rem;
    min-width: 0;
}

@media (min-width: 1400px) {
    .app-main { padding: 1.75rem 2rem; }
}

/* =========== Sidebar =========== */
.sidebar-brand {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: 0 1rem;
    height: var(--erp-topbar-h);
    color: #fff;
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    white-space: nowrap;
    overflow: hidden;
}
/* The one mark that is on screen on every page, so it is where the identity belongs.
   It used to be a blue-indigo-violet gradient that appears nowhere else in this product
   and matches no brand in the repo — the login page next door renders the real logo in
   navy and gold. Now it is the shell navy carrying a gold glyph: the same two colours,
   34 pixels of them. */
.sidebar-brand .brand-mark {
    width: 34px; height: 34px; flex-shrink: 0;
    background: linear-gradient(135deg, var(--erp-brand-2), var(--erp-brand));
    border-radius: 10px;
    display: grid; place-items: center;
    color: var(--erp-gold); font-weight: 800; font-size: .95rem;
    box-shadow: 0 6px 14px rgba(0, 0, 0, .35), inset 0 1px 0 rgba(255, 255, 255, .12);
    border: 1px solid rgba(201, 162, 39, .28);
}
.sidebar-brand .brand-text { overflow: hidden; text-overflow: ellipsis; }

.sidebar-nav {
    flex: 1;
    overflow-y: auto;
    padding: .75rem .55rem 1rem;
}
.sidebar-nav::-webkit-scrollbar { width: 6px; }
.sidebar-nav::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.08); border-radius: 999px; border: none; }
.sidebar-nav::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.14); }

.nav-group-label {
    color: #7b8aa8;
    font-size: .7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .1em;
    padding: .85rem 1rem .4rem;
}

.nav-item-link {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .55rem .85rem;
    margin: 2px 0;
    border-radius: var(--erp-radius-sm);
    color: var(--erp-brand-contrast);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    font-size: .915rem;
    font-weight: 500;
    transition: background var(--erp-dur-fast) var(--erp-ease),
                color var(--erp-dur-fast) var(--erp-ease),
                transform var(--erp-dur-fast) var(--erp-ease);
}
.nav-item-link:hover { background: var(--erp-brand-2); color: #fff; }
.nav-item-link.active {
    background: linear-gradient(90deg, rgba(96, 165, 250, 0.22), rgba(96, 165, 250, 0.04));
    color: #fff;
    box-shadow: inset 3px 0 0 var(--erp-brand-accent);
}
html[dir="rtl"] .nav-item-link.active {
    background: linear-gradient(-90deg, rgba(96, 165, 250, 0.22), rgba(96, 165, 250, 0.04));
    box-shadow: inset -3px 0 0 var(--erp-brand-accent);
}
.nav-item-link.is-locked { color: #7b8aa8; opacity: .7; }
.nav-item-link.is-locked:hover { background: transparent; color: #7b8aa8; cursor: default; }
.nav-item-link .nav-icon { font-size: 1.05rem; width: 22px; text-align: center; flex-shrink: 0; opacity: .9; }
.nav-item-link:hover .nav-icon,
.nav-item-link.active .nav-icon { opacity: 1; }
.nav-item-link .nav-text { overflow: hidden; text-overflow: ellipsis; }
.nav-item-link .nav-badge { margin-inline-start: auto; font-size: .7rem; }

/* Collapsible modules */
.nav-module { margin: 2px 0; }
.nav-module-header { display: flex; align-items: stretch; gap: 2px; }
.nav-module-header .nav-module-link { flex: 1; min-width: 0; margin: 0; }
.nav-module-toggle {
    background: transparent;
    border: 0;
    color: var(--erp-brand-contrast);
    padding: 0 .6rem;
    border-radius: var(--erp-radius-sm);
    cursor: pointer;
    display: grid;
    place-items: center;
    flex-shrink: 0;
    transition: background var(--erp-dur-fast) var(--erp-ease),
                color var(--erp-dur-fast) var(--erp-ease);
}
.nav-module-toggle:hover { background: var(--erp-brand-2); color: #fff; }
.nav-module-caret {
    font-size: .78rem;
    opacity: .7;
    transition: transform var(--erp-dur) var(--erp-ease), opacity var(--erp-dur-fast) var(--erp-ease);
}
.nav-module.is-open .nav-module-caret { transform: rotate(-180deg); opacity: 1; }

.nav-module-sub {
    list-style: none;
    margin: 0;
    padding: 0;
    max-height: 0;
    overflow: hidden;
    transition: max-height var(--erp-dur-slow) var(--erp-ease);
}
/* The open height must clear the LONGEST module, not a typical one.
   This was 520px — about 16 rows — while HR has 18 pages, so its last two
   (دورات الرواتب and قسائم الرواتب) were rendered in the DOM and silently
   clipped by `overflow: hidden`. It reads exactly like a permissions problem,
   which is what makes it worth a comment: the links were always there.
   2000px is far above any current module and still animates, because the
   transition interpolates max-height rather than the real height. */
.nav-module.is-open .nav-module-sub { max-height: 2000px; }

.nav-sub-link {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .42rem .85rem .42rem 2.5rem;
    color: #97a5c3;
    text-decoration: none;
    font-size: .865rem;
    border-radius: var(--erp-radius-sm);
    white-space: nowrap;
    overflow: hidden;
    transition: background var(--erp-dur-fast) var(--erp-ease),
                color var(--erp-dur-fast) var(--erp-ease);
}
html[dir="rtl"] .nav-sub-link {
    padding: .42rem 2.5rem .42rem .85rem;
}
.nav-sub-link:hover { background: var(--erp-brand-2); color: #fff; }
.nav-sub-link.active {
    background: linear-gradient(90deg, rgba(96, 165, 250, 0.18), rgba(96, 165, 250, 0.02));
    color: #fff;
    box-shadow: inset 3px 0 0 var(--erp-brand-accent);
}
html[dir="rtl"] .nav-sub-link.active {
    background: linear-gradient(-90deg, rgba(96, 165, 250, 0.18), rgba(96, 165, 250, 0.02));
    box-shadow: inset -3px 0 0 var(--erp-brand-accent);
}
.nav-sub-link .nav-sub-icon {
    font-size: .88rem;
    width: 18px;
    text-align: center;
    flex-shrink: 0;
    opacity: .8;
}
.nav-sub-link .nav-sub-text { overflow: hidden; text-overflow: ellipsis; }

/* ── The sidebar's second level ───────────────────────────────────────────────
   Every menu entry already carried a Group; nothing rendered it, so المحاسبة was a
   flat run of seventeen and الموارد البشرية of twenty. These headings chunk that list
   without adding a click: they are open by default and collapse only if the user
   tidies one away.

   Height is deliberately NOT animated here. The enclosing .nav-module-sub animates
   max-height, and nesting a second max-height transition inside it is how the last
   clipping bug happened — a group is shown or hidden outright, and only its caret
   moves. */
.nav-subgroup { list-style: none; }

.nav-subgroup-header {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    background: none;
    border: 0;
    color: #6f7f9e;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    padding: .6rem 1rem .3rem 1.6rem;
    cursor: pointer;
    text-align: start;
    transition: color var(--erp-dur-fast) var(--erp-ease);
}
html[dir="rtl"] .nav-subgroup-header { padding: .6rem 1.6rem .3rem 1rem; }
.nav-subgroup-header:hover { color: #9fb0d0; }

.nav-subgroup-icon { font-size: .72rem; opacity: .6; flex-shrink: 0; }

.nav-subgroup-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* How many screens are in here — the answer to "is it worth opening" without opening it. */
.nav-subgroup-count {
    font-size: .62rem;
    font-weight: 600;
    letter-spacing: 0;
    padding: .05rem .32rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, .06);
    color: #8494b4;
    flex-shrink: 0;
}

.nav-subgroup-caret {
    font-size: .62rem;
    opacity: .55;
    flex-shrink: 0;
    transition: transform var(--erp-dur) var(--erp-ease), opacity var(--erp-dur-fast) var(--erp-ease);
}
.nav-subgroup.is-open .nav-subgroup-caret { transform: rotate(-180deg); opacity: .85; }

.nav-subgroup-items { list-style: none; margin: 0; padding: 0; display: none; }
.nav-subgroup.is-open .nav-subgroup-items { display: block; }

/* A collapsed group still says it holds the page you are on. */
.nav-subgroup:not(.is-open) .nav-subgroup-header:has(+ .nav-subgroup-items .nav-sub-link.active) {
    color: var(--erp-brand-accent);
}

.sidebar-collapsed .nav-subgroup-header { display: none; }
.sidebar-collapsed .nav-subgroup-items { display: block; }

@media (prefers-reduced-motion: reduce) {
    .nav-subgroup-caret { transition: none; }
}


.sidebar-collapsed .nav-module-toggle,
.sidebar-collapsed .nav-module-sub { display: none; }

.sidebar-footer {
    padding: .85rem 1rem;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
    color: #7b8aa8;
    font-size: .76rem;
    white-space: nowrap;
    overflow: hidden;
    letter-spacing: .01em;
}

.sidebar-collapsed .sidebar-brand .brand-text,
.sidebar-collapsed .nav-group-label,
.sidebar-collapsed .nav-item-link .nav-text,
.sidebar-collapsed .nav-item-link .nav-badge,
.sidebar-collapsed .sidebar-footer { display: none; }

.sidebar-collapsed .nav-item-link { justify-content: center; padding: .6rem; }
.sidebar-collapsed .sidebar-brand { padding: 0; justify-content: center; }

/* =========== Module home — header, sections, tile grid =========== */
/* The module identity beside the title, so a landing page announces which module
   you are in before you read anything. */
.module-head { display: flex; align-items: center; gap: .9rem; min-width: 0; }
.module-head-icon {
    width: 48px;
    height: 48px;
    border-radius: 14px;
    display: grid;
    place-items: center;
    font-size: 1.45rem;
    flex-shrink: 0;
    background: linear-gradient(135deg, var(--erp-primary-50), var(--erp-surface-3));
    color: var(--erp-primary);
    box-shadow: inset 0 0 0 1px var(--erp-border);
}

/* One section per page group. Sections carry the hierarchy the old flat tile grid
   lacked: a titled band per intent, then its pages. */
.module-section + .module-section { margin-top: 1.75rem; }
.module-section-head {
    display: flex;
    align-items: center;
    gap: .7rem;
    margin: 0 0 .85rem;
    padding-bottom: .6rem;
    border-bottom: 1px solid var(--erp-border);
}
.module-section-icon {
    width: 34px;
    height: 34px;
    border-radius: 10px;
    display: grid;
    place-items: center;
    font-size: 1rem;
    flex-shrink: 0;
    background: var(--erp-surface-3);
    color: var(--erp-text-muted);
}
.module-section-heading { flex: 1; min-width: 0; }
.module-section-title {
    margin: 0;
    font-size: 1.02rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}
.module-section-desc {
    color: var(--erp-text-muted);
    font-size: .82rem;
    margin-top: .1rem;
    line-height: 1.4;
}
.module-section-count {
    flex-shrink: 0;
    font-size: .75rem;
    font-weight: 600;
    color: var(--erp-text-muted);
    background: var(--erp-surface-3);
    border-radius: 999px;
    padding: .12rem .55rem;
    line-height: 1.5;
    font-variant-numeric: tabular-nums;
}
/* Setup and reference pages: present, findable, and visibly not the point. */
.module-section.is-setup .module-section-title { font-size: .95rem; color: var(--erp-text-muted); }
.module-section.is-setup .module-section-icon { background: transparent; color: var(--erp-text-soft); }

.module-compact-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
    gap: .5rem;
}
.module-compact {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .55rem .7rem;
    border-radius: var(--erp-radius-sm);
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    color: var(--erp-text);
    text-decoration: none;
    font-size: .88rem;
    transition: border-color var(--erp-dur-fast) var(--erp-ease),
                background var(--erp-dur-fast) var(--erp-ease),
                color var(--erp-dur-fast) var(--erp-ease);
}
.module-compact:hover {
    border-color: var(--erp-border-strong);
    background: var(--erp-surface-2);
    color: var(--erp-primary);
    text-decoration: none;
}
.module-compact-icon {
    color: var(--erp-text-soft);
    font-size: 1rem;
    flex-shrink: 0;
    transition: color var(--erp-dur-fast) var(--erp-ease);
}
.module-compact:hover .module-compact-icon { color: var(--erp-primary); }
.module-compact-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.module-tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1rem;
}
.module-tile {
    display: flex;
    align-items: center;
    gap: .95rem;
    padding: 1rem 1.1rem;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    box-shadow: var(--erp-shadow-xs);
    color: var(--erp-text);
    text-decoration: none;
    position: relative;
    overflow: hidden;
    transition: transform var(--erp-dur-fast) var(--erp-ease),
                box-shadow var(--erp-dur) var(--erp-ease),
                border-color var(--erp-dur-fast) var(--erp-ease);
}
.module-tile::after {
    content: "";
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    inset-inline-end: 0;
    height: 2px;
    background: linear-gradient(90deg, var(--erp-primary), var(--erp-brand-accent));
    opacity: 0;
    transition: opacity var(--erp-dur) var(--erp-ease);
}
.module-tile:hover {
    transform: translateY(-2px);
    box-shadow: var(--erp-shadow);
    border-color: var(--erp-border-strong);
    color: var(--erp-text);
    text-decoration: none;
}
.module-tile:hover::after { opacity: 1; }
.module-tile-icon {
    width: 46px;
    height: 46px;
    border-radius: 12px;
    display: grid;
    place-items: center;
    font-size: 1.3rem;
    background: var(--erp-primary-50);
    color: var(--erp-primary);
    flex-shrink: 0;
    transition: transform var(--erp-dur-fast) var(--erp-ease);
}
.module-tile:hover .module-tile-icon { transform: scale(1.05); }
.module-tile-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .15rem; }
.module-tile-title-row { display: flex; align-items: center; gap: .5rem; justify-content: space-between; }
.module-tile-title { font-weight: 600; font-size: .97rem; color: var(--erp-text); }
.module-tile-badge {
    display: inline-flex;
    align-items: center;
    padding: .15rem .5rem;
    font-size: .72rem;
    font-weight: 600;
    background: var(--erp-primary-50);
    color: var(--erp-primary);
    border-radius: 999px;
    line-height: 1;
}
.module-tile-desc { font-size: .82rem; color: var(--erp-text-muted); white-space: normal; line-height: 1.4; }
.module-tile-chevron {
    color: var(--erp-text-soft);
    font-size: .95rem;
    flex-shrink: 0;
    transition: transform var(--erp-dur-fast) var(--erp-ease), color var(--erp-dur-fast) var(--erp-ease);
}
.module-tile:hover .module-tile-chevron { color: var(--erp-primary); transform: translateX(3px); }
html[dir="rtl"] .module-tile:hover .module-tile-chevron { transform: translateX(-3px); }

/* =========== Topbar =========== */
.topbar-toggle {
    background: transparent;
    border: 0;
    color: var(--erp-text-muted);
    font-size: 1.2rem;
    padding: .4rem .55rem;
    border-radius: var(--erp-radius-sm);
    cursor: pointer;
    transition: background var(--erp-dur-fast) var(--erp-ease), color var(--erp-dur-fast) var(--erp-ease);
}
.topbar-toggle:hover { background: var(--erp-surface-2); color: var(--erp-text); }

.breadcrumb-bar {
    display: flex;
    align-items: center;
    gap: .45rem;
    color: var(--erp-text-muted);
    font-size: .9rem;
}
.breadcrumb-bar .crumb {
    color: var(--erp-text-muted);
    padding: .15rem .15rem;
    transition: color var(--erp-dur-fast) var(--erp-ease);
}
.breadcrumb-bar a.crumb:hover { color: var(--erp-primary); }
.breadcrumb-bar .crumb.current { color: var(--erp-text); font-weight: 600; }
.breadcrumb-bar .sep { color: var(--erp-text-soft); font-size: .75rem; }

.topbar-right {
    margin-inline-start: auto;
    display: flex;
    align-items: center;
    gap: .5rem;
}

.topbar-btn {
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--erp-radius-sm);
    padding: .4rem .7rem;
    color: var(--erp-text-muted);
    font-size: .88rem;
    font-weight: 500;
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    cursor: pointer;
    transition: background var(--erp-dur-fast) var(--erp-ease),
                color var(--erp-dur-fast) var(--erp-ease),
                border-color var(--erp-dur-fast) var(--erp-ease);
}
.topbar-btn:hover { background: var(--erp-surface-2); color: var(--erp-text); border-color: var(--erp-border); }

.license-pill {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .28rem .7rem;
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 600;
    letter-spacing: -0.005em;
    border: 1px solid transparent;
}
.license-pill.ok {
    background: var(--erp-success-50);
    color: #047857;
    border-color: rgba(22, 163, 74, 0.15);
}
.license-pill.warn {
    background: var(--erp-warning-50);
    color: #9a5b11;
    border-color: rgba(217, 119, 6, 0.18);
}
.license-pill.err {
    background: var(--erp-danger-50);
    color: #b91c1c;
    border-color: rgba(220, 38, 38, 0.18);
}

/* The licence pill is a button now (icon + popover), so it needs the button
   reset the span never did. Same size and colours as before — only the text
   is gone, and only while the licence is healthy. */
.license-pill-btn {
    font: inherit;
    font-size: .78rem;
    font-weight: 600;
    cursor: pointer;
    line-height: 1;
}
.license-pill-btn:focus-visible {
    outline: 2px solid var(--erp-primary);
    outline-offset: 2px;
}
.license-pill-text { white-space: nowrap; }

.user-chip {
    display: inline-flex;
    align-items: center;
    gap: .55rem;
    padding: .25rem .7rem .25rem .25rem;
    border-radius: 999px;
    background: var(--erp-surface-2);
    border: 1px solid var(--erp-border);
    font-size: .88rem;
    font-weight: 500;
    transition: border-color var(--erp-dur-fast) var(--erp-ease);
}
html[dir="rtl"] .user-chip { padding: .25rem .25rem .25rem .7rem; }
.user-chip:hover { border-color: var(--erp-border-strong); }
.user-chip .avatar {
    width: 28px; height: 28px; border-radius: 50%;
    background: linear-gradient(135deg, #3b82f6, #6366f1 60%, #8b5cf6);
    color: #fff; font-weight: 700; font-size: .8rem;
    display: grid; place-items: center;
    box-shadow: 0 2px 6px rgba(99, 102, 241, 0.35);
}

/* =========== Banners =========== */
.license-banner {
    background: var(--erp-warning-50);
    border: 1px solid rgba(217, 119, 6, 0.2);
    border-radius: var(--erp-radius-sm);
    color: #9a5b11;
    padding: .7rem 1rem;
    font-size: .88rem;
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: .55rem;
}
.license-banner.error {
    background: var(--erp-danger-50);
    border-color: rgba(220, 38, 38, 0.2);
    color: #b91c1c;
}

/* =========== Page header =========== */
.page-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.25rem;
    flex-wrap: wrap;
}
.page-header .page-title {
    font-size: 1.5rem;
    font-weight: 700;
    margin: 0;
    color: var(--erp-text);
    letter-spacing: -0.015em;
}
.page-header .page-subtitle {
    color: var(--erp-text-muted);
    font-size: .9rem;
    margin-top: .25rem;
}

/* =========== Cards =========== */
.data-card {
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    box-shadow: var(--erp-shadow-xs);
    transition: box-shadow var(--erp-dur) var(--erp-ease);
}
.data-card:hover { box-shadow: var(--erp-shadow-sm); }
.data-card .data-card-header {
    padding: .95rem 1.15rem;
    border-bottom: 1px solid var(--erp-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
}
.data-card .data-card-header h5,
.data-card .data-card-header h6 {
    margin: 0;
    font-size: .98rem;
    font-weight: 600;
    letter-spacing: -0.005em;
}
.data-card .data-card-body { padding: 1.15rem; }
.data-card .data-card-body.p-0 { padding: 0; }

/* =========== KPI tiles =========== */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 1.1rem;
    margin-bottom: 1.5rem;
}
.kpi-tile {
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    padding: 1.15rem 1.3rem;
    box-shadow: var(--erp-shadow-xs);
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    position: relative;
    overflow: hidden;
    transition: transform var(--erp-dur-fast) var(--erp-ease),
                box-shadow var(--erp-dur) var(--erp-ease),
                border-color var(--erp-dur-fast) var(--erp-ease);
}
.kpi-tile::before {
    content: "";
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    width: 3px;
    height: 100%;
    background: var(--kpi-accent, var(--erp-primary));
    border-start-start-radius: var(--erp-radius);
    border-end-start-radius: var(--erp-radius);
}
.kpi-tile:hover {
    transform: translateY(-2px);
    box-shadow: var(--erp-shadow);
    border-color: var(--erp-border-strong);
}
a.kpi-link, a.kpi-link:hover { text-decoration: none; color: inherit; }
a.kpi-link { cursor: pointer; }
.kpi-tile .kpi-icon {
    width: 44px; height: 44px;
    border-radius: 12px;
    display: grid; place-items: center;
    font-size: 1.2rem;
    flex-shrink: 0;
    background: var(--kpi-bg, var(--erp-primary-50));
    color: var(--kpi-accent, var(--erp-primary));
    transition: transform var(--erp-dur-fast) var(--erp-ease);
}
.kpi-tile:hover .kpi-icon { transform: scale(1.06) rotate(-3deg); }
.kpi-tile .kpi-label {
    color: var(--erp-text-muted);
    font-size: .82rem;
    font-weight: 500;
    letter-spacing: .005em;
}
.kpi-tile .kpi-value {
    font-size: 1.7rem;
    font-weight: 700;
    line-height: 1.1;
    margin-top: .2rem;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    color: var(--erp-text);
}
.kpi-tile .kpi-sub {
    color: var(--erp-text-muted);
    font-size: .78rem;
    margin-top: .3rem;
}
.kpi-tile.kpi-primary { --kpi-accent: var(--erp-primary); --kpi-bg: var(--erp-primary-50); }
.kpi-tile.kpi-success { --kpi-accent: var(--erp-success); --kpi-bg: var(--erp-success-50); }
.kpi-tile.kpi-warning { --kpi-accent: var(--erp-warning); --kpi-bg: var(--erp-warning-50); }
.kpi-tile.kpi-danger  { --kpi-accent: var(--erp-danger);  --kpi-bg: var(--erp-danger-50); }
.kpi-tile.kpi-info    { --kpi-accent: var(--erp-info);    --kpi-bg: var(--erp-info-50); }

/* =========== Module chips (dashboard quick-access) =========== */
.module-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: .85rem;
}
.module-chip {
    display: flex;
    align-items: center;
    gap: .8rem;
    padding: .85rem .95rem;
    border-radius: var(--erp-radius);
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    text-decoration: none;
    color: var(--erp-text);
    position: relative;
    overflow: hidden;
    transition: border-color var(--erp-dur-fast) var(--erp-ease),
                box-shadow var(--erp-dur) var(--erp-ease),
                transform var(--erp-dur-fast) var(--erp-ease),
                background var(--erp-dur-fast) var(--erp-ease);
}
.module-chip:hover {
    border-color: var(--erp-primary);
    box-shadow: var(--erp-shadow);
    color: var(--erp-text);
    transform: translateY(-1px);
}
.module-chip:active { transform: translateY(0); box-shadow: var(--erp-shadow-xs); }
.module-chip.is-locked { opacity: .62; pointer-events: none; background: var(--erp-surface-2); }
.module-chip .chip-icon {
    width: 40px; height: 40px;
    display: grid; place-items: center;
    border-radius: 10px;
    background: var(--erp-primary-50);
    color: var(--erp-primary);
    font-size: 1.1rem;
    flex-shrink: 0;
    transition: transform var(--erp-dur-fast) var(--erp-ease);
}
.module-chip:hover .chip-icon { transform: scale(1.08); }
.module-chip .chip-title { font-weight: 600; font-size: .93rem; letter-spacing: -0.005em; }
.module-chip .chip-sub { color: var(--erp-text-muted); font-size: .78rem; margin-top: .15rem; line-height: 1.35; }
.module-chip .chip-lock { margin-inline-start: auto; color: var(--erp-text-soft); }

/* =========== Statement filter chips =========== */
/* Period presets and document-type narrowing on the account-statement screens. Rows of
   small buttons rather than more <select>s: the accountant is choosing between five known
   periods, and a chip shows the current one without being opened. */
.statement-filters { display: flex; flex-direction: column; gap: .5rem; }
.statement-filters .filter-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem;
}
.statement-filters .filter-label {
    font-size: .78rem;
    font-weight: 600;
    color: var(--erp-text-muted);
    min-width: 5rem;
}
.statement-filters .filter-count {
    display: inline-block;
    margin-inline-start: .35rem;
    padding: .05rem .4rem;
    border-radius: 999px;
    font-size: .7rem;
    font-weight: 600;
    line-height: 1.5;
    background: rgba(15, 23, 42, .08);
    font-variant-numeric: tabular-nums;
}
.statement-filters .btn-primary .filter-count { background: rgba(255, 255, 255, .25); }

/* =========== Activity list =========== */
.activity-list { list-style: none; margin: 0; padding: 0; }
.activity-list li {
    display: flex;
    align-items: flex-start;
    gap: .8rem;
    padding: .85rem 1.15rem;
    border-bottom: 1px solid var(--erp-border);
    transition: background var(--erp-dur-fast) var(--erp-ease);
}
.activity-list li:hover { background: var(--erp-surface-2); }
.activity-list li:last-child { border-bottom: 0; }
.activity-list .act-dot {
    width: 8px; height: 8px; border-radius: 50%;
    margin-top: .48rem;
    background: var(--erp-primary);
    flex-shrink: 0;
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}
.activity-list .act-body { flex: 1; min-width: 0; }
.activity-list .act-title { font-size: .9rem; font-weight: 500; color: var(--erp-text); }
.activity-list .act-meta { color: var(--erp-text-muted); font-size: .78rem; margin-top: .15rem; font-variant-numeric: tabular-nums; }
.activity-list .act-amount { font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* =========== Empty state =========== */
.empty-state {
    padding: 3rem 1.5rem;
    text-align: center;
    color: var(--erp-text-muted);
    font-size: .9rem;
}
.empty-state .empty-icon {
    font-size: 2.5rem;
    color: var(--erp-text-soft);
    margin-bottom: .75rem;
    opacity: .6;
}
.empty-state .empty-title {
    color: var(--erp-text);
    font-weight: 600;
    font-size: 1rem;
    margin-bottom: .3rem;
}

/* =========== Tables =========== */
.data-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin: 0;
}
.data-table thead th {
    background: var(--erp-surface-2);
    color: var(--erp-text-muted);
    font-weight: 600;
    font-size: .74rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    padding: .75rem 1rem;
    border-bottom: 1px solid var(--erp-border);
    white-space: nowrap;
    text-align: start;
}
.data-table tbody td {
    padding: .85rem 1rem;
    border-bottom: 1px solid var(--erp-border);
    vertical-align: middle;
    font-size: .9rem;
}
.data-table tbody tr { transition: background var(--erp-dur-fast) var(--erp-ease); }
.data-table tbody tr:hover td { background: var(--erp-surface-2); }
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table .cell-numeric { text-align: end; font-variant-numeric: tabular-nums; }
.data-table .cell-actions { text-align: end; white-space: nowrap; }
.data-table .row-primary { font-weight: 600; color: var(--erp-text); }
.data-table .row-muted { color: var(--erp-text-muted); font-size: .82rem; }

/* Bootstrap table polish (for unmigrated pages still using .table) */
.table { color: var(--erp-text); }
.table thead th {
    background: var(--erp-surface-2);
    color: var(--erp-text-muted);
    font-weight: 600;
    font-size: .78rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    border-bottom-color: var(--erp-border);
}
.table > :not(caption) > * > * { border-bottom-color: var(--erp-border); }
.table-striped > tbody > tr:nth-of-type(odd) > * { background: var(--erp-surface-2); color: var(--erp-text); }
.table-hover > tbody > tr:hover > * { background: var(--erp-surface-3); color: var(--erp-text); }

.status-pill {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .2rem .65rem;
    border-radius: 999px;
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: 0;
    border: 1px solid transparent;
}
.status-pill.on { background: var(--erp-success-50); color: #047857; border-color: rgba(22,163,74,.15); }
.status-pill.off { background: var(--erp-surface-3); color: #64748b; border-color: var(--erp-border); }
.status-pill.warn { background: var(--erp-warning-50); color: #9a5b11; border-color: rgba(217,119,6,.15); }

/* =========== Filter bar =========== */
.filter-bar {
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    padding: .85rem .95rem;
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: .7rem;
    flex-wrap: wrap;
    box-shadow: var(--erp-shadow-xs);
}
.filter-bar .search-input {
    position: relative;
    flex: 1 1 300px;
    max-width: 440px;
}
.filter-bar .search-input input {
    padding-inline-start: 2.4rem;
}
.filter-bar .search-input .bi-search {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: .85rem;
    transform: translateY(-50%);
    color: var(--erp-text-soft);
    pointer-events: none;
}

/* =========== Pagination =========== */
.pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: .75rem 1rem;
    border-top: 1px solid var(--erp-border);
    color: var(--erp-text-muted);
    font-size: .85rem;
}
.pager .pages { display: inline-flex; gap: .3rem; }
.pager .page-btn {
    min-width: 34px; height: 34px;
    border-radius: var(--erp-radius-sm);
    border: 1px solid var(--erp-border);
    background: var(--erp-surface);
    color: var(--erp-text);
    display: inline-grid; place-items: center;
    padding: 0 .6rem;
    text-decoration: none;
    font-size: .85rem;
    font-weight: 500;
    transition: all var(--erp-dur-fast) var(--erp-ease);
}
.pager .page-btn:hover { background: var(--erp-surface-2); border-color: var(--erp-border-strong); }
.pager .page-btn.current {
    background: var(--erp-primary);
    border-color: var(--erp-primary);
    color: #fff;
    box-shadow: 0 2px 6px rgba(37, 99, 235, 0.3);
}
.pager .page-btn.disabled { opacity: .4; pointer-events: none; }

/* =========== Forms =========== */
.form-section {
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    padding: 1.5rem;
    box-shadow: var(--erp-shadow-xs);
}
.form-section + .form-section { margin-top: 1rem; }
.form-section-title {
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--erp-text-muted);
    margin-bottom: 1rem;
    padding-bottom: .6rem;
    border-bottom: 1px solid var(--erp-border);
}
.form-control, .form-select {
    border-color: var(--erp-border-strong);
    border-radius: var(--erp-radius-sm);
    font-size: .9rem;
    padding: .5rem .75rem;
    transition: border-color var(--erp-dur-fast) var(--erp-ease),
                box-shadow var(--erp-dur-fast) var(--erp-ease);
}
.form-control:focus, .form-select:focus {
    border-color: var(--erp-primary);
    box-shadow: var(--erp-ring);
}
.form-control.is-invalid, .form-select.is-invalid {
    border-color: var(--erp-danger);
}
.form-control.is-invalid:focus, .form-select.is-invalid:focus {
    box-shadow: var(--erp-ring-danger);
}
.form-label {
    font-size: .82rem;
    font-weight: 600;
    color: var(--erp-text);
    margin-bottom: .35rem;
    letter-spacing: -0.005em;
}
.form-hint { color: var(--erp-text-muted); font-size: .76rem; margin-top: .25rem; }
.form-actions {
    display: flex;
    justify-content: flex-end;
    gap: .55rem;
    margin-top: 1.25rem;
}

/* =========== Buttons =========== */
.btn {
    border-radius: var(--erp-radius-sm);
    font-weight: 500;
    font-size: .88rem;
    padding: .5rem .95rem;
    transition: background var(--erp-dur-fast) var(--erp-ease),
                border-color var(--erp-dur-fast) var(--erp-ease),
                color var(--erp-dur-fast) var(--erp-ease),
                box-shadow var(--erp-dur-fast) var(--erp-ease),
                transform var(--erp-dur-fast) var(--erp-ease);
}
.btn:active { transform: translateY(1px); }
.btn:focus-visible { box-shadow: var(--erp-ring); outline: none; }
.btn-sm { padding: .3rem .65rem; font-size: .82rem; }
.btn-lg { padding: .7rem 1.3rem; font-size: .95rem; }

.btn-primary {
    background: var(--erp-primary);
    border-color: var(--erp-primary);
    box-shadow: 0 1px 2px rgba(37, 99, 235, 0.15);
}
.btn-primary:hover, .btn-primary:focus {
    background: var(--erp-primary-600);
    border-color: var(--erp-primary-600);
    box-shadow: 0 4px 12px rgba(37, 99, 235, 0.28);
}
.btn-primary:active {
    background: var(--erp-primary-700);
    border-color: var(--erp-primary-700);
}
.btn-soft {
    background: var(--erp-surface-2);
    border: 1px solid var(--erp-border);
    color: var(--erp-text);
}
.btn-soft:hover {
    background: var(--erp-surface-3);
    border-color: var(--erp-border-strong);
    color: var(--erp-text);
}

/* =========== Misc utility =========== */
.text-money { font-variant-numeric: tabular-nums; font-weight: 600; }
.text-money.neg { color: var(--erp-danger); }
.text-money.pos { color: var(--erp-success); }

.divider-v { width: 1px; height: 24px; background: var(--erp-border); }

/* =========== Skeleton loaders =========== */
.skeleton {
    display: inline-block;
    background: linear-gradient(90deg,
        var(--erp-surface-3) 25%,
        var(--erp-surface-2) 50%,
        var(--erp-surface-3) 75%);
    background-size: 200% 100%;
    animation: erp-skeleton-shimmer 1.4s linear infinite;
    border-radius: var(--erp-radius-xs);
}
.skeleton-text { height: .9em; width: 100%; }
.skeleton-title { height: 1.4em; width: 60%; }
.skeleton-circle { border-radius: 50%; }

@keyframes erp-skeleton-shimmer {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* =========== Alerts (top-of-page toasts) =========== */
.alert { border-radius: var(--erp-radius-sm); padding: .7rem 1rem; font-size: .9rem; border-width: 1px; }
.alert-success { background: var(--erp-success-50); color: #047857; border-color: rgba(22,163,74,.2); }
.alert-danger { background: var(--erp-danger-50); color: #b91c1c; border-color: rgba(220,38,38,.2); }
.alert-warning { background: var(--erp-warning-50); color: #9a5b11; border-color: rgba(217,119,6,.2); }
.alert-info { background: var(--erp-info-50); color: #0e7490; border-color: rgba(8,145,178,.2); }

/* =========== Mobile =========== */
@media (max-width: 900px) {
    .app-shell,
    .app-shell.sidebar-collapsed {
        grid-template-columns: 1fr;
    }
    .app-main { padding: 1rem; min-width: 0; }
    .app-sidebar {
        position: fixed;
        inset-block-start: 0;
        inset-inline-start: 0;
        width: var(--erp-sidebar-w);
        transform: translateX(-100%);
        transition: transform var(--erp-dur) var(--erp-ease);
        box-shadow: var(--erp-shadow-lg);
    }
    html[dir="rtl"] .app-sidebar { transform: translateX(100%); }
    .app-shell.sidebar-open .app-sidebar { transform: translateX(0); }

    /* When drawer is open on mobile, force full-width labels regardless of persisted collapsed state */
    .app-shell.sidebar-open.sidebar-collapsed .sidebar-brand .brand-text,
    .app-shell.sidebar-open.sidebar-collapsed .nav-group-label,
    .app-shell.sidebar-open.sidebar-collapsed .nav-item-link .nav-text,
    .app-shell.sidebar-open.sidebar-collapsed .nav-item-link .nav-badge,
    .app-shell.sidebar-open.sidebar-collapsed .sidebar-footer { display: block; }
    .app-shell.sidebar-open.sidebar-collapsed .nav-module-toggle,
    .app-shell.sidebar-open.sidebar-collapsed .nav-module-sub { display: block; }
    .app-shell.sidebar-open.sidebar-collapsed .nav-item-link { justify-content: flex-start; padding: .55rem .85rem; }
    .app-shell.sidebar-open.sidebar-collapsed .sidebar-brand { padding: 0 1rem; justify-content: flex-start; }
    .app-shell.sidebar-open::after {
        content: "";
        position: fixed; inset: 0;
        background: rgba(15, 23, 42, 0.45);
        backdrop-filter: blur(2px);
        z-index: 25;
    }
    .page-header { margin-bottom: 1rem; }
    .page-header .page-title { font-size: 1.25rem; }

    /* Topbar compact layout */
    .app-topbar {
        padding: 0 .5rem;
        gap: .25rem;
        min-width: 0;
    }
    .app-topbar .dropdown-menu {
        min-width: min(340px, calc(100vw - 16px)) !important;
        max-width: calc(100vw - 16px);
    }
    .topbar-toggle { padding: .35rem .45rem; font-size: 1.15rem; }
    .breadcrumb-bar {
        min-width: 0;
        overflow: hidden;
        white-space: nowrap;
        font-size: .82rem;
        gap: .25rem;
        flex: 1 1 auto;
    }
    .breadcrumb-bar .crumb {
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 40vw;
    }
    .breadcrumb-bar .crumb:not(.current):not(:last-of-type) { display: none; }
    .breadcrumb-bar .sep:not(:last-of-type) { display: none; }
    .topbar-right {
        gap: .15rem;
        flex-shrink: 0;
    }
    .topbar-right .divider-v { display: none; }
    .topbar-btn {
        padding: .35rem .45rem;
        font-size: .85rem;
    }
    .license-pill {
        padding: .3rem .45rem;
        gap: 0;
        font-size: 0;
    }
    .license-pill i { font-size: .9rem; }
    .user-chip { padding: .22rem; }
    .user-chip .avatar { width: 26px; height: 26px; font-size: .75rem; }
    .user-chip.dropdown-toggle::after { display: none; }
    .dropdown-toggle::after { margin-inline-start: .15rem; }
}

/* Extra-narrow phones */
@media (max-width: 480px) {
    .app-topbar { padding: 0 .35rem; }
    .breadcrumb-bar { font-size: .78rem; }
    .breadcrumb-bar .crumb { max-width: 32vw; }
    #themeToggle { display: none; }
    .topbar-btn { padding: .3rem .35rem; }
    .dropdown-toggle::after { display: none; }
}

/* =========== Dark theme =========== */
:root[data-theme="dark"] {
    --erp-bg: #0a1020;
    --erp-surface: #111a2e;
    --erp-surface-2: #0e1528;
    --erp-surface-3: #1a2540;
    --erp-border: #1f2a44;
    --erp-border-strong: #2a3860;

    --erp-text: #e6ecf7;
    --erp-text-muted: #9aa5bf;
    --erp-text-soft: #6b7491;

    --erp-brand: #070b18;
    --erp-brand-2: #141c33;
    --erp-brand-3: #1e2a47;
    --erp-brand-contrast: #c9d3ee;
    --erp-brand-accent: #60a5fa;

    --erp-primary: #3b82f6;
    --erp-primary-600: #60a5fa;
    --erp-primary-700: #93c5fd;
    --erp-primary-50: rgba(59, 130, 246, .15);
    --erp-primary-100: rgba(59, 130, 246, .28);

    --erp-success: #22c55e;
    --erp-success-50: rgba(34, 197, 94, .14);
    --erp-warning: #f59e0b;
    --erp-warning-50: rgba(245, 158, 11, .14);
    --erp-danger: #ef4444;
    --erp-danger-50: rgba(239, 68, 68, .14);
    --erp-info: #22d3ee;
    --erp-info-50: rgba(34, 211, 238, .14);

    /* Lifted, not reused. The light gold is a dark ink on white; on a near-black
       surface it reads as brown, so dark gets its own pair. */
    --erp-gold: #d9b74a;
    --erp-gold-lite: #f0d68a;

    --erp-shadow-xs: 0 1px 2px rgba(0,0,0,.35);
    --erp-shadow-sm: 0 1px 2px rgba(0,0,0,.4), 0 1px 3px rgba(0,0,0,.35);
    --erp-shadow: 0 2px 6px rgba(0,0,0,.4), 0 8px 18px rgba(0,0,0,.35);
    --erp-shadow-lg: 0 10px 30px rgba(0,0,0,.55);

    --erp-ring: 0 0 0 3px rgba(96, 165, 250, 0.28);
    --erp-ring-danger: 0 0 0 3px rgba(239, 68, 68, 0.28);

    color-scheme: dark;
}

:root[data-theme="dark"] .app-topbar {
    background: rgba(17, 26, 46, 0.82);
}
:root[data-theme="dark"] .license-pill.ok { color: #4ade80; border-color: rgba(34,197,94,.25); }
:root[data-theme="dark"] .license-pill.warn { color: #fbbf24; border-color: rgba(245,158,11,.25); }
:root[data-theme="dark"] .license-pill.err { color: #f87171; border-color: rgba(239,68,68,.25); }
:root[data-theme="dark"] .status-pill.on { color: #4ade80; border-color: rgba(34,197,94,.25); }
:root[data-theme="dark"] .status-pill.off { background: var(--erp-surface-3); color: #9aa5bf; }
:root[data-theme="dark"] .status-pill.warn { color: #fbbf24; border-color: rgba(245,158,11,.25); }

:root[data-theme="dark"] .license-banner { color: #fbbf24; border-color: rgba(245,158,11,.25); background: rgba(245,158,11,.08); }
:root[data-theme="dark"] .license-banner.error { color: #f87171; border-color: rgba(239,68,68,.25); background: rgba(239,68,68,.08); }

/* Bootstrap's .table-light hard-codes a light background AND near-black text via
   --bs-table-color. In dark mode our surfaces stay dark, so those rows rendered as
   black-on-dark and were effectively unreadable — it is used for the opening/closing
   and total rows on the AR/AP statements, agings, reconciliations, the account ledger
   and the ESS attendance calendar. Re-point Bootstrap's own table variables at the
   theme tokens so every one of those rows follows the active theme. */
:root[data-theme="dark"] .table-light,
:root[data-theme="dark"] .data-table .table-light,
:root[data-theme="dark"] .data-table tfoot.table-light th,
:root[data-theme="dark"] .data-table tfoot.table-light td,
:root[data-theme="dark"] .data-table tr.table-light th,
:root[data-theme="dark"] .data-table tr.table-light td {
    --bs-table-bg: var(--erp-surface-3);
    --bs-table-color: var(--erp-text);
    --bs-table-border-color: var(--erp-border);
    background-color: var(--erp-surface-3);
    color: var(--erp-text);
}

/* Hover must not re-assert the light background over a summary row. */
:root[data-theme="dark"] .data-table tbody tr.table-light:hover td {
    background-color: var(--erp-surface-3);
    color: var(--erp-text);
}

:root[data-theme="dark"] .form-control,
:root[data-theme="dark"] .form-select {
    background-color: var(--erp-surface-2);
    color: var(--erp-text);
    border-color: var(--erp-border-strong);
}
:root[data-theme="dark"] .form-control::placeholder { color: var(--erp-text-soft); }
:root[data-theme="dark"] .form-control:focus,
:root[data-theme="dark"] .form-select:focus {
    background-color: var(--erp-surface-2);
    color: var(--erp-text);
    border-color: var(--erp-primary);
    box-shadow: var(--erp-ring);
}
:root[data-theme="dark"] .form-check-input { background-color: var(--erp-surface-2); border-color: var(--erp-border-strong); }
:root[data-theme="dark"] .form-check-input:checked { background-color: var(--erp-primary); border-color: var(--erp-primary); }

:root[data-theme="dark"] .btn-soft {
    background: var(--erp-surface-2);
    border-color: var(--erp-border-strong);
    color: var(--erp-text);
}
:root[data-theme="dark"] .btn-soft:hover { background: var(--erp-surface-3); color: var(--erp-text); }

:root[data-theme="dark"] .btn-outline-secondary {
    color: var(--erp-text-muted);
    border-color: var(--erp-border-strong);
}
:root[data-theme="dark"] .btn-outline-secondary:hover {
    background: var(--erp-surface-2);
    color: var(--erp-text);
    border-color: var(--erp-border-strong);
}

:root[data-theme="dark"] .dropdown-menu {
    background-color: var(--erp-surface);
    border-color: var(--erp-border);
    color: var(--erp-text);
    box-shadow: var(--erp-shadow);
}
:root[data-theme="dark"] .dropdown-item { color: var(--erp-text); }
:root[data-theme="dark"] .dropdown-item:hover,
:root[data-theme="dark"] .dropdown-item:focus {
    background: var(--erp-surface-2);
    color: var(--erp-text);
}

:root[data-theme="dark"] .alert-success { background: rgba(34,197,94,.1); color: #4ade80; border-color: rgba(34,197,94,.25); }
:root[data-theme="dark"] .alert-danger { background: rgba(239,68,68,.1); color: #f87171; border-color: rgba(239,68,68,.25); }
:root[data-theme="dark"] .alert-warning { background: rgba(245,158,11,.1); color: #fbbf24; border-color: rgba(245,158,11,.25); }
:root[data-theme="dark"] .alert-info { background: rgba(34,211,238,.1); color: #67e8f9; border-color: rgba(34,211,238,.25); }

:root[data-theme="dark"] .text-muted { color: var(--erp-text-muted) !important; }

:root[data-theme="dark"] .sidebar-brand .brand-mark {
    box-shadow: 0 6px 14px rgba(99, 102, 241, 0.28), inset 0 1px 0 rgba(255,255,255,.15);
}

:root[data-theme="dark"] .table thead th {
    background: var(--erp-surface-2);
    color: var(--erp-text-muted);
    border-bottom-color: var(--erp-border);
}
:root[data-theme="dark"] .table,
:root[data-theme="dark"] .table td,
:root[data-theme="dark"] .table th { color: var(--erp-text); border-color: var(--erp-border); }
:root[data-theme="dark"] .table-striped > tbody > tr:nth-of-type(odd) > * {
    background: var(--erp-surface-2);
    color: var(--erp-text);
}
:root[data-theme="dark"] .table-hover > tbody > tr:hover > * {
    background: var(--erp-surface-3);
    color: var(--erp-text);
}

:root[data-theme="dark"] .user-chip { background: var(--erp-surface-2); border-color: var(--erp-border-strong); color: var(--erp-text); }

:root[data-theme="dark"] .module-tile {
    background: var(--erp-surface);
    border-color: var(--erp-border);
}
:root[data-theme="dark"] .statement-filters .filter-count { background: rgba(255, 255, 255, .10); }

:root[data-theme="dark"] .module-compact {
    background: var(--erp-surface);
    border-color: var(--erp-border);
}
:root[data-theme="dark"] .module-compact:hover { background: var(--erp-surface-3); }
:root[data-theme="dark"] .module-chip {
    background: var(--erp-surface);
    border-color: var(--erp-border);
    color: var(--erp-text);
}
:root[data-theme="dark"] .module-chip.is-locked { background: var(--erp-surface-2); }

:root[data-theme="dark"] .pager .page-btn {
    background: var(--erp-surface-2);
    border-color: var(--erp-border-strong);
    color: var(--erp-text);
}
:root[data-theme="dark"] .pager .page-btn:hover { background: var(--erp-surface-3); }

/* Reduced motion */
/* The global reduced-motion guard used to sit here. It now lives at the very END of this
   file — see the note there. Moving it was not cosmetic: it has to outrank every animation
   declared after it, and by this point in the file there are over a thousand lines of them. */

/* =========================================================
   ═══ POLISH LAYER — animations, gradients, interactivity ═══
   Phase: Professional UI polish (Phase H)
   ========================================================= */

/* ---------- Keyframes ---------- */
@keyframes erp-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes erp-fade-in-up {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes erp-fade-in-down {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes erp-slide-in-right {
    from { opacity: 0; transform: translateX(12px); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes erp-slide-in-left {
    from { opacity: 0; transform: translateX(-12px); }
    to   { opacity: 1; transform: translateX(0); }
}
@keyframes erp-pulse-ring {
    0%   { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.35); }
    70%  { box-shadow: 0 0 0 10px rgba(37, 99, 235, 0); }
    100% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0); }
}
@keyframes erp-shimmer-bg {
    0%   { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}
@keyframes erp-pop {
    0%   { transform: scale(.92); opacity: 0; }
    60%  { transform: scale(1.02); opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
}
@keyframes erp-spin {
    to { transform: rotate(360deg); }
}
@keyframes erp-bell-ring {
    0%, 100% { transform: rotate(0); }
    15%      { transform: rotate(-12deg); }
    30%      { transform: rotate(10deg); }
    45%      { transform: rotate(-8deg); }
    60%      { transform: rotate(6deg); }
    75%      { transform: rotate(-3deg); }
}

/* ---------- Utility animation classes ---------- */
.erp-animate-fade        { animation: erp-fade-in var(--erp-dur-slow) var(--erp-ease) both; }
.erp-animate-fade-up     { animation: erp-fade-in-up var(--erp-dur-slow) var(--erp-ease) both; }
.erp-animate-fade-down   { animation: erp-fade-in-down var(--erp-dur-slow) var(--erp-ease) both; }
.erp-animate-slide-right { animation: erp-slide-in-right var(--erp-dur-slow) var(--erp-ease) both; }
.erp-animate-pop         { animation: erp-pop .35s var(--erp-ease) both; }

/* Stagger delays for lists/grids */
.erp-stagger > *:nth-child(1)  { animation-delay: .02s; }
.erp-stagger > *:nth-child(2)  { animation-delay: .06s; }
.erp-stagger > *:nth-child(3)  { animation-delay: .10s; }
.erp-stagger > *:nth-child(4)  { animation-delay: .14s; }
.erp-stagger > *:nth-child(5)  { animation-delay: .18s; }
.erp-stagger > *:nth-child(6)  { animation-delay: .22s; }
.erp-stagger > *:nth-child(7)  { animation-delay: .26s; }
.erp-stagger > *:nth-child(8)  { animation-delay: .30s; }
.erp-stagger > *:nth-child(9)  { animation-delay: .34s; }
.erp-stagger > *:nth-child(10) { animation-delay: .38s; }
.erp-stagger > *:nth-child(11) { animation-delay: .42s; }
.erp-stagger > *:nth-child(12) { animation-delay: .46s; }

/* ---------- KPI tiles — gradient, glow, animated counter ---------- */
.kpi-grid { animation: erp-fade-in var(--erp-dur-slow) var(--erp-ease) both; }

.kpi-tile {
    background-image:
        radial-gradient(circle at 100% 0%, color-mix(in srgb, var(--kpi-accent, var(--erp-primary)) 10%, transparent), transparent 55%),
        linear-gradient(180deg, var(--erp-surface) 0%, var(--erp-surface) 100%);
    animation: erp-fade-in-up var(--erp-dur-slow) var(--erp-ease) both;
    transition: transform var(--erp-dur) var(--erp-ease),
                box-shadow var(--erp-dur) var(--erp-ease),
                border-color var(--erp-dur) var(--erp-ease);
}
.kpi-tile::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(115deg, transparent 40%, rgba(255,255,255,.35) 50%, transparent 60%);
    background-size: 200% 100%;
    background-position: -200% 0;
    opacity: 0;
    transition: opacity var(--erp-dur-slow) var(--erp-ease);
    border-radius: inherit;
    mix-blend-mode: overlay;
}
.kpi-tile:hover::after {
    opacity: 1;
    animation: erp-shimmer-bg 1.2s var(--erp-ease);
}
.kpi-tile:hover {
    transform: translateY(-3px);
    box-shadow: var(--erp-shadow-lg);
    border-color: color-mix(in srgb, var(--kpi-accent, var(--erp-primary)) 35%, var(--erp-border));
}
.kpi-tile .kpi-icon {
    background: linear-gradient(135deg,
        color-mix(in srgb, var(--kpi-accent, var(--erp-primary)) 100%, transparent) 0%,
        color-mix(in srgb, var(--kpi-accent, var(--erp-primary)) 70%, #ffffff) 100%);
    color: #fff;
    box-shadow: 0 4px 12px color-mix(in srgb, var(--kpi-accent, var(--erp-primary)) 35%, transparent);
}
.kpi-tile .kpi-value {
    font-feature-settings: "tnum" 1;
    background: linear-gradient(180deg, var(--erp-text) 0%, color-mix(in srgb, var(--kpi-accent, var(--erp-primary)) 40%, var(--erp-text)) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* Trend indicator inside KPI */
.kpi-trend {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    font-size: .72rem;
    font-weight: 600;
    padding: .08rem .4rem;
    border-radius: 999px;
    margin-inline-start: .4rem;
    line-height: 1.4;
}
.kpi-trend.up   { color: var(--erp-success); background: var(--erp-success-50); }
.kpi-trend.down { color: var(--erp-danger);  background: var(--erp-danger-50); }
.kpi-trend.flat { color: var(--erp-text-muted); background: var(--erp-surface-3); }

/* ---------- Data cards — top accent stripe, hover lift ---------- */
.data-card {
    position: relative;
    overflow: hidden;
    animation: erp-fade-in-up var(--erp-dur-slow) var(--erp-ease) both;
    transition: transform var(--erp-dur) var(--erp-ease),
                box-shadow var(--erp-dur) var(--erp-ease);
}
.data-card::before {
    content: '';
    position: absolute;
    top: 0;
    inset-inline-start: 0;
    inset-inline-end: 0;
    height: 2px;
    background: linear-gradient(90deg,
        var(--erp-primary) 0%,
        color-mix(in srgb, var(--erp-primary) 50%, var(--erp-info)) 50%,
        var(--erp-info) 100%);
    opacity: 0;
    transition: opacity var(--erp-dur) var(--erp-ease);
}
.data-card:hover::before { opacity: 1; }
.data-card:hover { transform: translateY(-2px); box-shadow: var(--erp-shadow); }

/* Accent variants for special cards */
.data-card.accent-success::before { background: linear-gradient(90deg, var(--erp-success), #34d399); opacity: 1; }
.data-card.accent-warning::before { background: linear-gradient(90deg, var(--erp-warning), #fbbf24); opacity: 1; }
.data-card.accent-danger::before  { background: linear-gradient(90deg, var(--erp-danger), #f87171); opacity: 1; }
.data-card.accent-info::before    { background: linear-gradient(90deg, var(--erp-info), #38bdf8); opacity: 1; }

/* ---------- Page header — gradient halo, title fade ---------- */
.page-header {
    position: relative;
    animation: erp-fade-in-down var(--erp-dur-slow) var(--erp-ease) both;
}
.page-header .page-title {
    background: linear-gradient(120deg, var(--erp-text) 0%, var(--erp-primary) 180%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* ---------- Info-help button + popover ---------- */
.erp-info-btn {
    --info-size: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--info-size);
    height: var(--info-size);
    padding: 0;
    border: 0;
    background: linear-gradient(135deg, var(--erp-primary) 0%, var(--erp-primary-600) 100%);
    color: #fff;
    border-radius: 999px;
    cursor: help;
    box-shadow: 0 2px 6px rgba(37, 99, 235, .35), inset 0 0 0 2px rgba(255, 255, 255, .2);
    transition: transform var(--erp-dur) var(--erp-ease),
                box-shadow var(--erp-dur) var(--erp-ease),
                background var(--erp-dur) var(--erp-ease);
    line-height: 1;
    margin-inline-start: .5rem;
    vertical-align: middle;
    position: relative;
    top: -2px;
}
.erp-info-btn i { font-size: 17px; }
.erp-info-btn:hover,
.erp-info-btn:focus-visible {
    outline: none;
    transform: scale(1.12);
    background: linear-gradient(135deg, var(--erp-primary-600) 0%, var(--erp-primary-700) 100%);
    box-shadow: 0 4px 12px rgba(37, 99, 235, .5), inset 0 0 0 2px rgba(255, 255, 255, .25);
    animation: erp-pulse-ring 1.2s var(--erp-ease) infinite;
}
.erp-info-btn[aria-expanded="true"] {
    background: linear-gradient(135deg, var(--erp-primary-700) 0%, var(--erp-primary) 100%);
    transform: scale(1.08);
}

/* Bootstrap popover skin (applies whenever a popover is opened) */
.popover.erp-info-popover {
    --bs-popover-max-width: 320px;
    --bs-popover-bg: var(--erp-surface);
    --bs-popover-border-color: var(--erp-border-strong);
    --bs-popover-header-bg: var(--erp-primary-50);
    --bs-popover-header-color: var(--erp-primary-700);
    border-radius: var(--erp-radius);
    box-shadow: var(--erp-shadow-lg);
    animation: erp-pop .25s var(--erp-ease) both;
}
.popover.erp-info-popover .popover-header {
    border-radius: var(--erp-radius) var(--erp-radius) 0 0;
    font-weight: 600;
    font-size: .88rem;
}
.popover.erp-info-popover .popover-body {
    font-size: .82rem;
    line-height: 1.55;
    color: var(--erp-text);
}
.popover.erp-info-popover .popover-body ul,
.popover.erp-info-popover .popover-body ol {
    padding-inline-start: 1.1rem;
    margin-bottom: 0;
}
.popover.erp-info-popover .popover-body li + li { margin-top: .22rem; }
.popover.erp-info-popover .popover-body strong { color: var(--erp-primary-700); }

/* ---------- Buttons — subtle gradient + shine on hover ---------- */
.btn-primary {
    background: linear-gradient(135deg, var(--erp-primary) 0%, var(--erp-primary-600) 100%);
    border-color: transparent;
    box-shadow: 0 1px 2px rgba(37,99,235,.25), 0 4px 12px rgba(37,99,235,.15);
    transition: transform var(--erp-dur) var(--erp-ease),
                box-shadow var(--erp-dur) var(--erp-ease),
                filter var(--erp-dur) var(--erp-ease);
}
.btn-primary:hover:not(:disabled),
.btn-primary:focus:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 2px 4px rgba(37,99,235,.35), 0 8px 20px rgba(37,99,235,.25);
    filter: brightness(1.05);
    border-color: transparent;
}
.btn-primary:active:not(:disabled) {
    transform: translateY(0);
    filter: brightness(.95);
}

.btn-success {
    background: linear-gradient(135deg, var(--erp-success) 0%, #15803d 100%);
    border-color: transparent;
}
.btn-danger {
    background: linear-gradient(135deg, var(--erp-danger) 0%, #b91c1c 100%);
    border-color: transparent;
}
.btn-warning {
    background: linear-gradient(135deg, #f59e0b 0%, var(--erp-warning) 100%);
    border-color: transparent;
    color: #fff;
}
.btn-info {
    background: linear-gradient(135deg, var(--erp-info) 0%, #0e7490 100%);
    border-color: transparent;
    color: #fff;
}

/* Subtle button ripple on press (pure CSS) */
.btn {
    position: relative;
    overflow: hidden;
}
.btn .erp-ripple {
    position: absolute;
    border-radius: 50%;
    transform: scale(0);
    animation: erp-ripple-expand .55s linear;
    background: rgba(255,255,255,.45);
    pointer-events: none;
}
@keyframes erp-ripple-expand {
    to { transform: scale(3); opacity: 0; }
}

/* ---------- Activity list — slide stagger ---------- */
.activity-list li {
    animation: erp-slide-in-right var(--erp-dur-slow) var(--erp-ease) both;
    transition: background var(--erp-dur) var(--erp-ease), transform var(--erp-dur) var(--erp-ease);
}
/* The Arabic mirror, which had been missing since this stagger shipped: every row slid
   in from the left, against the reading direction, in the app's primary language. The
   erp-slide-in-left keyframe was already sitting there defined and unused. */
html[dir="rtl"] .activity-list li { animation-name: erp-slide-in-left; }
.activity-list li:hover {
    background: var(--erp-surface-2);
    transform: translateX(2px);
}
html[dir="rtl"] .activity-list li:hover { transform: translateX(-2px); }
/* The infinite pulse on every activity dot was deleted here.

   It ran forever, on every row, on the busiest page in the app. It also hard-coded
   rgba(37,99,235,…), so it never followed --erp-primary into dark mode. And because an
   animated box-shadow outranks a normal declaration, it had been quietly masking the
   static ring set on .act-dot further up — deleting it restores a style that was
   written on purpose and has been invisible ever since the polish layer landed. */

/* ---------- Module grid chips — gradient sheen on hover ---------- */
.module-grid .module-chip {
    animation: erp-fade-in-up var(--erp-dur-slow) var(--erp-ease) both;
    transition: transform var(--erp-dur) var(--erp-ease),
                box-shadow var(--erp-dur) var(--erp-ease),
                border-color var(--erp-dur) var(--erp-ease);
    position: relative;
    overflow: hidden;
}
.module-grid .module-chip::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, transparent 40%, rgba(37,99,235,.06) 50%, transparent 60%);
    background-size: 200% 100%;
    background-position: -200% 0;
    opacity: 0;
    transition: opacity var(--erp-dur) var(--erp-ease);
    pointer-events: none;
}
.module-grid .module-chip:hover::before {
    opacity: 1;
    animation: erp-shimmer-bg 1.1s var(--erp-ease);
}
.module-grid .module-chip:hover:not(.is-locked) {
    transform: translateY(-3px);
    border-color: var(--erp-primary);
    box-shadow: var(--erp-shadow);
}
.module-grid .module-chip .chip-icon {
    transition: transform var(--erp-dur) var(--erp-ease),
                background var(--erp-dur) var(--erp-ease);
}
.module-grid .module-chip:hover:not(.is-locked) .chip-icon {
    transform: rotate(-5deg) scale(1.08);
    /* The company's own accent, on the one surface the cursor is already pointing at.
       Safe here and only here: a chip carries an icon, a name and a module label and no
       figure at all, so a company themed amber or rose cannot be misread as a warning.
       The counts live in the card next to it, in semantic colour. */
    background: var(--erp-company, var(--erp-primary));
    color: #fff;
}

/* ---------- Tables — row fade, hover accent ---------- */
.table tbody tr {
    transition: background var(--erp-dur-fast) var(--erp-ease);
}
.table tbody tr td {
    transition: color var(--erp-dur-fast) var(--erp-ease);
}
.data-card .table tbody tr:hover {
    background: color-mix(in srgb, var(--erp-primary) 4%, var(--erp-surface));
}

/* ---------- Forms — focus glow ---------- */
.form-control:focus,
.form-select:focus {
    border-color: var(--erp-primary);
    box-shadow: var(--erp-ring);
}
.form-control, .form-select {
    transition: border-color var(--erp-dur) var(--erp-ease),
                box-shadow var(--erp-dur) var(--erp-ease),
                background var(--erp-dur) var(--erp-ease);
}

/* ---------- Alerts — slide + fade in ---------- */
.alert {
    animation: erp-fade-in-down var(--erp-dur-slow) var(--erp-ease) both;
    border-radius: var(--erp-radius);
    border-width: 0;
    border-inline-start-width: 4px;
    border-style: solid;
}
.alert-success { border-inline-start-color: var(--erp-success); background: var(--erp-success-50); color: #065f46; }
.alert-danger  { border-inline-start-color: var(--erp-danger);  background: var(--erp-danger-50);  color: #991b1b; }
.alert-warning { border-inline-start-color: var(--erp-warning); background: var(--erp-warning-50); color: #92400e; }
.alert-info    { border-inline-start-color: var(--erp-info);    background: var(--erp-info-50);    color: #155e75; }

/* ---------- Topbar notification bell animate when unread ---------- */
.topbar-btn .bi-bell {
    transform-origin: 50% 10%;
}
.topbar-btn:has(.badge) .bi-bell {
    animation: erp-bell-ring 2.5s var(--erp-ease) infinite;
    animation-delay: 1.5s;
}

/* ---------- Sidebar active item subtle gradient ---------- */
.app-sidebar .nav-item-link.active,
.app-sidebar .nav-item-link[aria-current="page"] {
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--erp-brand-accent) 22%, transparent) 0%,
        transparent 100%);
    position: relative;
}
.app-sidebar .nav-item-link.active::before,
.app-sidebar .nav-item-link[aria-current="page"]::before {
    content: '';
    position: absolute;
    inset-inline-start: 0;
    top: 12%;
    bottom: 12%;
    width: 3px;
    background: var(--erp-brand-accent);
    border-radius: 2px;
}

/* ---------- Chart container — rounded, subtle border ---------- */
.data-card canvas {
    animation: erp-fade-in var(--erp-dur-slow) var(--erp-ease) both;
}

/* ---------- Badges — pill polish ---------- */
.badge.rounded-pill {
    font-weight: 600;
    letter-spacing: .01em;
    padding: .32em .7em;
}

/* Bootstrap's .bg-* utilities set ONLY a background — the badge text then inherits
   whatever colour surrounds it. Inside a .page-header or a table cell that inherit is
   often a muted grey, which is why status badges read as faint or near-invisible
   blocks, in both themes. There are ~140 of these across the app (bg-secondary alone
   accounts for 100), so pin an explicit, contrasting foreground per background rather
   than editing every view.

   :not(.text-dark):not(.text-white) leaves any deliberate override in the markup alone. */
.badge.bg-primary:not(.text-dark):not(.text-white),
.badge.bg-secondary:not(.text-dark):not(.text-white),
.badge.bg-success:not(.text-dark):not(.text-white),
.badge.bg-danger:not(.text-dark):not(.text-white),
.badge.bg-dark:not(.text-dark):not(.text-white) {
    color: #ffffff;
}

/* Light backgrounds need dark text in BOTH themes — on a dark page these would
   otherwise render light-on-light and vanish completely. */
.badge.bg-warning:not(.text-dark):not(.text-white),
.badge.bg-info:not(.text-dark):not(.text-white),
.badge.bg-light:not(.text-dark):not(.text-white) {
    color: #1f2937;
}

/* bg-secondary is Bootstrap's mid grey; on a dark surface it sits too close to the
   background to read as a badge at all. Lift it so the pill has a visible edge. */
:root[data-theme="dark"] .badge.bg-secondary:not(.text-dark):not(.text-white) {
    background-color: #4b5563 !important;
    color: #f3f4f6;
}
:root[data-theme="dark"] .badge.bg-dark:not(.text-dark):not(.text-white) {
    background-color: #1f2937 !important;
    color: #e5e7eb;
    border: 1px solid var(--erp-border-strong);
}
/* .bg-light on a dark page becomes a near-white block; tone it to the surface scale
   and keep the text light so it reads as a badge rather than a paper cut-out. */
:root[data-theme="dark"] .badge.bg-light:not(.text-dark):not(.text-white) {
    background-color: var(--erp-surface-3) !important;
    color: var(--erp-text);
}

/* MVC always emits the validation-summary container, adding .validation-summary-valid
   when there is nothing to report — which rendered as an empty red bar above every
   clean form (e.g. New supplier payment). Hide it until it actually has something. */
.alert.validation-summary-valid {
    display: none;
}

/* ---------- Dark theme refinements for polish layer ---------- */
:root[data-theme="dark"] .kpi-tile {
    background-image:
        radial-gradient(circle at 100% 0%, color-mix(in srgb, var(--kpi-accent, var(--erp-primary)) 14%, transparent), transparent 55%),
        linear-gradient(180deg, var(--erp-surface) 0%, var(--erp-surface) 100%);
}
:root[data-theme="dark"] .kpi-tile::after {
    background: linear-gradient(115deg, transparent 40%, rgba(255,255,255,.05) 50%, transparent 60%);
}
:root[data-theme="dark"] .popover.erp-info-popover {
    --bs-popover-header-bg: color-mix(in srgb, var(--erp-primary) 18%, var(--erp-surface));
    --bs-popover-header-color: #fff;
}
:root[data-theme="dark"] .erp-info-btn {
    background: linear-gradient(135deg, var(--erp-primary) 0%, var(--erp-primary-600) 100%);
    color: #fff;
    box-shadow: 0 2px 8px rgba(37, 99, 235, .45), inset 0 0 0 2px rgba(255, 255, 255, .18);
}
:root[data-theme="dark"] .erp-info-btn:hover {
    background: linear-gradient(135deg, var(--erp-primary-600) 0%, var(--erp-primary-700) 100%);
    box-shadow: 0 4px 14px rgba(37, 99, 235, .55), inset 0 0 0 2px rgba(255, 255, 255, .22);
}
:root[data-theme="dark"] .alert-success { color: #6ee7b7; background: color-mix(in srgb, var(--erp-success) 12%, transparent); }
:root[data-theme="dark"] .alert-danger  { color: #fca5a5; background: color-mix(in srgb, var(--erp-danger) 12%, transparent); }
:root[data-theme="dark"] .alert-warning { color: #fcd34d; background: color-mix(in srgb, var(--erp-warning) 12%, transparent); }
:root[data-theme="dark"] .alert-info    { color: #67e8f9; background: color-mix(in srgb, var(--erp-info) 12%, transparent); }

/* =========== Modals (token skin) ===========
   Bootstrap 5.1 predates the --bs-modal-* variables and hardcodes a white
   .modal-content. In dark mode the body colour (--erp-text) is inherited into
   that white box, so every modal in the app rendered near-white-on-white. Fixed
   centrally — the same way .table-light and .badge.bg-* were — rather than per
   view, so #itemCardModal / #erpItemSearchModal / #accountPickerModal and the new
   journal-entry modal are all correct in both themes. */
.modal-content {
    background: var(--erp-surface);
    color: var(--erp-text);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius);
    box-shadow: var(--erp-shadow-lg);
}
.modal-header, .modal-footer { border-color: var(--erp-border); }
.modal-header .modal-title { color: var(--erp-text); }
.modal-body { color: var(--erp-text); }

/* .btn-close is a black SVG mask in BS 5.1 and .btn-close-white is not applied
   anywhere — invert it on dark surfaces instead of touching every markup site. */
:root[data-theme="dark"] .modal .btn-close {
    filter: invert(1) grayscale(1) brightness(2);
}

/* =========== Account combobox (erp-account-picker.js) ===========
   The real <select> stays in the DOM as the form value carrier; it is clipped
   rather than display:none so jQuery-validate still treats it as a live field. */
.erp-ap { position: relative; }

.erp-ap-native {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.erp-ap-toggle { color: var(--erp-text-muted); }
.erp-ap-toggle:hover, .erp-ap-toggle:focus-visible {
    background: var(--erp-surface-3);
    border-color: var(--erp-border-strong);
    color: var(--erp-text);
}

.erp-ap-list {
    position: fixed;
    z-index: 1080;                 /* above .modal (1055) and its backdrop (1050) */
    margin: 0;
    padding: .25rem;
    list-style: none;
    max-height: 17rem;
    overflow-y: auto;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border-strong);
    border-radius: var(--erp-radius-sm);
    box-shadow: var(--erp-shadow-lg);
}
.erp-ap-list[hidden] { display: none; }

.erp-ap-option {
    display: flex;
    gap: .5rem;
    align-items: baseline;
    padding: .32rem .5rem;
    border-radius: var(--erp-radius-xs);
    cursor: pointer;
    transition: background var(--erp-dur-fast) var(--erp-ease);
}
.erp-ap-option .erp-ap-code {
    flex: 0 0 auto;
    font-family: var(--erp-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: .82rem;
    color: var(--erp-text-muted);
}
.erp-ap-option .erp-ap-name {
    flex: 1 1 auto;
    color: var(--erp-text);
    min-width: 0;
}
.erp-ap-option:hover { background: var(--erp-surface-2); }

/* Keyboard cursor: a step on the surface ramp plus an inline-start rail, because
   the global focus style is outline-less and the list needs its own cue. */
.erp-ap-option.is-active {
    background: var(--erp-surface-3);
    box-shadow: inset 2px 0 0 var(--erp-primary);
}
html[dir="rtl"] .erp-ap-option.is-active { box-shadow: inset -2px 0 0 var(--erp-primary); }

/* The currently-committed value: a primary TINT, not solid primary. In dark mode
   the primary ramp lightens (--erp-primary becomes #3b82f6, --erp-primary-600
   #60a5fa), so the usual white-on-primary treatment measured 2.5–3.7:1 — the same
   class of dark-mode contrast bug already patched twice in this file. A tint keeps
   --erp-text as the foreground, which stays above 12:1 in BOTH themes. */
.erp-ap-option[aria-selected="true"] { background: var(--erp-primary-50); }
.erp-ap-option[aria-selected="true"] .erp-ap-name { font-weight: 600; }
.erp-ap-option[aria-selected="true"].is-active,
.erp-ap-option[aria-selected="true"]:hover {
    background: var(--erp-primary-100);
}
/* --erp-text-muted on a tinted row drops to ~4:1, under AA for this 13px code
   text, so promote it to full --erp-text once the row is highlighted. */
.erp-ap-option.is-active .erp-ap-code,
.erp-ap-option[aria-selected="true"] .erp-ap-code { color: var(--erp-text); }

/* The matched characters are the whole point of the feature, so they must not be the
   least readable thing on screen. `color: inherit` inherited --erp-text-muted from
   .erp-ap-code, which measures 4.00:1 on --erp-primary-100 — under AA for this 13px
   text. An explicit full-strength foreground measures 14.27:1 light / 9.9:1 dark. */
.erp-ap-hl {
    padding: 0;
    background: var(--erp-primary-100);
    color: var(--erp-text);
    font-weight: 600;
    border-radius: 2px;
}

.erp-ap-empty {
    padding: .5rem;
    color: var(--erp-text-muted);
    font-size: .875rem;
}

/* ============ Employee picker (erp-employee-picker.js) ============
   Its OWN classes, deliberately not .erp-ap. erp-account-picker.js is loaded on
   every authenticated page, self-activates through a MutationObserver on
   document.body, and its outside-mousedown handler treats any .erp-ap / .erp-ap-list
   ancestor as its own territory and declines to close-commit there. An employee box
   wearing those classes would therefore stop an account picker committing on the
   first screen that ever shows both. The declarations are the same; the names are
   not shared.

   Same clipping trick, and for the same reason: the real <select name="EmployeeId">
   stays in the DOM as the value carrier, clipped rather than display:none so it is
   still a live constraint-validation target. */
.erp-emp { position: relative; }

.erp-emp-native {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.erp-emp-list {
    position: fixed;
    z-index: 1080;
    margin: 0;
    padding: .25rem;
    list-style: none;
    max-height: 17rem;
    overflow-y: auto;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border-strong);
    border-radius: var(--erp-radius-sm);
    box-shadow: var(--erp-shadow-lg);
}
.erp-emp-list[hidden] { display: none; }

.erp-emp-option {
    display: flex;
    gap: .5rem;
    align-items: baseline;
    padding: .32rem .5rem;
    border-radius: var(--erp-radius-xs);
    cursor: pointer;
    transition: background var(--erp-dur-fast) var(--erp-ease);
}
.erp-emp-option .erp-emp-code {
    flex: 0 0 auto;
    font-family: var(--erp-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: .82rem;
    color: var(--erp-text-muted);
}
.erp-emp-option .erp-emp-name {
    flex: 1 1 auto;
    color: var(--erp-text);
    min-width: 0;
}
.erp-emp-option:hover { background: var(--erp-surface-2); }

.erp-emp-option.is-active {
    background: var(--erp-surface-3);
    box-shadow: inset 2px 0 0 var(--erp-primary);
}
html[dir="rtl"] .erp-emp-option.is-active { box-shadow: inset -2px 0 0 var(--erp-primary); }

.erp-emp-option[aria-selected="true"] { background: var(--erp-primary-50); }
.erp-emp-option[aria-selected="true"] .erp-emp-name { font-weight: 600; }
.erp-emp-option[aria-selected="true"].is-active,
.erp-emp-option[aria-selected="true"]:hover {
    background: var(--erp-primary-100);
}
.erp-emp-option.is-active .erp-emp-code,
.erp-emp-option[aria-selected="true"] .erp-emp-code { color: var(--erp-text); }

/* Already on a device. Not decoration: the open-enrollment index rejects a second
   one, so without this the operator spends a row to earn an error. */
.erp-emp-option .erp-emp-flag {
    flex: 0 0 auto;
    font-size: .72rem;
    padding: .05rem .35rem;
    border-radius: var(--erp-radius-xs);
    background: var(--erp-warning-100, var(--erp-surface-3));
    color: var(--erp-text);
}

.erp-emp-hl {
    padding: 0;
    background: var(--erp-primary-100);
    color: var(--erp-text);
    font-weight: 600;
    border-radius: 2px;
}

.erp-emp-empty {
    padding: .5rem;
    color: var(--erp-text-muted);
    font-size: .875rem;
}

/* The typed-but-never-committed dead end: the box has text, the select has no value.
   Said out loud on the row, because the browser would anchor its own message to the
   clipped select, which is 1px and invisible. */
.erp-emp-warn {
    display: block;
    margin-top: .15rem;
    font-size: .78rem;
    color: var(--erp-danger, #b42318);
}

/* =========== Journal-entry drill-down modal (erp-journal-modal.js) =========== */
.je-modal-body .data-card { box-shadow: none; }
.je-modal-body .je-meta-label {
    color: var(--erp-text-muted);
    font-size: .78rem;
}
.je-modal-body .je-code {
    font-family: var(--erp-font-mono);
    font-variant-numeric: tabular-nums;
}

/* =========================================================
   Attendance report — the monthly grid, the day diagnostic
   and the ranked exceptions list.

   EVERY colour below resolves through an --erp-* token, so dark
   mode needs no override block: :root[data-theme="dark"] already
   redefines all of them. Hard-coding even one hex here is the
   defect this comment exists to prevent — a grid whose "absent"
   cells are invisible on a dark screen is a grid that gets signed
   off blind.

   RTL needs no override either: the grid is a <table>, so the
   browser reverses column order for dir="rtl" on its own, and the
   sticky offsets below use inset-inline-start rather than left.
   ========================================================= */

/* Per-status cell paint. Named once, used by the grid, the legend
   and the day header, so a status cannot look like one thing in the
   grid and another on the screen it links to. */
:root {
    --erp-att-present-bg: var(--erp-success-50);
    --erp-att-present-ink: var(--erp-success);
    --erp-att-late-bg: var(--erp-warning-50);
    --erp-att-late-ink: var(--erp-warning);
    --erp-att-absent-bg: var(--erp-danger-50);
    --erp-att-absent-ink: var(--erp-danger);
    --erp-att-leave-bg: var(--erp-info-50);
    --erp-att-leave-ink: var(--erp-info);
    --erp-att-holiday-bg: var(--erp-primary-50);
    --erp-att-holiday-ink: var(--erp-primary);
    --erp-att-rest-bg: var(--erp-surface-3);
    --erp-att-rest-ink: var(--erp-text-muted);
    --erp-att-empty-ink: var(--erp-text-soft);
}

/* The existing .data-card-header styles h5/h6 only. These screens use an
   <h2> for each card so the heading order under the page's <h1> is real
   for a screen reader, and this makes an h2 look like the h6 it sits
   beside on every other screen. Sizing, not semantics. */
.data-card .data-card-title {
    margin: 0;
    font-size: .98rem;
    font-weight: 600;
    letter-spacing: -0.005em;
    display: flex;
    align-items: center;
    gap: .4rem;
}

.att-grid-scroll {
    overflow-x: auto;
    overflow-y: visible;
    /* The grid is the one table in this app that is legitimately wider
       than any screen: 31 days plus a totals strip. It scrolls inside
       its own card so the PAGE never scrolls sideways. */
    max-width: 100%;
}

.att-grid {
    border-collapse: separate;
    border-spacing: 0;
    font-size: .8rem;
    width: max-content;
    min-width: 100%;
}

.att-grid th,
.att-grid td {
    border-bottom: 1px solid var(--erp-border);
    padding: 0;
    white-space: nowrap;
}

.att-grid thead th {
    background: var(--erp-surface-2);
    color: var(--erp-text-muted);
    font-weight: 600;
    font-size: .72rem;
    padding: .4rem .3rem;
    text-align: center;
    border-bottom: 1px solid var(--erp-border-strong);
    position: sticky;
    top: 0;
    z-index: 2;
}

/* The employee column stays put while the month scrolls. Without it,
   scrolling to the 28th leaves a wall of anonymous coloured squares. */
.att-grid .att-emp {
    position: sticky;
    inset-inline-start: 0;
    z-index: 3;
    background: var(--erp-surface);
    padding: .35rem .6rem;
    text-align: start;
    min-width: 200px;
    border-inline-end: 1px solid var(--erp-border-strong);
}

.att-grid thead .att-emp {
    z-index: 4;
    background: var(--erp-surface-2);
}

.att-grid tbody tr:hover .att-emp { background: var(--erp-surface-2); }
.att-grid tbody tr:hover td { background: var(--erp-surface-2); }

.att-emp-name {
    color: var(--erp-text);
    font-weight: 600;
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 260px;
}

.att-emp-code {
    color: var(--erp-text-muted);
    font-family: var(--erp-font-mono);
    font-size: .72rem;
}

/* A holiday column is tinted so the eye can find it without reading
   every cell. */
.att-grid .att-col-off { background: var(--erp-surface-2); }
.att-grid thead th.att-col-off { color: var(--erp-text); }

.att-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    width: 30px;
    height: 30px;
    margin: 2px auto;
    border-radius: var(--erp-radius-xs);
    font-size: .7rem;
    font-weight: 700;
    text-decoration: none;
    border: 1px solid transparent;
    font-variant-numeric: tabular-nums;
}

/* THE LETTER IS NOT DECORATION. Colour alone fails for the roughly
   one man in twelve with a colour vision deficiency, fails on a
   monochrome printout, and fails at the zoom level people actually
   read a 31-column grid at. Every cell carries a one-character
   status code as well as its colour. */
.att-cell.att-p { background: var(--erp-att-present-bg); color: var(--erp-att-present-ink); }
.att-cell.att-l { background: var(--erp-att-late-bg); color: var(--erp-att-late-ink); }
.att-cell.att-a { background: var(--erp-att-absent-bg); color: var(--erp-att-absent-ink); }
.att-cell.att-o { background: var(--erp-att-leave-bg); color: var(--erp-att-leave-ink); }
.att-cell.att-h { background: var(--erp-att-holiday-bg); color: var(--erp-att-holiday-ink); }
.att-cell.att-r { background: var(--erp-att-rest-bg); color: var(--erp-att-rest-ink); }

/* NO ROW AT ALL — deliberately not blank. An empty square and a
   square nobody has written to look identical, and the difference
   between them is the difference between "present" and "nothing was
   measured". A dashed outline says "expected, missing". */
.att-cell.att-none {
    background: transparent;
    color: var(--erp-att-empty-ink);
    border: 1px dashed var(--erp-border-strong);
    font-weight: 400;
}

.att-cell:hover {
    outline: 2px solid var(--erp-primary);
    outline-offset: 1px;
}

.att-cell:focus-visible {
    outline: 2px solid var(--erp-primary);
    outline-offset: 2px;
}

/* Flag corner. A dot rather than an icon: at 30px an icon is a
   smudge, and the tooltip carries the sentence anyway. */
.att-cell .att-flag {
    position: absolute;
    top: 1px;
    inset-inline-end: 1px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
}

.att-flag-Alarm { background: var(--erp-danger); }
.att-flag-Warn { background: var(--erp-warning); }
.att-flag-Info { background: var(--erp-info); }

/* An approved day gets an underline, not another colour — the cell
   already carries a status colour and a flag dot, and a third colour
   channel in a 30px square is unreadable. */
.att-cell.att-approved { border-bottom: 3px solid var(--erp-success); }

.att-grid td.att-total {
    text-align: end;
    padding: .35rem .5rem;
    color: var(--erp-text);
    font-variant-numeric: tabular-nums;
    border-inline-start: 1px solid var(--erp-border);
}

.att-grid thead th.att-total { border-inline-start: 1px solid var(--erp-border); }
.att-grid td.att-total-strong { font-weight: 700; }

.att-grid tfoot td {
    background: var(--erp-surface-2);
    font-weight: 700;
    padding: .4rem .5rem;
    text-align: end;
    border-top: 1px solid var(--erp-border-strong);
}

/* ---------- Legend ---------- */
.att-legend {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem .9rem;
    align-items: center;
    font-size: .78rem;
    color: var(--erp-text-muted);
}

.att-legend-item { display: inline-flex; align-items: center; gap: .35rem; }

.att-legend-swatch {
    width: 18px;
    height: 18px;
    border-radius: var(--erp-radius-xs);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: .62rem;
    font-weight: 700;
    border: 1px solid transparent;
}

/* ---------- Day diagnostic ---------- */
.att-fact {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: .35rem 0;
    border-bottom: 1px dashed var(--erp-border);
}

.att-fact:last-child { border-bottom: 0; }
.att-fact-label { color: var(--erp-text-muted); font-size: .82rem; }

.att-fact-value {
    color: var(--erp-text);
    font-weight: 600;
    font-size: .85rem;
    text-align: end;
    font-variant-numeric: tabular-nums;
}

/* One decoded DERIVE_FLAGS token: what it means, then what to do. The
   Fix line is what turns this screen from a report into an
   instrument, so it is never collapsed behind a tooltip. */
.att-flag-card {
    border: 1px solid var(--erp-border);
    border-inline-start-width: 4px;
    border-radius: var(--erp-radius-sm);
    padding: .6rem .8rem;
    background: var(--erp-surface-2);
}

.att-flag-card.sev-Alarm { border-inline-start-color: var(--erp-danger); }
.att-flag-card.sev-Warn { border-inline-start-color: var(--erp-warning); }
.att-flag-card.sev-Info { border-inline-start-color: var(--erp-info); }

.att-flag-token {
    font-family: var(--erp-font-mono);
    font-size: .7rem;
    color: var(--erp-text-soft);
    letter-spacing: .02em;
}

.att-flag-means { color: var(--erp-text); font-size: .85rem; }

.att-flag-fix {
    color: var(--erp-text-muted);
    font-size: .82rem;
    margin-top: .3rem;
    display: flex;
    gap: .35rem;
}

/* A punch the aggregator did NOT count, shown beside the ones it did.
   Muted rather than hidden: an empty day with six of these is a clock
   problem, an empty day with none is an attendance problem, and no
   other screen in the product distinguishes those two. */
.att-punch-nearby td { color: var(--erp-text-muted); background: var(--erp-surface-2); }

.att-mono {
    font-family: var(--erp-font-mono);
    font-variant-numeric: tabular-nums;
}

/* ---------- Exceptions ---------- */
.att-exc {
    border: 1px solid var(--erp-border);
    border-inline-start-width: 4px;
    border-radius: var(--erp-radius);
    padding: .8rem 1rem;
    background: var(--erp-surface);
    display: flex;
    gap: 1rem;
    align-items: flex-start;
}

.att-exc.sev-Alarm { border-inline-start-color: var(--erp-danger); }
.att-exc.sev-Warn { border-inline-start-color: var(--erp-warning); }
.att-exc.sev-Info { border-inline-start-color: var(--erp-info); }

.att-exc-count {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--erp-text);
    min-width: 3.5rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.att-exc-title { font-weight: 600; color: var(--erp-text); }
.att-exc-why { color: var(--erp-text-muted); font-size: .84rem; }

.att-exc-detail {
    font-family: var(--erp-font-mono);
    font-size: .78rem;
    color: var(--erp-text);
    background: var(--erp-surface-3);
    border-radius: var(--erp-radius-xs);
    padding: .05rem .35rem;
}

/* ── Command palette trigger (topbar) ─────────────────────────────────────
   Looks like a search field because that is what it does, but it is a button:
   it opens the palette rather than accepting text in place. The shortcut is
   printed on it so the faster route is discoverable without documentation. */
.cmdp-trigger{
    display:inline-flex; align-items:center; gap:.5rem;
    padding:.34rem .6rem; border-radius:var(--erp-radius-sm);
    background:var(--erp-bg); border:1px solid var(--erp-border-strong);
    color:var(--erp-text-muted); font-size:.83rem; cursor:pointer;
    transition:border-color .18s ease, color .18s ease, background .18s ease;
}
.cmdp-trigger:hover{ border-color:var(--erp-primary); color:var(--erp-text) }
.cmdp-trigger:focus-visible{ outline:2px solid var(--erp-primary); outline-offset:2px }
.cmdp-trigger kbd{
    font-family:inherit; font-size:.68rem; padding:.08rem .3rem; border-radius:4px;
    border:1px solid var(--erp-border-strong); background:var(--erp-surface);
    color:var(--erp-text-soft);
}
.cmdp-trigger-label{ min-width:7rem; text-align:start }
/* On a narrow topbar the label and the hint go; the icon still opens it. */
@media (max-width: 1100px){ .cmdp-trigger-label, .cmdp-trigger kbd{ display:none } }

/* ══════════════════════════════════════════════════════════════════════════
   COMPANY THEME — the top bar takes the current company's colour (sql/097).

   Recognition, not decoration. Every screen looks identical in company 1 and
   company 2 while the figures on them mean completely different things, and
   the only thing saying which is a name in a chip — read once at sign-in and
   never again. A colour is recognised before it is read.

   Each theme sets ONE variable. Everything below is driven from it, so adding
   a colour means adding a single block, and every option is defined for dark
   mode too — an accent that vanished on one of the two backgrounds would be
   worse than no theme at all, because it would look deliberate.
   ══════════════════════════════════════════════════════════════════════════ */

/* The palette, defined ONCE and unconditionally. The picker's swatches need
   every colour available at the same time — inside the per-theme blocks below
   only the active company's colour would exist, and the other five dots would
   render as nothing. */
:root {
    --erp-company-emerald: #047857;
    --erp-company-teal:    #0d9488;
    --erp-company-lime:    #4d7c0f;
    --erp-company-sky:     #0284c7;
    --erp-company-indigo:  #4338ca;
    --erp-company-violet:  #7c3aed;
    --erp-company-fuchsia: #a21caf;
    --erp-company-amber:   #b45309;
    --erp-company-orange:  #ea580c;
    --erp-company-rose:    #be123c;
    --erp-company-slate:   #475569;
    --erp-company-stone:   #78716c;
}

/* Lifted for dark mode: the same hues at full saturation read as muddy against
   a dark surface, and the accent has to stay legible as text on the chip. */
:root[data-theme="dark"] {
    --erp-company-emerald: #34d399;
    --erp-company-teal:    #2dd4bf;
    --erp-company-lime:    #a3e635;
    --erp-company-sky:     #38bdf8;
    --erp-company-indigo:  #818cf8;
    --erp-company-violet:  #a78bfa;
    --erp-company-fuchsia: #e879f9;
    --erp-company-amber:   #fbbf24;
    --erp-company-orange:  #fb923c;
    --erp-company-rose:    #fb7185;
    --erp-company-slate:   #94a3b8;
    --erp-company-stone:   #a8a29e;
}

/* The active company simply aliases one of them, so light/dark is already
   handled by the two blocks above and never restated per theme. */
:root[data-company-theme="emerald"]  { --erp-company: var(--erp-company-emerald); }
:root[data-company-theme="teal"]     { --erp-company: var(--erp-company-teal); }
:root[data-company-theme="lime"]     { --erp-company: var(--erp-company-lime); }
:root[data-company-theme="sky"]      { --erp-company: var(--erp-company-sky); }
:root[data-company-theme="indigo"]   { --erp-company: var(--erp-company-indigo); }
:root[data-company-theme="violet"]   { --erp-company: var(--erp-company-violet); }
:root[data-company-theme="fuchsia"]  { --erp-company: var(--erp-company-fuchsia); }
:root[data-company-theme="amber"]    { --erp-company: var(--erp-company-amber); }
:root[data-company-theme="orange"]   { --erp-company: var(--erp-company-orange); }
:root[data-company-theme="rose"]     { --erp-company: var(--erp-company-rose); }
:root[data-company-theme="slate"]    { --erp-company: var(--erp-company-slate); }
:root[data-company-theme="stone"]    { --erp-company: var(--erp-company-stone); }

/* GUARDED against an EMPTY attribute. Razor can emit data-company-theme="" for a
   company with no theme, and a bare [data-company-theme] matches that — leaving
   --erp-company undefined, which made the bar's background and its border BOTH
   resolve to transparent. The result was a see-through top bar with page content
   scrolling underneath it, on the default configuration of every existing
   installation. The :not() is what makes "no theme" mean "unchanged". */

/* The strip. Sits under the bar rather than replacing its border, so nothing
   shifts by a pixel when a company has no theme. */
:root[data-company-theme]:not([data-company-theme=""]) .app-topbar {
    position: sticky;                 /* already sticky; restated because ::after is absolute */
    border-bottom-color: transparent;
}
:root[data-company-theme]:not([data-company-theme=""]) .app-topbar::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 3px;
    background: var(--erp-company);
}

/* A wash of the same colour, deliberately faint. The bar must still read as
   chrome; anything stronger competes with the page content for attention all
   day, which is how people learn to stop seeing it. */
:root[data-company-theme]:not([data-company-theme=""]) .app-topbar {
    background:
        linear-gradient(color-mix(in srgb, var(--erp-company) 7%, transparent),
                        color-mix(in srgb, var(--erp-company) 7%, transparent)),
        rgba(255, 255, 255, 0.9);
}
:root[data-theme="dark"][data-company-theme]:not([data-company-theme=""]) .app-topbar {
    background:
        linear-gradient(color-mix(in srgb, var(--erp-company) 12%, transparent),
                        color-mix(in srgb, var(--erp-company) 12%, transparent)),
        rgba(17, 26, 46, 0.82);
}

/* The switcher chip carries it too, so the colour and the company NAME appear
   together — that is what teaches which colour means which company. */
:root[data-company-theme]:not([data-company-theme=""]) .company-chip,
:root[data-company-theme]:not([data-company-theme=""]) .topbar-btn.company-switch {
    color: var(--erp-company);
    border-color: color-mix(in srgb, var(--erp-company) 35%, transparent);
    background: color-mix(in srgb, var(--erp-company) 10%, transparent);
}

/* Browsers without color-mix() get the strip and the chip colour, just no wash. */
@supports not (color: color-mix(in srgb, red 10%, transparent)) {
    :root[data-company-theme]:not([data-company-theme=""]) .app-topbar { background: rgba(255, 255, 255, 0.9); }
    :root[data-theme="dark"][data-company-theme]:not([data-company-theme=""]) .app-topbar { background: rgba(17, 26, 46, 0.82); }
    :root[data-company-theme]:not([data-company-theme=""]) .company-chip,
    :root[data-company-theme]:not([data-company-theme=""]) .topbar-btn.company-switch { background: transparent; }
}

/* Swatches on the picker in company settings. */
.theme-swatch-row { display: flex; flex-wrap: wrap; gap: .5rem; }
.theme-swatch {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .35rem .7rem;
    border-radius: 999px;
    border: 1.5px solid var(--erp-border);
    background: var(--erp-surface);
    cursor: pointer;
    font-size: .82rem;
    transition: border-color var(--erp-dur-fast) var(--erp-ease);
}
.theme-swatch input { position: absolute; opacity: 0; pointer-events: none; }
.theme-swatch .dot { width: .85rem; height: .85rem; border-radius: 50%; background: var(--sw); }
.theme-swatch:has(input:checked) { border-color: var(--sw, var(--erp-primary)); font-weight: 600; }
.theme-swatch:hover { border-color: var(--sw, var(--erp-primary)); }

/* ---------- Back to top ----------
   A long ledger or a year's journal entries runs to thousands of rows, and the
   filters, the export buttons and the "add" button all live at the TOP of the
   page — so reaching the bottom of a list currently means scrolling all the way
   back by hand to do anything else with it.

   Fixed to the page's inline-END corner. `inset-inline-end` rather than `right`
   so it follows direction: the app runs RTL, where the natural resting corner
   for the thumb is the left. Above the print toolbar's z-index and below any
   modal, so it neither hides behind content nor floats over a dialog. */
.back-to-top {
    position: fixed;
    inset-inline-end: 1.25rem;
    bottom: 1.25rem;
    z-index: 1030;

    width: 2.75rem;
    height: 2.75rem;
    display: grid;
    place-items: center;

    border: 1px solid var(--erp-border-strong);
    border-radius: 50%;
    background: var(--erp-surface);
    color: var(--erp-text-muted);
    box-shadow: var(--erp-shadow);
    cursor: pointer;

    /* Hidden until there is something to scroll back from. Opacity and a nudge
       rather than display:none, so it fades instead of appearing mid-scroll. */
    opacity: 0;
    transform: translateY(0.5rem);
    pointer-events: none;
    transition: opacity .18s ease, transform .18s ease, color .18s ease, border-color .18s ease;
}

.back-to-top.is-visible {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

.back-to-top:hover,
.back-to-top:focus-visible {
    color: var(--erp-primary);
    border-color: var(--erp-primary);
}

.back-to-top i { font-size: 1.1rem; line-height: 1; }

/* Never on paper, and never in the way of a print preview. */
@media print { .back-to-top { display: none !important; } }

/* Respect a user who has asked the system to stop animating things. */
@media (prefers-reduced-motion: reduce) {
    .back-to-top { transition: none; }
}

:root[data-theme="dark"] .back-to-top {
    background: var(--erp-surface-2);
    border-color: var(--erp-border-strong);
}

/* ── Account statement: rows tinted by voucher type ───────────────────────────
   The legacy كشف حساب tints its rows so the eye can group cheques and invoices
   without reading every line. Kept DELIBERATELY faint: this is a table of money
   that people read for minutes at a time, and a saturated background makes the
   figures on top of it harder to read, not easier.

   A hand-keyed journal entry gets NO class at all and stays plain. It is the
   majority of rows, and colour that appears everywhere says nothing.

   Applied with a low-alpha overlay rather than a flat colour so it composes with
   the striping and hover states already on .table rather than fighting them. */
.ledger-row-cheque   { background-color: rgba(6, 182, 212, .10); }   /* شيكات   */
.ledger-row-purchase { background-color: rgba(245, 158, 11, .09); }  /* مشتريات */
.ledger-row-sales    { background-color: rgba(34, 197, 94, .09); }   /* مبيعات  */
.ledger-row-payroll  { background-color: rgba(139, 92, 246, .09); }  /* رواتب   */
.ledger-row-other    { background-color: rgba(148, 163, 184, .10); } /* غير ذلك */

/* Dark mode needs MORE alpha, not less: the same overlay over a dark surface is
   nearly invisible, which would silently drop the feature for anyone using it. */
:root[data-theme="dark"] .ledger-row-cheque   { background-color: rgba(6, 182, 212, .16); }
:root[data-theme="dark"] .ledger-row-purchase { background-color: rgba(245, 158, 11, .14); }
:root[data-theme="dark"] .ledger-row-sales    { background-color: rgba(34, 197, 94, .14); }
:root[data-theme="dark"] .ledger-row-payroll  { background-color: rgba(139, 92, 246, .14); }
:root[data-theme="dark"] .ledger-row-other    { background-color: rgba(148, 163, 184, .16); }

/* On PAPER the tints go: they cost toner, and a statement is filed in black and
   white where a pale wash reads as a smudge rather than as a category. */
@media print {
    .ledger-row-cheque, .ledger-row-purchase, .ledger-row-sales,
    .ledger-row-payroll, .ledger-row-other { background-color: transparent !important; }
}


/* ═════════════════════════════════════════════════════════════════════════════
   DASHBOARD — 2026-08

   Everything the landing page needs that did not already exist. Appended at the end
   deliberately: this file already carries one "polish layer" around 1553-2035 that
   re-declares earlier rules and wins on order, so a rule edited at its original line
   can appear to have no effect. Nothing here re-declares anything above; where an
   existing component needed changing it was changed in place.

   Each class below appears exactly ONCE in this file, and a test asserts that, because
   a second declaration somewhere else is exactly how the polish layer happened.
   ═════════════════════════════════════════════════════════════════════════════ */

.erp-skip-link {
    position: absolute;
    inset-block-start: -100px;
    inset-inline-start: 1rem;
    z-index: 40;                       /* over the sidebar (30) and the topbar (20) */
    padding: .55rem 1rem;
    border-radius: var(--erp-radius-sm);
    background: var(--erp-surface);
    color: var(--erp-primary);
    font-weight: 600;
    box-shadow: var(--erp-shadow);
}
.erp-skip-link:focus { inset-block-start: .5rem; outline: 2px solid var(--erp-primary); outline-offset: 2px; }

/* ── The verdict: one sentence saying what the day looks like ──────────────── */
.verdict {
    margin: 0 0 1rem;
    padding-inline-start: .75rem;
    border-inline-start: 3px solid var(--erp-company, var(--erp-primary));
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--erp-text);
    line-height: 1.5;
}
.verdict.is-unavailable { color: var(--erp-warning); border-inline-start-color: var(--erp-warning); }
.verdict-num { font-variant-numeric: tabular-nums; }

/* A modifier, not a redeclaration: .module-grid keeps its own rules and the chips keep
   every polish-layer rule scoped to ".module-grid .module-chip". Needed because that grid
   auto-fits at a 200px minimum, and in the launcher's third-width column that resolves to
   a single column — fourteen modules became fourteen stacked rows, 1,222px tall, which
   stretched the card beside it to match and left it mostly empty. */
.module-grid.is-launcher { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .6rem; }
.module-grid.is-launcher .module-chip { padding: .6rem; }
.module-grid.is-launcher .chip-title { font-size: .82rem; }
@media (max-width: 420px) {
    .module-grid.is-launcher { grid-template-columns: 1fr; }
}

/* ── The day ribbon: fiscal period state, one line, always present ─────────── */
.day-ribbon { display: flex; align-items: center; gap: .7rem; min-height: 44px; }
.day-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--erp-text-soft); }
.day-dot.is-ok     { background: var(--erp-success); }
.day-dot.is-warn   { background: var(--erp-warning); }
.day-dot.is-danger { background: var(--erp-danger); }
.day-text { flex: 1; min-width: 0; color: var(--erp-text); }
.day-link { flex-shrink: 0; font-size: .85rem; }

/* ── يحتاج انتباهك: the rows that are actually waiting for someone ─────────── */
.needs-row {
    display: flex;
    align-items: center;
    gap: .8rem;
    flex: 1;
    min-width: 0;
    text-decoration: none;
    color: inherit;
    padding: .1rem 0;
}
.needs-row:hover { color: inherit; }

/* Its own colour, not .kpi-value's: that one is painted by a gradient with
   -webkit-text-fill-color:transparent later in the file, so any colour set on it is
   invisible. Borrowing it here would have produced a number that renders blank. */
.needs-count {
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1;
    color: var(--erp-text);
    font-variant-numeric: tabular-nums;
}

.needs-clean, .needs-footnote {
    padding: .6rem 1rem;
    font-size: .82rem;
    color: var(--erp-text-muted);
}
.needs-clean { color: var(--erp-success); }
.needs-footnote { border-top: 1px solid var(--erp-border); }

/* Scoped past BOTH the background at .activity-list .act-dot and the ring the polish
   layer stacked on it, so a severity actually shows. */
.activity-list .act-dot.is-ok     { background: var(--erp-success); }
.activity-list .act-dot.is-warn   { background: var(--erp-warning); }
.activity-list .act-dot.is-danger { background: var(--erp-danger); }

/* ── مدى الشيكات: what matures when, in and out ────────────────────────────── */
.runway { display: flex; gap: .9rem; flex-wrap: wrap; }
.runway-bucket {
    flex: 1 1 160px;
    min-width: 0;
    padding: .8rem;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius-sm);
    background: var(--erp-surface-2);
}
.runway-bucket.is-overdue { border-color: var(--erp-danger); background: var(--erp-danger-50); }
.runway-label { font-size: .78rem; font-weight: 600; color: var(--erp-text-muted); display: block; margin-bottom: .5rem; }
.runway-label:hover { color: var(--erp-primary); }
.runway-row { margin-bottom: .45rem; }
.runway-row:last-child { margin-bottom: 0; }
.runway-figure { font-size: .78rem; font-variant-numeric: tabular-nums; display: flex; justify-content: space-between; gap: .4rem; }
.runway-track { height: 6px; border-radius: 3px; background: var(--erp-surface-3); overflow: hidden; margin-top: .2rem; }
.runway-fill {
    display: block;
    height: 100%;
    border-radius: 3px;
    transform-origin: 0 50%;
    animation: erp-grow-x var(--erp-dur-slow) var(--erp-ease) both;
}
/* transform-origin has no logical keyword — `inline-start` is not valid CSS — so the
   Arabic mirror has to be written out. Without it every bar grows from the left while
   the text beside it reads right to left. */
html[dir="rtl"] .runway-fill { transform-origin: 100% 50%; }
.runway-fill.is-in  { background: var(--erp-success); }
.runway-fill.is-out { background: var(--erp-danger); }
.runway-net { margin-top: .8rem; font-size: .88rem; font-weight: 600; }

@keyframes erp-grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* ── Charts, drawn server-side as SVG ──────────────────────────────────────────
   No charting library anywhere on the page. Every one of these is a handful of rects
   and a path with numbers the server has already worked out, which means the figures
   are right on first paint, in the reader's language, with nothing to fetch. */
.chart { display: block; width: 100%; height: 92px; overflow: visible; }
.chart-tall { height: 150px; }

.chart-bar {
    fill: var(--erp-primary);
    opacity: .78;
    transition: opacity var(--erp-dur-fast) var(--erp-ease);
}
.chart-bar:hover { opacity: 1; }

/* A day with nothing in it still gets a sliver. A bar of no height is indistinguishable
   from a day the chart forgot, and the quiet days are part of what is being read. */
.chart-bar.is-zero { fill: var(--erp-text-soft); opacity: .35; }
.chart-bar.is-danger { fill: var(--erp-danger); opacity: .8; }

.chart-line {
    fill: none;
    stroke: var(--erp-warning);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
}

.chart-axis {
    display: flex;
    justify-content: space-between;
    font-size: .68rem;
    color: var(--erp-text-muted);
    margin-top: .35rem;
    font-variant-numeric: tabular-nums;
}
.chart-note { font-size: .76rem; color: var(--erp-text-muted); margin-top: .5rem; }

.chart-key { display: inline-flex; align-items: center; gap: .35rem; font-size: .74rem; color: var(--erp-text-muted); }
.key-swatch { width: 10px; height: 10px; border-radius: 2px; display: inline-block; flex-shrink: 0; }
.key-swatch.is-bar { background: var(--erp-primary); }
.key-swatch.is-line { background: var(--erp-warning); }

/* ── The share ring ───────────────────────────────────────────────────────────── */
.ring-wrap { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.ring { width: 116px; height: 116px; flex-shrink: 0; }
.ring-arc { fill: none; stroke-width: 7; }
.ring-centre { font-size: 7px; font-weight: 700; fill: var(--erp-text); }

.ring-legend { list-style: none; margin: 0; padding: 0; flex: 1; min-width: 120px; }
.ring-legend li { display: flex; align-items: center; gap: .45rem; font-size: .78rem; padding: .16rem 0; }
.ring-legend-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ring-legend-value { font-variant-numeric: tabular-nums; color: var(--erp-text-muted); }

/* ── Horizontal bars, for a handful of named quantities ───────────────────────── */
.hbars { list-style: none; margin: 0; padding: 0; }
.hbars li { margin-bottom: .7rem; }
.hbars li:last-child { margin-bottom: 0; }
.hbar-head { display: flex; justify-content: space-between; gap: .5rem; font-size: .8rem; margin-bottom: .25rem; }
.hbar-value { color: var(--erp-text-muted); font-variant-numeric: tabular-nums; }
.hbar-track { height: 8px; border-radius: 4px; background: var(--erp-surface-3); overflow: hidden; }
.hbar-fill {
    display: block;
    height: 100%;
    border-radius: 4px;
    background: var(--erp-primary);
    transform-origin: 0 50%;
    animation: erp-grow-x var(--erp-dur-slow) var(--erp-ease) both;
}
html[dir="rtl"] .hbar-fill { transform-origin: 100% 50%; }
.hbar-fill.is-warn { background: var(--erp-warning); }
.hbar-fill.is-open { background: var(--erp-info); }

.bucket-legend { list-style: none; margin: .6rem 0 0; padding: 0; font-size: .76rem; }
.bucket-legend li { display: flex; justify-content: space-between; gap: .5rem; padding: .12rem 0; color: var(--erp-text-muted); }
.bucket-value { font-variant-numeric: tabular-nums; color: var(--erp-text); font-weight: 600; }

/* The headline figure on a KPI tile. NOT .kpi-value, whose colour is painted over by a
   gradient with -webkit-text-fill-color: transparent further up this file — anything
   coloured there renders blank. */
.kpi-figure { font-variant-numeric: tabular-nums; }

.badge-draft {
    font-size: .66rem;
    padding: .05rem .35rem;
    border-radius: 999px;
    background: var(--erp-warning-50);
    color: var(--erp-warning);
    margin-inline-start: .35rem;
}

/* ── The row cursor ────────────────────────────────────────────────────────────
   For reading a ledger against the paper it came from, one line at a time.

   The fill goes on the CELLS, not on the row. Bootstrap gives every table cell its
   own background plus an inset box-shadow the width of the cell, so a colour set on
   a <tr> is painted over and never appears — measured here, even an INLINE
   background-color on the row changed nothing on screen. The voucher-type tints
   further up work only because they show through cells that are transparent, and
   the moment two backgrounds compete the cell wins. So the cursor paints where the
   paint lands.

   The outline stays on the row, where it draws one rectangle around the whole line
   rather than a box per cell. */
.table tbody tr.is-cursor > td,
.table tbody tr.is-cursor > th {
    background-color: var(--erp-primary-50);
}
.table tbody tr.is-cursor {
    outline: 2px solid var(--erp-primary);
    outline-offset: -2px;
}
:root[data-theme="dark"] .table tbody tr.is-cursor > td,
:root[data-theme="dark"] .table tbody tr.is-cursor > th {
    background-color: rgba(96, 165, 250, .20);
}
:root[data-theme="dark"] .table tbody tr.is-cursor { outline-color: var(--erp-brand-accent); }

/* The row is focusable, so it gets the browser's focus ring too. One marker is
   enough — the outline above already says where you are. */
.table tbody tr[data-row]:focus { outline: none; }
.table tbody tr[data-row]:focus-visible { outline: 2px solid var(--erp-primary); outline-offset: -2px; }

/* Room for a sticky header to not sit on top of the row being scrolled to. The
   ledger inside the voucher dialog has one; the full page does not, and this costs
   nothing where there is no sticky header. */
.table tbody tr[data-row] { scroll-margin-block: 3rem; }

/* A hint worth showing once, at the top of a long statement. */
.row-cursor-hint {
    font-size: .78rem;
    color: var(--erp-text-muted);
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    flex-wrap: wrap;
}
.row-cursor-hint kbd {
    font-size: .72rem;
    padding: .05rem .3rem;
    border-radius: 3px;
    background: var(--erp-surface-3);
    border: 1px solid var(--erp-border);
    color: var(--erp-text);
}

/* On paper the cursor means nothing — it is a reading aid for the screen, and a
   grey band across one row of a printed statement reads as a defect. */
@media print {
    .table tbody tr.is-cursor > td,
    .table tbody tr.is-cursor > th { background-color: transparent !important; }
    .table tbody tr.is-cursor { outline: none !important; }
    .row-cursor-hint { display: none !important; }
}

/* ── The one gold hairline on the page ─────────────────────────────────────── */
.data-card.accent-elts::before { background: linear-gradient(90deg, var(--erp-gold), var(--erp-gold-lite)); opacity: 1; }
html[dir="rtl"] .data-card.accent-elts::before { background: linear-gradient(-90deg, var(--erp-gold), var(--erp-gold-lite)); }

/* Repairs the blanket `outline: none` near the top of this file for the one control
   a keyboard user lands on most often here. Copies .cmdp-trigger, the single place in
   the file that already does this correctly. */
.module-chip:focus-visible {
    outline: 2px solid var(--erp-company, var(--erp-primary));
    outline-offset: 2px;
}


/* ═════════════════════════════════════════════════════════════════════════════
   REDUCED MOTION — this must stay the LAST block in the file.

   It used to sit at line 1544, ahead of roughly 1,250 lines of animation. Every
   one of those still lost to it, but only because every declaration here carries
   !important — the guard's correctness rested entirely on nobody ever writing
   `animation: … !important` further down. Last means it wins on order instead,
   and the !importants become belt to that braces.

   animation-delay is the repair. Zeroing duration alone left the delays intact,
   and the staggered entrances use `both` fill — so the reader who asked for less
   motion was pinned at opacity 0 for up to 460ms and then flashed in all at once.
   That is worse than the animation they turned off.

   Anything added below this block is not covered by it.
   ═════════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-delay: 0s !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ── Inline ITEM picker ──────────────────────────────────────────────────────
   Deliberately built on the employee picker's rules above rather than restating
   them: same list, same affordances, so two pickers on the same screen cannot
   drift apart visually. Only the class names differ, because "emp" would be a
   lie on a stock grid. */
.erp-pick-list {
    position: fixed;
    z-index: 1080;
    margin: 0;
    padding: .25rem;
    list-style: none;
    max-height: 17rem;
    overflow-y: auto;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border-strong);
    border-radius: var(--erp-radius-sm);
    box-shadow: var(--erp-shadow-lg);
}
.erp-pick-item {
    display: flex;
    gap: .5rem;
    align-items: baseline;
    padding: .32rem .5rem;
    border-radius: var(--erp-radius-xs);
    cursor: pointer;
}
.erp-pick-item .erp-pick-code {
    flex: 0 0 auto;
    font-family: var(--erp-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: .82rem;
    color: var(--erp-text-muted);
}
.erp-pick-item .erp-pick-name { flex: 1 1 auto; color: var(--erp-text); min-width: 0; }
.erp-pick-item:hover { background: var(--erp-surface-2); }
.erp-pick-item.is-armed {
    background: var(--erp-surface-3);
    box-shadow: inset 2px 0 0 var(--erp-primary);
}
html[dir="rtl"] .erp-pick-item.is-armed { box-shadow: inset -2px 0 0 var(--erp-primary); }
.erp-pick-empty { padding: .32rem .5rem; color: var(--erp-text-muted); font-size: .85rem; }
