/* ============================================================================
   EasyAccounting — Design System
   ----------------------------------------------------------------------------
   A clean, modern, professional dashboard system (Linear / Notion / Stripe
   feel) built on Near-black + Mint, with Coral as the outflow accent.

   HOW IT WORKS
   • Section 1 defines every design decision as a reusable TOKEN (CSS variable):
     color, typography, spacing, radius, shadow. Use the tokens — never raw hex.
   • Section 1 also remaps the app's legacy variables (--brand, --sidebar-active,
     --neg …) onto the new palette, so every screen adopts the system with no
     per-screen edits.
   • Section 2 is a small COMPONENT LIBRARY: Button, Card, Table, Input, Select,
     Checkbox, Modal, Dropdown, Grid, Sidebar, Topbar. Components are delivered
     two ways: net-new `.ds-*` classes AND a themed layer over the Bootstrap /
     app classes already wired to JS (.btn, .form-control, .form-select, .card,
     table.dataTable, .modal …) so nothing in the existing markup breaks.

   Loaded AFTER site.css so its tokens and overrides take precedence.
   ============================================================================ */

/* ============================================================================
   1 · TOKENS
   ============================================================================ */
:root {
    /* ---- Color · surfaces ----
       canvas is the warm neutral the app sits on; surface (white) is where the
       actual work happens, so a card always reads as raised without a shadow. */
    --ds-canvas:        #F1EFE8;   /* app background            */
    --ds-surface:       #FFFFFF;   /* cards, inputs, panels     */
    --ds-surface-2:     #F5F3EC;   /* subtle raised / hover     */
    --ds-surface-3:     #E7E3D8;

    /* ---- Color · accent (mint) ----
       --ds-accent-ink is the ONLY text colour allowed on solid mint: white on
       #3ED9A6 fails contrast, the dark green-black passes comfortably. */
    --ds-accent:        #3ED9A6;
    --ds-accent-ink:    #0B2B21;
    --ds-accent-hover:  #33C593;
    --ds-accent-active: #27A97B;
    --ds-accent-soft:   rgba(62, 217, 166, .14);   /* tinted background       */
    --ds-accent-soft-solid: #E6F9F1;               /* where opacity won't do  */
    --ds-accent-border: #A6EDD4;
    --ds-accent-ring:   rgba(62, 217, 166, .28);
    /* Mint is too light to read as text on white — links / icon glyphs use the
       deeper step instead, and keep the raw mint for fills. */
    --ds-accent-text:   #1B8B67;

    /* ---- Color · secondary (coral) · money going out, attention ---- */
    --ds-coral:         #F4633A;
    --ds-coral-ink:     #4A1B0C;
    --ds-coral-hover:   #E1552D;
    --ds-coral-soft:    rgba(244, 99, 58, .12);

    /* ---- Color · ink / text ---- */
    --ds-text:          #12181F;   /* primary text + nav        */
    --ds-text-2:        #454F5B;   /* secondary text / labels   */
    --ds-text-muted:    #78818C;   /* muted / meta              */
    --ds-text-inverse:  #FFFFFF;

    /* ---- Color · borders · hairlines only ---- */
    --ds-border:        #E4E1D8;
    --ds-border-strong: #D2CEC2;

    /* ---- Color · status ---- */
    --ds-success:       #12996E;  --ds-success-soft: #E8F7F1;  --ds-success-border: #A7E7CE;
    --ds-warning:       #C2691C;  --ds-warning-soft: #FBF1E5;  --ds-warning-border: #EDCFA8;
    --ds-danger:        #D6452A;  --ds-danger-soft:  #FBEBE7;  --ds-danger-border:  #F3C7BC;

    /* ---- Color · near-black ramp (sidebar / nav / dark blocks) ----
       Names kept as --ds-slate-* so every existing rule picks the new ramp up
       without being rewritten. */
    --ds-slate-950:     #0A0E13;
    --ds-slate-900:     #12181F;   /* sidebar / header / dark blocks */
    --ds-slate-800:     #1B222B;
    --ds-slate-700:     #2B333D;
    --ds-slate-400:     #8A919B;
    --ds-slate-300:     rgba(255, 255, 255, .55);

    /* ---- Typography ---- */
    --ds-font-sans: "Inter", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
    /* Ledger figures, invoice numbers and amounts are set in this — digits of
       equal width line up down a column, which is the whole point of a grid of
       money. Labels and prose stay sans. Applied in §7.3. */
    --ds-font-mono: "JetBrains Mono", "SFMono-Regular", ui-monospace, Menlo, Consolas, "Courier New", monospace;

    --ds-text-xs:   .75rem;    /* 12 */
    --ds-text-sm:   .8125rem;  /* 13 */
    --ds-text-base: .875rem;   /* 14 — body default */
    --ds-text-lg:   1rem;      /* 16 */
    --ds-text-xl:   1.125rem;  /* 18 */
    --ds-text-2xl:  1.375rem;  /* 22 */
    --ds-text-3xl:  1.75rem;   /* 28 */

    --ds-leading-tight: 1.25;
    --ds-leading-base:  1.5;

    --ds-weight-normal:   400;
    --ds-weight-medium:   500;
    --ds-weight-semibold: 600;
    --ds-weight-bold:     700;

    --ds-tracking-wide: .04em;   /* uppercase eyebrows / th */

    /* ---- Spacing (4px base) ---- */
    --ds-space-1: .25rem;
    --ds-space-2: .5rem;
    --ds-space-3: .75rem;
    --ds-space-4: 1rem;
    --ds-space-5: 1.25rem;
    --ds-space-6: 1.5rem;
    --ds-space-8: 2rem;
    --ds-space-10: 2.5rem;

    /* ---- Radius ---- */
    --ds-radius-sm:   6px;
    --ds-radius-md:   8px;    /* default control radius */
    --ds-radius-lg:   12px;   /* cards */
    --ds-radius-xl:   16px;
    --ds-radius-pill: 999px;

    /* ---- Shadows ----
       The system is flat: separation comes from the hairline border and the
       canvas/surface contrast, not from a drop shadow. The three in-flow steps
       are therefore `none`, and only genuinely FLOATING layers (modal, popover
       menu, Select2 list) keep a shadow — an overlay with nothing under it but
       the page it covers has no other way to say it is on top. */
    --ds-shadow-xs: none;
    --ds-shadow-sm: none;
    --ds-shadow-md: none;
    --ds-shadow-lg: 0 8px 28px rgba(18, 24, 31, .16);
    --ds-shadow-focus: 0 0 0 3px var(--ds-accent-ring);

    /* ---- Motion ---- */
    --ds-ease: .15s ease;

    /* ========================================================================
       Legacy-variable remap — retints the whole app to the new palette.
       (site.css defines these; redefining here — after it — wins.)
       ======================================================================== */
    --brand:          var(--ds-accent-text);
    --sidebar-bg:     var(--ds-slate-900);
    --sidebar-bg-2:   var(--ds-slate-800);
    --sidebar-fg:     var(--ds-slate-300);
    --sidebar-active: var(--ds-accent);
    --ink:            var(--ds-text);
    --muted:          var(--ds-text-muted);
    --line:           var(--ds-border);
    --bg:             var(--ds-canvas);
    --pos:            var(--ds-success);
    --neg:            var(--ds-danger);
}

body {
    font-family: var(--ds-font-sans);
    font-size: var(--ds-text-base);
    color: var(--ds-text);
    -webkit-font-smoothing: antialiased;
    /* Tints native form controls (select option highlight, checkbox, radio, range)
       to the ERP accent instead of the browser's default blue. */
    accent-color: var(--ds-accent);
}
/* Native <select> (short lists kept non-Select2): teal-tint the chosen/hovered option */
.form-select option:checked,
.form-select option:hover { box-shadow: 0 0 10px 100px var(--ds-accent-soft) inset; color: var(--ds-accent-active); }

/* ============================================================================
   2 · COMPONENT LIBRARY
   ============================================================================ */

/* ---------------------------------------------------------------------------
   2.1 · Button
   Net-new: .ds-btn (+ --primary / --secondary / --ghost / --danger / --success
            / --outline / --sm / --block / --icon).
   Themed:  Bootstrap .btn-* remapped to the token palette so JS-wired buttons
            (New / Save / grid actions) match without markup changes.
   --------------------------------------------------------------------------- */
.ds-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
    font-family: inherit; font-size: var(--ds-text-base); font-weight: var(--ds-weight-semibold);
    line-height: 1; white-space: nowrap; cursor: pointer;
    padding: .55rem .95rem; border: 1px solid transparent; border-radius: var(--ds-radius-md);
    color: var(--ds-text); background: var(--ds-surface);
    transition: background-color var(--ds-ease), border-color var(--ds-ease),
                color var(--ds-ease), box-shadow var(--ds-ease), transform var(--ds-ease);
    text-decoration: none;
}
.ds-btn:hover { text-decoration: none; }
.ds-btn:active { transform: translateY(1px); }
.ds-btn:focus-visible { outline: none; box-shadow: var(--ds-shadow-focus); }
.ds-btn:disabled, .ds-btn.disabled { opacity: .55; cursor: not-allowed; }
.ds-btn i { font-size: 1em; line-height: 1; }

/* Solid mint carries the dark green-black ink, here and everywhere else. */
.ds-btn--primary   { background: var(--ds-accent); border-color: var(--ds-accent); color: var(--ds-accent-ink); }
.ds-btn--primary:hover { background: var(--ds-accent-hover); border-color: var(--ds-accent-hover); color: var(--ds-accent-ink); }
.ds-btn--secondary { background: var(--ds-surface); border-color: var(--ds-border-strong); color: var(--ds-text-2); }
.ds-btn--secondary:hover { background: var(--ds-surface-2); color: var(--ds-text); }
.ds-btn--ghost     { background: transparent; border-color: transparent; color: var(--ds-text-2); }
.ds-btn--ghost:hover { background: var(--ds-surface-2); color: var(--ds-text); }
.ds-btn--outline   { background: transparent; border-color: var(--ds-accent-active); color: var(--ds-accent-text); }
.ds-btn--outline:hover { background: var(--ds-accent-soft); }
/* The dark secondary action (modal footers, "do the other thing" buttons) */
.ds-btn--dark      { background: var(--ds-slate-900); border-color: var(--ds-slate-900); color: #fff; }
.ds-btn--dark:hover { background: var(--ds-slate-800); border-color: var(--ds-slate-800); color: #fff; }
/* Coral = money leaving / needs attention. Same ink rule as mint. */
.ds-btn--coral     { background: var(--ds-coral); border-color: var(--ds-coral); color: var(--ds-coral-ink); }
.ds-btn--coral:hover { background: var(--ds-coral-hover); border-color: var(--ds-coral-hover); color: var(--ds-coral-ink); }
.ds-btn--danger    { background: var(--ds-danger); border-color: var(--ds-danger); color: #fff; }
.ds-btn--danger:hover { filter: brightness(.94); color: #fff; }
.ds-btn--success   { background: var(--ds-success); border-color: var(--ds-success); color: #fff; }
.ds-btn--success:hover { filter: brightness(.94); color: #fff; }

.ds-btn--sm    { padding: .38rem .7rem; font-size: var(--ds-text-sm); border-radius: var(--ds-radius-sm); }
.ds-btn--block { width: 100%; }
.ds-btn--icon  { padding: .4rem; width: 2rem; height: 2rem; }

/* Icon-only action button used in data-grid rows (keeps .record-view / .record-log hooks) */
.ds-icon-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem; padding: 0; border-radius: var(--ds-radius-sm);
    border: 1px solid var(--ds-border); background: var(--ds-surface); color: var(--ds-text-2);
    cursor: pointer; transition: background-color var(--ds-ease), color var(--ds-ease), border-color var(--ds-ease);
    text-decoration: none;
}
.ds-icon-btn:hover  { background: var(--ds-accent-soft); border-color: var(--ds-accent-border); color: var(--ds-accent-text); }
.ds-icon-btn--danger:hover { background: var(--ds-danger-soft); border-color: var(--ds-danger-border); color: var(--ds-danger); }
.ds-icon-btn:focus-visible { outline: none; box-shadow: var(--ds-shadow-focus); }

/* Themed Bootstrap buttons (JS-wired: New / Save / grid outline actions).
   Driven through Bootstrap's own --bs-btn-* variables rather than flat colour
   declarations, because that is the only way to reach EVERY state (hover,
   active, focus, disabled) — writing `color:` on .btn-primary alone leaves
   :hover still painting Bootstrap's white on mint. */
.btn { border-radius: var(--ds-radius-md); font-weight: var(--ds-weight-semibold); transition: all var(--ds-ease); }
.btn-sm { border-radius: var(--ds-radius-sm); }
.btn-primary {
    --bs-btn-bg: var(--ds-accent);            --bs-btn-border-color: var(--ds-accent);
    --bs-btn-color: var(--ds-accent-ink);
    --bs-btn-hover-bg: var(--ds-accent-hover); --bs-btn-hover-border-color: var(--ds-accent-hover);
    --bs-btn-hover-color: var(--ds-accent-ink);
    --bs-btn-active-bg: var(--ds-accent-active); --bs-btn-active-border-color: var(--ds-accent-active);
    --bs-btn-active-color: var(--ds-accent-ink);
    --bs-btn-disabled-bg: var(--ds-accent);    --bs-btn-disabled-border-color: var(--ds-accent);
    --bs-btn-disabled-color: var(--ds-accent-ink);
}
.btn-outline-primary {
    --bs-btn-color: var(--ds-accent-text);     --bs-btn-border-color: var(--ds-accent-active);
    --bs-btn-hover-bg: var(--ds-accent);       --bs-btn-hover-border-color: var(--ds-accent);
    --bs-btn-hover-color: var(--ds-accent-ink);
    --bs-btn-active-bg: var(--ds-accent-active); --bs-btn-active-border-color: var(--ds-accent-active);
    --bs-btn-active-color: #fff;
    --bs-btn-disabled-color: var(--ds-accent-text); --bs-btn-disabled-border-color: var(--ds-accent-border);
}
/* The dark secondary action, per the modal-footer spec (Cancel · dark · mint) */
.btn-dark {
    --bs-btn-bg: var(--ds-slate-900);          --bs-btn-border-color: var(--ds-slate-900);
    --bs-btn-hover-bg: var(--ds-slate-800);    --bs-btn-hover-border-color: var(--ds-slate-800);
    --bs-btn-active-bg: var(--ds-slate-800);   --bs-btn-active-border-color: var(--ds-slate-800);
}
.btn-check:focus + .btn, .btn:focus { box-shadow: var(--ds-shadow-focus); }

/* ---------------------------------------------------------------------------
   2.2 · Card
   --------------------------------------------------------------------------- */
.ds-card {
    background: var(--ds-surface); border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg); box-shadow: var(--ds-shadow-sm); overflow: hidden;
}
.ds-card__header {
    display: flex; align-items: center; gap: .6rem;
    padding: var(--ds-space-4) var(--ds-space-5);
    border-bottom: 1px solid var(--ds-border);
    font-size: var(--ds-text-lg); font-weight: var(--ds-weight-semibold); color: var(--ds-text);
}
.ds-card__header .ds-card__icon {
    width: 30px; height: 30px; flex: 0 0 auto; display: grid; place-items: center;
    border-radius: var(--ds-radius-sm); background: var(--ds-accent-soft); color: var(--ds-accent-text); font-size: 1rem;
}
.ds-card__body   { padding: var(--ds-space-5); }
.ds-card__footer { padding: var(--ds-space-4) var(--ds-space-5); border-top: 1px solid var(--ds-border); background: var(--ds-canvas); }

/* Themed Bootstrap card (used by the data-grid screens) */
.card { border: 1px solid var(--ds-border); border-radius: var(--ds-radius-lg); box-shadow: var(--ds-shadow-sm); }
.card-header { background: var(--ds-surface); border-bottom: 1px solid var(--ds-border); font-weight: var(--ds-weight-semibold); color: var(--ds-text); }

/* ---------------------------------------------------------------------------
   2.3 · Page header  (title + actions row)
   --------------------------------------------------------------------------- */
.ds-page-header {
    display: flex; align-items: center; justify-content: space-between; gap: var(--ds-space-4);
    margin-bottom: var(--ds-space-5); flex-wrap: wrap;
}
.ds-page-header__title { display: flex; align-items: center; gap: .6rem; margin: 0;
    font-size: var(--ds-text-2xl); font-weight: var(--ds-weight-bold); color: var(--ds-text); letter-spacing: -.01em; }
.ds-page-header__title .ds-page-header__eyebrow { display: block; font-size: var(--ds-text-xs); font-weight: var(--ds-weight-semibold);
    text-transform: uppercase; letter-spacing: var(--ds-tracking-wide); color: var(--ds-text-muted); margin-bottom: .15rem; }
.ds-page-header__actions { display: flex; align-items: center; gap: var(--ds-space-2); }

/* ---------------------------------------------------------------------------
   2.4 · Grid  (form field layout)
   --------------------------------------------------------------------------- */
.ds-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--ds-space-4); }
.ds-col-3  { grid-column: span 3; }
.ds-col-4  { grid-column: span 4; }
.ds-col-6  { grid-column: span 6; }
.ds-col-9  { grid-column: span 9; }
.ds-col-12 { grid-column: span 12; }
@media (max-width: 767.98px) {
    .ds-col-3, .ds-col-4, .ds-col-6, .ds-col-9 { grid-column: span 12; }
}

/* ---------------------------------------------------------------------------
   2.5 · Field · Input · Select
   Component = .ds-field (layout) + .ds-label + themed .form-control / .form-select
   (kept for Bootstrap validation visuals and the Select2 / cross-tab-refresh JS).
   --------------------------------------------------------------------------- */
.ds-field { display: flex; flex-direction: column; gap: .35rem; }
.ds-label { font-size: var(--ds-text-sm); font-weight: var(--ds-weight-semibold); color: var(--ds-text-2); }
.ds-label .ds-req { color: var(--ds-danger); margin-inline-start: .15rem; }
.ds-hint  { font-size: var(--ds-text-xs); color: var(--ds-text-muted); }

.form-label { font-weight: var(--ds-weight-semibold); font-size: var(--ds-text-sm); color: var(--ds-text-2); }

.form-control, .form-select {
    font-size: var(--ds-text-base); color: var(--ds-text);
    border: 1px solid var(--ds-border-strong); border-radius: var(--ds-radius-md);
    padding: .5rem .7rem; background-color: var(--ds-surface);
    transition: border-color var(--ds-ease), box-shadow var(--ds-ease);
}
.form-control::placeholder { color: var(--ds-slate-400); }
.form-control:focus, .form-select:focus {
    border-color: var(--ds-accent); box-shadow: var(--ds-shadow-focus);
}
.form-control:disabled, .form-select:disabled,
.form-control[readonly] { background-color: var(--ds-surface-2); color: var(--ds-text-muted); }
.form-control.is-invalid, .form-select.is-invalid { border-color: var(--ds-danger); }
.form-control.is-invalid:focus { box-shadow: 0 0 0 3px var(--ds-danger-soft); }

/* Select2 combobox — match the design-system control */
.select2-container--bootstrap-5 .select2-selection {
    border: 1px solid var(--ds-border-strong); border-radius: var(--ds-radius-md); min-height: calc(1.5em + .9rem + 2px);
}
.select2-container--bootstrap-5.select2-container--focus .select2-selection,
.select2-container--bootstrap-5.select2-container--open .select2-selection {
    border-color: var(--ds-accent); box-shadow: var(--ds-shadow-focus);
}
/* Option the user is hovering / arrow-keying to — solid teal */
.select2-container--bootstrap-5 .select2-results__option--highlighted,
.select2-container--bootstrap-5 .select2-results__option--highlighted[aria-selected] {
    background: var(--ds-accent) !important; color: var(--ds-accent-ink) !important;
}
/* The already-chosen option (was Bootstrap blue) — tinted teal, not blue */
.select2-container--bootstrap-5 .select2-results__option--selected,
.select2-container--bootstrap-5 .select2-results__option[aria-selected="true"] {
    background: var(--ds-accent-soft) !important; color: var(--ds-accent-active) !important; font-weight: var(--ds-weight-semibold);
}
/* …but hovering the chosen option still gives the solid teal highlight */
.select2-container--bootstrap-5 .select2-results__option--selected.select2-results__option--highlighted {
    background: var(--ds-accent) !important; color: var(--ds-accent-ink) !important;
}
/* Multi-select tags */
.select2-container--bootstrap-5 .select2-selection__choice {
    background: var(--ds-accent-soft) !important; border-color: var(--ds-accent-border) !important; color: var(--ds-accent-active) !important;
}
.select2-container--bootstrap-5 .select2-selection__choice__remove { color: var(--ds-accent-active) !important; }
.select2-container--bootstrap-5 .select2-selection__clear:hover { color: var(--ds-accent-text) !important; }
/* The open list floats over the page, so it keeps a shadow (see the token note). */
.select2-container--bootstrap-5 .select2-dropdown { box-shadow: var(--ds-shadow-lg); }
/* The search box inside the open dropdown — teal focus, not the browser's blue */
.select2-container--bootstrap-5 .select2-dropdown .select2-search__field:focus {
    border-color: var(--ds-accent) !important; box-shadow: var(--ds-shadow-focus) !important; outline: none !important;
}

/* --- Touch devices: 16px form text ----------------------------------------
   Mobile Safari zooms the whole page in whenever a control with a font under
   16px takes focus. Everything then sits somewhere other than where it was
   tapped, which is why a dropdown could look like it selected the wrong row —
   or nothing. Only coarse pointers are bumped, so desktop density is unchanged. */
@media (hover: none) and (pointer: coarse) {
    .form-control, .form-select, .select2-search__field { font-size: 16px !important; }
    .form-control, .form-select { min-height: 44px; }               /* thumb-sized targets */
    .select2-container--bootstrap-5 .select2-selection--single { display: flex; align-items: center; min-height: 44px; }
    /* The row-actions popover must not run off a short screen */
    .ds-menu { max-height: 70vh; overflow-y: auto; overscroll-behavior: contain; }
    .ds-menu__item { min-height: 44px; }
}

/* --- Touch devices: the open list is a full-screen sheet -------------------
   Select2 draws its list absolutely against the PAGE and re-positions only on
   window scroll/resize. Opening the list focuses its search box, the on-screen
   keyboard shrinks the visual viewport (iOS fires no window resize for that),
   and the list is left drawn where the field used to be — so the option under
   the finger is not the option that gets picked. Pinning the list to the
   viewport removes the drift; site.js puts .ea-s2-sheet on <html> while one is
   open and .ea-s2-sheet__box on that list's container. */
html.ea-s2-sheet, html.ea-s2-sheet body { overflow: hidden !important; }

html.ea-s2-sheet .select2-container.ea-s2-sheet__box {
    position: fixed !important;
    inset-block: 0 !important; inset-inline: 0 !important;
    top: 0 !important; left: 0 !important; right: 0 !important;
    width: 100% !important;
    height: var(--ea-vvh, 100dvh) !important;
    max-height: none !important;
    z-index: 2000 !important;                       /* over .modal (1055) + backdrop */
    display: flex !important; align-items: flex-end;
    background: rgba(15, 23, 42, .45);
}
html.ea-s2-sheet .ea-s2-sheet__box .select2-dropdown {
    position: static !important;
    width: 100% !important; max-width: 100% !important;
    max-height: 100%;
    display: flex; flex-direction: column;
    border: 0; border-radius: var(--ds-radius-lg) var(--ds-radius-lg) 0 0;
    box-shadow: 0 -12px 40px rgba(2, 6, 23, .35);
}
html.ea-s2-sheet .ea-s2-sheet__box .select2-search--dropdown { flex: 0 0 auto; padding: .55rem .75rem; }
html.ea-s2-sheet .ea-s2-sheet__box .select2-search__field { min-height: 44px; border-radius: var(--ds-radius-md); }
html.ea-s2-sheet .ea-s2-sheet__box .select2-results { flex: 1 1 auto; min-height: 0; display: flex; }
html.ea-s2-sheet .ea-s2-sheet__box .select2-results__options {
    flex: 1 1 auto; max-height: none !important;
    overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
}
html.ea-s2-sheet .ea-s2-sheet__box .select2-results__option {
    padding: .8rem .9rem; font-size: 1rem; min-height: 48px;        /* one thumb per row */
    display: flex; align-items: center;
    border-bottom: 1px solid var(--ds-border);
}

/* Sheet header: which field is being filled + a way out. Injected once per
   dropdown by site.js, so it stays in the markup on desktop — hidden there. */
.ea-s2-sheet__head { display: none; }
html.ea-s2-sheet .ea-s2-sheet__box .ea-s2-sheet__head {
    display: flex; align-items: center; gap: .5rem; flex: 0 0 auto;
    padding: .7rem .9rem; border-bottom: 1px solid var(--ds-border);
}
.ea-s2-sheet__title { font-size: var(--ds-text-lg); font-weight: var(--ds-weight-semibold); color: var(--ds-text); }
.ea-s2-sheet__close {
    margin-inline-start: auto; flex: 0 0 auto;
    width: 36px; height: 36px; border: 0; border-radius: 50%;
    background: var(--ds-surface-2); color: var(--ds-text-2);
    font-size: 1.4rem; line-height: 1;
}

/* ---------------------------------------------------------------------------
   2.6 · Checkbox
   --------------------------------------------------------------------------- */
.ds-check { display: inline-flex; align-items: center; gap: .55rem; cursor: pointer; user-select: none; }
.ds-check__label { font-size: var(--ds-text-base); color: var(--ds-text-2); }
.form-check-input { border-color: var(--ds-border-strong); cursor: pointer; }
.form-check-input:checked { background-color: var(--ds-accent); border-color: var(--ds-accent); }
.form-check-input:focus { border-color: var(--ds-accent); box-shadow: var(--ds-shadow-focus); }

/* ---------------------------------------------------------------------------
   2.7 · Table  (themes the DataTables grid used across the ERP)
   --------------------------------------------------------------------------- */
/* Flat mint rule instead of the old three-stop gradient bar. */
.card:has(.dataTable)::before { background: var(--ds-accent); height: 3px; }
table.dataTable thead th {
    background: var(--ds-surface-2);
    color: var(--ds-text-muted); border-bottom: 1px solid var(--ds-border);
    font-size: var(--ds-text-xs); text-transform: uppercase; letter-spacing: var(--ds-tracking-wide);
    font-weight: var(--ds-weight-bold);
}
table.dataTable tbody td { font-size: var(--ds-text-base); border-bottom: 1px solid var(--ds-border); }
table.dataTable tbody td:first-child { font-weight: var(--ds-weight-bold); color: var(--ds-accent-text); }
/* Flat rows: the hairline divider does the separating, so no zebra tint. */
table.dataTable tbody tr:nth-child(even) > td { background-color: transparent; }
table.dataTable.table-hover tbody tr:hover > td { background-color: var(--ds-accent-soft); }
table.dataTable thead th.sorting:before, table.dataTable thead th.sorting:after,
table.dataTable thead th.sorting_asc:before, table.dataTable thead th.sorting_asc:after,
table.dataTable thead th.sorting_desc:before, table.dataTable thead th.sorting_desc:after { color: var(--ds-accent-text); }

/* Data-grid chrome: search, segmented rows control, pagination, advanced panel */
.dataTables_wrapper .dataTables_filter input:focus { border-color: var(--ds-accent); box-shadow: var(--ds-shadow-focus); }
.ea-seg button:hover { color: var(--ds-accent-text); background: var(--ds-accent-soft); }
.ea-seg button.active { background: var(--ds-accent); color: var(--ds-accent-ink); box-shadow: none; }
.ea-adv-toggle.active { background: var(--ds-accent); border-color: var(--ds-accent); color: var(--ds-accent-ink); }
.dataTables_wrapper .pagination .page-item.active .page-link { background: var(--ds-accent); border-color: var(--ds-accent); color: var(--ds-accent-ink); }
.dataTables_wrapper .pagination .page-link:hover { background: var(--ds-accent-soft); border-color: var(--ds-accent-border); color: var(--ds-accent-text); }
.dataTables_wrapper .pagination .page-item.active .page-link:hover { color: var(--ds-accent-ink); }
.dataTables_wrapper .pagination .page-link:focus { box-shadow: var(--ds-shadow-focus); }

/* Row action group (View / Edit / Log / Delete) */
.ds-row-actions { display: inline-flex; align-items: center; gap: .3rem; }

/* Status pills (Active / Inactive …) */
.badge.bg-success   { background-color: var(--ds-success) !important; }
.badge.bg-secondary { background-color: var(--ds-slate-400) !important; }

/* ---------------------------------------------------------------------------
   2.8 · Modal  (themes the shared _RecordView / _LogView dialogs)
   --------------------------------------------------------------------------- */
.modal-content { border: 1px solid var(--ds-border); border-radius: var(--ds-radius-lg); box-shadow: var(--ds-shadow-lg); overflow: hidden; }

/* ---- Dark header bar, white title, mint icon ----
   Every dialog in the app gets it, so a modal reads the same whether it is the
   Add Item form, the record View popup or a confirmation. Written against
   .modal-header itself rather than a new class, so no view has to be touched. */
.modal-header {
    background: var(--ds-slate-900); color: #fff;
    border-bottom: 1px solid var(--ds-slate-800);
    padding: var(--ds-space-3) var(--ds-space-5);
}
.modal-header .modal-title { color: #fff; font-size: var(--ds-text-lg); font-weight: var(--ds-weight-semibold); }
.modal-header .modal-title i, .modal-header > i { color: var(--ds-accent); }
/* Bootstrap's close glyph is a black SVG; invert it for the dark bar — but not
   where the view already asked for the white one, or it would invert to black. */
.modal-header .btn-close:not(.btn-close-white) { filter: invert(1) grayscale(100%) brightness(200%); opacity: .65; }
.modal-header .btn-close:not(.btn-close-white):hover { opacity: 1; }

.modal-body   { background: var(--ds-surface); }
.modal-footer { border-top: 1px solid var(--ds-border); background: var(--ds-surface); }

/* ---------------------------------------------------------------------------
   2.9 · Dropdown  (themes Bootstrap dropdown menus)
   --------------------------------------------------------------------------- */
.dropdown-menu { border: 1px solid var(--ds-border); border-radius: var(--ds-radius-md); box-shadow: var(--ds-shadow-lg); padding: .35rem; }
.dropdown-item { border-radius: var(--ds-radius-sm); font-size: var(--ds-text-base); padding: .45rem .6rem; }
.dropdown-item:hover, .dropdown-item:focus { background: var(--ds-accent-soft); color: var(--ds-accent-active); }
.dropdown-item.active, .dropdown-item:active { background: var(--ds-accent); color: var(--ds-accent-ink); }

/* ---------------------------------------------------------------------------
   2.10 · Sidebar  (themes the app-shell nav — retinted to the slate + teal ramp)
   --------------------------------------------------------------------------- */
.sidebar .brand i { color: var(--ds-accent); }
.sidebar .brand { border-bottom: 1px solid rgba(255, 255, 255, .07); }

/* The active screen: soft mint wash + mint text and icon, per the spec. The
   3px left rule stays as the second, redundant signal (a wash alone is easy to
   miss at a glance down a long menu). */
.nav-menu .nav-link.active {
    border-left-color: var(--ds-accent);
    background: var(--ds-accent-soft);
    color: var(--ds-accent);
}
.nav-menu .nav-link.active i { color: var(--ds-accent); opacity: 1; }
.nav-menu .nav-link:hover { background: rgba(255, 255, 255, .05); color: #fff; }
.nav-menu .nav-link.active:hover { background: rgba(62, 217, 166, .2); color: var(--ds-accent); }
[dir="rtl"] .nav-menu .nav-link.active { border-right-color: var(--ds-accent); }
/* Group headings: quieter than the items they head */
.nav-section { color: rgba(255, 255, 255, .38); font-weight: var(--ds-weight-bold); }

/* ---- Nested transaction sub-menus: tree guide-rail look ----
   Replaces the old `bi-dot` marker with a Notion/Linear-style guide rail +
   node. Scoped to the transaction buckets ([data-group^="tx-"]) so the
   General Master sub-menu keeps its meaningful per-item icons.
   The item's icon is hidden here (used only for the collapsed rail + tab
   icon) and a teal-on-hover node sits on the rail instead. */
.nav-group[data-group^="tx-"] .nav-group-body { position: relative; }
.nav-group[data-group^="tx-"] .nav-group-body::before {
    content: ""; position: absolute; top: .2rem; bottom: .2rem; left: 1.78rem;
    width: 1px; background: rgba(148, 163, 184, .22);
}
.nav-menu .nav-group[data-group^="tx-"] .nav-link.nav-sublink { position: relative; }
.nav-menu .nav-group[data-group^="tx-"] .nav-link.nav-sublink i { display: none; }
.nav-menu .nav-group[data-group^="tx-"] .nav-link.nav-sublink::before {
    content: ""; position: absolute; left: calc(1.78rem - 3px); top: 50%; transform: translateY(-50%);
    width: 7px; height: 7px; border-radius: 50%; background: var(--ds-slate-700);
    box-shadow: 0 0 0 3px var(--sidebar-bg);
    transition: background-color var(--ds-ease), transform var(--ds-ease);
}
.nav-menu .nav-group[data-group^="tx-"] .nav-link.nav-sublink:hover::before { background: var(--ds-slate-400); }
.nav-menu .nav-group[data-group^="tx-"] .nav-link.nav-sublink.active::before {
    background: var(--ds-accent); transform: translateY(-50%) scale(1.15);
}
[dir="rtl"] .nav-group[data-group^="tx-"] .nav-group-body::before { left: auto; right: 1.78rem; }
[dir="rtl"] .nav-menu .nav-group[data-group^="tx-"] .nav-link.nav-sublink::before { left: auto; right: calc(1.78rem - 3px); }

/* Collapsed icon rail: drop the rail/node and restore the (bucket) icon */
@media (min-width: 992px) {
    .sidebar-collapsed .nav-group[data-group^="tx-"] .nav-group-body::before,
    .sidebar-collapsed .nav-menu .nav-group[data-group^="tx-"] .nav-link.nav-sublink::before { display: none; }
    .sidebar-collapsed .nav-menu .nav-group[data-group^="tx-"] .nav-link.nav-sublink i { display: inline; }
}

/* ---------------------------------------------------------------------------
   2.11 · Topbar  (themes the app-shell header)
   --------------------------------------------------------------------------- */
.topbar { background: var(--ds-surface); border-bottom: 1px solid var(--ds-border); }
.badge-ctx { background: var(--ds-surface-2); color: var(--ds-text-2); border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm); }
.badge-ctx i { color: var(--ds-accent-text); }
.badge-ctx-btn:hover { background: var(--ds-accent-soft); border-color: var(--ds-accent-border); color: var(--ds-accent-active); }
.ea-menu-btn:hover { background: var(--ds-accent-soft); color: var(--ds-accent-text); }

/* ---- In-app tab strip ---- */
.ea-tabbar { background: var(--ds-canvas); border-bottom: 1px solid var(--ds-border); }
.ea-tab { background: transparent; border-color: transparent; color: var(--ds-text-muted); }
.ea-tab:hover { background: var(--ds-surface-2); color: var(--ds-text); }
.ea-tab.active {
    background: var(--ds-surface); border-color: var(--ds-border); border-bottom-color: var(--ds-surface);
    color: var(--ds-text); box-shadow: inset 0 2px 0 var(--ds-accent);
}
.ea-tab .ea-tab-close:hover { background: var(--ds-surface-3); color: var(--ds-coral); }
.ea-tabs { background: var(--ds-canvas); }
.ea-tab-pane > iframe { background: var(--ds-surface); }

/* ---------------------------------------------------------------------------
   2.12 · Auth  (login / password screens)
   --------------------------------------------------------------------------- */
/* Two panels: near-black identity on the left, the form on white at the right.
   No card, no shadow, no gradient — the split IS the composition. */
.auth-body {
    display: grid; grid-template-columns: 1.05fr 1fr;
    min-height: 100vh; min-height: 100dvh;
    padding: 0; background: var(--ds-surface); place-items: stretch;
}

.auth-aside {
    background: var(--ds-slate-900); color: #fff;
    padding: var(--ds-space-10) var(--ds-space-8);
    display: flex; flex-direction: column; justify-content: space-between; gap: var(--ds-space-8);
}
.auth-aside__brand { display: flex; align-items: center; gap: .7rem; }
.auth-aside__mark {
    width: 40px; height: 40px; flex: 0 0 auto; display: grid; place-items: center;
    border-radius: var(--ds-radius-md); font-size: 1.35rem;
    background: var(--ds-accent); color: var(--ds-accent-ink);
}
.auth-aside__name { font-size: var(--ds-text-lg); font-weight: var(--ds-weight-bold); letter-spacing: -.01em; }
.auth-aside__head {
    margin: 0 0 var(--ds-space-6); max-width: 22ch;
    font-size: 2.25rem; line-height: 1.15; font-weight: var(--ds-weight-bold); letter-spacing: -.02em;
}
.auth-aside__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--ds-space-3); }
.auth-aside__list li {
    display: flex; align-items: flex-start; gap: .6rem; max-width: 34ch;
    font-size: var(--ds-text-base); color: rgba(255, 255, 255, .70);
}
.auth-aside__list i { color: var(--ds-accent); flex: 0 0 auto; margin-top: .1rem; }
.auth-aside__foot { font-size: var(--ds-text-xs); color: rgba(255, 255, 255, .38); }

.auth-panel { display: grid; place-items: center; padding: var(--ds-space-8) var(--ds-space-6); background: var(--ds-surface); }
.auth-wrap  { width: 100%; max-width: 400px; }
/* The panel is already the surface, so the card is a wrapper and nothing more. */
.auth-card  { background: transparent; border: 0; border-radius: 0; box-shadow: none; padding: 0; }

.auth-brand { padding-bottom: var(--ds-space-4); margin-bottom: var(--ds-space-5); border-bottom: 1px solid var(--ds-border); }
.auth-brand .auth-logo {
    width: 46px; height: 46px; flex: 0 0 auto; display: grid; place-items: center;
    border-radius: var(--ds-radius-md); font-size: 1.5rem;
    background: var(--ds-accent); color: var(--ds-accent-ink); box-shadow: none;
}
.auth-brand i { color: var(--ds-accent-ink); font-size: 1.5rem; }
.auth-title { font-size: var(--ds-text-xl); font-weight: var(--ds-weight-bold); color: var(--ds-text); }
.auth-sub   { font-size: var(--ds-text-sm); color: var(--ds-text-muted); }

/* Small uppercase grey field labels, per the form spec */
.auth-card .ds-label, .auth-card .form-label {
    font-size: var(--ds-text-xs); font-weight: var(--ds-weight-bold);
    text-transform: uppercase; letter-spacing: var(--ds-tracking-wide); color: var(--ds-text-muted);
}
.auth-card .ds-btn { padding: .7rem 1rem; }        /* full-width actions get some height */

.auth-links { padding-top: var(--ds-space-4); margin-top: var(--ds-space-4); border-top: 1px solid var(--ds-border); }
.auth-links a, .auth-footer a { color: var(--ds-accent-text); text-decoration: none; }
.auth-links a:hover { color: var(--ds-accent-active); text-decoration: underline; }
.auth-lang { justify-content: flex-end; }
.auth-lang a.active, .auth-lang a:hover { color: var(--ds-accent-text); }
.auth-footer { color: var(--ds-text-muted); }
.auth-footer--sm { display: none; }                /* the dark panel carries it */

/* Below 900px the identity panel is dropped — on a phone the only thing worth
   the screen is the form, and the company's own logo is already above it. */
@media (max-width: 900px) {
    .auth-body { grid-template-columns: 1fr; }
    .auth-aside { display: none; }
    .auth-panel { padding: var(--ds-space-6) var(--ds-space-4); }
    .auth-footer--sm { display: block; }
}

/* ============================================================================
   3 · DATA GRID  (Linear / Notion-style)
   ----------------------------------------------------------------------------
   Progressive enhancement over every `.datatable` grid. The JS in site.js
   injects the selection column, per-row ⋯ menu, bulk bar, toolbar controls,
   avatars and progress bars; these rules style them. All colors come from the
   grid token block below (which reuses the --ds-* tokens).
   ============================================================================ */
:root {
    --grid-canvas:       var(--ds-canvas);        /* #F1EFE8 */
    --grid-surface:      var(--ds-surface);       /* #FFFFFF */
    --grid-accent:       var(--ds-accent);        /* #3ED9A6 — fills   */
    --grid-accent-text:  var(--ds-accent-text);   /* #1B8B67 — glyphs  */
    --grid-accent-soft:  var(--ds-accent-soft);
    --grid-text:         var(--ds-text);          /* #12181F */
    --grid-secondary:    var(--ds-text-2);        /* #454F5B */
    --grid-muted:        var(--ds-text-muted);    /* #78818C */
    --grid-border:       var(--ds-border);        /* #E4E1D8 */
    --grid-success:      var(--ds-success);
    --grid-warning:      var(--ds-warning);
    --grid-danger:       var(--ds-danger);
}

/* ---- Card / sticky header ----
   The grid card must NOT be its own scroll container, otherwise the sticky
   header has nothing to stick to. Keep the top accent bar rounded instead. */
.card:has(.dataTable) { overflow: visible; }
.card:has(.dataTable)::before { border-radius: var(--ds-radius-lg) var(--ds-radius-lg) 0 0; }
.card:has(.dataTable) .card-body { border-radius: var(--ds-radius-lg); }

table.dataTable thead th {
    position: sticky; top: 0; z-index: 3; cursor: pointer;
    /* Light flat header row — no gradient, one hairline under it. */
    background: var(--ds-surface-2);
    color: var(--grid-muted); border-bottom: 1px solid var(--grid-border);
    box-shadow: 0 1px 0 var(--grid-border);
}
table.dataTable thead th.ea-sel, table.dataTable thead th.ea-act { cursor: default; }
table.dataTable thead th:hover:not(.ea-sel):not(.ea-act) { color: var(--grid-secondary); }
table.dataTable tbody tr { transition: background-color var(--ds-ease); }
table.dataTable tbody td { color: var(--grid-secondary); }
table.dataTable tbody td:first-child { color: var(--grid-secondary); font-weight: var(--ds-weight-normal); }
/* first *data* cell (after the injected selection column) reads as the row's key */
table.dataTable tbody td.ea-sel-cell + td { font-weight: var(--ds-weight-semibold); color: var(--grid-text); }
table.dataTable.table-hover tbody tr:hover > td { background-color: var(--grid-accent-soft); }
/* Amount / numeric columns: right-aligned, tabular figures */
table.dataTable td.text-end, table.dataTable th.text-end { font-variant-numeric: tabular-nums; }

/* ---- Custom checkbox (selection + select-all) ---- */
.ea-check { display: inline-flex; align-items: center; justify-content: center; cursor: pointer; position: relative; }
.ea-check input { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; }
.ea-check > span {
    width: 16px; height: 16px; border: 1.5px solid var(--ds-border-strong); border-radius: 5px;
    display: inline-block; position: relative; background: var(--grid-surface);
    transition: background-color var(--ds-ease), border-color var(--ds-ease);
}
.ea-check:hover > span { border-color: var(--grid-accent); }
.ea-check input:checked + span, .ea-check input:indeterminate + span { background: var(--grid-accent); border-color: var(--grid-accent); }
.ea-check input:checked + span::after {
    content: ""; position: absolute; left: 4.5px; top: 1px; width: 4px; height: 8px;
    border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.ea-check input:indeterminate + span::after {
    content: ""; position: absolute; left: 3px; top: 6.5px; width: 8px; height: 2px; background: #fff; border-radius: 1px;
}
.ea-check input:focus-visible + span { box-shadow: var(--ds-shadow-focus); }
table.dataTable td.ea-sel-cell, table.dataTable th.ea-sel { width: 40px; text-align: center; padding-left: 0; padding-right: 0; }

/* ---- Supplier / name initials avatar ---- */
.ds-avatar {
    width: 26px; height: 26px; flex: 0 0 auto; border-radius: 7px; display: inline-grid; place-items: center;
    font-size: .68rem; font-weight: var(--ds-weight-bold); color: #fff; letter-spacing: .02em;
    margin-inline-end: .55rem; vertical-align: middle;
}
.ds-cell-named { display: inline-flex; align-items: center; }

/* ---- Fulfillment mini progress bar ---- */
.ds-progress { display: inline-flex; align-items: center; gap: .55rem; min-width: 120px; }
.ds-progress__track { flex: 1 1 auto; height: 6px; border-radius: 999px; background: var(--ds-surface-3); overflow: hidden; min-width: 60px; }
.ds-progress__fill  { height: 100%; border-radius: 999px; background: var(--grid-accent); transition: width .3s ease; }
.ds-progress__val   { font-size: var(--ds-text-xs); font-weight: var(--ds-weight-semibold); color: var(--grid-muted); min-width: 34px; text-align: right; }
.ds-progress--done .ds-progress__fill { background: var(--grid-success); }

/* ---- Status pill with colored dot (upgrades existing .badge status cells) ---- */
.badge.bg-success, .badge.bg-secondary, .badge.bg-danger, .badge.bg-warning, .ds-pill {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .28rem .62rem; border-radius: 999px; font-size: var(--ds-text-xs); font-weight: var(--ds-weight-semibold); line-height: 1;
}
.badge.bg-success::before, .badge.bg-secondary::before, .badge.bg-danger::before,
.badge.bg-warning::before, .ds-pill::before {
    content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 auto;
}
.badge.bg-success   { background: var(--ds-success-soft) !important; color: var(--grid-success) !important; }
.badge.bg-secondary { background: var(--ds-surface-2)  !important; color: var(--grid-muted)   !important; }
.badge.bg-danger    { background: var(--ds-danger-soft)  !important; color: var(--grid-danger)  !important; }
.badge.bg-warning   { background: var(--ds-warning-soft) !important; color: var(--grid-warning) !important; }

/* ---- Per-row actions: always-visible ⋯ trigger + popover menu ---- */
.ea-act-cell > *:not(.ds-actions) { display: none !important; }   /* hide the original icon buttons; menu proxies to them */
.ds-actions { display: inline-flex; }
.ds-actions__trigger {
    display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
    border: 1px solid transparent; border-radius: var(--ds-radius-sm); background: transparent;
    color: var(--grid-muted); cursor: pointer; transition: background-color var(--ds-ease), color var(--ds-ease);
}
.ds-actions__trigger:hover, .ds-actions__trigger.open { background: var(--ds-surface-2); color: var(--grid-text); border-color: var(--grid-border); }

.ds-menu {
    position: fixed; z-index: 1090; min-width: 220px; padding: .35rem;
    background: var(--grid-surface); border: 1px solid var(--grid-border);
    border-radius: var(--ds-radius-md); box-shadow: var(--ds-shadow-lg);
    opacity: 0; transform: translateY(-4px); pointer-events: none; transition: opacity .12s ease, transform .12s ease;
}
.ds-menu.open { opacity: 1; transform: translateY(0); pointer-events: auto; }
.ds-menu__label { padding: .3rem .6rem .4rem; font-size: var(--ds-text-xs); font-weight: var(--ds-weight-semibold); color: var(--grid-muted); }
.ds-menu__item {
    display: flex; align-items: center; gap: .6rem; width: 100%; padding: .5rem .6rem;
    border: 0; background: transparent; border-radius: var(--ds-radius-sm); cursor: pointer;
    font-size: var(--ds-text-base); font-weight: var(--ds-weight-medium); color: var(--grid-text); text-align: start; text-decoration: none;
}
.ds-menu__item i:first-child { width: 16px; text-align: center; color: var(--grid-muted); font-size: 1rem; }
.ds-menu__item:hover, .ds-menu__item:focus { background: var(--grid-accent-soft); color: var(--grid-accent-text); }
.ds-menu__item:hover i:first-child, .ds-menu__item:focus i:first-child { color: var(--grid-accent-text); }
.ds-menu__item .ds-menu__key {
    margin-inline-start: auto; font-size: .68rem; font-weight: var(--ds-weight-semibold); color: var(--grid-muted);
    background: var(--ds-surface-2); border: 1px solid var(--grid-border); border-radius: 5px; padding: .1rem .35rem; min-width: 18px; text-align: center;
}
.ds-menu__divider { height: 1px; background: var(--grid-border); margin: .35rem .3rem; }
.ds-menu__item--danger { color: var(--grid-danger); }
.ds-menu__item--danger i:first-child { color: var(--grid-danger); }
.ds-menu__item--danger:hover, .ds-menu__item--danger:focus { background: var(--ds-danger-soft); color: var(--grid-danger); }
.ds-menu__item--danger:hover i:first-child { color: var(--grid-danger); }

/* ---- Bulk action bar (solid mint, appears on selection) ---- */
.ds-bulkbar {
    display: none; align-items: center; gap: .9rem; margin-bottom: .9rem;
    padding: .55rem .5rem .55rem .9rem; border-radius: var(--ds-radius-md);
    background: var(--grid-accent); color: var(--ds-accent-ink); box-shadow: none;
}
.ds-bulkbar.show { display: flex; }
.ds-bulkbar__count { font-weight: var(--ds-weight-semibold); font-size: var(--ds-text-base); }
.ds-bulkbar__count b { font-weight: var(--ds-weight-bold); }
.ds-bulkbar__spacer { margin-inline-start: auto; }
.ds-bulkbar__btn {
    display: inline-flex; align-items: center; gap: .4rem; padding: .38rem .7rem; border-radius: var(--ds-radius-sm);
    background: rgba(11, 43, 33, .10); border: 1px solid rgba(11, 43, 33, .22); color: var(--ds-accent-ink);
    font-size: var(--ds-text-sm); font-weight: var(--ds-weight-semibold); cursor: pointer; transition: background-color var(--ds-ease);
}
.ds-bulkbar__btn:hover { background: rgba(11, 43, 33, .18); color: var(--ds-accent-ink); }

/* ---- Toolbar: chips, Sort / Columns buttons, view switcher ---- */
.ds-chips { display: inline-flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.ds-chip {
    display: inline-flex; align-items: center; gap: .4rem; padding: .32rem .7rem; border-radius: var(--ds-radius-pill);
    font-size: var(--ds-text-sm); font-weight: var(--ds-weight-semibold); cursor: pointer;
    border: 1px dashed var(--ds-border-strong); background: var(--grid-surface); color: var(--grid-secondary);
    transition: all var(--ds-ease);
}
.ds-chip:hover { border-color: var(--grid-accent); color: var(--grid-accent-text); }
.ds-chip--active { border-style: solid; border-color: var(--grid-accent); background: var(--grid-accent-soft); color: var(--grid-accent-text); }
.ds-chip--active .ds-chip__x { display: inline-flex; }
.ds-chip__x { display: none; align-items: center; justify-content: center; width: 15px; height: 15px; border-radius: 50%; font-size: .9rem; line-height: 1; }
.ds-chip__x:hover { background: rgba(62, 217, 166, .28); }

.ds-tool-btn {
    display: inline-flex; align-items: center; gap: .4rem; padding: .4rem .7rem; border-radius: var(--ds-radius-md);
    border: 1px solid var(--grid-border); background: var(--grid-surface); color: var(--grid-secondary);
    font-size: var(--ds-text-sm); font-weight: var(--ds-weight-semibold); cursor: pointer; transition: all var(--ds-ease);
}
.ds-tool-btn:hover, .ds-tool-btn.open { border-color: var(--ds-border-strong); background: var(--ds-surface-2); color: var(--grid-text); }

.ds-viewswitch { display: inline-flex; padding: 3px; gap: 2px; background: var(--ds-surface-2); border: 1px solid var(--grid-border); border-radius: var(--ds-radius-md); }
.ds-viewswitch button {
    display: inline-flex; align-items: center; gap: .35rem; padding: .32rem .6rem; border: 0; border-radius: var(--ds-radius-sm);
    background: transparent; color: var(--grid-secondary); font-size: var(--ds-text-sm); font-weight: var(--ds-weight-semibold); cursor: pointer;
    transition: all var(--ds-ease);
}
.ds-viewswitch button:hover { color: var(--grid-text); }
.ds-viewswitch button.active { background: var(--grid-surface); color: var(--grid-accent-text); border: 1px solid var(--grid-border); }

/* Columns visibility dropdown (shares .ds-menu look) */
.ds-colmenu .ds-menu__item { font-weight: var(--ds-weight-medium); }
.ds-colmenu .ea-check { margin-inline-end: .1rem; }

/* Placeholder shown for the (presentational) Board / Calendar views */
.ds-view-placeholder {
    display: none; flex-direction: column; align-items: center; justify-content: center; gap: .6rem;
    padding: 3rem 1rem; text-align: center; color: var(--grid-muted);
}
.ds-view-placeholder i { font-size: 2rem; color: var(--ds-border-strong); }
.ds-view-placeholder.show { display: flex; }

/* ---- Grouped rows with subtotals (opt-in via data-group-col) ---- */
tr.ds-group-row > td {
    background: var(--grid-canvas) !important; border-top: 1px solid var(--grid-border); border-bottom: 1px solid var(--grid-border);
    padding-top: .5rem; padding-bottom: .5rem;
}
.ds-group { display: inline-flex; align-items: center; gap: .5rem; font-weight: var(--ds-weight-bold); color: var(--grid-text); font-size: var(--ds-text-sm); }
.ds-group__caret { color: var(--grid-muted); transition: transform var(--ds-ease); }
tr.ds-group-row.collapsed .ds-group__caret { transform: rotate(-90deg); }
.ds-group__meta { font-weight: var(--ds-weight-medium); color: var(--grid-muted); }
.ds-group__meta b { color: var(--grid-secondary); font-weight: var(--ds-weight-semibold); }

@media (max-width: 575px) {
    .ds-menu { min-width: 190px; }
    .ds-viewswitch button span { display: none; }
}

/* ============================================================================
   4 · DASHBOARD  (Dashboard/Index — KPI cards, trend chart, donut, activity)
   ----------------------------------------------------------------------------
   A modern analytics overview built entirely on the --ds-* tokens. Charts are
   inline SVG (no chart-library / CDN dependency); colors resolve from tokens so
   the whole surface retints with the design system.
   ============================================================================ */
.dash { display: flex; flex-direction: column; gap: var(--ds-space-5); }

/* ---- Header ---- */
.dash-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ds-space-4); flex-wrap: wrap; }
.dash-title { margin: 0; font-size: var(--ds-text-2xl); font-weight: var(--ds-weight-bold); color: var(--ds-text); letter-spacing: -.01em; }
.dash-sub { font-size: var(--ds-text-sm); color: var(--ds-text-muted); margin-top: .15rem; }
.dash-head-actions { display: flex; align-items: center; gap: var(--ds-space-2); flex-wrap: wrap; }

.dash-seg { display: inline-flex; padding: 3px; gap: 2px; background: var(--ds-surface-2); border: 1px solid var(--ds-border); border-radius: var(--ds-radius-md); }
.dash-seg button {
    border: 0; background: transparent; color: var(--ds-text-2); cursor: pointer;
    padding: .3rem .6rem; border-radius: var(--ds-radius-sm);
    font-size: var(--ds-text-sm); font-weight: var(--ds-weight-semibold); transition: all var(--ds-ease);
}
.dash-seg button:hover { color: var(--ds-text); }
.dash-seg button.active { background: var(--ds-surface); color: var(--ds-accent-text); border: 1px solid var(--ds-border); }

/* ---- KPI cards · bento ----------------------------------------------------
   Not four equal boxes: the number that matters most is bigger and solid mint,
   the supporting figures are plain white cards, and the one that is a problem
   (money owed out, stock below its level) takes coral or near-black. Reading
   order comes from weight, so the eye lands on the headline first.
   The tiles are the same .dash-kpi markup throughout — only a modifier class
   changes, so a tile can be promoted or demoted without restructuring. */
.dash-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--ds-space-4); align-items: stretch; }
.dash-kpi {
    background: var(--ds-surface); border: 1px solid var(--ds-border); border-radius: var(--ds-radius-lg);
    box-shadow: none; padding: var(--ds-space-5);
    display: flex; flex-direction: column; gap: .55rem;
    transition: border-color var(--ds-ease), background-color var(--ds-ease);
}
.dash-kpi:hover { border-color: var(--ds-border-strong); }
.dash-kpi-top { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.dash-kpi-label { font-size: var(--ds-text-xs); color: var(--ds-text-muted); font-weight: var(--ds-weight-semibold);
    text-transform: uppercase; letter-spacing: var(--ds-tracking-wide); }
.dash-kpi-ic { width: 34px; height: 34px; flex: 0 0 auto; display: grid; place-items: center; border-radius: var(--ds-radius-md); font-size: 1.05rem; }
.dash-kpi-ic--teal   { background: var(--ds-accent-soft);  color: var(--ds-accent-text); }
.dash-kpi-ic--indigo { background: var(--ds-surface-2);    color: var(--ds-text-2); }
.dash-kpi-ic--green  { background: var(--ds-success-soft); color: var(--ds-success); }
.dash-kpi-ic--rose   { background: var(--ds-coral-soft);   color: var(--ds-coral); }
.dash-kpi-val { font-size: var(--ds-text-3xl); font-weight: var(--ds-weight-bold); color: var(--ds-text); letter-spacing: -.02em; line-height: 1.1;
    font-family: var(--ds-font-mono); font-variant-numeric: tabular-nums; }

/* --- The headline tile: twice the width, solid mint, dark green-black ink --- */
.dash-kpi--hero {
    grid-column: span 2;
    background: var(--ds-accent); border-color: var(--ds-accent); color: var(--ds-accent-ink);
    justify-content: space-between;
}
.dash-kpi--hero:hover { border-color: var(--ds-accent-active); }
.dash-kpi--hero .dash-kpi-label { color: rgba(11, 43, 33, .72); }
.dash-kpi--hero .dash-kpi-val   { color: var(--ds-accent-ink); font-size: 2.75rem; }
.dash-kpi--hero .dash-kpi-hint  { color: rgba(11, 43, 33, .70); }
.dash-kpi--hero .dash-kpi-ic    { background: rgba(11, 43, 33, .12); color: var(--ds-accent-ink); }
.dash-kpi--hero .dash-delta     { background: rgba(11, 43, 33, .12); color: var(--ds-accent-ink); }
.dash-kpi--hero .dash-kpi-pill  { background: rgba(11, 43, 33, .12); color: var(--ds-accent-ink); }

/* --- Attention tiles: coral for money going out, near-black for a shortfall --- */
.dash-kpi--coral {
    background: var(--ds-coral); border-color: var(--ds-coral); color: var(--ds-coral-ink);
}
.dash-kpi--coral .dash-kpi-label { color: rgba(74, 27, 12, .72); }
.dash-kpi--coral .dash-kpi-val   { color: var(--ds-coral-ink); }
.dash-kpi--coral .dash-kpi-hint  { color: rgba(74, 27, 12, .72); }
.dash-kpi--coral .dash-kpi-ic,
.dash-kpi--coral .dash-kpi-pill,
.dash-kpi--coral .dash-delta     { background: rgba(74, 27, 12, .12); color: var(--ds-coral-ink); }

.dash-kpi--dark {
    background: var(--ds-slate-900); border-color: var(--ds-slate-900); color: #fff;
}
.dash-kpi--dark .dash-kpi-label { color: rgba(255, 255, 255, .55); }
.dash-kpi--dark .dash-kpi-val   { color: #fff; }
.dash-kpi--dark .dash-kpi-hint  { color: rgba(255, 255, 255, .55); }
.dash-kpi--dark .dash-kpi-ic    { background: rgba(255, 255, 255, .10); color: var(--ds-accent); }
.dash-kpi--dark .dash-kpi-pill,
.dash-kpi--dark .dash-delta     { background: rgba(255, 255, 255, .12); color: #fff; }
/* Whole-tile links (Low stock, Notes due) must not pick up a link underline */
a.dash-kpi, a.dash-kpi:hover { text-decoration: none; }
.dash-kpi-foot { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.dash-kpi-hint { font-size: var(--ds-text-xs); color: var(--ds-text-muted); }

.dash-delta { display: inline-flex; align-items: center; gap: .1rem; padding: .15rem .45rem .15rem .3rem; border-radius: var(--ds-radius-pill);
    font-size: var(--ds-text-xs); font-weight: var(--ds-weight-bold); line-height: 1; }
.dash-delta i { font-size: 1rem; margin: -2px 0; }
.dash-delta--up   { background: var(--ds-success-soft); color: var(--ds-success); }
.dash-delta--down { background: var(--ds-coral-soft);   color: var(--ds-coral); }
.dash-delta--flat { background: var(--ds-surface-2);    color: var(--ds-text-muted); padding: .15rem .5rem; }

.dash-kpi-pill { display: inline-flex; align-items: center; padding: .15rem .5rem; border-radius: var(--ds-radius-pill);
    font-size: var(--ds-text-xs); font-weight: var(--ds-weight-bold); background: var(--ds-accent-soft); color: var(--ds-accent-text); }
.dash-kpi-pill--warn { background: var(--ds-coral-soft); color: var(--ds-coral); }

/* ---- Rows ---- */
.dash-row { display: grid; gap: var(--ds-space-4); }
.dash-row--chart { grid-template-columns: 1.9fr 1fr; }
.dash-row--split { grid-template-columns: 1fr 1fr; }

.dash-panel { padding: var(--ds-space-5); display: flex; flex-direction: column; }
.dash-panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: .5rem; margin-bottom: var(--ds-space-4); }
.dash-panel-title { font-size: var(--ds-text-lg); font-weight: var(--ds-weight-semibold); color: var(--ds-text); }
.dash-panel-sub { font-size: var(--ds-text-sm); color: var(--ds-text-muted); margin-top: .1rem; }
.dash-panel-fig { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: .3rem; }
.dash-panel-amt { font-size: var(--ds-text-2xl); font-weight: var(--ds-weight-bold); color: var(--ds-text); letter-spacing: -.01em;
    font-family: var(--ds-font-mono); font-variant-numeric: tabular-nums; }
.dash-panel-link { font-size: var(--ds-text-sm); font-weight: var(--ds-weight-semibold); color: var(--ds-accent-text); text-decoration: none; }
.dash-panel-link:hover { color: var(--ds-accent-active); text-decoration: underline; }

/* ---- Area chart ---- */
.dash-chart { flex: 1 1 auto; min-height: 210px; }
.dash-area { width: 100%; height: 210px; display: block; }
.dash-chart-axis { display: flex; justify-content: space-between; margin-top: .6rem; font-size: var(--ds-text-xs); color: var(--ds-text-muted); }

/* ---- Donut ---- */
.dash-donut-wrap { display: flex; align-items: center; gap: var(--ds-space-5); flex: 1 1 auto; }
.dash-donut { position: relative; width: 140px; height: 140px; flex: 0 0 auto; }
.dash-donut-svg { width: 140px; height: 140px; display: block; }
.dash-donut-svg circle { transition: stroke-dasharray .4s ease; }
.dash-donut-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.dash-donut-num { font-size: var(--ds-text-2xl); font-weight: var(--ds-weight-bold); color: var(--ds-text); line-height: 1; font-family: var(--ds-font-mono); }
.dash-donut-cap { font-size: var(--ds-text-xs); color: var(--ds-text-muted); margin-top: .1rem; }
.dash-legend { list-style: none; margin: 0; padding: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: .5rem; }
.dash-legend li { display: flex; align-items: center; gap: .55rem; font-size: var(--ds-text-sm); }
.dash-legend-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.dash-legend-label { color: var(--ds-text-2); }
.dash-legend-val { margin-inline-start: auto; font-weight: var(--ds-weight-bold); color: var(--ds-text);
    font-family: var(--ds-font-mono); font-variant-numeric: tabular-nums; }

/* ---- Activity list ---- */
.dash-list { display: flex; flex-direction: column; }
.dash-item { display: flex; align-items: center; gap: .8rem; padding: .7rem 0; border-top: 1px solid var(--ds-border); }
.dash-item:first-child { border-top: 0; }
.dash-item-ic { width: 32px; height: 32px; flex: 0 0 auto; display: grid; place-items: center; border-radius: 50%; font-size: 1rem; }
.dash-item-ic--ok     { background: var(--ds-success-soft); color: var(--ds-success); }
.dash-item-ic--accent { background: var(--ds-accent-soft);  color: var(--ds-accent-text); }
.dash-item-ic--warn   { background: var(--ds-coral-soft);   color: var(--ds-coral); }
.dash-item-ic--muted  { background: var(--ds-surface-2);    color: var(--ds-text-muted); }
.dash-item-body { flex: 1 1 auto; min-width: 0; }
.dash-item-title { font-size: var(--ds-text-base); color: var(--ds-text-2); }
.dash-item-title b { color: var(--ds-text); font-weight: var(--ds-weight-semibold); }
.dash-item-sub { font-size: var(--ds-text-xs); color: var(--ds-text-muted); margin-top: .1rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-item-time { font-size: var(--ds-text-xs); color: var(--ds-text-muted); flex: 0 0 auto; white-space: nowrap; }

/* ---- New orders from the customer app ----
   Tinted and rule-marked rather than styled like the panels around it: this is
   the one block on the dashboard that is a request from outside the company, and
   it has to read as something to answer, not something to look at. */
.dash-appord { border-inline-start: 3px solid var(--ds-coral); }
.dash-appord .dash-panel-title i { color: var(--ds-coral); margin-inline-end: .25rem; }
.dash-appord .dash-kpi-pill { margin-inline-start: .35rem; vertical-align: middle; }
.dash-item--link { text-decoration: none; color: inherit; border-radius: var(--ds-radius-md); }
.dash-item--link:hover { background: var(--ds-surface-2); }
.dash-item--link:hover .dash-item-title b { color: var(--ds-accent-text); }

/* The "one just arrived" line, revealed by the poll in Dashboard/Index. Inside
   the panel, because the news is about the panel. */
.dash-appord-new { display: none; align-items: center; gap: .5rem; margin-bottom: var(--ds-space-3);
    padding: .5rem .75rem; border-radius: var(--ds-radius-md);
    background: var(--ds-coral-soft); color: var(--ds-coral);
    font-size: var(--ds-text-sm); font-weight: var(--ds-weight-semibold); }
.dash-appord-new.show { display: flex; }
.dash-appord-new a { color: inherit; text-decoration: underline; }

/* ---- Top suppliers ---- */
.dash-sup { display: flex; align-items: center; gap: .8rem; padding: .7rem 0; border-top: 1px solid var(--ds-border); }
.dash-sup:first-child { border-top: 0; }
.dash-sup-av { width: 34px; height: 34px; flex: 0 0 auto; display: grid; place-items: center; border-radius: var(--ds-radius-md);
    color: #fff; font-size: var(--ds-text-xs); font-weight: var(--ds-weight-bold); letter-spacing: .02em; }
.dash-sup-body { flex: 1 1 auto; min-width: 0; }
.dash-sup-name { font-size: var(--ds-text-base); font-weight: var(--ds-weight-semibold); color: var(--ds-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-sup-meta { font-size: var(--ds-text-xs); color: var(--ds-text-muted); margin-top: .1rem; }
.dash-sup-right { flex: 0 0 130px; display: flex; flex-direction: column; align-items: flex-end; gap: .3rem; }
.dash-sup-amt { font-size: var(--ds-text-base); font-weight: var(--ds-weight-bold); color: var(--ds-text);
    font-family: var(--ds-font-mono); font-variant-numeric: tabular-nums; }
.dash-sup-bar { width: 100%; height: 5px; border-radius: 999px; background: var(--ds-surface-2); overflow: hidden; }
.dash-sup-bar span { display: block; height: 100%; border-radius: 999px; background: var(--ds-accent); }

/* ---- Empty states ---- */
.dash-empty { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .5rem;
    padding: 2.5rem 1rem; color: var(--ds-text-muted); text-align: center; }
.dash-empty i { font-size: 1.8rem; color: var(--ds-border-strong); }
.dash-empty span { font-size: var(--ds-text-sm); }
.dash-empty--sm { padding: 1.5rem 1rem; }

/* ---- Responsive ---- */
@media (max-width: 1100px) {
    .dash-kpis { grid-template-columns: repeat(2, 1fr); }   /* hero fills the row */
    .dash-row--chart, .dash-row--split { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
    .dash-kpis { grid-template-columns: 1fr; }
    .dash-kpi--hero { grid-column: span 1; }                /* nothing to span into */
    .dash-kpi--hero .dash-kpi-val { font-size: var(--ds-text-3xl); }
    .dash-donut-wrap { flex-direction: column; align-items: stretch; }
    .dash-legend { width: 100%; }
}

/* ============================================================================
   5 · STICKY FORM ACTION BAR  (Save / Back follow the scroll on long forms)
   ----------------------------------------------------------------------------
   On any long data-entry form the primary Save button and a mirror of the
   header Back link are pinned to the bottom of the scroll viewport, so the
   actions stay reachable without scrolling to the top or bottom of the page.
   Built + toggled centrally by site.js (no per-screen markup): the bar is
   appended as the last child of <main class="content"> and only revealed
   (.ea-actionbar-on) when the screen actually overflows its scroll viewport.
   The real Save button stays inside its <form> (id / listeners / validation
   untouched) but is hidden while the bar is shown; the bar's Save proxies a
   click to it and mirrors its disabled state.
   ============================================================================ */
.ea-actionbar {
    position: sticky; bottom: 0; z-index: 20;
    display: none;
    margin-top: var(--ds-space-5);
    padding: var(--ds-space-3) var(--ds-space-4);
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
}
.ea-actionbar__inner { display: flex; align-items: center; gap: var(--ds-space-2); justify-content: flex-end; }
.ea-actionbar__back  { margin-inline-end: auto; }   /* Back sits far-left; Cancel + Save group right */

/* Cancel injected next to the inline Save on forms that don't show the bar */
.ea-inline-cancel { margin-inline-end: .5rem; }

.ea-actionbar-on .ea-actionbar     { display: block; }
.ea-actionbar-on .ea-inline-save,
.ea-actionbar-on .ea-inline-cancel { display: none !important; }

@media (max-width: 575px) {
    /* Pull the bar flush to the pane edges, and pad past the phone's bottom
       safe area (iOS home indicator) so Save / Cancel are never under it. */
    .ea-actionbar {
        margin-inline: calc(-1 * var(--ds-space-2));
        padding-bottom: calc(var(--ds-space-3) + env(safe-area-inset-bottom, 0px));
    }
}

/* ============================================================================
   5b · STICKY MATRIX HEADER  (.ds-matrix)
   ----------------------------------------------------------------------------
   For the hand-built permission matrices (Roles & Rights, per-user overrides):
   tables long enough that the column you are ticking scrolls off the screen,
   leaving a grid of anonymous checkboxes. The header row pins to the top of the
   scroll viewport instead.

   The WRAPPER is the whole trick. Bootstrap's .table-responsive sets
   overflow-x: auto, which makes it the sticky containing block - and since it is
   exactly as tall as its content it never scrolls, so a sticky header inside it
   stays put relative to a box that is already fully visible, i.e. it scrolls
   away exactly as if nothing had been done. .ds-matrix therefore keeps overflow
   visible and lets the page (or the tab pane) be the scroller. Same reason
   §grid keeps the DataTables card at overflow: visible.

   Below lg the table is wider than the viewport and side-scrolling matters more
   than a pinned header, so the wrapper takes overflow-x back.
   ============================================================================ */
.ds-matrix { overflow: visible; }
.ds-matrix > table > thead > tr > th {
    position: sticky; top: 0; z-index: 3;
    /* Opaque by necessity: rows scroll UNDER this, and Bootstrap's .table-light
       paints through a shadow that a sticky cell does not carry with it. */
    background: var(--ds-surface-2, #F5F3EC);
    box-shadow: inset 0 -1px 0 var(--ds-border, #E4E1D8);
}
@media (max-width: 991.98px) {
    .ds-matrix { overflow-x: auto; }
    .ds-matrix > table > thead > tr > th { position: static; }
}

/* ============================================================================
   6 · REPORT FILTER PANEL  (.rf-*)
   ----------------------------------------------------------------------------
   The shared chrome for every screen under Reports: one card carrying the
   report's identity (icon + title + period chip), a read-at-a-glance summary
   strip of what is currently selected, and the filter controls themselves.

   It is PRESENTATION ONLY. Every control underneath is still the same plain
   <input type="checkbox"> / <select> / <input type="date"> posting the same
   name+value as before — a chip and a pick row are a checkbox plus a <label>
   styled through the `:checked + label` sibling selector, so the look needs no
   JavaScript and none of the report logic changes.
   ============================================================================ */

.rf-card {
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    box-shadow: var(--ds-shadow-sm);
    overflow: hidden;
    margin-bottom: var(--ds-space-5);
}

/* ---- Header: icon tile, title + subtitle, period chip ---- */
.rf-head {
    display: flex; align-items: center; gap: var(--ds-space-4);
    padding: var(--ds-space-5);
    border-bottom: 1px solid var(--ds-border);
}
.rf-head__icon {
    flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.75rem; height: 2.75rem;
    border-radius: var(--ds-radius-md);
    background: var(--ds-accent-soft); color: var(--ds-accent-text);
    font-size: 1.25rem;
}
.rf-head__text  { min-width: 0; }
.rf-head__title { margin: 0; font-size: 1.15rem; font-weight: 700; color: var(--ds-text); }
.rf-head__sub   { margin: .125rem 0 0; font-size: var(--ds-text-sm); color: var(--ds-text-muted); }
.rf-head__meta  { margin-inline-start: auto; display: flex; flex-wrap: wrap; gap: var(--ds-space-2); }

.rf-chip-meta {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .4rem .85rem;
    border: 1px solid var(--ds-border); border-radius: var(--ds-radius-pill);
    background: var(--ds-surface);
    font-size: var(--ds-text-sm); font-weight: 600; color: var(--ds-text-2);
    white-space: nowrap;
}
.rf-chip-meta .bi { color: var(--ds-text-muted); }

/* ---- Summary strip: what the report will run with, at a glance ---- */
.rf-summary {
    display: flex; flex-wrap: wrap;
    border-bottom: 1px solid var(--ds-border);
}
.rf-summary__cell {
    flex: 1 1 12rem; min-width: 0;
    padding: var(--ds-space-3) var(--ds-space-5);
    border-inline-end: 1px solid var(--ds-border);
}
.rf-summary__cell:last-child { border-inline-end: 0; }
.rf-summary__label { font-size: var(--ds-text-sm); color: var(--ds-text-muted); }
.rf-summary__value {
    font-weight: 600; color: var(--ds-text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---- Body + one filter block ---- */
.rf-body  { padding: var(--ds-space-5); }
.rf-field { margin-bottom: var(--ds-space-5); }
.rf-field:last-child { margin-bottom: 0; }
.rf-field__head {
    display: flex; align-items: center; gap: var(--ds-space-3);
    margin-bottom: var(--ds-space-2);
    flex-wrap: wrap;   /* label + Select all / Clear share a half-width column */
}
.rf-label {
    font-size: .75rem; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--ds-text-muted); margin: 0;
}
.rf-hint    { margin-inline-start: auto; font-size: var(--ds-text-sm); color: var(--ds-text-muted); }
.rf-actions { margin-inline-start: auto; display: flex; align-items: center; gap: .5rem; }
.rf-actions .rf-sep { color: var(--ds-border-strong); }
.rf-link {
    background: none; border: 0; padding: 0;
    font-size: var(--ds-text-sm); font-weight: 600;
    color: var(--ds-accent-text); display: inline-flex; align-items: center; gap: .3rem;
}
.rf-link:hover        { color: var(--ds-accent-active); text-decoration: underline; }
.rf-link--muted       { color: var(--ds-text-muted); }
.rf-link--muted:hover { color: var(--ds-text-2); }

/* ---- Chip toggles (a checkbox + its label) ---- */
.rf-chips { display: flex; flex-wrap: wrap; gap: var(--ds-space-2); }
.rf-chip-input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.rf-chip {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .5rem 1rem;
    border: 1px solid var(--ds-border); border-radius: var(--ds-radius-pill);
    background: var(--ds-surface);
    font-weight: 600; color: var(--ds-text-2);
    cursor: pointer; user-select: none;
    transition: all var(--ds-ease, .15s ease);
}
.rf-chip:hover { background: var(--ds-surface-2); border-color: var(--ds-border-strong); color: var(--ds-text); }
/* The tick only exists once the chip is on, so an unchecked chip keeps its own
   width and the row doesn't reflow as chips are toggled. */
.rf-chip .bi { display: none; font-size: .9em; }
.rf-chip-input:checked + .rf-chip {
    background: var(--ds-accent); border-color: var(--ds-accent); color: var(--ds-accent-ink);
    box-shadow: none;
}
.rf-chip-input:checked + .rf-chip .bi   { display: inline-block; }
.rf-chip-input:checked + .rf-chip:hover { background: var(--ds-accent-hover); color: var(--ds-accent-ink); }
.rf-chip-input:disabled + .rf-chip      { opacity: .5; cursor: not-allowed; }
.rf-chip-input:focus-visible + .rf-chip { outline: none; box-shadow: var(--ds-shadow-focus); }

/* ---- Date / select control with a leading icon ---- */
.rf-control { position: relative; display: block; }
.rf-control--date { max-width: 16rem; }
.rf-control > .bi {
    position: absolute; inset-inline-start: .85rem; top: 50%; transform: translateY(-50%);
    color: var(--ds-accent-text); pointer-events: none; z-index: 2;
}
.rf-control > .form-control,
.rf-control > .form-select { padding-inline-start: 2.5rem; }
.rf-control--date > .form-control { font-weight: 600; }

/* ---- Pick list (search + scrollable rows + count footer) ---- */
.rf-picker {
    border: 1px solid var(--ds-border); border-radius: var(--ds-radius-md);
    overflow: hidden; background: var(--ds-surface);
}
.rf-picker__search { position: relative; border-bottom: 1px solid var(--ds-border); }
.rf-picker__search > .bi {
    position: absolute; inset-inline-start: .85rem; top: 50%; transform: translateY(-50%);
    color: var(--ds-text-muted); pointer-events: none;
}
.rf-picker__search .form-control {
    border: 0; border-radius: 0; padding-inline-start: 2.5rem; box-shadow: none;
}
.rf-picker__list { max-height: 15rem; overflow-y: auto; }

.rf-row { position: relative; border-bottom: 1px solid var(--ds-border); }
.rf-row:last-child { border-bottom: 0; }
.rf-row-input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.rf-row-label {
    display: flex; align-items: center; gap: var(--ds-space-3);
    padding: .55rem var(--ds-space-4);
    margin: 0; cursor: pointer; width: 100%;
    transition: background var(--ds-ease, .15s ease);
}
.rf-row-label:hover { background: var(--ds-surface-2); }
.rf-row-input:checked + .rf-row-label { background: var(--ds-accent-soft); }

/* Custom tick box — the real checkbox is hidden, so this is what the user sees. */
.rf-check {
    flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.15rem; height: 1.15rem;
    border: 1.5px solid var(--ds-border-strong); border-radius: var(--ds-radius-sm);
    background: var(--ds-surface);
    color: var(--ds-accent-ink); font-size: .8rem;
}
.rf-check::before { content: "\F26E"; font-family: bootstrap-icons; opacity: 0; }  /* bi-check2 */
.rf-row-input:checked + .rf-row-label .rf-check {
    background: var(--ds-accent); border-color: var(--ds-accent);
}
.rf-row-input:checked + .rf-row-label .rf-check::before { opacity: 1; }
.rf-row-input:focus-visible + .rf-row-label .rf-check { box-shadow: var(--ds-shadow-focus); }

.rf-code {
    flex: 0 0 auto;
    font-family: var(--ds-font-mono); font-size: var(--ds-text-sm);
    padding: .1rem .45rem;
    border: 1px solid var(--ds-border); border-radius: var(--ds-radius-sm);
    background: var(--ds-surface-2); color: var(--ds-text-2);
}
.rf-row-input:checked + .rf-row-label .rf-code {
    border-color: var(--ds-accent-border); background: var(--ds-surface); color: var(--ds-accent-active);
}
.rf-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ds-text); }

.rf-picker__foot {
    display: flex; align-items: center; flex-wrap: wrap; gap: .4rem;
    padding: .5rem var(--ds-space-4);
    border-top: 1px solid var(--ds-border); background: var(--ds-canvas);
    font-size: var(--ds-text-sm); color: var(--ds-text-muted);
}
.rf-picker__count { font-weight: 600; color: var(--ds-accent-text); }

/* ---- Footer actions ---- */
.rf-foot {
    display: flex; align-items: center; justify-content: flex-end; gap: var(--ds-space-3);
    padding: var(--ds-space-4) var(--ds-space-5);
    border-top: 1px solid var(--ds-border);
}
.rf-foot__left { margin-inline-end: auto; }

/* Result-side toolbar (Print / Excel) so it reads as part of the same system */
.rf-toolbar { display: flex; align-items: center; justify-content: flex-end; gap: var(--ds-space-2); margin-bottom: var(--ds-space-4); }

@media (max-width: 575px) {
    .rf-head { flex-wrap: wrap; }
    .rf-head__meta { margin-inline-start: 0; width: 100%; }
    .rf-summary__cell { flex-basis: 100%; border-inline-end: 0; border-bottom: 1px solid var(--ds-border); }
    .rf-summary__cell:last-child { border-bottom: 0; }
}

/* ============================================================================
   7 · FLAT SKIN  (near-black · mint · coral)
   ----------------------------------------------------------------------------
   site.css was written against the old blue/indigo palette and still carries a
   number of literal hex values and gradients. This section is loaded after it
   and re-points those rules at the tokens, so the whole app follows §1 without
   site.css being rewritten rule by rule.

   Three things are enforced everywhere:
     · no gradients, and no shadow on an in-flow surface — a hairline border and
       the canvas/surface contrast do the separating;
     · solid mint never carries white text (see --ds-accent-ink);
     · figures are set in the mono face and right-aligned, so a column of money
       lines up digit over digit.
   ============================================================================ */

/* ---------------------------------------------------------------------------
   7.1 · App shell leftovers
   --------------------------------------------------------------------------- */
.ea-nav-tip { background: var(--ds-slate-900); }
.ea-nav-tip::before { border-right-color: var(--ds-slate-900); }

/* A screen opened in a tab renders in its own iframe. It gets the same canvas
   as the home tab, otherwise every card would be white on white and the page
   would lose the one layer of separation this design has. */
body.ea-embed { background: var(--ds-canvas); }
.ea-tab-pane > iframe { background: var(--ds-canvas); }
.ea-pane-status { background: var(--ds-canvas); }

.card { box-shadow: none; }
.page-head h4 { letter-spacing: -.01em; }

/* Group heading on a card - the small uppercase grey label the layout asks for
   above each group of fields. */
.card > .card-header {
    font-size: var(--ds-text-xs); font-weight: var(--ds-weight-bold);
    text-transform: uppercase; letter-spacing: var(--ds-tracking-wide);
    color: var(--ds-text-muted); background: var(--ds-surface);
    padding: var(--ds-space-3) var(--ds-space-5);
}
/* Several headers carry a button or a toggle beside the label. Those are
   controls, not the label, so they keep their own case and size. */
.card > .card-header .btn,
.card > .card-header .badge,
.card > .card-header .form-control,
.card > .card-header .form-select,
.card > .card-header .form-check-label {
    text-transform: none; letter-spacing: normal; font-size: var(--ds-text-sm);
}
.card > .card-header i { color: var(--ds-accent-text); }

/* ---------------------------------------------------------------------------
   7.2 · Data-grid chrome that site.css still paints blue
   --------------------------------------------------------------------------- */
.ea-seg { box-shadow: none; border-color: var(--ds-border); }
.ea-adv-search { background: var(--ds-surface-2); border-color: var(--ds-border); }
.dataTables_wrapper .pagination .page-link { border-color: var(--ds-border); color: var(--ds-text-2); }
.dataTables_wrapper .pagination .page-item.disabled .page-link { color: var(--ds-border-strong); background: var(--ds-surface); }
table.dataTable tbody tr:hover .btn-outline-secondary { border-color: var(--ds-border-strong); }

/* ---------------------------------------------------------------------------
   7.3 · Figures in mono
   ----------------------------------------------------------------------------
   Applied by ROLE, not per screen: a right-aligned cell in a data grid, a
   right-aligned input in a transaction form, a total, a rate, a voucher number.
   Labels, headings and prose stay in the sans face.

   The :not(:has(...)) guards keep the action column out of it - that cell is
   right-aligned too, but it holds buttons, not a figure.
   --------------------------------------------------------------------------- */
.ds-num,
table.dataTable tbody td.text-end:not(:has(button)):not(:has(a)):not(:has(form)),
table.dataTable tfoot td.text-end,
.pi-grid td.text-end, .pi-grid tfoot td.text-end,
.table td.text-end:not(:has(button)):not(:has(a)):not(:has(form)),
.form-control.text-end, input.pi-rate, .pi-total,
#vocNumber, .dash-item-title b {
    font-family: var(--ds-font-mono);
    font-variant-numeric: tabular-nums;
    letter-spacing: -.01em;
}
/* Right-align every numeric input in a form, not only the ones a view
   remembered to mark. */
input[type="number"].form-control {
    text-align: right;
    font-family: var(--ds-font-mono); font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
   7.4 · Transaction forms (.pi-* - shared by Purchase, Sales, Returns, Notes)
   --------------------------------------------------------------------------- */
.pi-card { border-color: var(--ds-border); border-radius: var(--ds-radius-lg); }
.pi-card-head {
    background: var(--ds-surface);                       /* was a gradient */
    border-bottom: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg) var(--ds-radius-lg) 0 0;
    padding: var(--ds-space-3) var(--ds-space-4);
}
/* The group's name: small, uppercase, grey */
.pi-card-head span {
    color: var(--ds-text-muted); font-size: var(--ds-text-xs);
    font-weight: var(--ds-weight-bold); letter-spacing: var(--ds-tracking-wide);
}
/* Every section icon takes the accent, whatever utility colour the view asked
   for - one accent per screen reads as a system, five read as decoration. */
.pi-card-head > i, .pi-sub-ic > i { color: var(--ds-accent-text) !important; }
.pi-card .form-label { color: var(--ds-text-muted); }
.pi-card .req, .pi-block .req { color: var(--ds-coral); }

.pi-sub { color: var(--ds-text); }
.pi-sub-ic { background: var(--ds-accent-soft) !important; }
.pi-block { background: var(--ds-surface); border-color: var(--ds-border); }
.pi-block .form-label { color: var(--ds-text-muted); }
.pi-total { background: var(--ds-surface-2); font-weight: var(--ds-weight-semibold); }
.pi-item-img-wrap, .si-item-img { background: var(--ds-surface); border-color: var(--ds-border); }

/* Line grid: light header row, hairline dividers */
.pi-grid { border-color: var(--ds-border); }
.pi-grid thead th, .pi-grid tfoot td {
    background: var(--ds-surface-2) !important;
    color: var(--ds-text-muted); font-weight: var(--ds-weight-bold);
    letter-spacing: var(--ds-tracking-wide);
    border-color: var(--ds-border);
}
.pi-grid tfoot td { color: var(--ds-text); letter-spacing: 0; }
.pi-grid td { border-color: var(--ds-border); }

/* Item / charge dialogs: dark bar, white title, mint glyph (see §2.8) */
.pi-modal-head { background: var(--ds-slate-900); color: #fff; }
.pi-modal-head .modal-title { font-weight: var(--ds-weight-semibold); }
.pi-modal-head .modal-title i { color: var(--ds-accent); }

/* Bootstrap tabs inside a transaction card */
.nav-tabs { border-bottom-color: var(--ds-border); }
.nav-tabs .nav-link { color: var(--ds-text-muted); border: 0; border-bottom: 2px solid transparent; font-weight: var(--ds-weight-semibold); }
.nav-tabs .nav-link:hover { color: var(--ds-text); border-bottom-color: var(--ds-border-strong); }
.nav-tabs .nav-link.active { color: var(--ds-text); background: transparent; border-bottom-color: var(--ds-accent); }
.nav-tabs .nav-link i { color: var(--ds-accent-text) !important; }

.totals-box { background: var(--ds-surface-2); border-color: var(--ds-border); }
.totals-box .grand { border-top-color: var(--ds-border-strong); }

/* ---------------------------------------------------------------------------
   7.5 · Legacy KPI tiles (screens still on the pre-bento .kpi markup)
   --------------------------------------------------------------------------- */
.kpi { background: var(--ds-surface); border-color: var(--ds-border); border-radius: var(--ds-radius-lg); }
.kpi .kpi-value { font-family: var(--ds-font-mono); font-variant-numeric: tabular-nums; }
.i-sales, .i-collect, .i-recv { background: var(--ds-accent); color: var(--ds-accent-ink); }
.i-purchase, .i-out { background: var(--ds-slate-900); color: #fff; }
.i-pay, .i-payb { background: var(--ds-coral); color: var(--ds-coral-ink); }

/* ---------------------------------------------------------------------------
   7.6 · Bootstrap utilities used across the views
   ----------------------------------------------------------------------------
   Views mark meaning up with .text-primary / .btn-info / .alert-* and so on.
   Left alone those keep painting Bootstrap's blue next to the mint, so they are
   re-pointed at the palette here rather than edited out of a few hundred views.
   --------------------------------------------------------------------------- */
.text-primary { color: var(--ds-accent-text) !important; }
.text-success { color: var(--ds-success) !important; }
.text-info    { color: var(--ds-accent-text) !important; }
.text-warning { color: var(--ds-warning) !important; }
.text-danger  { color: var(--ds-danger) !important; }
.text-muted   { color: var(--ds-text-muted) !important; }
a { color: var(--ds-accent-text); }
a:hover { color: var(--ds-accent-active); }

.alert { border-radius: var(--ds-radius-md); border-width: 1px; }
.alert-success { background: var(--ds-accent-soft); border-color: var(--ds-accent-border); color: var(--ds-accent-active); }
.alert-danger  { background: var(--ds-danger-soft);  border-color: var(--ds-danger-border);  color: var(--ds-danger); }
.alert-warning { background: var(--ds-warning-soft); border-color: var(--ds-warning-border); color: var(--ds-warning); }
.alert-info    { background: var(--ds-surface-2);    border-color: var(--ds-border);         color: var(--ds-text-2); }

.btn-success { --bs-btn-bg: var(--ds-success); --bs-btn-border-color: var(--ds-success);
               --bs-btn-hover-bg: #0E8760; --bs-btn-hover-border-color: #0E8760;
               --bs-btn-active-bg: #0E8760; --bs-btn-active-border-color: #0E8760; }
.btn-info    { --bs-btn-bg: var(--ds-accent); --bs-btn-border-color: var(--ds-accent);
               --bs-btn-color: var(--ds-accent-ink);
               --bs-btn-hover-bg: var(--ds-accent-hover); --bs-btn-hover-border-color: var(--ds-accent-hover);
               --bs-btn-hover-color: var(--ds-accent-ink); }
.btn-secondary { --bs-btn-bg: var(--ds-surface); --bs-btn-border-color: var(--ds-border-strong);
                 --bs-btn-color: var(--ds-text-2);
                 --bs-btn-hover-bg: var(--ds-surface-2); --bs-btn-hover-border-color: var(--ds-border-strong);
                 --bs-btn-hover-color: var(--ds-text); }
.btn-outline-secondary { --bs-btn-color: var(--ds-text-2); --bs-btn-border-color: var(--ds-border-strong);
                         --bs-btn-hover-bg: var(--ds-surface-2); --bs-btn-hover-border-color: var(--ds-border-strong);
                         --bs-btn-hover-color: var(--ds-text); }
.btn-outline-danger  { --bs-btn-color: var(--ds-danger); --bs-btn-border-color: var(--ds-danger-border);
                       --bs-btn-hover-bg: var(--ds-danger); --bs-btn-hover-border-color: var(--ds-danger); }
.btn-outline-info    { --bs-btn-color: var(--ds-text-2); --bs-btn-border-color: var(--ds-border-strong);
                       --bs-btn-hover-bg: var(--ds-surface-2); --bs-btn-hover-border-color: var(--ds-border-strong);
                       --bs-btn-hover-color: var(--ds-text); }
.btn-light { --bs-btn-bg: var(--ds-surface-2); --bs-btn-border-color: var(--ds-border); --bs-btn-color: var(--ds-text-2); }

/* Subtle-background utilities the item modals use behind their section icons */
.bg-info-subtle, .bg-primary-subtle, .bg-success-subtle { background-color: var(--ds-accent-soft) !important; }
.bg-warning-subtle { background-color: var(--ds-coral-soft) !important; }
.bg-light { background-color: var(--ds-surface-2) !important; }

.table > :not(caption) > * > * { border-color: var(--ds-border); }
.table-light > :not(caption) > * > * { background-color: var(--ds-surface-2); color: var(--ds-text-muted); }
.input-group-text { background: var(--ds-surface-2); border-color: var(--ds-border-strong); color: var(--ds-text-muted); }
.form-text { color: var(--ds-text-muted); }
hr { border-color: var(--ds-border); opacity: 1; }
