/* ═══════════════════════════════════════════════════════════════════════════
   ALCINEX DESIGN TOKENS  ·  Batch 7
   ───────────────────────────────────────────────────────────────────────────
   The single source of truth for every colour, size, space, radius and shadow
   in the application. Nothing downstream — no component, no view — may declare
   a raw hex code or a raw pixel value. If you need a value that is not here,
   add it here first.

   Why that rule is worth keeping: 96 screens get rolled out against this file.
   A direction change must stay a one-file edit, not a 96-screen rewrite.

   LAYERS, in cascade order (later wins on equal specificity):
     1. PRIMITIVES   — the raw ramps. Direction-independent. Never used directly
                       by a component; only referenced by layer 2.
     2. SEMANTICS    — role-named tokens (surface, text, border, ...). These are
                       what components consume. Redefined per direction.
     3. DIRECTIONS   — A / B / C swap layer 2 only. No component markup changes.
     4. DARK         — overrides layer 2 again, and wins over any direction,
                       because dark mode is dark whichever direction is applied.
     5. BOOTSTRAP    — Bootstrap 5.3's own CSS variables mapped onto layer 2, so
                       Bootstrap components inherit the theme instead of being
                       fought with !important overrides.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ── Typeface ───────────────────────────────────────────────────────────────
   Inter, self-hosted. NOT a CDN: the brief calls for reliable loading in India
   and a same-origin woff2 removes a third-party DNS + TLS + cache-miss from the
   critical path entirely. 48 KB (latin) + 85 KB (latin-ext), variable weight, so
   one file covers 400/500/600/700 with no extra requests.

   Inter is chosen over the system stack specifically for `tnum` — real tabular
   figures. This app is wall-to-wall money columns, and proportional digits make
   a column of rupee amounts impossible to scan or compare vertically.
   `font-display: swap` so text is never invisible while the font arrives.       */

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../../fonts/inter/inter-latin-wght-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                   U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                   U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../../fonts/inter/inter-latin-ext-wght-normal.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                   U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                   U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


/* ═══ LAYER 1 — PRIMITIVES ═══════════════════════════════════════════════════
   Raw ramps. Direction-independent. Components must NOT reference these.       */

:root {

    /* ── Primary: dark blue ──────────────────────────────────────────────────
       Buttons, links, active states, focus rings. The 600 step is the base:
       white text on it measures 6.81:1, comfortably past WCAG AA (4.5:1) and
       close to AAA, so a primary button never needs a contrast exception.      */
    --ax-blue-50:  #eef4fb;
    --ax-blue-100: #d6e4f5;
    --ax-blue-200: #adc8ea;
    --ax-blue-300: #7ea6dc;
    --ax-blue-400: #4b7fc7;
    --ax-blue-500: #2a6ab8;
    --ax-blue-600: #1e5aa8;   /* BASE */
    --ax-blue-700: #17488a;
    --ax-blue-800: #0e2d58;
    --ax-blue-900: #0a2140;

    /* ── Neutral: white → gray → charcoal → near-black ──────────────────────
       Surfaces, borders, text, and the Direction C navigation shell.           */
    --ax-neutral-0:   #ffffff;
    --ax-neutral-25:  #fafbfc;
    --ax-neutral-50:  #f5f6f8;
    --ax-neutral-100: #eceef2;
    --ax-neutral-200: #dde0e7;
    --ax-neutral-300: #c3c8d2;
    --ax-neutral-400: #98a0af;
    --ax-neutral-500: #6b7480;   /* muted text — 4.74:1 on white, passes AA */
    --ax-neutral-600: #4d5561;
    --ax-neutral-700: #363c46;
    --ax-neutral-800: #262b33;   /* body text — 14.2:1 on white */
    --ax-neutral-900: #1a1d23;   /* headings, Direction C sidebar */
    --ax-neutral-950: #121418;

    /* ── Semantic hues ──────────────────────────────────────────────────────
       DANGER IS THE DARK RED, AND IT IS AN ACCENT ONLY. Destructive actions,
       validation errors, overdue money, alerts. It is never a Save button and
       never a primary CTA: in a CRM red already means delete / error / overdue,
       and a red confirm button trains users to read every action as a warning.
       This is enforced in components.css — there is no `.btn-danger` styling
       applied to submit buttons, and the rule is restated in COMPONENTS.md.    */
    --ax-success-50:  #e8f5ee;
    --ax-success-100: #c6e6d4;
    --ax-success-600: #1a7f4b;   /* white on it: 5.04:1 */
    --ax-success-700: #14653c;

    --ax-warning-50:  #fdf3e3;
    --ax-warning-100: #f8e2bd;
    --ax-warning-600: #a35a00;   /* dark amber — readable as TEXT on light */
    --ax-warning-700: #834800;

    --ax-danger-50:   #fbecef;
    --ax-danger-100:  #f4ccd4;
    --ax-danger-600:  #9b1c2e;   /* THE dark red — white on it: 8.08:1 */
    --ax-danger-700:  #7d1625;

    --ax-info-50:     #e6f2f7;
    --ax-info-100:    #c2e0eb;
    --ax-info-600:    #0b6b8f;
    --ax-info-700:    #08556f;

    /* ── Typography ─────────────────────────────────────────────────────────
       BASE SIZE 14px (0.875rem), not Bootstrap's 16px.

       The root stays at 16px on purpose. Shrinking `html` to 14px would scale
       every rem in Bootstrap — including ones that should not shrink — and
       silently break any px/rem mixing already in the views. Instead the root
       keeps standard rem arithmetic and the BODY size is set explicitly, so
       every number below means exactly what it says.                           */
    --ax-font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto,
                    'Helvetica Neue', Arial, 'Noto Sans', sans-serif;
    --ax-font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
                    'Liberation Mono', monospace;

    --ax-text-2xs: 0.6875rem;  /* 11px — badge text, table meta */
    --ax-text-xs:  0.75rem;    /* 12px — help text, captions */
    --ax-text-sm:  0.8125rem;  /* 13px — TABLE CELLS, dense UI */
    --ax-text-md:  0.875rem;   /* 14px — BODY BASE, inputs, buttons */
    --ax-text-lg:  1rem;       /* 16px — card titles */
    --ax-text-xl:  1.125rem;   /* 18px — page title */
    --ax-text-2xl: 1.375rem;   /* 22px — stat card figures */
    --ax-text-3xl: 1.75rem;    /* 28px — dashboard hero numbers */

    --ax-weight-normal:   400;
    --ax-weight-medium:   500;
    --ax-weight-semibold: 600;
    --ax-weight-bold:     700;

    --ax-leading-tight:  1.25;
    --ax-leading-snug:   1.35;
    --ax-leading-normal: 1.45;   /* the table-row line-height */
    --ax-leading-loose:  1.6;

    /* ── Spacing — a single 4px-based scale ─────────────────────────────────
       Every margin and padding in the app comes from this scale. Nothing in
       between: if a gap "needs" 7px, it needs 6 or 8.                          */
    --ax-space-0:  0;
    --ax-space-1:  0.125rem;   /*  2px */
    --ax-space-2:  0.25rem;    /*  4px */
    --ax-space-3:  0.375rem;   /*  6px */
    --ax-space-4:  0.5rem;     /*  8px */
    --ax-space-5:  0.625rem;   /* 10px */
    --ax-space-6:  0.75rem;    /* 12px */
    --ax-space-7:  1rem;       /* 16px */
    --ax-space-8:  1.25rem;    /* 20px */
    --ax-space-9:  1.5rem;     /* 24px */
    --ax-space-10: 2rem;       /* 32px */
    --ax-space-11: 2.5rem;     /* 40px */
    --ax-space-12: 3rem;       /* 48px */

    /* ── Z-index — named, so nothing is invented at the call site ───────────
       Kept above the existing maintenance banner (3000) already in the layout. */
    --ax-z-base:      0;
    --ax-z-sticky:    100;   /* sticky table headers */
    --ax-z-sidebar:   1030;
    --ax-z-topbar:    1035;
    --ax-z-dropdown:  1050;
    --ax-z-modal:     1060;
    --ax-z-toast:     1080;
    --ax-z-banner:    3000;

    /* ── Motion ─────────────────────────────────────────────────────────────
       Short, because this is a tool people use all day, not a landing page.    */
    --ax-transition-fast: 120ms ease;
    --ax-transition-base: 180ms ease;
    --ax-easing-standard: cubic-bezier(0.2, 0, 0.2, 1);
}

/* Anyone who has asked their OS to reduce motion gets none of it. */
@media (prefers-reduced-motion: reduce) {
    :root {
        --ax-transition-fast: 0ms;
        --ax-transition-base: 0ms;
    }
}


/* ═══ LAYER 2 — SEMANTICS ════════════════════════════════════════════════════
   Role-named tokens. THESE are what components consume. The values here are
   Direction A (professional / conservative), which is also the working default
   — see LAYER 3 for how B and C replace them.                                  */

:root,
:root[data-ax-direction="a"],
.ax-dir-a {

    /* Surfaces */
    --ax-surface-app:       var(--ax-neutral-50);    /* the page canvas */
    --ax-surface-raised:    var(--ax-neutral-0);     /* cards, tables, modals */
    --ax-surface-sunken:    var(--ax-neutral-100);   /* table headers, wells */
    --ax-surface-hover:     var(--ax-neutral-50);
    --ax-surface-selected:  var(--ax-blue-50);
    --ax-surface-disabled:  var(--ax-neutral-100);
    --ax-surface-elevated:  var(--ax-surface-raised);  /* a card lifted above the raised plane; only differs from raised in dark */

    /* The navigation shell. Direction C is the one that moves these. */
    --ax-shell-sidebar-bg:      var(--ax-neutral-0);
    --ax-shell-sidebar-fg:      var(--ax-neutral-700);
    --ax-shell-sidebar-muted:   var(--ax-neutral-500);
    --ax-shell-sidebar-border:  var(--ax-neutral-200);
    --ax-shell-sidebar-hover:   var(--ax-neutral-100);
    --ax-shell-sidebar-active-bg: var(--ax-blue-50);
    --ax-shell-sidebar-active-fg: var(--ax-blue-700);
    --ax-shell-sidebar-active-marker: var(--ax-blue-600);
    --ax-shell-topbar-bg:       var(--ax-neutral-0);
    --ax-shell-topbar-fg:       var(--ax-neutral-900);
    --ax-shell-topbar-border:   var(--ax-neutral-200);

    /* Text */
    --ax-text-primary:  var(--ax-neutral-800);
    --ax-text-heading:  var(--ax-neutral-900);
    --ax-text-muted:    var(--ax-neutral-500);
    --ax-text-inverse:  var(--ax-neutral-0);
    --ax-text-link:     var(--ax-blue-600);
    --ax-text-link-hover: var(--ax-blue-700);
    --ax-text-disabled: var(--ax-neutral-400);

    /* Borders */
    --ax-border:        var(--ax-neutral-200);
    --ax-border-strong: var(--ax-neutral-300);
    --ax-border-subtle: var(--ax-neutral-100);

    /* Form-control surfaces (promoted from the retired LAYER 6 bridge). */
    --ax-input-bg:      var(--ax-surface-raised);
    --ax-input-border:  var(--ax-border);

    /* Interactive — primary */
    --ax-primary:          var(--ax-blue-600);
    --ax-primary-hover:    var(--ax-blue-700);
    --ax-primary-active:   var(--ax-blue-800);
    --ax-primary-subtle:   var(--ax-blue-50);
    --ax-primary-on:       var(--ax-neutral-0);
    --ax-focus-ring:       var(--ax-blue-400);

    /* Status — foreground / subtle background pairs, both AA on their pair */
    --ax-success:        var(--ax-success-600);
    --ax-success-subtle: var(--ax-success-50);
    --ax-success-on:     var(--ax-neutral-0);
    --ax-warning:        var(--ax-warning-600);
    --ax-warning-subtle: var(--ax-warning-50);
    --ax-warning-on:     var(--ax-neutral-0);
    --ax-danger:         var(--ax-danger-600);
    --ax-danger-subtle:  var(--ax-danger-50);
    --ax-danger-on:      var(--ax-neutral-0);
    --ax-info:           var(--ax-info-600);
    --ax-info-subtle:    var(--ax-info-50);
    --ax-info-on:        var(--ax-neutral-0);

    /* Shape — Direction A keeps corners tight and borders doing the work */
    --ax-radius-sm:   3px;
    --ax-radius-md:   4px;
    --ax-radius-lg:   6px;
    --ax-radius-pill: 999px;
    --ax-border-width: 1px;

    /* Structural widths that are design decisions, not arbitrary pixels: the
       accent stripe down an alert / active nav link / toast, the tab underline,
       and the focus-ring offset. Tokenised so "how thick is our accent bar" has
       one answer, and so a direction can change it. */
    --ax-border-width-accent: 3px;
    --ax-border-width-marker: 2px;
    --ax-focus-offset:        2px;
    --ax-spinner-size:        14px;
    --ax-empty-icon-size:     44px;
    --ax-filter-field-min:    150px;

    /* Elevation — Direction A is deliberately near-flat; borders separate. */
    --ax-shadow-none: none;
    --ax-shadow-sm:   0 1px 2px rgba(16, 24, 40, 0.04);
    --ax-shadow-md:   0 1px 3px rgba(16, 24, 40, 0.08);
    --ax-shadow-lg:   0 4px 12px rgba(16, 24, 40, 0.10);
    --ax-shadow-modal:0 12px 32px rgba(16, 24, 40, 0.18);

    /* ── Density ────────────────────────────────────────────────────────────
       The arithmetic, because "compact" on its own is not a specification:

         a 1080px screen, minus the 56px topbar, minus ~120px of page header
         and filter bar, minus ~56px of pagination, leaves ~848px of table.
         Take off the 34px header row and 20 rows must fit in 814px, so a row
         must be at most 40px. 36px gives 22 rows with margin to spare.

       36px = 13px text x 1.45 line-height (18.85px) + 8px padding top and
       bottom + the 1px bottom border, rounded. Those three numbers are the
       three tokens directly below, and they must stay consistent with each
       other — change one, redo the arithmetic.                                 */
    --ax-table-row-h:      36px;
    --ax-table-cell-py:    var(--ax-space-4);   /*  8px */
    --ax-table-cell-px:    var(--ax-space-5);   /* 10px */
    --ax-table-header-h:   34px;
    --ax-table-font:       var(--ax-text-sm);   /* 13px */

    --ax-control-h:        32px;   /* inputs, selects, default buttons */
    --ax-control-h-sm:     28px;
    --ax-control-h-lg:     38px;
    --ax-control-px:       var(--ax-space-5);
    --ax-card-padding:     var(--ax-space-7);   /* 16px */
    --ax-page-padding:     var(--ax-space-7);
    --ax-section-gap:      var(--ax-space-9);   /* 24px between sections */

    --ax-shell-sidebar-w:  255px;
    --ax-shell-topbar-h:   56px;
}


/* ═══ LAYER 3 — DIRECTIONS ═══════════════════════════════════════════════════
   Set `data-ax-direction` on <html>. Each block below overrides LAYER 2 ONLY.
   No direction adds a selector for a component, and no component knows which
   direction is active — that is the test of whether the token system works.
   If a direction ever needs markup, the tokens are wrong, not the markup.

   Each direction is also exposed as a CLASS (.ax-dir-a / -b / -c). Custom
   properties inherit, so putting the class on any container themes that subtree
   — which is what lets the preview page show all three side by side on one page
   with genuinely identical markup, rather than three screenshots taken apart.  */

/* ── Direction B — modern / elevated ────────────────────────────────────────
   Same palette, softer handling: depth instead of hard borders, rounder
   corners, and more room inside each row and card while the grid stays
   compact. Costs about 3 table rows per screen against Direction A.           */
:root[data-ax-direction="b"],
.ax-dir-b {
    --ax-surface-app:      var(--ax-neutral-100);
    --ax-surface-sunken:   var(--ax-neutral-50);
    --ax-border:           var(--ax-neutral-100);
    --ax-border-strong:    var(--ax-neutral-200);
    --ax-border-subtle:    var(--ax-neutral-50);

    --ax-radius-sm:   5px;
    --ax-radius-md:   8px;
    --ax-radius-lg:   12px;
    --ax-border-width-accent: 4px;

    --ax-shadow-sm:   0 1px 2px rgba(16, 24, 40, 0.06);
    --ax-shadow-md:   0 2px 6px rgba(16, 24, 40, 0.08), 0 1px 2px rgba(16, 24, 40, 0.04);
    --ax-shadow-lg:   0 8px 24px rgba(16, 24, 40, 0.10), 0 2px 6px rgba(16, 24, 40, 0.05);
    --ax-shadow-modal:0 20px 48px rgba(16, 24, 40, 0.20);

    --ax-table-row-h:    40px;
    --ax-table-cell-py:  var(--ax-space-5);   /* 10px */
    --ax-table-cell-px:  var(--ax-space-6);   /* 12px */
    --ax-table-header-h: 38px;

    --ax-control-h:      36px;
    --ax-card-padding:   var(--ax-space-8);   /* 20px */
    --ax-page-padding:   var(--ax-space-8);
}

/* ── Direction C — dark sidebar / light content ─────────────────────────────
   The familiar CRM shell: a charcoal navigation rail anchoring a light working
   area. Only the shell tokens move — the content area is Direction A, so every
   table, form and card is pixel-identical to A. This is the clearest proof the
   swap layer is doing its job.

   The charcoal is neutral-900 rather than pure black so the active-state blue
   still reads against it, and sidebar text is neutral-200 (13.0:1 on that
   ground) rather than the mid-gray that a dark rail tempts you into.           */
:root[data-ax-direction="c"],
.ax-dir-c {
    --ax-shell-sidebar-bg:      var(--ax-neutral-900);
    --ax-shell-sidebar-fg:      var(--ax-neutral-200);
    --ax-shell-sidebar-muted:   var(--ax-neutral-400);
    --ax-shell-sidebar-border:  var(--ax-neutral-700);
    --ax-shell-sidebar-hover:   var(--ax-neutral-800);
    --ax-shell-sidebar-active-bg: var(--ax-blue-800);
    --ax-shell-sidebar-active-fg: var(--ax-neutral-0);
    --ax-shell-sidebar-active-marker: var(--ax-blue-300);
    --ax-shell-topbar-bg:       var(--ax-neutral-900);
    --ax-shell-topbar-fg:       var(--ax-neutral-0);
    --ax-shell-topbar-border:   var(--ax-neutral-700);
}


/* ═══ LAYER 4 — DARK MODE ════════════════════════════════════════════════════
   Placed after the directions on purpose: dark is dark whichever direction is
   applied, and on equal specificity the later block wins. The existing
   VS Code-inspired dark palette already shipped in the layout is preserved
   exactly — this batch re-expresses it as tokens, it does not restyle it.      */
:root[data-bs-theme="dark"] {
    --ax-surface-app:      #1e1e1e;
    --ax-surface-raised:   #252526;
    --ax-surface-sunken:   #2d2d30;
    --ax-surface-hover:    #2a2d2e;
    --ax-surface-selected: #094771;
    --ax-surface-disabled: #2d2d30;
    --ax-surface-elevated: var(--ax-surface-sunken);   /* #2d2d30 — lifts above the raised card */

    --ax-shell-sidebar-bg:     #252526;
    --ax-shell-sidebar-fg:     #cccccc;
    --ax-shell-sidebar-muted:  #b3b3b3;
    --ax-shell-sidebar-border: #3c3c3c;
    --ax-shell-sidebar-hover:  #2a2d2e;
    --ax-shell-sidebar-active-bg: #094771;
    --ax-shell-sidebar-active-fg: #ffffff;
    --ax-shell-sidebar-active-marker: #3794ff;
    --ax-shell-topbar-bg:      #252526;
    --ax-shell-topbar-fg:      #ffffff;
    --ax-shell-topbar-border:  #3c3c3c;

    --ax-text-primary:  #cccccc;
    --ax-text-heading:  #ffffff;
    --ax-text-muted:    #b3b3b3;
    --ax-text-inverse:  #1e1e1e;
    --ax-text-link:     #3794ff;
    --ax-text-link-hover: #6cb0ff;
    --ax-text-disabled: #6b6b6b;

    --ax-border:        #454545;
    --ax-border-strong: #565656;
    --ax-border-subtle: #3c3c3c;
    --ax-input-bg:      #3c3c3c;
    --ax-input-border:  #3c3c3c;

    /* Dark grounds need a lighter blue to stay legible — the 600 step that is
       correct on white drops under AA against #1e1e1e. */
    --ax-primary:        #2f7fd4;
    --ax-primary-hover:  #3d90e6;
    --ax-primary-active: #4b9bf0;
    --ax-primary-subtle: #10304d;
    --ax-primary-on:     #ffffff;
    --ax-focus-ring:     #3794ff;

    --ax-success:        #3fa46b;
    --ax-success-subtle: #14301f;
    --ax-warning:        #d08a2c;
    --ax-warning-subtle: #33260f;
    --ax-danger:         #d15a6c;
    --ax-danger-subtle:  #3a1219;
    --ax-info:           #3fa0c4;
    --ax-info-subtle:    #0f2a33;

    --ax-shadow-sm:   0 1px 2px rgba(0, 0, 0, 0.30);
    --ax-shadow-md:   0 1px 3px rgba(0, 0, 0, 0.40);
    --ax-shadow-lg:   0 4px 12px rgba(0, 0, 0, 0.50);
    --ax-shadow-modal:0 12px 32px rgba(0, 0, 0, 0.60);
}


/* ═══ LAYER 5 — BOOTSTRAP 5.3 VARIABLE MAPPING ═══════════════════════════════
   Bootstrap 5.3 drives almost everything through its own CSS variables. Pointing
   those at our tokens means Bootstrap's components come out themed on their own
   — no `!important`, no shadowing selector per component, and any Bootstrap
   markup a future screen uses is themed the moment it is written.

   RGB triplets: several Bootstrap rules build rgba() from `--bs-*-rgb`, which
   cannot be derived from a hex custom property in CSS. They are therefore
   declared literally here, and MUST be kept in step with the hex tokens above.
   The pairs are adjacent so a change to one is visibly a change to both.       */

:root {
    --ax-primary-rgb: 30, 90, 168;      /* == var(--ax-blue-600)  #1e5aa8 */
    --ax-danger-rgb:  155, 28, 46;      /* == var(--ax-danger-600) #9b1c2e */
    --ax-success-rgb: 26, 127, 75;      /* == var(--ax-success-600) #1a7f4b */
    --ax-warning-rgb: 163, 90, 0;       /* == var(--ax-warning-600) #a35a00 */
    --ax-info-rgb:    11, 107, 143;     /* == var(--ax-info-600)   #0b6b8f */
    --ax-body-rgb:    38, 43, 51;       /* == var(--ax-neutral-800) #262b33 */
}
:root[data-bs-theme="dark"] {
    --ax-primary-rgb: 47, 127, 212;     /* == #2f7fd4 */
    --ax-danger-rgb:  209, 90, 108;     /* == #d15a6c */
    --ax-success-rgb: 63, 164, 107;     /* == #3fa46b */
    --ax-warning-rgb: 208, 138, 44;     /* == #d08a2c */
    --ax-info-rgb:    63, 160, 196;     /* == #3fa0c4 */
    --ax-body-rgb:    204, 204, 204;    /* == #cccccc */
}

:root {
    /* Foundation */
    --bs-body-font-family: var(--ax-font-sans);
    --bs-body-font-size:   var(--ax-text-md);
    --bs-body-font-weight: var(--ax-weight-normal);
    --bs-body-line-height: var(--ax-leading-normal);
    --bs-body-color:       var(--ax-text-primary);
    --bs-body-color-rgb:   var(--ax-body-rgb);
    --bs-body-bg:          var(--ax-surface-app);
    --bs-emphasis-color:   var(--ax-text-heading);
    --bs-secondary-color:  var(--ax-text-muted);

    --bs-border-color:        var(--ax-border);
    --bs-border-color-translucent: var(--ax-border);
    --bs-border-width:        var(--ax-border-width);
    --bs-border-radius:       var(--ax-radius-md);
    --bs-border-radius-sm:    var(--ax-radius-sm);
    --bs-border-radius-lg:    var(--ax-radius-lg);
    --bs-border-radius-xl:    var(--ax-radius-lg);
    --bs-border-radius-pill:  var(--ax-radius-pill);

    --bs-box-shadow-sm: var(--ax-shadow-sm);
    --bs-box-shadow:    var(--ax-shadow-md);
    --bs-box-shadow-lg: var(--ax-shadow-lg);

    /* Theme colours */
    --bs-primary:       var(--ax-primary);
    --bs-primary-rgb:   var(--ax-primary-rgb);
    --bs-success:       var(--ax-success);
    --bs-success-rgb:   var(--ax-success-rgb);
    --bs-warning:       var(--ax-warning);
    --bs-warning-rgb:   var(--ax-warning-rgb);
    --bs-danger:        var(--ax-danger);
    --bs-danger-rgb:    var(--ax-danger-rgb);
    --bs-info:          var(--ax-info);
    --bs-info-rgb:      var(--ax-info-rgb);
    --bs-light:         var(--ax-neutral-50);
    --bs-dark:          var(--ax-neutral-900);

    /* Links */
    --bs-link-color:            var(--ax-text-link);
    --bs-link-color-rgb:        var(--ax-primary-rgb);
    --bs-link-hover-color:      var(--ax-text-link-hover);
    --bs-link-hover-color-rgb:  var(--ax-primary-rgb);
    --bs-link-decoration:       none;
    --bs-link-hover-decoration: underline;

    /* Headings and code */
    --bs-heading-color: var(--ax-text-heading);
    --bs-font-monospace: var(--ax-font-mono);

    /* Tables — Bootstrap reads these on .table, so the dense default lands
       everywhere without every view opting in. */
    --bs-table-color:        var(--ax-text-primary);
    --bs-table-bg:           var(--ax-surface-raised);
    --bs-table-border-color: var(--ax-border);
    --bs-table-striped-bg:   var(--ax-neutral-25);
    --bs-table-hover-bg:     var(--ax-surface-hover);
    --bs-table-active-bg:    var(--ax-surface-selected);

    /* Focus ring — one ring, everywhere, always visible. */
    --bs-focus-ring-width:  3px;
    --bs-focus-ring-opacity: 0.35;
    --bs-focus-ring-color:  rgba(var(--ax-primary-rgb), 0.35);
}


/* ═══ LAYER 5b — BOOTSTRAP SUBTLE / EMPHASIS VARIANTS ════════════════════════
   Bootstrap's `.bg-success-subtle`, `.text-danger-emphasis` and friends read a
   separate set of variables from the base theme colours. Views across the app
   already use those utilities, so without this block they keep Bootstrap's stock
   palette and drift away from the themed components sitting next to them.
   Mapping them here means an unconverted screen still lands close to the theme.  */

:root {
    --bs-primary-bg-subtle: var(--ax-primary-subtle);
    --bs-success-bg-subtle: var(--ax-success-subtle);
    --bs-warning-bg-subtle: var(--ax-warning-subtle);
    --bs-danger-bg-subtle:  var(--ax-danger-subtle);
    --bs-info-bg-subtle:    var(--ax-info-subtle);
    --bs-secondary-bg-subtle: var(--ax-surface-sunken);
    --bs-light-bg-subtle:   var(--ax-surface-sunken);

    --bs-primary-border-subtle: var(--ax-primary-subtle);
    --bs-success-border-subtle: var(--ax-success-subtle);
    --bs-warning-border-subtle: var(--ax-warning-subtle);
    --bs-danger-border-subtle:  var(--ax-danger-subtle);
    --bs-info-border-subtle:    var(--ax-info-subtle);
    --bs-secondary-border-subtle: var(--ax-border);

    --bs-primary-text-emphasis: var(--ax-primary);
    --bs-success-text-emphasis: var(--ax-success);
    --bs-warning-text-emphasis: var(--ax-warning);
    --bs-danger-text-emphasis:  var(--ax-danger);
    --bs-info-text-emphasis:    var(--ax-info);
    --bs-secondary-text-emphasis: var(--ax-text-muted);

    /* The plain .text-success / .text-danger utilities, used widely for inline
       status text, are driven by these. */
    --bs-success-rgb-fallback: var(--ax-success-rgb);
}

/* .text-muted is Bootstrap's most-used utility and its stock value is under AA
   on our surfaces. Point it at the token that is measured at 4.74:1. */
:root { --bs-secondary-color: var(--ax-text-muted); }
