/* ============================================================================
   Our Apps World — accounting CRM design layer
   ----------------------------------------------------------------------------
   Loaded after app.min.css. Everything here is additive: it introduces
   accounting-specific components rather than restyling the base theme, so a
   theme upgrade does not fight this file.

   Colour is semantic, not decorative. In a ledger a colour is a claim about
   money, so each one is defined once and reused:

       receivable  money owed to us          indigo
       collected   money actually received   blue
       payable     money we owe              amber
       tax         statutory amounts         violet
       overdue     past its due date         red

   Those five are claims about money. A second, smaller set makes claims about
   *the system* — whether an action worked — and is deliberately kept apart:

       ok       the action succeeded
       bad      the action failed
       warn     it worked, but read this
       info     neither good nor bad

   Keeping them separate matters because the hues collide. "Collected" blue and
   "succeeded" teal look alike but mean different things, and a toast tinted
   with --crm-collected would be claiming money arrived. Feedback is transient
   and about the request; money colour is persistent and about the ledger.

   Everything derives from Bootstrap's own tokens, so light/dark switching via
   [data-bs-theme] needs no extra work.
   ========================================================================= */

:root {
    --crm-receivable: #4f46e5;
    --crm-collected:  #0284c7;
    --crm-payable:    #d97706;
    --crm-tax:        #7c3aed;
    --crm-overdue:    #dc2626;
    --crm-neutral:    #64748b;

    --crm-surface:        var(--bs-secondary-bg);
    --crm-surface-sunken: #f1f3f6;
    --crm-border:         #e4e7ec;
    --crm-border-strong:  #d3d8e0;

    /* Ink versions of the same meanings, for text sitting on a pale tint of
       itself (pills, chips). The accent colours above are tuned to be read as
       colour — a 3px bar, a chart bar — and amber or blue at that lightness
       only reaches ~2.4:1 as small text on a near-white background. These are
       the same hues taken far enough down to clear 4.5:1. */
    --crm-ink-receivable: #3730a3;
    --crm-ink-collected:  #075985;
    --crm-ink-payable:    #92400e;
    --crm-ink-tax:        #5b21b6;
    --crm-ink-overdue:    #991b1b;
    --crm-ink-neutral:    #475569;

    /* Feedback — see the header note on why these are not the money hues.
       Teal rather than blue for `info`, so it cannot be mistaken for the
       indigo that means receivable, or for a link. */
    --crm-ok:   #0e7490;
    --crm-bad:  #dc2626;
    --crm-warn: #d97706;
    --crm-info: #475569;

    --crm-ink-ok:   #155e75;
    --crm-ink-bad:  #991b1b;
    --crm-ink-warn: #92400e;
    --crm-ink-info: #334155;

    /* Muted text — sub-lines, table headings, counts. The theme's own
       --bs-secondary-color is fine here (5.4:1 on white) but too dim once the
       page goes dark, so it is aliased rather than used directly. */
    --crm-muted: var(--bs-secondary-color);

    /* Text laid on a solid accent fill. Light mode fills with the accent at
       full strength, so white wins; see the dark block for why that flips. */
    --crm-on-accent: #ffffff;

    --crm-radius:    12px;
    --crm-radius-sm: 8px;

    --crm-shadow-sm: 0 1px 2px rgba(16, 24, 40, .05);
    --crm-shadow:    0 2px 8px rgba(16, 24, 40, .06), 0 1px 2px rgba(16, 24, 40, .04);
    --crm-shadow-lg: 0 12px 28px rgba(16, 24, 40, .10);
}

/* Dark mode: lift the accents so they hold contrast on a dark surface, and
   pull the greys from the theme rather than hard-coding them. */
html[data-bs-theme="dark"] {
    --crm-receivable: #818cf8;
    --crm-collected:  #38bdf8;
    --crm-payable:    #fbbf24;
    --crm-tax:        #a78bfa;
    --crm-overdue:    #f87171;
    --crm-neutral:    #94a3b8;

    /* On a dark surface the accents are already the readable version, so ink
       and accent converge. */
    --crm-ink-receivable: #a5b4fc;
    --crm-ink-collected:  #7dd3fc;
    --crm-ink-payable:    #fcd34d;
    --crm-ink-tax:        #c4b5fd;
    --crm-ink-overdue:    #fca5a5;
    --crm-ink-neutral:    #cbd5e1;

    --crm-ok:   #2dd4bf;
    --crm-bad:  #f87171;
    --crm-warn: #fbbf24;
    --crm-info: #94a3b8;

    --crm-ink-ok:   #5eead4;
    --crm-ink-bad:  #fca5a5;
    --crm-ink-warn: #fcd34d;
    --crm-ink-info: #cbd5e1;

    /* The theme's #8391a2 measures 4.2:1 on the panel and 3.9:1 on the table
       head tint — under AA for the 11–13px this token is used at. Slate-400
       clears 5:1 in both places while still reading as secondary. */
    --crm-muted: #94a3b8;

    /* The accents above were lightened to hold their own against a dark
       surface, which means white text no longer contrasts with them — white on
       the dark-mode indigo is 3.0:1. On a light fill the ink has to be dark. */
    --crm-on-accent: #0f172a;

    --crm-surface-sunken: rgba(255, 255, 255, .03);
    --crm-border:         rgba(255, 255, 255, .10);
    --crm-border-strong:  rgba(255, 255, 255, .16);

    --crm-shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
    --crm-shadow:    0 2px 8px rgba(0, 0, 0, .35);
    --crm-shadow-lg: 0 12px 28px rgba(0, 0, 0, .45);
}

/* ============================================================================
   1. PAGE HEADER
   Title, context line and actions on one row, collapsing to a stack on mobile.
   ========================================================================= */

.crm-page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.crm-page-head__title {
    font-size: 1.35rem;
    font-weight: 600;
    line-height: 1.2;
    margin: 0;
    letter-spacing: -.01em;
}

.crm-page-head__sub {
    margin: .35rem 0 0;
    font-size: .8125rem;
    color: var(--crm-muted);
}

.crm-page-head__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
}

.crm-breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem;
    padding: 0;
    margin: 0 0 .5rem;
    list-style: none;
    font-size: .75rem;
    color: var(--crm-muted);
}

.crm-breadcrumb a {
    color: inherit;
    text-decoration: none;
}

.crm-breadcrumb a:hover {
    color: var(--bs-emphasis-color);
}

.crm-breadcrumb li + li::before {
    content: "/";
    margin-right: .4rem;
    opacity: .45;
}

/* ============================================================================
   2. KPI CARDS
   The accent bar is the only place the semantic colour appears at full
   strength, which keeps a row of four tiles readable rather than loud.
   ========================================================================= */

.crm-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.crm-kpi {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: .3rem;
    padding: 1.1rem 1.15rem 1.15rem;
    background: var(--crm-surface);
    border: 1px solid var(--crm-border);
    border-radius: var(--crm-radius);
    box-shadow: var(--crm-shadow-sm);
    overflow: hidden;
    transition: box-shadow .18s ease, transform .18s ease;
}

.crm-kpi::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 3px;
    background: var(--crm-kpi-accent, var(--crm-neutral));
}

.crm-kpi:hover {
    box-shadow: var(--crm-shadow);
    transform: translateY(-1px);
}

.crm-kpi__label {
    display: flex;
    align-items: center;
    gap: .4rem;
    font-size: .75rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--crm-muted);
}

.crm-kpi__label svg {
    width: 14px;
    height: 14px;
    color: var(--crm-kpi-accent, var(--crm-neutral));
}

.crm-kpi__value {
    font-size: 1.5rem;
    font-weight: 650;
    line-height: 1.15;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: var(--bs-emphasis-color);
}

.crm-kpi__meta {
    font-size: .75rem;
    color: var(--crm-muted);
}

.crm-kpi--receivable { --crm-kpi-accent: var(--crm-receivable); }
.crm-kpi--collected  { --crm-kpi-accent: var(--crm-collected); }
.crm-kpi--payable    { --crm-kpi-accent: var(--crm-payable); }
.crm-kpi--tax        { --crm-kpi-accent: var(--crm-tax); }
.crm-kpi--overdue    { --crm-kpi-accent: var(--crm-overdue); }
.crm-kpi--neutral    { --crm-kpi-accent: var(--crm-neutral); }

/* A KPI whose value is the headline of the page. */
.crm-kpi--hero .crm-kpi__value { font-size: 2rem; }

/* ============================================================================
   3. PANELS AND FORMS
   ========================================================================= */

.crm-panel {
    background: var(--crm-surface);
    border: 1px solid var(--crm-border);
    border-radius: var(--crm-radius);
    box-shadow: var(--crm-shadow-sm);
    margin-bottom: 1.25rem;
}

.crm-panel__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .9rem 1.15rem;
    border-bottom: 1px solid var(--crm-border);
}

.crm-panel__title {
    margin: 0;
    font-size: .9375rem;
    font-weight: 600;
}

.crm-panel__sub {
    margin: .15rem 0 0;
    font-size: .75rem;
    color: var(--crm-muted);
}

.crm-panel__body { padding: 1.15rem; }
.crm-panel__body--flush { padding: 0; }

.crm-panel__foot {
    padding: .75rem 1.15rem;
    border-top: 1px solid var(--crm-border);
    background: var(--crm-surface-sunken);
    border-radius: 0 0 var(--crm-radius) var(--crm-radius);
    font-size: .8125rem;
}

/* A caption band that sits at the *top* of a panel rather than the bottom —
   the "what this table is" note above a GSTR-1 section. Same sunken surface as
   the foot, with the rule and the radius flipped. */
.crm-panel__foot--top {
    border-top: 0;
    border-bottom: 1px solid var(--crm-border);
    border-radius: var(--crm-radius) var(--crm-radius) 0 0;
    color: var(--crm-muted);
}

/* Row actions — the icon strip at the end of a register row.
   The invoice register had six of these in one row, each a different Bootstrap
   colour: primary to add a payment, info to view, warning to raise a note,
   muted to edit. None of that is a claim about money, so none of it should be
   carrying a money colour — it was decoration, and it made the row look like
   six unrelated warnings. They are one neutral affordance now, and only the
   destructive one is coloured, because that is the only one you cannot undo. */
.crm-rowact {
    color: var(--crm-muted);
    line-height: 0;
    display: inline-flex;
    padding: .25rem;
    border-radius: var(--crm-radius-sm);
}

.crm-rowact:hover,
.crm-rowact:focus-visible {
    color: var(--bs-emphasis-color);
    background: var(--crm-surface-sunken);
}

.crm-rowact--danger:hover,
.crm-rowact--danger:focus-visible {
    color: var(--crm-ink-overdue);
}

/* A colour key for a chart series. It was a Bootstrap badge with a solid
   `bg-primary` / `bg-warning` fill, which is neither of the hues the chart
   actually draws with. */
.crm-swatch {
    display: inline-block;
    width: .7rem;
    height: .7rem;
    border-radius: 3px;
    vertical-align: baseline;
    background: var(--crm-neutral);
}

.crm-swatch--receivable { background: var(--crm-receivable); }
.crm-swatch--collected  { background: var(--crm-collected); }
.crm-swatch--payable    { background: var(--crm-payable); }
.crm-swatch--tax        { background: var(--crm-tax); }
.crm-swatch--overdue    { background: var(--crm-overdue); }

/* An in-cell proportional bar — revenue against expenses, month by month. The
   pair shares a row, so the widths are directly comparable. */
.crm-bars {
    display: flex;
    gap: 2px;
    height: 16px;
    align-items: stretch;
}

.crm-bar {
    border-radius: 3px;
    min-width: 1px;
    background: var(--crm-neutral);
}

.crm-bar--receivable { background: var(--crm-receivable); }
.crm-bar--collected  { background: var(--crm-collected); }
.crm-bar--payable    { background: var(--crm-payable); }
.crm-bar--tax        { background: var(--crm-tax); }
.crm-bar--overdue    { background: var(--crm-overdue); }

/* --- Forms -----------------------------------------------------------------
   A form is a panel whose body is fields and whose foot is the commit. The
   submit button used to sit in the field grid carrying style="margin-top:24px"
   to fake alignment with the inputs beside it — which put the irreversible
   action in a different place on every page, and moved it again whenever the
   grid rewrapped. In the foot it is always the last thing on the page, and the
   sunken band reads as the edge of the form rather than another field.
   ------------------------------------------------------------------------- */

.crm-form-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: .5rem;
}

/* Anything before the buttons — a required-fields note, a last-saved stamp —
   sits left while the actions stay right. */
.crm-form-actions__note {
    margin: 0 auto 0 0;
    font-size: .75rem;
    color: var(--crm-muted);
}

/* One button per row on a phone, primary action on top: at that width a row of
   buttons wraps into an order nobody chose. */
@media (max-width: 575.98px) {
    .crm-form-actions {
        flex-direction: column-reverse;
        align-items: stretch;
    }

    .crm-form-actions .btn { width: 100%; }
    .crm-form-actions__note { margin: .25rem 0 0; text-align: center; }
}

/* A named group of fields inside one panel body. Long forms (an invoice, a
   company profile) are several subjects at once, and the rule is what tells
   you the subject changed — a heading alone gets lost in a field grid. */
.crm-form-section {
    display: flex;
    align-items: center;
    gap: .6rem;
    margin: 1.5rem 0 .25rem;
    font-size: .75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--crm-muted);
}

.crm-form-section::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--crm-border);
}

/* The first section sits directly under the panel head, which is already a
   boundary. */
.crm-panel__body > .crm-form-section:first-child { margin-top: 0; }

/* Form controls. These were written against stock .card markup in the uplift
   below; they are not card-specific and belong with the components they
   actually style. */
.page-content .form-label {
    font-size: .8125rem;
    font-weight: 500;
    margin-bottom: .3rem;
}

.page-content .form-control,
.page-content .form-select {
    border-color: var(--crm-border-strong);
}

.page-content .form-text {
    font-size: .75rem;
    color: var(--crm-muted);
}

/* Live validation feedback on a field's help text — the GSTIN checksum result,
   say. These carry the .page-content prefix deliberately: the rule above is two
   classes, so a bare .text-success on the same element never won and the hint
   stayed muted whatever it said. */
.page-content .form-text.crm-form-text--ok  { color: var(--crm-ink-ok); }
.page-content .form-text.crm-form-text--bad { color: var(--crm-ink-overdue); }

/* A required field is marked on the label, not by colouring the input — the
   input only turns red once it is actually wrong. */
.crm-req::after {
    content: "*";
    margin-left: .2em;
    color: var(--crm-ink-overdue);
}

/* A derived value shown where a field would be — the tax treatment an invoice
   worked out from the place of supply, say. It sits on the form's grid like an
   input but must not look typed into, so it takes the sunken surface and the
   muted ink rather than .form-control's paper. (It used to be a .form-control
   with .bg-light, which is one fixed colour in both themes: a pale grey slab on
   a dark page.) */
.crm-readout {
    display: block;
    width: 100%;
    padding: .375rem .75rem;
    border: 1px solid var(--crm-border);
    border-radius: var(--bs-border-radius, .375rem);
    background: var(--crm-surface-sunken);
    color: var(--crm-muted);
    font-size: .8125rem;
    line-height: 1.5;
    min-height: calc(1.5em + .75rem + 2px);
}

/* Destructive text button — removing a line, discarding a row. Bootstrap's
   .text-danger is the raw danger hue in both themes; this is the ink token that
   was checked for text contrast on both surfaces. */
.crm-link-danger {
    color: var(--crm-ink-overdue);
    text-decoration: none;
}

.crm-link-danger:hover,
.crm-link-danger:focus {
    color: var(--crm-ink-overdue);
    text-decoration: underline;
}

/* --- Detail list -----------------------------------------------------------
   The read-only half of a record: label on the left, value on the right. The
   detail pages each spelled this as <p><strong>Label:</strong> value</p>, which
   gives no column to scan down and sets the label at the same weight and colour
   as the value it introduces. A grid puts every value on one edge and lets the
   label recede, so the page reads as data rather than prose.
   ------------------------------------------------------------------------- */

.crm-dl {
    display: grid;
    grid-template-columns: minmax(7rem, 34%) 1fr;
    gap: .55rem .9rem;
    margin: 0;
    font-size: .8125rem;
}

.crm-dl dt {
    font-weight: 400;
    color: var(--crm-muted);
}

.crm-dl dd {
    margin: 0;
    font-weight: 500;
    overflow-wrap: anywhere;
}

/* An empty value is stated, not left blank — a gap reads as a rendering fault
   rather than as "we do not have this". */
.crm-dl dd:empty::after {
    content: "—";
    color: var(--crm-muted);
    font-weight: 400;
}

/* A rule across both columns, to break a long list into subjects. */
.crm-dl__rule {
    grid-column: 1 / -1;
    height: 1px;
    margin: .35rem 0;
    background: var(--crm-border);
}

@media (max-width: 575.98px) {
    .crm-dl {
        grid-template-columns: 1fr;
        gap: .15rem;
    }

    .crm-dl dd { margin-bottom: .6rem; }
}

/* One entry in a running history — a remark on a lead, an audit line. Separated
   by a rule rather than boxed, because the list is one thread and boxing each
   entry makes the scroll read as unrelated cards. */
.crm-feed__item {
    padding: .75rem 1.15rem;
    border-bottom: 1px solid var(--crm-border);
    font-size: .8125rem;
}

.crm-feed__item:last-child { border-bottom: 0; }

/* --- Toast -----------------------------------------------------------------
   Flash feedback after a redirect. Toastify is told to add no background of its
   own; the tone class carries it, so the toast follows the theme like anything
   else. It previously took four hard-coded Bootstrap-4 hexes inline, which were
   one colour in both modes.

   A tinted surface rather than a solid fill: a solid colour slab at the corner
   of a dark page is a flashbang, and the tint keeps the ink on the same token
   scale everything else uses.
   ------------------------------------------------------------------------- */

.crm-toast {
    display: flex;
    align-items: flex-start;
    gap: .6rem;
    max-width: 26rem;
    padding: .75rem .9rem;
    border: 1px solid var(--crm-border-strong);
    border-left: 3px solid var(--crm-toast-accent, var(--crm-neutral));
    border-radius: var(--crm-radius-sm);
    background: var(--crm-surface);
    box-shadow: var(--crm-shadow-lg);
    color: var(--bs-body-color);
    font-size: .8125rem;
    line-height: 1.5;
    text-align: left;
}

/* The icon takes the tone colour; the message stays body ink so it is read at
   full contrast whatever the tone. */
.crm-toast__icon {
    flex: 0 0 auto;
    display: flex;
    margin-top: .05rem;
    color: var(--crm-toast-accent, var(--crm-neutral));
}

.crm-toast__icon svg { width: 16px; height: 16px; }
.crm-toast__body { flex: 1 1 auto; }

.crm-toast--ok   { --crm-toast-accent: var(--crm-ink-ok); }
.crm-toast--bad  { --crm-toast-accent: var(--crm-ink-bad); }
.crm-toast--warn { --crm-toast-accent: var(--crm-ink-warn); }
.crm-toast--info { --crm-toast-accent: var(--crm-ink-info); }

/* Toastify sets its own inline background on the wrapper; neutralise it so the
   .crm-toast inside is the only thing drawing. */
.toastify.crm-toast-wrap {
    position: fixed;
    background: none;
    box-shadow: none;
    padding: 0;
    border-radius: var(--crm-radius-sm);
}

/* Toastify appends its close button as a *sibling* of the node it was handed,
   so without this it lands outside the panel it is supposed to close — a stray
   glyph floating off the bottom-left corner. Pull it back inside, top-right,
   and give it a real hit area. */
.crm-toast-wrap .toast-close {
    position: absolute;
    top: 0;
    right: 0;
    width: 1.9rem;
    height: 1.9rem;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: none;
    color: var(--crm-muted);
    font-size: 1rem;
    line-height: 1;
    opacity: 1;
    cursor: pointer;
}

.crm-toast-wrap .toast-close:hover {
    color: var(--bs-emphasis-color);
}

/* Leave room for it, so a long message does not run under the button. */
.crm-toast--bad { padding-right: 2rem; }

/* --- Banner ----------------------------------------------------------------
   A statement about the document you are looking at — cancelled, still a draft.
   Not Bootstrap's .alert: .alert-dark is near-black text on near-black in dark
   mode, and .alert-warning's amber ink is ~2.4:1 on its own tint. The tint/ink
   pairs here are the ones already checked in both themes, and the left bar
   carries the meaning so it survives being read in greyscale.
   ------------------------------------------------------------------------- */

.crm-banner {
    padding: .8rem 1.05rem;
    margin-bottom: 1.25rem;
    border: 1px solid var(--crm-border);
    border-left: 3px solid var(--crm-neutral);
    border-radius: var(--crm-radius);
    background: var(--crm-surface-sunken);
    font-size: .8125rem;
    line-height: 1.55;
}

.crm-banner--cancelled {
    border-left-color: var(--crm-overdue);
    background: color-mix(in srgb, var(--crm-overdue) 8%, transparent);
    color: var(--crm-ink-overdue);
}

.crm-banner--draft {
    border-left-color: var(--crm-payable);
    background: color-mix(in srgb, var(--crm-payable) 10%, transparent);
    color: var(--crm-ink-payable);
}

/* An initial standing in for a photograph, on a record that has no photograph.
   The tint and ink are the receivable pair rather than Bootstrap's
   .bg-primary-subtle, whose ink is the theme's washed lilac. */
.crm-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 70px;
    height: 70px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--crm-receivable) 14%, transparent);
    color: var(--crm-ink-receivable);
    font-size: 28px;
    font-weight: 600;
    line-height: 1;
}

/* Raw stored data — a JSON blob on a record. Monospaced and on the sunken
   surface, so it reads as machine output rather than as prose. */
.crm-code {
    padding: .75rem .9rem;
    border-radius: var(--crm-radius);
    background: var(--crm-surface-sunken);
    color: var(--crm-muted);
    font-size: .75rem;
    line-height: 1.55;
    overflow-x: auto;
    white-space: pre;
}

/* --- Tabs ------------------------------------------------------------------
   A tab strip standing in for the panel head, so the rule under the tabs is the
   panel's own boundary rather than a second line just below it.
   ------------------------------------------------------------------------- */

.crm-tabs {
    gap: .25rem;
    padding: 0 1.15rem;
    margin: 0;
    border-bottom: 1px solid var(--crm-border);
}

.crm-tabs .nav-link {
    padding: .7rem .35rem;
    margin-bottom: -1px;
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    background: none;
    font-size: .8125rem;
    font-weight: 500;
    color: var(--crm-muted);
}

.crm-tabs .nav-link:hover {
    border-bottom-color: var(--crm-border-strong);
    color: var(--bs-emphasis-color);
    isolation: auto;
}

/* The active tab is marked by the underline and the ink together. Colour alone
   would be the only signal for anyone who cannot separate these two hues. */
.crm-tabs .nav-link.active {
    background: none;
    border-bottom-color: var(--crm-receivable);
    color: var(--crm-ink-receivable);
    font-weight: 600;
}

.crm-tabs .nav-link + .nav-link { margin-left: .9rem; }
.crm-tabs .nav-item + .nav-item { margin-left: .9rem; }

/* ============================================================================
   4. DATA TABLES
   Money is set in tabular figures so columns of digits line up, and numeric
   columns are right-aligned — the two things that make a ledger scannable.
   ========================================================================= */

.crm-table {
    width: 100%;
    margin: 0;
    border-collapse: separate;
    border-spacing: 0;
    font-size: .8125rem;
}

.crm-table > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: .7rem .85rem;
    background: var(--crm-surface-sunken);
    border-bottom: 1px solid var(--crm-border-strong);
    font-size: .6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--crm-muted);
    white-space: nowrap;
}

.crm-table > tbody > tr > td {
    padding: .7rem .85rem;
    border-bottom: 1px solid var(--crm-border);
    vertical-align: middle;
}

.crm-table > tbody > tr:last-child > td { border-bottom: 0; }

.crm-table > tbody > tr {
    transition: background-color .12s ease;
}

.crm-table > tbody > tr:hover {
    background: var(--crm-surface-sunken);
}

/* Numeric cells. `.num` on the th and td keeps the header over its column. */
.crm-table .num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Dates and short labels are read as one token — wrapping "11-Jul-26" or
   "Intra-state" over three lines makes a register unscannable and triples the
   row height. The table scrolls horizontally instead. */
.crm-table .date,
.crm-table .date .crm-sub,
.crm-table .nowrap {
    white-space: nowrap;
}

.crm-table .num--strong {
    font-weight: 600;
    color: var(--bs-emphasis-color);
}

/* A total row that closes a table. */
.crm-table > tfoot > tr > td,
.crm-table tr.crm-total > td {
    padding: .75rem .85rem;
    background: var(--crm-surface-sunken);
    border-top: 2px solid var(--crm-border-strong);
    font-weight: 650;
    font-variant-numeric: tabular-nums;
}

/* Secondary line beneath a cell's main value. */
.crm-sub {
    display: block;
    margin-top: .1rem;
    font-size: .6875rem;
    line-height: 1.35;
    color: var(--crm-muted);
}

.crm-sub--warn  { color: var(--crm-ink-payable); }
.crm-sub--alert { color: var(--crm-ink-overdue); }

/* Row states. */
tr.crm-row--void td { opacity: .55; }
tr.crm-row--void .crm-docnum { text-decoration: line-through; }

/* ============================================================================
   5. PILLS AND CHIPS
   ========================================================================= */

.crm-pill {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .18rem .5rem;
    border-radius: 999px;
    font-size: .6875rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    border: 1px solid transparent;
}

.crm-pill::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.crm-pill--none::before { display: none; }

.crm-pill--draft     { color: var(--crm-ink-neutral);    background: color-mix(in srgb, var(--crm-neutral) 14%, transparent); }
.crm-pill--sent      { color: var(--crm-ink-receivable); background: color-mix(in srgb, var(--crm-receivable) 14%, transparent); }
.crm-pill--unpaid    { color: var(--crm-ink-payable);    background: color-mix(in srgb, var(--crm-payable) 16%, transparent); }
.crm-pill--partial   { color: var(--crm-ink-receivable); background: color-mix(in srgb, var(--crm-receivable) 14%, transparent); }
.crm-pill--paid      { color: var(--crm-ink-collected);  background: color-mix(in srgb, var(--crm-collected) 16%, transparent); }
.crm-pill--overdue   { color: var(--crm-ink-overdue);    background: color-mix(in srgb, var(--crm-overdue) 16%, transparent); }
.crm-pill--cancelled { color: var(--crm-ink-neutral);    background: color-mix(in srgb, var(--crm-neutral) 14%, transparent); }
.crm-pill--tax       { color: var(--crm-ink-tax);        background: color-mix(in srgb, var(--crm-tax) 16%, transparent); }

/* Document-type chip — squarer than a status pill so the two never read as
   the same kind of information. */
.crm-chip {
    display: inline-block;
    padding: .1rem .4rem;
    border-radius: 5px;
    font-size: .625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    border: 1px solid currentColor;
    line-height: 1.6;
    white-space: nowrap;
}

.crm-chip--invoice  { color: var(--crm-ink-receivable); }
.crm-chip--credit   { color: var(--crm-ink-overdue); }
.crm-chip--debit    { color: var(--crm-ink-collected); }
.crm-chip--proforma { color: var(--crm-ink-neutral); }
.crm-chip--bos      { color: var(--crm-ink-tax); }
.crm-chip--rcm      { color: var(--crm-ink-overdue); }

.crm-docnum {
    font-weight: 600;
    letter-spacing: -.01em;
    white-space: nowrap;
}

/* Tag whose colour is data — a contact group the owner painted themselves.
   Unlike a pill or chip the hue carries no meaning the stylesheet knows, so
   crmTag() computes the pair and passes it in: a tint of the chosen colour for
   the field and the same colour stepped darker (or lighter) for the text, each
   already checked to clear AA. Both themes are supplied because a tint mixed
   over white disappears on a dark panel.

   Reading them as a tint rather than a solid fill also stops a table full of
   groups turning into a paint chart. */
.crm-tag {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    padding: .1rem .45rem;
    border-radius: 5px;
    font-size: .6875rem;
    font-weight: 600;
    line-height: 1.6;
    white-space: nowrap;
    color: var(--tag-ink);
    background: var(--tag-bg);
}

html[data-bs-theme="dark"] .crm-tag {
    color: var(--tag-ink-dark);
    background: var(--tag-bg-dark);
}

.crm-tag i,
.crm-tag svg { width: 12px; height: 12px; }

.crm-tag + .crm-tag { margin-left: .25rem; }

/* ============================================================================
   5b. PAGINATION
   ========================================================================= */

/* The base theme sizes every .page-link as a fixed 30px square, which suits
   numbers and truncates the words either side of them. Width goes back to the
   content while the square minimum keeps the numeric buttons even. */
.crm-pager .page-link {
    width: auto;
    min-width: 30px;
    padding-inline: .5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-color: var(--crm-border);
    color: var(--crm-ink-neutral);
    font-size: .8125rem;
}

.crm-pager .page-item.active .page-link {
    background: var(--crm-receivable);
    border-color: var(--crm-receivable);
    color: var(--crm-on-accent);
}

.crm-pager .page-item.disabled .page-link {
    color: var(--crm-muted);
    background: transparent;
    border-color: var(--crm-border);
    opacity: 1;   /* the theme fades disabled items, which compounds on the grey */
}

/* ============================================================================
   6. FILTER BAR
   ========================================================================= */

.crm-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
}

.crm-filters .form-select,
.crm-filters .form-control {
    width: auto;
    min-width: 130px;
    font-size: .8125rem;
    border-color: var(--crm-border-strong);
}

.crm-filters .form-control[type="search"] { min-width: 210px; }

/* ============================================================================
   7. EMPTY STATE
   ========================================================================= */

.crm-empty {
    padding: 3rem 1.5rem;
    text-align: center;
    color: var(--crm-muted);
}

.crm-empty svg {
    width: 34px;
    height: 34px;
    margin-bottom: .75rem;
    opacity: .35;
}

.crm-empty__title {
    font-size: .9375rem;
    font-weight: 600;
    color: var(--bs-emphasis-color);
    margin-bottom: .25rem;
}

.crm-empty__text {
    font-size: .8125rem;
    max-width: 380px;
    margin: 0 auto;
}

/* ============================================================================
   8. ACTION ITEMS
   The dashboard's "what needs doing" list.
   ========================================================================= */

.crm-actions { display: grid; gap: .5rem; }

.crm-action {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .7rem .85rem;
    border: 1px solid var(--crm-border);
    border-left: 3px solid var(--crm-action-accent, var(--crm-neutral));
    border-radius: var(--crm-radius-sm);
    background: var(--crm-surface);
    color: inherit;
    text-decoration: none;
    transition: border-color .15s ease, background-color .15s ease;
}

.crm-action:hover {
    background: var(--crm-surface-sunken);
    border-color: var(--crm-border-strong);
    border-left-color: var(--crm-action-accent, var(--crm-neutral));
    color: inherit;
}

.crm-action__count {
    font-size: 1.1rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--crm-action-ink, var(--crm-ink-neutral));
    min-width: 2ch;
    text-align: center;
}

.crm-action__text { font-size: .8125rem; line-height: 1.35; }
.crm-action__text strong { display: block; font-weight: 600; }
.crm-action__text span { color: var(--crm-muted); font-size: .75rem; }

.crm-action--overdue    { --crm-action-accent: var(--crm-overdue); --crm-action-ink: var(--crm-ink-overdue); }
.crm-action--payable    { --crm-action-accent: var(--crm-payable); --crm-action-ink: var(--crm-ink-payable); }
.crm-action--tax        { --crm-action-accent: var(--crm-tax); --crm-action-ink: var(--crm-ink-tax); }
.crm-action--receivable { --crm-action-accent: var(--crm-receivable); --crm-action-ink: var(--crm-ink-receivable); }
.crm-action--collected  { --crm-action-accent: var(--crm-collected); --crm-action-ink: var(--crm-ink-collected); }

/* ============================================================================
   9. AGEING BAR
   Receivables split into buckets, as one bar rather than five numbers.
   ========================================================================= */

.crm-ageing {
    display: flex;
    height: 8px;
    border-radius: 999px;
    overflow: hidden;
    background: var(--crm-surface-sunken);
    margin-bottom: .75rem;
}

.crm-ageing__seg { height: 100%; }

.crm-ageing__seg--current { background: var(--crm-collected); }
.crm-ageing__seg--b30     { background: var(--crm-receivable); }
.crm-ageing__seg--b60     { background: var(--crm-payable); }
.crm-ageing__seg--b90     { background: #f97316; }
.crm-ageing__seg--b90p    { background: var(--crm-overdue); }

.crm-legend {
    display: flex;
    flex-wrap: wrap;
    gap: .85rem;
    font-size: .75rem;
    color: var(--crm-muted);
}

.crm-legend__item { display: flex; align-items: center; gap: .35rem; }

.crm-legend__dot {
    width: 8px;
    height: 8px;
    border-radius: 2px;
    flex: none;
}

/* ============================================================================
   10. UTILITIES
   ========================================================================= */

.crm-num      { font-variant-numeric: tabular-nums; }
.crm-money-in { color: var(--crm-ink-collected); font-weight: 600; }
.crm-money-out{ color: var(--crm-ink-overdue);  font-weight: 600; }

.crm-scroll-x {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* The sidebar highlight the base theme leaves to the page. */
.wrapper .main-nav .navbar-nav .menu-item.active > .menu-link .nav-text {
    font-weight: 600;
}

/* ============================================================================
   11. DOCUMENT SHEET

   An invoice is a printed artifact. inc/invoice_template.php sets ink colours
   directly because the same markup has to survive mPDF, which knows nothing
   about themes — so on a dark page that would be near-black text on a
   near-black panel.

   Rather than theming the document, the preview is given the paper it is
   printed on: a light sheet in both modes. `color-scheme: light` also keeps
   form controls and scrollbars inside it light, so the sheet reads as one
   object. What the customer receives and what the owner sees stay identical.
   ========================================================================= */

.crm-document {
    color-scheme: light;
    background: #ffffff;
    color: #1a1a1a;
    border-radius: var(--crm-radius-sm);
    padding: 1.5rem;
    overflow-x: auto;
}

html[data-bs-theme="dark"] .crm-document {
    /* A pure-white sheet against a dark page is a glare source; this is still
       clearly paper, just turned down. */
    background: #f4f5f7;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .08);
}

.crm-document a { color: #0d4ea6; }

@media (max-width: 575.98px) {
    .crm-document { padding: 1rem .75rem; }
}

/* ============================================================================
   12. BASE-THEME FIXES

   This section used to also carry a "uplift" for stock Bootstrap .card and
   .table markup, so that pages not yet rebuilt on the components above did not
   read as a second product. Every page is now on .crm-panel and .crm-table, so
   those rules have been deleted — the last five (reports_business,
   reports_gstr1, reports_gstr3b, add_payment, expense_payments) were migrated
   and nothing renders a stock card any more.

   What remains is not migration debt. These are corrections to theme defaults
   that fail contrast, and they stay regardless of which components a page uses.
   ========================================================================= */

/* Brand. The base theme made primary actions use a financial-state colour, which muddled navigation
   and "add" buttons with financial states. Indigo is the product accent; blue
   marks collection and teal marks a successful system action. */
:root {
    --crm-brand:       #4f46e5;
    --crm-brand-hover: #4338ca;
    --crm-brand-active:#3730a3;

    --bs-primary:                var(--crm-brand);
    --bs-primary-rgb:            79, 70, 229;
    --bs-primary-text-emphasis:  #3730a3;
    --bs-primary-bg-subtle:      #e8e7ff;
    --bs-primary-border-subtle:  #c7c5ff;
    --bs-focus-ring-color:       rgba(79, 70, 229, .25);
}

html[data-bs-theme="dark"] {
    --crm-brand:       #818cf8;
    --crm-brand-hover: #a5b4fc;
    --crm-brand-active:#6366f1;

    --bs-primary-rgb:            129, 140, 248;
    --bs-primary-text-emphasis:  #c7d2fe;
    --bs-primary-bg-subtle:      rgba(129, 140, 248, .16);
    --bs-primary-border-subtle:  #4f46a5;
    --bs-focus-ring-color:       rgba(129, 140, 248, .32);
}

.btn-primary {
    --bs-btn-color: var(--crm-on-accent);
    --bs-btn-bg: var(--crm-brand);
    --bs-btn-border-color: var(--crm-brand);
    --bs-btn-hover-color: var(--crm-on-accent);
    --bs-btn-hover-bg: var(--crm-brand-hover);
    --bs-btn-hover-border-color: var(--crm-brand-hover);
    --bs-btn-active-color: var(--crm-on-accent);
    --bs-btn-active-bg: var(--crm-brand-active);
    --bs-btn-active-border-color: var(--crm-brand-active);
    --bs-btn-disabled-bg: var(--crm-brand);
    --bs-btn-disabled-border-color: var(--crm-brand);
}

.btn-outline-primary {
    --bs-btn-color: var(--crm-ink-receivable);
    --bs-btn-border-color: var(--crm-receivable);
    --bs-btn-hover-color: var(--crm-on-accent);
    --bs-btn-hover-bg: var(--crm-brand);
    --bs-btn-hover-border-color: var(--crm-brand);
    --bs-btn-active-color: var(--crm-on-accent);
    --bs-btn-active-bg: var(--crm-brand-active);
    --bs-btn-active-border-color: var(--crm-brand-active);
}

.form-check-input:checked {
    background-color: var(--crm-brand);
    border-color: var(--crm-brand);
}

html.topbar-dark { --bs-topbar-bg: #4338ca; }
html[data-bs-theme="dark"].topbar-dark { --bs-topbar-bg: #1e1b4b; }
html.sidebar-light { --bs-main-menu-item-hover-color: var(--crm-brand); }
html.sidebar-dark { --bs-main-menu-item-hover-color: #c7d2fe; }

/* The bundled theme hard-codes its old primary colour in navigation selectors, so
   variables alone cannot recolour the active sidebar and topbar controls. */
.topbar .topbar-item .topbar-button.active,
.topbar .topbar-item .topbar-button.show,
.topbar .topbar-item .topbar-button:active,
.topbar .topbar-item .topbar-button:hover {
    color: var(--crm-brand);
}

.wrapper .main-nav .navbar-nav .menu-item .menu-link:hover .nav-icon svg,
.wrapper .main-nav .navbar-nav .menu-item.active .nav-icon,
.wrapper .main-nav .navbar-nav .menu-item.active .nav-text,
.wrapper .main-nav .navbar-nav .menu-item.active .nav-icon svg,
.wrapper .main-nav .navbar-nav .menu-item.active .nav-text svg {
    color: var(--crm-brand);
    fill: var(--crm-brand);
}

.wrapper .main-nav .navbar-nav .menu-item.active .menu-link::before {
    background-color: var(--crm-brand);
}

/* Links. The theme ships --bs-link-color: #8486a7, a washed lilac grey that
   measures 3.5:1 on white — under AA for body text, and every link in the app
   inherits it, including the row-opening document numbers and any pill drawn as
   a link. This is not the brand colour (that is indigo on .btn-primary), so
   repointing it changes nothing anyone chose; it reuses the design layer's own
   primary hue, which is already checked in both modes. */
:root {
    --bs-link-color:       var(--crm-ink-receivable);
    --bs-link-hover-color: var(--crm-receivable);
    --bs-link-color-rgb:   55, 48, 163;
}

html[data-bs-theme="dark"] {
    --bs-link-color-rgb: 165, 180, 252;
}

/* ==========================================================================
   12b. BUSINESS REPORTS
   The report is a working financial review, not a dashboard copied from a
   chart library: the selected period is explicit, trend bars share one scale,
   and ageing is visible before its invoice detail.
   ========================================================================= */

.crm-report-filter .crm-panel__body {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.crm-report-filter__intro { display: grid; gap: .12rem; }
.crm-report-filter__intro strong { font-size: .9375rem; }
.crm-report-filter__intro > span:last-child { font-size: .75rem; color: var(--crm-muted); }

.crm-report-filter__eyebrow {
    color: var(--crm-ink-receivable);
    font-size: .6875rem;
    font-weight: 650;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.crm-report-filter__form {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
}

.crm-report-series { display: grid; gap: 3px; min-width: 7rem; }
.crm-report-series__track {
    height: 6px;
    overflow: hidden;
    border-radius: 999px;
    background: var(--crm-surface-sunken);
}
.crm-report-series__bar { height: 100%; min-width: 2px; border-radius: inherit; }
.crm-report-series__bar--revenue { background: var(--crm-collected); }
.crm-report-series__bar--expense { background: var(--crm-payable); }

.crm-report-breakdown { padding: .25rem 1.15rem .85rem; }
.crm-report-breakdown__item { padding: .85rem 0; border-bottom: 1px solid var(--crm-border); }
.crm-report-breakdown__item:last-child { border-bottom: 0; }
.crm-report-breakdown__top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    font-size: .8125rem;
}
.crm-report-breakdown__top strong { font-weight: 600; }
.crm-report-breakdown__track {
    height: 5px;
    margin-top: .55rem;
    overflow: hidden;
    border-radius: 999px;
    background: var(--crm-surface-sunken);
}
.crm-report-breakdown__track > div {
    height: 100%;
    min-width: 2px;
    border-radius: inherit;
    background: var(--crm-payable);
}

tr.crm-report-row--credit > td { background: color-mix(in srgb, var(--crm-overdue) 7%, transparent); }

@media (max-width: 575.98px) {
    .crm-report-filter__form { width: 100%; }
    .crm-report-filter__form .form-select,
    .crm-report-filter__form .form-control,
    .crm-report-filter__form .btn { flex: 1 1 auto; }
}

/* .btn-outline-secondary keeps its light-mode ink (#5d7186) when the page goes
   dark, landing at 3.0:1 on the dark surface. The theme has no dark variant, so
   the button borrows the muted token that is already checked in both modes. */
html[data-bs-theme="dark"] .btn-outline-secondary {
    --bs-btn-color:              var(--crm-muted);
    --bs-btn-border-color:       var(--crm-border-strong);
    --bs-btn-hover-color:        var(--bs-emphasis-color);
    --bs-btn-hover-bg:           rgba(255, 255, 255, .06);
    --bs-btn-hover-border-color: var(--crm-border-strong);
}


/* The theme keeps the same grey for `.text-secondary` in both modes, which
   lands at about 2.5:1 on a dark surface — under the 3:1 floor and genuinely
   hard to read. Lifted here rather than in the theme so a theme upgrade does
   not silently undo it. */
html[data-bs-theme="dark"] .text-secondary,
html[data-bs-theme="dark"] .badge.text-secondary {
    color: #9aa7b8 !important;
}


/* ============================================================================
   13. PRINT
   Reports and invoices are printed and handed to an accountant, so the chrome
   has to disappear rather than merely shrink.
   ========================================================================= */

@media print {
    .main-nav,
    .topbar,
    .footer,
    .crm-page-head__actions,
    .crm-filters,
    .no-print { display: none !important; }

    .page-container,
    .page-content { margin: 0 !important; padding: 0 !important; }

    .crm-panel,
    .crm-kpi {
        box-shadow: none !important;
        border: 1px solid #ccc !important;
        break-inside: avoid;
    }

    .crm-table > thead > tr > th {
        position: static;
        background: #f2f2f2 !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    a[href]::after { content: ""; }
}

/* ============================================================================
   14. MOTION
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
    .crm-kpi,
    .crm-action,
    .crm-table > tbody > tr {
        transition: none;
    }

    .crm-kpi:hover { transform: none; }
}
