/*!
 * BijoyPay Design System v1.0
 * Generated file - do not edit directly.
 * Sources live in design-system/ and are concatenated by build-product.ps1:
 *   01-tokens  02-base  03-components  04-layout  06-app-shim
 * Prefix: bx-  |  No legacy framework classes are used or referenced.
 */

/* ================= 01-tokens.css ================= */
/* ==========================================================================
   BIJOY DESIGN SYSTEM — v1.0
   File 1 of 4 : TOKENS
   --------------------------------------------------------------------------
   Every visual decision in the product comes from this file. Nothing in the
   application may hard-code a colour, size, radius or shadow again.
   Prefix: `bx-`  — chosen so that no legacy Bootstrap / Blithe class can
   ever collide with the new system.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. COLOUR — LIGHT (default)
   Contrast notes are measured against --bx-surface (#FFFFFF) unless stated.
   -------------------------------------------------------------------------- */
:root {

  /* ------------------------------------------------------------------------
     THE PALETTE COMES FROM THE BIJOYPAY BRAND BOARD
     Sampled from the supplied artwork rather than eyeballed: the mark runs
     from a deep teal (#002727 / #005048) through mid green to a vivid
     #01C958, with a #F1181A red accent, mint #E0FAEA tints and white.

     NOTE ON THE RAMP NAMES. `navy-*`, `blue-*`, `teal-*` and `green-*` are
     legacy labels kept on purpose: roughly thirty rules across the other four
     sheets reference the ramps directly, so renaming a token would be a
     thirty-file change with no visual benefit and real regression risk. Read
     them as "foundation / primary / accent / status", which is what they are.

     The logo gradient is green through teal, so the system keeps a genuine
     second hue (teal) for accent and info. That is what stops success, info
     and primary from collapsing into one indistinguishable green.
     ------------------------------------------------------------------------ */

  /* Foundation — deep teal-green (sidebar, dark bands, marketing surfaces) */
  --bx-navy-950: #03201E;
  --bx-navy-900: #042A28;
  --bx-navy-800: #013B37;
  --bx-navy-700: #005048;
  --bx-navy-600: #006E4E;
  --bx-navy-300: #8FBEB2;
  --bx-navy-100: #D3EAE4;

  /* Primary — the brand green.  White text on 600 = 5.2:1  (AA pass) */
  --bx-blue-700: #065C3A;
  --bx-blue-600: #0A7D4F;
  --bx-blue-500: #12995F;
  --bx-blue-300: #7FDCAB;
  --bx-blue-100: #CFF3E0;
  --bx-blue-50:  #E4FAEE;

  /* Accent — the teal end of the logo gradient.  White on 600 = 5.5:1 */
  --bx-teal-700: #066456;
  --bx-teal-600: #0B7C6B;
  --bx-teal-300: #7ED7C6;
  --bx-teal-100: #C7EEE6;
  --bx-teal-50:  #E6F7F3;

  /* Status — green for success (mint tint + deep text), amber, brand red */
  --bx-green-700: #04663D;
  --bx-green-600: #0A8048;
  --bx-green-50:  #E0FAEA;
  --bx-amber-700: #92400E;
  --bx-amber-600: #B45309;
  --bx-amber-50:  #FEF6E7;
  --bx-red-700:   #B01519;
  --bx-red-600:   #E11A1F;
  --bx-red-50:    #FDEDED;
  --bx-violet-600:#6D28D9;
  --bx-violet-50: #F1EBFE;

  /* Neutrals — text, green-tinted so the greys sit with the brand.
     ink-700 on white = 13.9:1, ink-500 on white = 6.8:1 */
  --bx-ink-900: #0A1A16;
  --bx-ink-800: #132520;
  --bx-ink-700: #1E302B;
  --bx-ink-600: #33463F;
  --bx-ink-500: #4B5F57;
  --bx-ink-400: #6C8078;
  --bx-ink-300: #9AABA3;
  --bx-ink-200: #C4D2CC;

  /* Neutrals — structure */
  --bx-line:        #DEE7E3;
  --bx-line-strong: #C6D4CE;
  --bx-surface:     #FFFFFF;
  --bx-surface-2:   #F5F8F6;
  --bx-surface-3:   #ECF1EE;
  --bx-overlay:     rgba(1, 32, 30, .48);

  /* Semantic aliases — components reference THESE, never the raw scales */
  --bx-bg:              var(--bx-surface-2);
  --bx-bg-elevated:     var(--bx-surface);
  --bx-bg-sunken:       var(--bx-surface-3);
  --bx-text:            var(--bx-ink-700);
  --bx-text-strong:     var(--bx-ink-900);
  --bx-text-muted:      var(--bx-ink-500);
  --bx-text-subtle:     var(--bx-ink-400);
  --bx-text-onDark:     #E6F5F0;
  --bx-text-onDark-dim: #A5C9BE;
  --bx-border:          var(--bx-line);
  --bx-border-strong:   var(--bx-line-strong);
  --bx-focus:           var(--bx-blue-500);

  --bx-primary:         var(--bx-blue-600);
  --bx-primary-hover:   var(--bx-blue-700);
  --bx-primary-soft:    var(--bx-blue-50);
  --bx-primary-text:    var(--bx-blue-700);

  --bx-accent:          var(--bx-teal-600);
  --bx-accent-hover:    var(--bx-teal-700);
  --bx-accent-soft:     var(--bx-teal-50);
  --bx-accent-text:     var(--bx-teal-700);

  --bx-success: var(--bx-green-600);   --bx-success-soft: var(--bx-green-50);   --bx-success-text: var(--bx-green-700);
  --bx-warning: var(--bx-amber-600);   --bx-warning-soft: var(--bx-amber-50);   --bx-warning-text: var(--bx-amber-700);
  --bx-danger:  var(--bx-red-600);     --bx-danger-soft:  var(--bx-red-50);     --bx-danger-text:  var(--bx-red-700);
  /* info rides the teal ramp, not the primary green: in a green brand a
     blue-green "info" pill would be indistinguishable from a "success" one */
  --bx-info:    var(--bx-teal-600);    --bx-info-soft:    var(--bx-teal-50);    --bx-info-text:    var(--bx-teal-700);
  --bx-neutral: var(--bx-ink-400);     --bx-neutral-soft: var(--bx-surface-3);  --bx-neutral-text: var(--bx-ink-600);

  /* Brand gradient — hero / marketing surfaces only */
  --bx-gradient-brand: linear-gradient(135deg, var(--bx-navy-900) 0%, var(--bx-navy-800) 45%, #0B6B58 100%);
  --bx-gradient-accent: linear-gradient(135deg, var(--bx-blue-600), var(--bx-teal-600));

  /* ------------------------------------------------------------------------
     2. TYPOGRAPHY
     ------------------------------------------------------------------------ */
  --bx-font-sans: "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans Bengali", sans-serif;
  --bx-font-bn:   "Noto Sans Bengali", "Inter", "Segoe UI", Roboto, sans-serif;
  --bx-font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  /* Type scale — 14px base keeps dense data tables readable */
  --bx-fs-2xs: 11px;
  --bx-fs-xs:  12px;
  --bx-fs-sm:  13px;
  --bx-fs-md:  14px;   /* base body */
  --bx-fs-lg:  15px;
  --bx-fs-xl:  17px;
  --bx-fs-2xl: 20px;
  --bx-fs-3xl: 24px;
  --bx-fs-4xl: 30px;
  --bx-fs-5xl: 38px;
  --bx-fs-6xl: 48px;

  --bx-lh-tight: 1.15;
  --bx-lh-snug:  1.35;
  --bx-lh-base:  1.6;
  --bx-lh-loose: 1.75;

  --bx-fw-regular: 400;
  --bx-fw-medium:  500;
  --bx-fw-semi:    600;
  --bx-fw-bold:    700;
  --bx-fw-black:   800;

  --bx-tracking-tight: -0.02em;
  --bx-tracking-wide:   0.04em;
  --bx-tracking-caps:   0.09em;

  /* Fluid display sizes for marketing headings */
  --bx-fs-display:  clamp(1.85rem, 4.2vw, 3rem);
  --bx-fs-section:  clamp(1.4rem, 2.6vw, 2.05rem);

  /* ------------------------------------------------------------------------
     3. SPACE — 4px base grid
     ------------------------------------------------------------------------ */
  --bx-sp-0:  0;
  --bx-sp-1:  4px;
  --bx-sp-2:  8px;
  --bx-sp-3:  12px;
  --bx-sp-4:  16px;
  --bx-sp-5:  20px;
  --bx-sp-6:  24px;
  --bx-sp-7:  28px;
  --bx-sp-8:  32px;
  --bx-sp-10: 40px;
  --bx-sp-12: 48px;
  --bx-sp-14: 56px;
  --bx-sp-16: 64px;
  --bx-sp-20: 80px;
  --bx-sp-24: 96px;

  /* ------------------------------------------------------------------------
     4. RADIUS — restrained; fintech should read as precise, not pill-shaped
     ------------------------------------------------------------------------ */
  --bx-r-xs:   6px;
  --bx-r-sm:   8px;
  --bx-r-md:   10px;
  --bx-r-lg:   14px;
  --bx-r-xl:   18px;
  --bx-r-2xl:  24px;
  --bx-r-full: 999px;

  /* ------------------------------------------------------------------------
     5. ELEVATION — low-spread, navy-tinted so shadows stay neutral on white
     ------------------------------------------------------------------------ */
  --bx-shadow-xs: 0 1px 2px rgba(1, 42, 38, .06);
  --bx-shadow-sm: 0 1px 2px rgba(1, 42, 38, .06), 0 1px 3px rgba(1, 42, 38, .08);
  --bx-shadow-md: 0 4px 12px rgba(1, 42, 38, .08), 0 1px 3px rgba(1, 42, 38, .06);
  --bx-shadow-lg: 0 12px 32px rgba(1, 42, 38, .12), 0 2px 8px rgba(1, 42, 38, .06);
  --bx-shadow-xl: 0 24px 60px rgba(1, 42, 38, .16), 0 4px 12px rgba(1, 42, 38, .08);
  --bx-shadow-focus: 0 0 0 4px rgba(10, 125, 79, .28);
  --bx-shadow-inset: inset 0 1px 2px rgba(1, 42, 38, .06);

  /* ------------------------------------------------------------------------
     6. MOTION
     ------------------------------------------------------------------------ */
  --bx-dur-instant: 90ms;
  --bx-dur-fast:    150ms;
  --bx-dur-base:    220ms;
  --bx-dur-slow:    340ms;
  --bx-ease-out:    cubic-bezier(.22, .61, .36, 1);
  --bx-ease-in-out: cubic-bezier(.4, 0, .2, 1);
  --bx-ease-spring: cubic-bezier(.34, 1.4, .5, 1);

  /* ------------------------------------------------------------------------
     7. LAYOUT
     ------------------------------------------------------------------------ */
  --bx-sidebar-w:        268px;
  --bx-sidebar-w-collapsed: 74px;
  --bx-topbar-h:         62px;
  --bx-container:        1200px;
  --bx-container-wide:   1400px;
  --bx-container-narrow: 760px;

  /* ------------------------------------------------------------------------
     8. Z-INDEX — one place, no magic numbers in components
     ------------------------------------------------------------------------ */
  --bx-z-base:      1;
  --bx-z-sticky:    100;
  --bx-z-sidebar:   200;
  --bx-z-topbar:    300;
  --bx-z-drawer:    400;
  --bx-z-dropdown:  500;
  --bx-z-modal:     600;
  --bx-z-toast:     700;
  --bx-z-tooltip:   800;
}

/* --------------------------------------------------------------------------
   9. COLOUR — DARK
   Activated by [data-bx-theme="dark"] on <html>.  Only the semantic layer is
   overridden — components never need a dark-mode branch.
   -------------------------------------------------------------------------- */
[data-bx-theme="dark"] {
  --bx-surface:     #0D1F1C;
  --bx-surface-2:   #071614;
  --bx-surface-3:   #142A26;
  --bx-line:        #21403A;
  --bx-line-strong: #2F554C;
  --bx-overlay:     rgba(1, 12, 11, .68);

  --bx-ink-900: #EAF7F2;
  --bx-ink-800: #DCEDE7;
  --bx-ink-700: #CBE0D9;
  --bx-ink-600: #AFC9C1;
  --bx-ink-500: #8EAAA2;
  --bx-ink-400: #7A948C;
  --bx-ink-300: #5C736B;
  --bx-ink-200: #41564F;

  --bx-bg:          var(--bx-surface-2);
  --bx-bg-elevated: var(--bx-surface);
  --bx-bg-sunken:   #041110;
  --bx-text:        var(--bx-ink-700);
  --bx-text-strong: var(--bx-ink-900);
  --bx-text-muted:  var(--bx-ink-500);
  --bx-text-subtle: var(--bx-ink-400);

  --bx-primary-soft: #0A2F20;
  --bx-primary-text: #6FE0A4;
  --bx-accent-soft:  #062C28;
  --bx-accent-text:  #6FD8C6;

  --bx-success-soft: #06301F;  --bx-success-text: #6FD9A4;
  --bx-warning-soft: #2C2008;  --bx-warning-text: #F3C36B;
  --bx-danger-soft:  #2E1214;  --bx-danger-text:  #F5A19B;
  /* info is cyan-leaning so it does not read as a second success in the dark */
  --bx-info-soft:    #082C33;  --bx-info-text:    #6FD3DE;
  --bx-neutral-soft: #1B2A27;  --bx-neutral-text: #AFC9C1;

  --bx-shadow-xs: 0 1px 2px rgba(0, 0, 0, .4);
  --bx-shadow-sm: 0 1px 3px rgba(0, 0, 0, .45);
  --bx-shadow-md: 0 4px 14px rgba(0, 0, 0, .45);
  --bx-shadow-lg: 0 14px 36px rgba(0, 0, 0, .5);
  --bx-shadow-xl: 0 26px 64px rgba(0, 0, 0, .58);
  --bx-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, .4);

  --bx-gradient-brand: linear-gradient(135deg, #071527 0%, #0C2338 55%, #0A2E3C 100%);
  color-scheme: dark;
}

/* --------------------------------------------------------------------------
   10. ACCESSIBILITY & PLATFORM PREFERENCES
   -------------------------------------------------------------------------- */
:root { color-scheme: light; }

@media (prefers-reduced-motion: reduce) {
  :root {
    --bx-dur-instant: 0ms;
    --bx-dur-fast:    0ms;
    --bx-dur-base:    0ms;
    --bx-dur-slow:    0ms;
  }
}

@media (prefers-contrast: more) {
  :root {
    --bx-text:        var(--bx-ink-900);
    --bx-text-muted:  var(--bx-ink-600);
    --bx-border:      var(--bx-line-strong);
  }
}

/* Density modes — data-heavy admin tables can opt into a tighter grid */
[data-bx-density="compact"] { --bx-sp-3: 10px; --bx-sp-4: 12px; --bx-sp-6: 18px; }


/* ================= 02-base.css ================= */
/* ==========================================================================
   BIJOY DESIGN SYSTEM — v1.0
   File 2 of 4 : BASE (reset, elements, typography, layout helpers, utilities)
   Depends on: 01-tokens.css
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. RESET
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  text-size-adjust: 100%;
}

body {
  min-height: 100dvh;
  font-family: var(--bx-font-sans);
  font-size: var(--bx-fs-md);
  line-height: var(--bx-lh-base);
  font-weight: var(--bx-fw-regular);
  color: var(--bx-text);
  background: var(--bx-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-wrap: break-word;
}

/* Bengali copy needs a touch more line-height to breathe */
:lang(bn), .bx-bn { font-family: var(--bx-font-bn); line-height: var(--bx-lh-loose); }

img, svg, video, canvas, picture {
  display: block;
  max-width: 100%;
  height: auto;
}

input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }

table { border-collapse: collapse; border-spacing: 0; width: 100%; }

ul[class], ol[class] { list-style: none; padding: 0; }

hr {
  border: 0;
  border-top: 1px solid var(--bx-border);
  margin: var(--bx-sp-6) 0;
}

::selection { background: var(--bx-blue-100); color: var(--bx-ink-900); }
[data-bx-theme="dark"] ::selection { background: var(--bx-navy-600); color: #fff; }

/* --------------------------------------------------------------------------
   2. TYPOGRAPHY
   -------------------------------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
  color: var(--bx-text-strong);
  font-weight: var(--bx-fw-bold);
  line-height: var(--bx-lh-tight);
  letter-spacing: var(--bx-tracking-tight);
  text-wrap: balance;
}

h1 { font-size: var(--bx-fs-4xl); }
h2 { font-size: var(--bx-fs-3xl); }
h3 { font-size: var(--bx-fs-xl); }
h4 { font-size: var(--bx-fs-lg); }
h5 { font-size: var(--bx-fs-md); }
h6 {
  font-size: var(--bx-fs-xs);
  font-weight: var(--bx-fw-bold);
  letter-spacing: var(--bx-tracking-caps);
  text-transform: uppercase;
  color: var(--bx-text-muted);
}

p { text-wrap: pretty; }

small, .bx-small { font-size: var(--bx-fs-sm); }
strong, b { font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); }

a { color: var(--bx-primary-text); text-decoration: none; transition: color var(--bx-dur-fast) var(--bx-ease-out); }
a:hover { color: var(--bx-primary-hover); text-decoration: underline; text-underline-offset: 3px; }

code, kbd, samp, pre { font-family: var(--bx-font-mono); font-size: .92em; }
code {
  background: var(--bx-bg-sunken);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-xs);
  padding: .1em .4em;
}
pre {
  background: var(--bx-navy-900);
  color: var(--bx-text-onDark);
  border-radius: var(--bx-r-lg);
  padding: var(--bx-sp-5);
  overflow-x: auto;
  line-height: 1.7;
}
pre code { background: none; border: 0; padding: 0; color: inherit; }

blockquote {
  border-left: 3px solid var(--bx-accent);
  padding-left: var(--bx-sp-4);
  color: var(--bx-text-muted);
  font-style: italic;
}

/* --------------------------------------------------------------------------
   3. FOCUS — visible, consistent, never removed
   -------------------------------------------------------------------------- */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--bx-focus);
  outline-offset: 2px;
  border-radius: var(--bx-r-xs);
}
.bx-focus-ring:focus-visible { box-shadow: var(--bx-shadow-focus); outline: 2px solid transparent; }

/* --------------------------------------------------------------------------
   4. LAYOUT PRIMITIVES
   -------------------------------------------------------------------------- */
.bx-container {
  width: 100%;
  max-width: var(--bx-container);
  margin-inline: auto;
  padding-inline: var(--bx-sp-5);
}
.bx-container--wide   { max-width: var(--bx-container-wide); }
.bx-container--narrow { max-width: var(--bx-container-narrow); }
.bx-container--flush  { padding-inline: 0; }

.bx-stack     { display: flex; flex-direction: column; }
.bx-stack--xs { gap: var(--bx-sp-2); }
.bx-stack--sm { gap: var(--bx-sp-3); }
.bx-stack--md { gap: var(--bx-sp-4); }
.bx-stack--lg { gap: var(--bx-sp-6); }
.bx-stack--xl { gap: var(--bx-sp-8); }

.bx-row { display: flex; align-items: center; gap: var(--bx-sp-3); }
.bx-row--between { justify-content: space-between; }
.bx-row--start   { align-items: flex-start; }
.bx-row--wrap    { flex-wrap: wrap; }
.bx-row--end     { justify-content: flex-end; }

/* Auto-fit grids — minmax(0,…) is deliberate: it prevents long content from
   blowing a track open and forcing horizontal page scroll. */
.bx-grid { display: grid; gap: var(--bx-sp-5); }
/* Grid tracks stretch by default, which is right for stat rows and pricing
   cards but leaves a tall empty void under a short content panel. `--top`
   sizes each panel to its own content. */
.bx-grid--top { align-items: start; }
.bx-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
.bx-grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); }
.bx-grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }
.bx-grid--cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.bx-grid--cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.bx-grid--cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* Asymmetric "content + side rail" layout. Class-based on purpose: an inline
   grid-template-columns would beat the media query below and keep two columns
   on a phone, which is exactly how a layout silently overflows. */
/* `align-items: start` stops the main card from stretching to match the height
   of the side rail, which would leave a large blank area under its content. */
.bx-grid--main-side { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); align-items: start; }
@media (max-width: 980px) { .bx-grid--main-side { grid-template-columns: minmax(0, 1fr); } }

@media (max-width: 900px) {
  .bx-grid--cols-3, .bx-grid--cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .bx-grid--cols-2, .bx-grid--cols-3, .bx-grid--cols-4 { grid-template-columns: minmax(0, 1fr); }
}

/* --------------------------------------------------------------------------
   5. SECTION SPACING (marketing pages)
   -------------------------------------------------------------------------- */
.bx-section { padding: var(--bx-sp-16) 0; }
.bx-section--sm  { padding: var(--bx-sp-10) 0; }
.bx-section--lg  { padding: var(--bx-sp-24) 0; }
.bx-section--alt { background: var(--bx-bg-elevated); }
.bx-section--sunken { background: var(--bx-bg-sunken); }

.bx-section-head {
  max-width: 720px;
  margin: 0 auto var(--bx-sp-10);
  text-align: center;
}
.bx-section-head > :last-child { margin-bottom: 0; }

.bx-eyebrow {
  display: inline-block;
  font-size: var(--bx-fs-xs);
  font-weight: var(--bx-fw-bold);
  letter-spacing: var(--bx-tracking-caps);
  text-transform: uppercase;
  color: var(--bx-primary-text);
  margin-bottom: var(--bx-sp-3);
}

/* --------------------------------------------------------------------------
   6. SURFACE HELPERS
   -------------------------------------------------------------------------- */
.bx-surface   { background: var(--bx-bg-elevated); }
.bx-sunken    { background: var(--bx-bg-sunken); }
.bx-border    { border: 1px solid var(--bx-border); }
.bx-rounded   { border-radius: var(--bx-r-lg); }
.bx-rounded--lg { border-radius: var(--bx-r-xl); }
.bx-shadow    { box-shadow: var(--bx-shadow-sm); }
.bx-shadow--md { box-shadow: var(--bx-shadow-md); }
.bx-shadow--lg { box-shadow: var(--bx-shadow-lg); }

.bx-divider { height: 1px; background: var(--bx-border); border: 0; }

/* --------------------------------------------------------------------------
   7. TEXT / COLOUR UTILITIES
   -------------------------------------------------------------------------- */
.bx-t-strong { color: var(--bx-text-strong); }
.bx-t-muted  { color: var(--bx-text-muted); }
.bx-t-subtle { color: var(--bx-text-subtle); }
.bx-t-primary{ color: var(--bx-primary-text); }
.bx-t-accent { color: var(--bx-accent-text); }
.bx-t-success{ color: var(--bx-success-text); }
.bx-t-warning{ color: var(--bx-warning-text); }
.bx-t-danger { color: var(--bx-danger-text); }

.bx-fs-2xs { font-size: var(--bx-fs-2xs); }
.bx-fs-xs  { font-size: var(--bx-fs-xs); }
.bx-fs-sm  { font-size: var(--bx-fs-sm); }
.bx-fs-lg  { font-size: var(--bx-fs-lg); }
.bx-fs-xl  { font-size: var(--bx-fs-xl); }
.bx-fs-2xl { font-size: var(--bx-fs-2xl); }
.bx-fs-3xl { font-size: var(--bx-fs-3xl); }

.bx-fw-medium { font-weight: var(--bx-fw-medium); }
.bx-fw-semi   { font-weight: var(--bx-fw-semi); }
.bx-fw-bold   { font-weight: var(--bx-fw-bold); }

.bx-caps { text-transform: uppercase; letter-spacing: var(--bx-tracking-caps); font-weight: var(--bx-fw-bold); }
.bx-mono { font-family: var(--bx-font-mono); font-variant-numeric: tabular-nums; }
.bx-nums { font-variant-numeric: tabular-nums; }

.bx-nowrap  { white-space: nowrap; }
.bx-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.bx-balance { text-wrap: balance; }

/* --------------------------------------------------------------------------
   8. SPACING / DISPLAY UTILITIES
   -------------------------------------------------------------------------- */
.bx-mt-0{margin-top:0}.bx-mt-2{margin-top:var(--bx-sp-2)}.bx-mt-3{margin-top:var(--bx-sp-3)}
.bx-mt-4{margin-top:var(--bx-sp-4)}.bx-mt-6{margin-top:var(--bx-sp-6)}.bx-mt-8{margin-top:var(--bx-sp-8)}
.bx-mb-0{margin-bottom:0}.bx-mb-2{margin-bottom:var(--bx-sp-2)}.bx-mb-3{margin-bottom:var(--bx-sp-3)}
.bx-mb-4{margin-bottom:var(--bx-sp-4)}.bx-mb-6{margin-bottom:var(--bx-sp-6)}.bx-mb-8{margin-bottom:var(--bx-sp-8)}
.bx-ml-auto{margin-left:auto}.bx-mr-auto{margin-right:auto}.bx-mx-auto{margin-inline:auto}

.bx-flex{display:flex}.bx-inline-flex{display:inline-flex}
.bx-block{display:block}.bx-inline-block{display:inline-block}
.bx-hidden{display:none !important}
.bx-grow{flex:1 1 auto; min-width:0}
.bx-shrink-0{flex-shrink:0}
.bx-relative{position:relative}.bx-absolute{position:absolute}
.bx-text-center{text-align:center}.bx-text-right{text-align:right}.bx-text-left{text-align:left}
.bx-w-full{width:100%}.bx-h-full{height:100%}
.bx-overflow-hidden{overflow:hidden}
.bx-rounded-full{border-radius:var(--bx-r-full)}

/* Breakpoint utilities.
   Names state the condition they hide UNDER, so there is no ambiguity about
   which side of the breakpoint they act on.
     .bx-hide-below-md  -> hidden while the viewport is narrower than 768px
     .bx-hide-from-md   -> hidden once the viewport reaches 768px
   Every rule that hides something is `!important` so a component class can
   never accidentally win the specificity fight. */
@media (max-width: 479px)  { .bx-hide-below-sm { display: none !important; } }
@media (max-width: 767px)  { .bx-hide-below-md { display: none !important; } }
@media (max-width: 1023px) { .bx-hide-below-lg { display: none !important; } }
@media (min-width: 768px)  { .bx-hide-from-md  { display: none !important; } }
@media (min-width: 1024px) { .bx-hide-from-lg  { display: none !important; } }
@media (min-width: 480px)  { .bx-show-under-sm-only { display: none !important; } }
@media (min-width: 768px)  { .bx-show-under-md-only { display: none !important; } }

/* --------------------------------------------------------------------------
   9. ACCESSIBILITY HELPERS
   -------------------------------------------------------------------------- */
.bx-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.bx-skip-link {
  position: absolute;
  top: var(--bx-sp-3);
  left: var(--bx-sp-3);
  z-index: var(--bx-z-tooltip);
  background: var(--bx-navy-800);
  color: #fff;
  padding: var(--bx-sp-3) var(--bx-sp-5);
  border-radius: var(--bx-r-md);
  transform: translateY(-200%);
  transition: transform var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-skip-link:focus { transform: translateY(0); color: #fff; text-decoration: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------------------------------------------------
   10. SCROLLBARS — subtle, themed
   -------------------------------------------------------------------------- */
.bx-scroll { scrollbar-width: thin; scrollbar-color: var(--bx-ink-200) transparent; }
.bx-scroll::-webkit-scrollbar { width: 10px; height: 10px; }
.bx-scroll::-webkit-scrollbar-track { background: transparent; }
.bx-scroll::-webkit-scrollbar-thumb {
  background: var(--bx-ink-200);
  border-radius: var(--bx-r-full);
  border: 3px solid transparent;
  background-clip: content-box;
}
.bx-scroll::-webkit-scrollbar-thumb:hover { background: var(--bx-ink-300); background-clip: content-box; }

/* Horizontal scroll container for wide data tables — keeps the PAGE from
   ever scrolling sideways. */
.bx-table-scroll {
  width: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
}

/* --------------------------------------------------------------------------
   11. PRINT
   -------------------------------------------------------------------------- */
@media print {
  body { background: #fff; color: #000; }
  .bx-no-print, .bx-sidebar, .bx-topbar, .bx-toast-region { display: none !important; }
  .bx-card, .bx-panel { box-shadow: none !important; border-color: #999 !important; }
  a[href]::after { content: " (" attr(href) ")"; font-size: 11px; color: #555; }
}


/* ================= 03-components.css ================= */
/* ==========================================================================
   BIJOY DESIGN SYSTEM — v1.0
   File 3 of 4 : COMPONENTS
   Depends on: 01-tokens.css, 02-base.css
   --------------------------------------------------------------------------
   Rule: components reference the SEMANTIC token layer only. That is what makes
   dark mode, high-contrast and density modes free — no component ever needs a
   theme branch. No legacy Bootstrap / Blithe class is referenced or reused.
   ========================================================================== */

/* ==========================================================================
   A. BUTTONS
   ========================================================================== */
.bx-btn {
  --_bg: var(--bx-primary);
  --_fg: #fff;
  --_bd: var(--bx-primary);
  --_bg-hover: var(--bx-primary-hover);
  --_bd-hover: var(--bx-primary-hover);

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--bx-sp-2);
  position: relative;

  min-height: 40px;
  padding: var(--bx-sp-3) var(--bx-sp-5);
  border: 1px solid var(--_bd);
  border-radius: var(--bx-r-md);
  background: var(--_bg);
  color: var(--_fg);

  font-family: inherit;
  font-size: var(--bx-fs-sm);
  font-weight: var(--bx-fw-semi);
  line-height: 1.2;
  letter-spacing: 0;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;

  transition:
    background-color var(--bx-dur-fast) var(--bx-ease-out),
    border-color     var(--bx-dur-fast) var(--bx-ease-out),
    color            var(--bx-dur-fast) var(--bx-ease-out),
    box-shadow       var(--bx-dur-fast) var(--bx-ease-out),
    transform        var(--bx-dur-instant) var(--bx-ease-out);
}
.bx-btn:hover { background: var(--_bg-hover); border-color: var(--_bd-hover); text-decoration: none; color: var(--_fg); }
.bx-btn:active { transform: translateY(1px); }
.bx-btn:focus-visible { outline: 2px solid var(--bx-focus); outline-offset: 2px; }

/* --- shapes / sizes --- */
.bx-btn--sm { min-height: 32px; padding: var(--bx-sp-2) var(--bx-sp-3); font-size: var(--bx-fs-xs); border-radius: var(--bx-r-sm); }
.bx-btn--lg { min-height: 48px; padding: var(--bx-sp-4) var(--bx-sp-7); font-size: var(--bx-fs-md); border-radius: var(--bx-r-lg); }
.bx-btn--block { width: 100%; }
.bx-btn--pill { border-radius: var(--bx-r-full); }
.bx-btn--icon { min-width: 40px; padding-inline: var(--bx-sp-2); }
.bx-btn--icon.bx-btn--sm { min-width: 32px; }
.bx-btn--icon.bx-btn--lg { min-width: 48px; }

/* --- variants --- */
.bx-btn--secondary {
  --_bg: var(--bx-bg-elevated); --_fg: var(--bx-text-strong);
  --_bd: var(--bx-border-strong);
  --_bg-hover: var(--bx-bg-sunken); --_bd-hover: var(--bx-ink-300);
}
.bx-btn--ghost { --_bg: transparent; --_fg: var(--bx-text); --_bd: transparent; --_bg-hover: var(--bx-bg-sunken); --_bd-hover: transparent; }
.bx-btn--accent { --_bg: var(--bx-accent); --_fg: #fff; --_bd: var(--bx-accent); --_bg-hover: var(--bx-accent-hover); --_bd-hover: var(--bx-accent-hover); }
.bx-btn--success { --_bg: var(--bx-success); --_fg: #fff; --_bd: var(--bx-success); --_bg-hover: var(--bx-green-700); --_bd-hover: var(--bx-green-700); }
.bx-btn--danger { --_bg: var(--bx-danger); --_fg: #fff; --_bd: var(--bx-danger); --_bg-hover: var(--bx-red-700); --_bd-hover: var(--bx-red-700); }
.bx-btn--dark { --_bg: var(--bx-navy-800); --_fg: #fff; --_bd: var(--bx-navy-800); --_bg-hover: var(--bx-navy-700); --_bd-hover: var(--bx-navy-700); }
.bx-btn--white { --_bg: #fff; --_fg: var(--bx-navy-800); --_bd: #fff; --_bg-hover: var(--bx-blue-50); --_bd-hover: var(--bx-blue-50); }
.bx-btn--link {
  --_bg: transparent; --_fg: var(--bx-primary-text); --_bd: transparent;
  --_bg-hover: transparent; --_bd-hover: transparent;
  min-height: 0; padding: 0; text-decoration: underline; text-underline-offset: 3px;
}

.bx-btn[disabled], .bx-btn[aria-disabled="true"], .bx-btn.is-disabled {
  opacity: .5; cursor: not-allowed; transform: none; box-shadow: none;
}
.bx-btn[disabled]:hover, .bx-btn[aria-disabled="true"]:hover { background: var(--_bg); border-color: var(--_bd); }

/* --- loading --- */
.bx-btn.is-loading { color: transparent !important; pointer-events: none; }
.bx-btn.is-loading::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  color: var(--_fg);
  animation: bx-spin .7s linear infinite;
}
.bx-btn--secondary.is-loading::after, .bx-btn--ghost.is-loading::after { color: var(--bx-primary); }
@keyframes bx-spin { to { transform: rotate(360deg); } }

/* --- button group --- */
.bx-btn-group { display: inline-flex; }
.bx-btn-group > .bx-btn { border-radius: 0; }
.bx-btn-group > .bx-btn:first-child { border-start-start-radius: var(--bx-r-md); border-end-start-radius: var(--bx-r-md); }
.bx-btn-group > .bx-btn:last-child  { border-start-end-radius: var(--bx-r-md);   border-end-end-radius: var(--bx-r-md); }
.bx-btn-group > .bx-btn + .bx-btn { margin-inline-start: -1px; }
.bx-btn-group > .bx-btn:hover { z-index: 1; }

/* --- icon-only button used in topbars / table rows --- */
.bx-iconbtn {
  display: inline-grid; place-items: center;
  width: 36px; height: 36px; flex: 0 0 36px;
  border: 1px solid transparent; border-radius: var(--bx-r-md);
  background: transparent; color: var(--bx-text-muted);
  transition: background-color var(--bx-dur-fast) var(--bx-ease-out), color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-iconbtn:hover { background: var(--bx-bg-sunken); color: var(--bx-text-strong); }
.bx-iconbtn:focus-visible { outline: 2px solid var(--bx-focus); outline-offset: 1px; }
.bx-iconbtn svg { width: 18px; height: 18px; }

/* ==========================================================================
   B. BADGES / PILLS / STATUS
   ========================================================================== */
.bx-badge {
  display: inline-flex; align-items: center; gap: var(--bx-sp-1);
  padding: 3px var(--bx-sp-2);
  border: 1px solid transparent;
  border-radius: var(--bx-r-xs);
  background: var(--bx-neutral-soft);
  color: var(--bx-neutral-text);
  font-size: var(--bx-fs-2xs);
  font-weight: var(--bx-fw-bold);
  line-height: 1.5;
  letter-spacing: var(--bx-tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
  vertical-align: middle;
}
.bx-badge--pill { border-radius: var(--bx-r-full); padding-inline: var(--bx-sp-3); text-transform: none; letter-spacing: 0; }
.bx-badge--lg { font-size: var(--bx-fs-xs); padding: 5px var(--bx-sp-3); }
.bx-badge--success { background: var(--bx-success-soft); color: var(--bx-success-text); }
.bx-badge--warning { background: var(--bx-warning-soft); color: var(--bx-warning-text); }
.bx-badge--danger  { background: var(--bx-danger-soft);  color: var(--bx-danger-text); }
.bx-badge--info    { background: var(--bx-info-soft);    color: var(--bx-info-text); }
.bx-badge--primary { background: var(--bx-primary-soft); color: var(--bx-primary-text); }
.bx-badge--accent  { background: var(--bx-accent-soft);  color: var(--bx-accent-text); }
.bx-badge--outline { background: transparent; border-color: var(--bx-border-strong); color: var(--bx-text-muted); }

.bx-dot { width: 7px; height: 7px; flex: 0 0 7px; border-radius: 50%; background: currentColor; display: inline-block; }
.bx-dot--live { box-shadow: 0 0 0 0 currentColor; animation: bx-pulse 2.2s var(--bx-ease-out) infinite; }
@keyframes bx-pulse { 70% { box-shadow: 0 0 0 7px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
.bx-status { display: inline-flex; align-items: center; gap: var(--bx-sp-2); font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-medium); color: var(--bx-text); }

.bx-count {
  display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: var(--bx-r-full); background: var(--bx-primary); color: #fff;
  font-size: var(--bx-fs-2xs); font-weight: var(--bx-fw-bold); line-height: 1;
}

/* ==========================================================================
   C. AVATAR
   ========================================================================== */
.bx-avatar {
  display: inline-grid; place-items: center; flex: 0 0 auto;
  width: 38px; height: 38px;
  border-radius: var(--bx-r-full);
  background: var(--bx-primary-soft); color: var(--bx-primary-text);
  font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-bold);
  line-height: 1; overflow: hidden;
  border: 1px solid var(--bx-border);
}
.bx-avatar--sm { width: 28px; height: 28px; font-size: var(--bx-fs-2xs); }
.bx-avatar--lg { width: 48px; height: 48px; font-size: var(--bx-fs-lg); }
.bx-avatar--xl { width: 64px; height: 64px; font-size: var(--bx-fs-2xl); }
.bx-avatar--square { border-radius: var(--bx-r-md); }
.bx-avatar--accent { background: var(--bx-accent-soft); color: var(--bx-accent-text); }
.bx-avatar--dark { background: var(--bx-navy-800); color: #fff; border-color: transparent; }
.bx-avatar img { width: 100%; height: 100%; object-fit: cover; }
.bx-avatar-stack { display: flex; }
.bx-avatar-stack > .bx-avatar + .bx-avatar { margin-inline-start: -10px; }
.bx-avatar-stack > .bx-avatar { box-shadow: 0 0 0 2px var(--bx-bg-elevated); }

/* ==========================================================================
   D. ALERTS / BANNERS
   ========================================================================== */
.bx-alert {
  display: flex; gap: var(--bx-sp-3); align-items: flex-start;
  padding: var(--bx-sp-4);
  border: 1px solid var(--bx-border);
  border-inline-start: 3px solid var(--bx-neutral);
  border-radius: var(--bx-r-md);
  background: var(--bx-bg-elevated);
  font-size: var(--bx-fs-sm);
}
.bx-alert__icon { flex: 0 0 20px; width: 20px; height: 20px; margin-top: 1px; color: var(--bx-neutral); }
.bx-alert__body { min-width: 0; flex: 1 1 auto; }
.bx-alert__title { display: block; font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); margin-bottom: 2px; }
.bx-alert__text { color: var(--bx-text-muted); margin: 0; }
.bx-alert__close { margin-inline-start: auto; flex: 0 0 auto; }

.bx-alert--success { background: var(--bx-success-soft); border-color: transparent; border-inline-start-color: var(--bx-success); }
.bx-alert--success .bx-alert__icon { color: var(--bx-success-text); }
.bx-alert--success .bx-alert__text { color: var(--bx-success-text); }
.bx-alert--warning { background: var(--bx-warning-soft); border-color: transparent; border-inline-start-color: var(--bx-warning); }
.bx-alert--warning .bx-alert__icon, .bx-alert--warning .bx-alert__text { color: var(--bx-warning-text); }
.bx-alert--danger  { background: var(--bx-danger-soft);  border-color: transparent; border-inline-start-color: var(--bx-danger); }
.bx-alert--danger .bx-alert__icon, .bx-alert--danger .bx-alert__text { color: var(--bx-danger-text); }
.bx-alert--info    { background: var(--bx-info-soft);    border-color: transparent; border-inline-start-color: var(--bx-info); }
.bx-alert--info .bx-alert__icon, .bx-alert--info .bx-alert__text { color: var(--bx-info-text); }

/* ==========================================================================
   E. CARDS & PANELS
   ========================================================================== */
.bx-card {
  background: var(--bx-bg-elevated);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-lg);
  box-shadow: var(--bx-shadow-xs);
  min-width: 0;
}
.bx-card--pad { padding: var(--bx-sp-6); }
.bx-card--flush { overflow: hidden; }
.bx-card--raised { box-shadow: var(--bx-shadow-md); border-color: transparent; }
.bx-card--interactive { transition: transform var(--bx-dur-base) var(--bx-ease-out), box-shadow var(--bx-dur-base) var(--bx-ease-out), border-color var(--bx-dur-base) var(--bx-ease-out); }
.bx-card--interactive:hover { transform: translateY(-2px); box-shadow: var(--bx-shadow-md); border-color: var(--bx-blue-300); }
.bx-card--accent-line { border-top: 3px solid var(--bx-primary); }
.bx-card--dark { background: var(--bx-navy-800); border-color: transparent; color: var(--bx-text-onDark); }
.bx-card--dark h1, .bx-card--dark h2, .bx-card--dark h3, .bx-card--dark h4 { color: #fff; }

.bx-card__head {
  display: flex; align-items: center; gap: var(--bx-sp-3);
  padding: var(--bx-sp-4) var(--bx-sp-6);
  border-bottom: 1px solid var(--bx-border);
  min-width: 0;
}
.bx-card__head--wrap { flex-wrap: wrap; }
/* The text slot is the only part allowed to shrink; the actions cluster keeps
   its intrinsic width and wraps within itself instead. */
.bx-card__heading { min-width: 0; flex: 1 1 auto; }
.bx-card__title { font-size: var(--bx-fs-md); font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); margin: 0; line-height: 1.35; min-width: 0; }
.bx-card__sub   { font-size: var(--bx-fs-xs); color: var(--bx-text-muted); margin: 2px 0 0; }
.bx-card__actions { margin-inline-start: auto; display: flex; align-items: center; gap: var(--bx-sp-2); flex-wrap: wrap; }
.bx-card__body  { padding: var(--bx-sp-6); min-width: 0; }
.bx-card__body--tight { padding: var(--bx-sp-4); }
.bx-card__body--flush { padding: 0; }
.bx-card__foot {
  display: flex; align-items: center; gap: var(--bx-sp-3); flex-wrap: wrap;
  padding: var(--bx-sp-4) var(--bx-sp-6);
  border-top: 1px solid var(--bx-border);
  background: var(--bx-bg-sunken);
  border-radius: 0 0 var(--bx-r-lg) var(--bx-r-lg);
}

/* --- stat card --- */
.bx-stat {
  display: flex; flex-direction: column; gap: var(--bx-sp-2);
  padding: var(--bx-sp-5);
  background: var(--bx-bg-elevated);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-lg);
  min-width: 0;
}
.bx-stat__label { font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-semi); color: var(--bx-text-muted); letter-spacing: var(--bx-tracking-wide); text-transform: uppercase; }
.bx-stat__value { font-size: var(--bx-fs-3xl); font-weight: var(--bx-fw-black); color: var(--bx-text-strong); letter-spacing: var(--bx-tracking-tight); line-height: 1.1; overflow-wrap: anywhere; }
.bx-stat__value--sm { font-size: var(--bx-fs-2xl); }
.bx-stat__foot { display: flex; align-items: center; gap: var(--bx-sp-2); font-size: var(--bx-fs-xs); color: var(--bx-text-muted); }
.bx-stat__icon {
  width: 40px; height: 40px; border-radius: var(--bx-r-md);
  display: grid; place-items: center; flex: 0 0 40px;
  background: var(--bx-primary-soft); color: var(--bx-primary-text);
}
.bx-stat__icon svg { width: 20px; height: 20px; }
.bx-stat__icon--accent  { background: var(--bx-accent-soft);  color: var(--bx-accent-text); }
.bx-stat__icon--success { background: var(--bx-success-soft); color: var(--bx-success-text); }
.bx-stat__icon--warning { background: var(--bx-warning-soft); color: var(--bx-warning-text); }
.bx-stat__icon--danger  { background: var(--bx-danger-soft);  color: var(--bx-danger-text); }

.bx-trend { display: inline-flex; align-items: center; gap: 3px; font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-semi); }
.bx-trend--up   { color: var(--bx-success-text); }
.bx-trend--down { color: var(--bx-danger-text); }
.bx-trend--flat { color: var(--bx-text-muted); }

/* --- key/value rows (used heavily in detail pages) --- */
.bx-kv { display: grid; gap: 0; }
.bx-kv__row {
  display: grid; grid-template-columns: minmax(0, 190px) minmax(0, 1fr);
  gap: var(--bx-sp-4); padding: var(--bx-sp-3) 0;
  border-bottom: 1px solid var(--bx-border);
  align-items: start;
}
.bx-kv__row:last-child { border-bottom: 0; }
.bx-kv__k { font-size: var(--bx-fs-sm); color: var(--bx-text-muted); font-weight: var(--bx-fw-medium); }
.bx-kv__v { font-size: var(--bx-fs-sm); color: var(--bx-text-strong); min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 560px) { .bx-kv__row { grid-template-columns: minmax(0, 1fr); gap: var(--bx-sp-1); } }

/* ==========================================================================
   F. FORMS
   ========================================================================== */
.bx-field { display: block; margin-bottom: var(--bx-sp-5); min-width: 0; }
.bx-field:last-child { margin-bottom: 0; }

.bx-label {
  display: block;
  font-size: var(--bx-fs-sm);
  font-weight: var(--bx-fw-semi);
  color: var(--bx-text-strong);
  margin-bottom: var(--bx-sp-2);
}
.bx-label__req { color: var(--bx-danger); margin-inline-start: 3px; }
.bx-label__opt { font-weight: var(--bx-fw-regular); color: var(--bx-text-subtle); font-size: var(--bx-fs-xs); margin-inline-start: 5px; }

.bx-input, .bx-select, .bx-textarea {
  display: block; width: 100%;
  min-height: 42px;
  padding: 10px var(--bx-sp-3);
  border: 1px solid var(--bx-border-strong);
  border-radius: var(--bx-r-md);
  background: var(--bx-surface);
  color: var(--bx-text-strong);
  font-family: inherit; font-size: var(--bx-fs-sm); line-height: 1.4;
  transition: border-color var(--bx-dur-fast) var(--bx-ease-out), box-shadow var(--bx-dur-fast) var(--bx-ease-out);
  appearance: none;
}
.bx-textarea { min-height: 104px; resize: vertical; padding-block: var(--bx-sp-3); }
.bx-input::placeholder, .bx-textarea::placeholder { color: var(--bx-text-subtle); }
.bx-input:hover, .bx-select:hover, .bx-textarea:hover { border-color: var(--bx-ink-300); }
.bx-input:focus, .bx-select:focus, .bx-textarea:focus {
  outline: none;
  border-color: var(--bx-primary);
  box-shadow: var(--bx-shadow-focus);
}
.bx-input[disabled], .bx-select[disabled], .bx-textarea[disabled] {
  background: var(--bx-bg-sunken); color: var(--bx-text-subtle); cursor: not-allowed;
}
.bx-input[readonly] { background: var(--bx-bg-sunken); }

.bx-select {
  padding-inline-end: var(--bx-sp-8);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%234A5A70' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--bx-sp-3) center;
  cursor: pointer;
}
[dir="rtl"] .bx-select { background-position: left var(--bx-sp-3) center; }
.bx-select--sm, .bx-input--sm { min-height: 34px; padding-block: 5px; font-size: var(--bx-fs-xs); }

/* --- input with leading / trailing addon --- */
.bx-inputgroup { display: flex; align-items: stretch; min-width: 0; }
.bx-inputgroup > .bx-input { border-radius: 0; min-width: 0; }
.bx-inputgroup > :first-child { border-start-start-radius: var(--bx-r-md); border-end-start-radius: var(--bx-r-md); }
.bx-inputgroup > :last-child  { border-start-end-radius: var(--bx-r-md);   border-end-end-radius: var(--bx-r-md); }
.bx-inputgroup > * + * { margin-inline-start: -1px; }
.bx-inputgroup > .bx-input:focus { z-index: 2; position: relative; }

.bx-addon {
  display: inline-flex; align-items: center; gap: var(--bx-sp-2);
  padding: 10px var(--bx-sp-3);
  border: 1px solid var(--bx-border-strong);
  background: var(--bx-bg-sunken);
  color: var(--bx-text-muted);
  font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-medium);
  white-space: nowrap; flex: 0 0 auto;
}

/* --- help / error / success text --- */
.bx-help { display: block; margin-top: var(--bx-sp-2); font-size: var(--bx-fs-xs); color: var(--bx-text-muted); }
.bx-error-text { display: flex; align-items: center; gap: 5px; margin-top: var(--bx-sp-2); font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-medium); color: var(--bx-danger-text); }
.bx-success-text { display: flex; align-items: center; gap: 5px; margin-top: var(--bx-sp-2); font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-medium); color: var(--bx-success-text); }

.bx-input.is-invalid, .bx-select.is-invalid, .bx-textarea.is-invalid { border-color: var(--bx-danger); }
.bx-input.is-invalid:focus { box-shadow: 0 0 0 4px rgba(192, 39, 31, .18); }
.bx-input.is-valid { border-color: var(--bx-success); }

/* --- checkbox & radio (real inputs, restyled) --- */
.bx-check { display: inline-flex; align-items: flex-start; gap: var(--bx-sp-3); font-size: var(--bx-fs-sm); color: var(--bx-text); cursor: pointer; min-width: 0; }
.bx-check input[type="checkbox"], .bx-check input[type="radio"] {
  appearance: none; -webkit-appearance: none;
  width: 18px; height: 18px; flex: 0 0 18px; margin-top: 1px;
  border: 1.5px solid var(--bx-border-strong);
  border-radius: var(--bx-r-xs);
  background: var(--bx-surface);
  cursor: pointer; position: relative;
  transition: background-color var(--bx-dur-fast) var(--bx-ease-out), border-color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-check input[type="radio"] { border-radius: 50%; }
.bx-check input:hover { border-color: var(--bx-primary); }
.bx-check input:checked { background: var(--bx-primary); border-color: var(--bx-primary); }
.bx-check input[type="checkbox"]:checked::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 5px; height: 9px;
  border: solid #fff; border-width: 0 2px 2px 0;
  transform: translateY(-1px) rotate(45deg);
}
.bx-check input[type="radio"]:checked::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 7px; height: 7px; border-radius: 50%; background: #fff;
}
.bx-check input:focus-visible { outline: 2px solid var(--bx-focus); outline-offset: 2px; }
.bx-check input:disabled { background: var(--bx-bg-sunken); border-color: var(--bx-border); cursor: not-allowed; }
.bx-check__text { min-width: 0; }
.bx-check__text small { display: block; color: var(--bx-text-muted); font-size: var(--bx-fs-xs); margin-top: 2px; }

/* --- switch --- */
.bx-switch { display: inline-flex; align-items: center; gap: var(--bx-sp-3); cursor: pointer; font-size: var(--bx-fs-sm); }
.bx-switch input { appearance: none; -webkit-appearance: none; position: absolute; opacity: 0; width: 0; height: 0; }
.bx-switch__track {
  position: relative; flex: 0 0 40px; width: 40px; height: 22px;
  border-radius: var(--bx-r-full);
  background: var(--bx-ink-200);
  transition: background-color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-switch__track::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  background: #fff; box-shadow: var(--bx-shadow-xs);
  transition: transform var(--bx-dur-base) var(--bx-ease-spring);
}
.bx-switch input:checked + .bx-switch__track { background: var(--bx-primary); }
.bx-switch input:checked + .bx-switch__track::after { transform: translateX(18px); }
.bx-switch input:focus-visible + .bx-switch__track { outline: 2px solid var(--bx-focus); outline-offset: 2px; }
.bx-switch input:disabled + .bx-switch__track { opacity: .5; cursor: not-allowed; }
.bx-switch--sm .bx-switch__track { flex-basis: 32px; width: 32px; height: 18px; }
.bx-switch--sm .bx-switch__track::after { width: 14px; height: 14px; }
.bx-switch--sm input:checked + .bx-switch__track::after { transform: translateX(14px); }

/* --- fieldset / form section --- */
.bx-fieldset { border: 0; padding: 0; margin: 0 0 var(--bx-sp-8); min-width: 0; }
.bx-fieldset:last-child { margin-bottom: 0; }
.bx-fieldset__legend {
  font-size: var(--bx-fs-2xs); font-weight: var(--bx-fw-bold); letter-spacing: var(--bx-tracking-caps);
  text-transform: uppercase; color: var(--bx-text-subtle);
  padding: 0 0 var(--bx-sp-4); margin: 0;
  border-bottom: 1px solid var(--bx-border);
  width: 100%; margin-bottom: var(--bx-sp-5);
}

/* --- form grid --- */
.bx-form-grid { display: grid; gap: 0 var(--bx-sp-5); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.bx-form-grid > .bx-field--full { grid-column: 1 / -1; }
@media (max-width: 700px) { .bx-form-grid { grid-template-columns: minmax(0, 1fr); } }

/* --- file drop --- */
.bx-file {
  display: grid; place-items: center; gap: var(--bx-sp-2);
  padding: var(--bx-sp-8) var(--bx-sp-5);
  border: 1.5px dashed var(--bx-border-strong);
  border-radius: var(--bx-r-lg);
  background: var(--bx-bg-sunken);
  text-align: center; cursor: pointer;
  transition: border-color var(--bx-dur-fast) var(--bx-ease-out), background-color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-file:hover { border-color: var(--bx-primary); background: var(--bx-primary-soft); }
.bx-file svg { width: 26px; height: 26px; color: var(--bx-primary-text); }
.bx-file__title { font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); }
.bx-file__hint { font-size: var(--bx-fs-xs); color: var(--bx-text-muted); }
.bx-file input[type="file"] { display: none; }

/* --- copyable code / secret field --- */
.bx-copyfield {
  display: flex; align-items: center; gap: var(--bx-sp-2);
  padding: var(--bx-sp-2) var(--bx-sp-2) var(--bx-sp-2) var(--bx-sp-3);
  border: 1px solid var(--bx-border-strong);
  border-radius: var(--bx-r-md);
  background: var(--bx-bg-sunken);
  min-width: 0;
}
.bx-copyfield code {
  flex: 1 1 auto; min-width: 0; background: none; border: 0; padding: 0;
  font-family: var(--bx-font-mono); font-size: var(--bx-fs-xs);
  color: var(--bx-text-strong); overflow-wrap: anywhere;
}

/* ==========================================================================
   G. TABLES
   Wide tables scroll INSIDE .bx-table-scroll — the page itself never does.
   ========================================================================== */
.bx-table-wrap {
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-lg);
  background: var(--bx-bg-elevated);
  overflow: hidden;
  min-width: 0;
}
.bx-table { width: 100%; border-collapse: collapse; font-size: var(--bx-fs-sm); }
.bx-table caption {
  caption-side: top; text-align: start;
  padding: var(--bx-sp-4) var(--bx-sp-5) 0;
  font-size: var(--bx-fs-xs); color: var(--bx-text-muted);
}
.bx-table th {
  position: sticky; top: 0; z-index: 1;
  text-align: start;
  padding: var(--bx-sp-3) var(--bx-sp-4);
  background: var(--bx-bg-sunken);
  border-bottom: 1px solid var(--bx-border);
  font-size: var(--bx-fs-2xs);
  font-weight: var(--bx-fw-bold);
  letter-spacing: var(--bx-tracking-caps);
  text-transform: uppercase;
  color: var(--bx-text-muted);
  white-space: nowrap;
}
.bx-table td {
  padding: var(--bx-sp-3) var(--bx-sp-4);
  border-bottom: 1px solid var(--bx-border);
  color: var(--bx-text);
  vertical-align: middle;
}
.bx-table tbody tr:last-child td { border-bottom: 0; }
.bx-table tbody tr { transition: background-color var(--bx-dur-fast) var(--bx-ease-out); }
.bx-table tbody tr:hover { background: var(--bx-bg-sunken); }
.bx-table tbody tr.is-selected { background: var(--bx-primary-soft); }
.bx-table tbody tr.is-muted td { color: var(--bx-text-subtle); }

.bx-table--compact th, .bx-table--compact td { padding: var(--bx-sp-2) var(--bx-sp-3); }
.bx-table--bordered th, .bx-table--bordered td { border-inline-end: 1px solid var(--bx-border); }
.bx-table--bordered th:last-child, .bx-table--bordered td:last-child { border-inline-end: 0; }
.bx-table--fixed { table-layout: fixed; }

.bx-table .bx-cell-num { text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; }
.bx-table .bx-cell-strong { font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); }
.bx-table .bx-cell-muted { color: var(--bx-text-muted); font-size: var(--bx-fs-xs); }
.bx-table .bx-cell-actions { text-align: end; white-space: nowrap; }
.bx-table .bx-cell-actions .bx-iconbtn { width: 30px; height: 30px; flex-basis: 30px; }

.bx-table__primary { display: block; font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); line-height: 1.3; }
.bx-table__secondary { display: block; font-size: var(--bx-fs-xs); color: var(--bx-text-muted); line-height: 1.35; }
.bx-table__id { font-family: var(--bx-font-mono); font-size: var(--bx-fs-xs); color: var(--bx-text-muted); }

/* sortable header */
.bx-th-sort {
  display: inline-flex; align-items: center; gap: 5px;
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
}
.bx-th-sort:hover { color: var(--bx-text-strong); }
.bx-th-sort svg { width: 12px; height: 12px; opacity: .45; }
.bx-th-sort[aria-sort="ascending"] svg, .bx-th-sort[aria-sort="descending"] svg { opacity: 1; color: var(--bx-primary-text); }

.bx-table__empty { padding: var(--bx-sp-12) var(--bx-sp-5); text-align: center; }

/* ==========================================================================
   H. PAGINATION
   ========================================================================== */
.bx-pagination {
  display: flex; align-items: center; gap: var(--bx-sp-3); flex-wrap: wrap;
  padding: var(--bx-sp-4) var(--bx-sp-5);
  border-top: 1px solid var(--bx-border);
  background: var(--bx-bg-elevated);
}
.bx-pagination__meta { font-size: var(--bx-fs-xs); color: var(--bx-text-muted); margin-inline-end: auto; }
.bx-pagination__list { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.bx-page {
  display: inline-grid; place-items: center;
  min-width: 34px; height: 34px; padding: 0 var(--bx-sp-2);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-sm);
  background: var(--bx-bg-elevated);
  color: var(--bx-text);
  font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-semi);
  cursor: pointer;
  transition: background-color var(--bx-dur-fast) var(--bx-ease-out), border-color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-page:hover { background: var(--bx-bg-sunken); border-color: var(--bx-border-strong); text-decoration: none; }
.bx-page[aria-current="page"] { background: var(--bx-primary); border-color: var(--bx-primary); color: #fff; }
.bx-page[disabled], .bx-page.is-disabled { opacity: .45; pointer-events: none; }
.bx-page--gap { border-color: transparent; background: none; cursor: default; }

/* ==========================================================================
   I. TABS / SEGMENTED CONTROL
   ========================================================================== */
.bx-tabs { border-bottom: 1px solid var(--bx-border); }
.bx-tabs__list {
  display: flex; gap: var(--bx-sp-1); overflow-x: auto;
  scrollbar-width: none; -ms-overflow-style: none;
}
.bx-tabs__list::-webkit-scrollbar { display: none; }
.bx-tab {
  position: relative;
  padding: var(--bx-sp-3) var(--bx-sp-4);
  border: 0; background: none;
  font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-semi);
  color: var(--bx-text-muted);
  white-space: nowrap; cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--bx-dur-fast) var(--bx-ease-out), border-color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-tab:hover { color: var(--bx-text-strong); }
.bx-tab[aria-selected="true"], .bx-tab.is-active { color: var(--bx-primary-text); border-bottom-color: var(--bx-primary); }
.bx-tab__count {
  display: inline-grid; place-items: center; min-width: 18px; height: 18px;
  margin-inline-start: 6px; padding: 0 5px; border-radius: var(--bx-r-full);
  background: var(--bx-bg-sunken); color: var(--bx-text-muted);
  font-size: 10px; font-weight: var(--bx-fw-bold);
}
.bx-tab[aria-selected="true"] .bx-tab__count { background: var(--bx-primary-soft); color: var(--bx-primary-text); }
.bx-tabpanel { padding-top: var(--bx-sp-5); }
.bx-tabpanel[hidden] { display: none; }

/* pill-style tab bar (used inside cards).
   `max-width` + `overflow-x` keep a long segmented control scrolling inside
   its own rounded box instead of widening the page on a phone. */
.bx-tabpill {
  display: inline-flex; gap: 3px; padding: 3px;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  background: var(--bx-bg-sunken); border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-md);
}
.bx-tabpill::-webkit-scrollbar { display: none; }
.bx-tabpill__item { flex: 0 0 auto; }
.bx-tabpill__item {
  padding: 6px var(--bx-sp-3);
  border: 0; border-radius: var(--bx-r-sm);
  background: transparent; color: var(--bx-text-muted);
  font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-semi);
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--bx-dur-fast) var(--bx-ease-out), color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-tabpill__item:hover { color: var(--bx-text-strong); }
.bx-tabpill__item.is-active { background: var(--bx-bg-elevated); color: var(--bx-text-strong); box-shadow: var(--bx-shadow-xs); }

/* ==========================================================================
   J. ACCORDION
   ========================================================================== */
.bx-accordion { display: grid; gap: var(--bx-sp-3); }
.bx-acc {
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-md);
  background: var(--bx-bg-elevated);
  overflow: hidden;
  transition: border-color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-acc[open] { border-color: var(--bx-blue-300); }
.bx-acc__summary {
  display: flex; align-items: center; gap: var(--bx-sp-3);
  padding: var(--bx-sp-4) var(--bx-sp-5);
  cursor: pointer; list-style: none;
  font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-semi); color: var(--bx-text-strong);
}
.bx-acc__summary::-webkit-details-marker { display: none; }
.bx-acc__summary::after {
  content: ""; margin-inline-start: auto; flex: 0 0 16px;
  width: 16px; height: 16px;
  background: currentColor; opacity: .55;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") center/contain no-repeat;
  transition: transform var(--bx-dur-base) var(--bx-ease-out);
}
.bx-acc[open] .bx-acc__summary::after { transform: rotate(180deg); }
.bx-acc__summary:hover { background: var(--bx-bg-sunken); }
.bx-acc__body { padding: 0 var(--bx-sp-5) var(--bx-sp-5); font-size: var(--bx-fs-sm); color: var(--bx-text-muted); border-top: 1px solid var(--bx-border); padding-top: var(--bx-sp-4); }
.bx-acc__body > :last-child { margin-bottom: 0; }

/* ==========================================================================
   K. MODAL / DRAWER / TOAST / DROPDOWN / TOOLTIP
   ========================================================================== */
.bx-overlay {
  position: fixed; inset: 0; z-index: var(--bx-z-modal);
  background: var(--bx-overlay);
  display: grid; place-items: center;
  padding: var(--bx-sp-4);
  backdrop-filter: blur(2px);
}
.bx-modal {
  width: min(560px, 100%);
  max-height: min(86dvh, 900px);
  display: flex; flex-direction: column;
  background: var(--bx-bg-elevated);
  border-radius: var(--bx-r-xl);
  box-shadow: var(--bx-shadow-xl);
  overflow: hidden;
}
.bx-modal--sm { width: min(400px, 100%); }
.bx-modal--lg { width: min(820px, 100%); }
.bx-modal--xl { width: min(1080px, 100%); }
.bx-modal__head {
  display: flex; align-items: center; gap: var(--bx-sp-3);
  padding: var(--bx-sp-5) var(--bx-sp-6);
  border-bottom: 1px solid var(--bx-border);
  flex: 0 0 auto;
}
.bx-modal__title { font-size: var(--bx-fs-xl); font-weight: var(--bx-fw-bold); color: var(--bx-text-strong); margin: 0; min-width: 0; }
.bx-modal__body { padding: var(--bx-sp-6); overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.bx-modal__foot {
  display: flex; align-items: center; gap: var(--bx-sp-3); flex-wrap: wrap;
  justify-content: flex-end;
  padding: var(--bx-sp-4) var(--bx-sp-6);
  border-top: 1px solid var(--bx-border);
  background: var(--bx-bg-sunken);
  flex: 0 0 auto;
}
.bx-modal__foot .bx-btn--link, .bx-modal__foot .bx-mr-auto { margin-inline-end: auto; }

/* --- drawer --- */
.bx-drawer {
  position: fixed; top: 0; bottom: 0; z-index: var(--bx-z-drawer);
  width: min(420px, 92vw);
  display: flex; flex-direction: column;
  background: var(--bx-bg-elevated);
  box-shadow: var(--bx-shadow-xl);
}
.bx-drawer--end   { inset-inline-end: 0; }
.bx-drawer--start { inset-inline-start: 0; }
.bx-drawer__head {
  display: flex; align-items: center; gap: var(--bx-sp-3);
  padding: var(--bx-sp-4) var(--bx-sp-5);
  border-bottom: 1px solid var(--bx-border); flex: 0 0 auto;
}
.bx-drawer__body { padding: var(--bx-sp-5); overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.bx-drawer__foot { padding: var(--bx-sp-4) var(--bx-sp-5); border-top: 1px solid var(--bx-border); display: flex; gap: var(--bx-sp-3); flex: 0 0 auto; }

/* --- toast --- */
.bx-toast-region {
  position: fixed; z-index: var(--bx-z-toast);
  inset-block-end: var(--bx-sp-5); inset-inline-end: var(--bx-sp-5);
  display: grid; gap: var(--bx-sp-3);
  width: min(380px, calc(100vw - var(--bx-sp-8)));
  pointer-events: none;
}
.bx-toast {
  display: flex; gap: var(--bx-sp-3); align-items: flex-start;
  padding: var(--bx-sp-4);
  background: var(--bx-navy-800);
  color: var(--bx-text-onDark);
  border-radius: var(--bx-r-md);
  box-shadow: var(--bx-shadow-lg);
  pointer-events: auto;
  animation: bx-toast-in var(--bx-dur-base) var(--bx-ease-out);
}
.bx-toast__icon { flex: 0 0 18px; width: 18px; height: 18px; margin-top: 1px; }
.bx-toast__body { min-width: 0; flex: 1 1 auto; font-size: var(--bx-fs-sm); }
.bx-toast__title { display: block; font-weight: var(--bx-fw-semi); color: #fff; }
.bx-toast--success .bx-toast__icon { color: var(--bx-teal-300); }
.bx-toast--danger  { background: var(--bx-red-700); color: #FBDDDB; }
.bx-toast--danger .bx-toast__icon { color: #FBDDDB; }
.bx-toast--warning { background: var(--bx-amber-700); color: #FDF0D9; }
.bx-toast--warning .bx-toast__icon { color: #FDF0D9; }
@keyframes bx-toast-in { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }
@media (max-width: 520px) { .bx-toast-region { inset-inline: var(--bx-sp-3); width: auto; } }

/* --- dropdown menu --- */
.bx-menu {
  min-width: 200px;
  padding: var(--bx-sp-2);
  background: var(--bx-bg-elevated);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-md);
  box-shadow: var(--bx-shadow-lg);
}
.bx-menu__item {
  display: flex; align-items: center; gap: var(--bx-sp-3);
  width: 100%; padding: var(--bx-sp-2) var(--bx-sp-3);
  border: 0; border-radius: var(--bx-r-sm);
  background: none; color: var(--bx-text);
  font-size: var(--bx-fs-sm); text-align: start; text-decoration: none;
  cursor: pointer;
  transition: background-color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-menu__item:hover { background: var(--bx-bg-sunken); text-decoration: none; color: var(--bx-text-strong); }
.bx-menu__item svg { width: 16px; height: 16px; flex: 0 0 16px; color: var(--bx-text-subtle); }
.bx-menu__item--danger { color: var(--bx-danger-text); }
.bx-menu__item--danger:hover { background: var(--bx-danger-soft); color: var(--bx-danger-text); }
.bx-menu__item--danger svg { color: currentColor; }
.bx-menu__sep { height: 1px; background: var(--bx-border); margin: var(--bx-sp-2) 0; border: 0; }
.bx-menu__label {
  padding: var(--bx-sp-2) var(--bx-sp-3) 4px;
  font-size: var(--bx-fs-2xs); font-weight: var(--bx-fw-bold);
  letter-spacing: var(--bx-tracking-caps); text-transform: uppercase; color: var(--bx-text-subtle);
}

/* --- tooltip (CSS-only, uses data-bx-tip) --- */
[data-bx-tip] { position: relative; }
[data-bx-tip]::after {
  content: attr(data-bx-tip);
  position: absolute; inset-block-end: calc(100% + 8px); inset-inline-start: 50%;
  transform: translateX(-50%);
  padding: 5px var(--bx-sp-2);
  background: var(--bx-ink-900); color: #fff;
  font-size: var(--bx-fs-2xs); font-weight: var(--bx-fw-medium); line-height: 1.4;
  border-radius: var(--bx-r-xs); white-space: nowrap; max-width: 260px;
  opacity: 0; pointer-events: none; z-index: var(--bx-z-tooltip);
  transition: opacity var(--bx-dur-fast) var(--bx-ease-out);
}
[data-bx-tip]:hover::after, [data-bx-tip]:focus-visible::after { opacity: 1; }
@media (hover: none) { [data-bx-tip]::after { display: none; } }

/* ==========================================================================
   L. PROGRESS / METER / SPINNER
   ========================================================================== */
.bx-progress { width: 100%; height: 8px; border-radius: var(--bx-r-full); background: var(--bx-bg-sunken); overflow: hidden; }
.bx-progress--sm { height: 5px; }
.bx-progress--lg { height: 12px; }
.bx-progress__bar {
  height: 100%; width: 0;
  border-radius: inherit;
  background: var(--bx-primary);
  transition: width var(--bx-dur-slow) var(--bx-ease-out);
}
.bx-progress__bar--accent  { background: var(--bx-accent); }
.bx-progress__bar--success { background: var(--bx-success); }
.bx-progress__bar--warning { background: var(--bx-warning); }
.bx-progress__bar--danger  { background: var(--bx-danger); }
.bx-progress__bar--striped {
  background-image: linear-gradient(45deg, rgba(255,255,255,.28) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.28) 50%, rgba(255,255,255,.28) 75%, transparent 75%, transparent);
  background-size: 14px 14px;
  animation: bx-stripes 1s linear infinite;
}
@keyframes bx-stripes { to { background-position: 14px 0; } }

.bx-spinner {
  width: 20px; height: 20px; flex: 0 0 20px;
  border-radius: 50%;
  border: 2px solid var(--bx-blue-100);
  border-top-color: var(--bx-primary);
  animation: bx-spin .7s linear infinite;
}
.bx-spinner--sm { width: 14px; height: 14px; border-width: 2px; }
.bx-spinner--lg { width: 32px; height: 32px; border-width: 3px; }
.bx-spinner--onDark { border-color: rgba(255,255,255,.28); border-top-color: #fff; }

/* ==========================================================================
   M. SKELETON / EMPTY / LOADING
   ========================================================================== */
.bx-skeleton {
  display: block; border-radius: var(--bx-r-xs);
  background: linear-gradient(90deg, var(--bx-bg-sunken) 25%, var(--bx-surface-3) 37%, var(--bx-bg-sunken) 63%);
  background-size: 400% 100%;
  animation: bx-shimmer 1.4s ease-in-out infinite;
}
[data-bx-theme="dark"] .bx-skeleton { background-image: linear-gradient(90deg, var(--bx-surface-3) 25%, var(--bx-line) 37%, var(--bx-surface-3) 63%); }
.bx-skeleton--text { height: 12px; margin-bottom: 8px; }
.bx-skeleton--title { height: 20px; width: 45%; margin-bottom: var(--bx-sp-3); }
.bx-skeleton--circle { border-radius: 50%; width: 38px; height: 38px; }
.bx-skeleton--block { height: 120px; border-radius: var(--bx-r-md); }
@keyframes bx-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }

.bx-empty {
  display: grid; place-items: center; gap: var(--bx-sp-3);
  padding: var(--bx-sp-14) var(--bx-sp-6);
  text-align: center;
}
.bx-empty__art {
  width: 60px; height: 60px; border-radius: var(--bx-r-xl);
  display: grid; place-items: center;
  background: var(--bx-bg-sunken); color: var(--bx-text-subtle);
  margin-bottom: var(--bx-sp-1);
}
.bx-empty__art svg { width: 28px; height: 28px; }
.bx-empty__title { font-size: var(--bx-fs-lg); font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); margin: 0; }
.bx-empty__text { font-size: var(--bx-fs-sm); color: var(--bx-text-muted); margin: 0; max-width: 44ch; }
.bx-empty__actions { margin-top: var(--bx-sp-3); display: flex; gap: var(--bx-sp-3); flex-wrap: wrap; justify-content: center; }

/* ==========================================================================
   N. BREADCRUMB / PAGE HEADER / STEPPER
   ========================================================================== */
.bx-breadcrumb { display: flex; align-items: center; gap: var(--bx-sp-2); flex-wrap: wrap; font-size: var(--bx-fs-xs); }
.bx-breadcrumb a { color: var(--bx-text-muted); text-decoration: none; }
.bx-breadcrumb a:hover { color: var(--bx-primary-text); text-decoration: none; }
.bx-breadcrumb__sep { color: var(--bx-ink-300); }
.bx-breadcrumb [aria-current="page"] { color: var(--bx-text-strong); font-weight: var(--bx-fw-medium); }

.bx-pagehead { display: flex; align-items: flex-start; gap: var(--bx-sp-4); flex-wrap: wrap; margin-bottom: var(--bx-sp-6); }
.bx-pagehead__main { min-width: 0; flex: 1 1 auto; }
.bx-pagehead h1 { font-size: var(--bx-fs-2xl); margin-bottom: var(--bx-sp-1); }
.bx-pagehead__sub { font-size: var(--bx-fs-sm); color: var(--bx-text-muted); margin: 0; }
.bx-pagehead__actions { display: flex; align-items: center; gap: var(--bx-sp-2); flex-wrap: wrap; }

.bx-steps { display: flex; gap: 0; counter-reset: bxstep; }
.bx-step { flex: 1 1 0; min-width: 0; position: relative; padding-top: 34px; }
.bx-step::before {
  content: counter(bxstep); counter-increment: bxstep;
  position: absolute; top: 0; inset-inline-start: 0;
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--bx-bg-sunken); color: var(--bx-text-muted);
  border: 1.5px solid var(--bx-border-strong);
  font-size: var(--bx-fs-2xs); font-weight: var(--bx-fw-bold);
}
.bx-step::after {
  content: ""; position: absolute; top: 13px; inset-inline-start: 30px; inset-inline-end: 4px;
  height: 1.5px; background: var(--bx-border);
}
.bx-step:last-child::after { display: none; }
.bx-step__title { font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-semi); color: var(--bx-text-muted); }
.bx-step.is-done::before { content: "✓"; background: var(--bx-success); border-color: var(--bx-success); color: #fff; }
.bx-step.is-done::after { background: var(--bx-success); }
.bx-step.is-current::before { background: var(--bx-primary); border-color: var(--bx-primary); color: #fff; }
.bx-step.is-current .bx-step__title { color: var(--bx-text-strong); }

/* ==========================================================================
   O. ACTIVITY FEED / TIMELINE
   ========================================================================== */
.bx-feed { display: grid; gap: 0; min-width: 0; }
.bx-feed__item { position: relative; display: flex; gap: var(--bx-sp-3); padding-bottom: var(--bx-sp-5); min-width: 0; }
.bx-feed__item:last-child { padding-bottom: 0; }
.bx-feed__item::before {
  content: ""; position: absolute; inset-inline-start: 15px; top: 32px; bottom: 0;
  width: 1.5px; background: var(--bx-border);
}
.bx-feed__item:last-child::before { display: none; }
.bx-feed__dot {
  position: relative; z-index: 1;
  width: 32px; height: 32px; flex: 0 0 32px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--bx-bg-sunken); color: var(--bx-text-muted);
  border: 1px solid var(--bx-border);
}
.bx-feed__dot svg { width: 15px; height: 15px; }
.bx-feed__dot--success { background: var(--bx-success-soft); color: var(--bx-success-text); border-color: transparent; }
.bx-feed__dot--warning { background: var(--bx-warning-soft); color: var(--bx-warning-text); border-color: transparent; }
.bx-feed__dot--danger  { background: var(--bx-danger-soft);  color: var(--bx-danger-text);  border-color: transparent; }
.bx-feed__dot--primary { background: var(--bx-primary-soft); color: var(--bx-primary-text); border-color: transparent; }
.bx-feed__body { min-width: 0; flex: 1 1 auto; }
.bx-feed__title { font-size: var(--bx-fs-sm); color: var(--bx-text-strong); font-weight: var(--bx-fw-medium); line-height: 1.45; }
.bx-feed__meta { font-size: var(--bx-fs-xs); color: var(--bx-text-muted); margin-top: 2px; }

/* ==========================================================================
   P. CHART CONTAINER
   ========================================================================== */
.bx-chart { display: flex; flex-direction: column; min-width: 0; }
/* A DEFINITE height, not just min-height: the pure-CSS bar strip inside sets
   `height: 100%`, and a percentage height cannot resolve against an auto-height
   parent — the bars silently collapse to nothing. */
.bx-chart__canvas { position: relative; width: 100%; height: 220px; }
.bx-chart__canvas--sm { height: 150px; }
.bx-chart__canvas--lg { height: 320px; }
.bx-chart__canvas > svg, .bx-chart__canvas > canvas { width: 100%; height: 100%; }
.bx-chart__legend { display: flex; flex-wrap: wrap; gap: var(--bx-sp-4); margin-top: var(--bx-sp-4); }
.bx-chart__legend-item { display: inline-flex; align-items: center; gap: var(--bx-sp-2); font-size: var(--bx-fs-xs); color: var(--bx-text-muted); }
.bx-legend-swatch { width: 10px; height: 10px; border-radius: 3px; background: var(--bx-primary); flex: 0 0 10px; }
.bx-legend-swatch--accent  { background: var(--bx-accent); }
.bx-legend-swatch--navy    { background: var(--bx-navy-700); }
.bx-legend-swatch--warning { background: var(--bx-warning); }

/* Sparkline / bar column strip — pure CSS, no JS dependency */
.bx-bars { display: flex; align-items: flex-end; gap: 4px; height: 72px; }
.bx-bars--fill { height: 100%; }
.bx-bars--gap { gap: 7px; }
.bx-bars > span { flex: 1 1 0; min-width: 0; background: var(--bx-blue-300); border-radius: 3px 3px 0 0; }
.bx-bars > span:nth-child(odd) { background: var(--bx-primary); }

/* ==========================================================================
   Q. MARKETING PIECES (used by the public site)
   ========================================================================== */
.bx-hero {
  position: relative; overflow: hidden;
  background: var(--bx-gradient-brand);
  color: var(--bx-text-onDark);
}
.bx-hero::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: linear-gradient(rgba(255,255,255,.045) 1px, transparent 1px),
                    linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px);
  background-size: 46px 46px;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 30%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 30%, transparent);
}
.bx-hero > * { position: relative; z-index: 2; }
.bx-hero__grid {
  display: grid; grid-template-columns: minmax(0, 1.06fr) minmax(0, .94fr);
  gap: var(--bx-sp-12); align-items: center;
  padding: var(--bx-sp-16) 0 var(--bx-sp-20);
}
.bx-hero h1 { color: #fff; font-size: var(--bx-fs-display); margin-bottom: var(--bx-sp-4); }
.bx-hero__lead { font-size: var(--bx-fs-lg); color: #C2D3E6; max-width: 56ch; margin: 0; }
.bx-hero__cta { display: flex; flex-wrap: wrap; gap: var(--bx-sp-3); margin: var(--bx-sp-8) 0 var(--bx-sp-5); }
.bx-hero__points { display: flex; flex-wrap: wrap; gap: var(--bx-sp-2) var(--bx-sp-5); font-size: var(--bx-fs-sm); color: #9FB6CE; }
.bx-hero__points li { display: flex; align-items: center; gap: var(--bx-sp-2); }
.bx-tick { width: 16px; height: 16px; flex: 0 0 16px; color: var(--bx-teal-300); }
@media (max-width: 940px) { .bx-hero__grid { grid-template-columns: minmax(0, 1fr); gap: var(--bx-sp-10); padding: var(--bx-sp-12) 0 var(--bx-sp-14); } }

.bx-chip {
  display: inline-flex; align-items: center; gap: var(--bx-sp-2);
  padding: 5px var(--bx-sp-3);
  border: 1px solid rgba(255,255,255,.22);
  border-radius: var(--bx-r-full);
  background: rgba(255,255,255,.07);
  color: var(--bx-text-onDark);
  font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-medium);
  white-space: nowrap;
}
.bx-chip--light { border-color: var(--bx-border); background: var(--bx-bg-elevated); color: var(--bx-text); }
.bx-chip__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--bx-teal-300); flex: 0 0 7px; }

/* trust bar / channel strip */
.bx-chanstrip { display: flex; flex-wrap: wrap; gap: var(--bx-sp-2); justify-content: center; }
.bx-chan {
  display: inline-flex; align-items: center; gap: var(--bx-sp-2);
  padding: 7px var(--bx-sp-4);
  border: 1px solid var(--bx-border); border-radius: var(--bx-r-full);
  background: var(--bx-bg-elevated); color: var(--bx-text);
  font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-semi);
  white-space: nowrap;
}
.bx-chan__mark { width: 9px; height: 9px; border-radius: 3px; background: var(--bx-primary); flex: 0 0 9px; }
.bx-chan--teal  .bx-chan__mark { background: var(--bx-accent); }
.bx-chan--navy  .bx-chan__mark { background: var(--bx-navy-700); }
.bx-chan--amber .bx-chan__mark { background: var(--bx-amber-600); }
.bx-chan--slate .bx-chan__mark { background: var(--bx-ink-400); }

/* feature icon tile */
.bx-ico {
  width: 44px; height: 44px; border-radius: var(--bx-r-md);
  display: grid; place-items: center; margin-bottom: var(--bx-sp-4);
  background: var(--bx-primary-soft); color: var(--bx-primary-text);
}
.bx-ico svg { width: 22px; height: 22px; }
.bx-ico--accent  { background: var(--bx-accent-soft);  color: var(--bx-accent-text); }
.bx-ico--navy    { background: var(--bx-navy-800);     color: #fff; }
.bx-ico--success { background: var(--bx-success-soft); color: var(--bx-success-text); }
.bx-ico--warning { background: var(--bx-warning-soft); color: var(--bx-warning-text); }

/* plan / pricing card */
.bx-plan {
  position: relative;
  display: flex; flex-direction: column;
  padding: var(--bx-sp-7) var(--bx-sp-6);
  background: var(--bx-bg-elevated);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-xl);
  box-shadow: var(--bx-shadow-xs);
  min-width: 0;
}
.bx-plan--featured { border: 2px solid var(--bx-primary); box-shadow: var(--bx-shadow-lg); }
.bx-plan__flag {
  position: absolute; top: calc(var(--bx-sp-4) * -1); inset-inline-start: var(--bx-sp-6);
  padding: 4px var(--bx-sp-3);
  background: var(--bx-primary); color: #fff;
  border-radius: var(--bx-r-full);
  font-size: var(--bx-fs-2xs); font-weight: var(--bx-fw-bold);
  letter-spacing: var(--bx-tracking-wide); text-transform: uppercase;
}
.bx-plan__name { font-size: var(--bx-fs-md); font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); margin-bottom: var(--bx-sp-1); }
.bx-plan__price { font-size: var(--bx-fs-5xl); font-weight: var(--bx-fw-black); color: var(--bx-text-strong); letter-spacing: var(--bx-tracking-tight); line-height: 1; }
.bx-plan__price small { font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-medium); color: var(--bx-text-muted); }
.bx-plan__note { font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-semi); color: var(--bx-accent-text); margin-top: var(--bx-sp-2); }
.bx-plan__list { display: grid; gap: var(--bx-sp-3); margin: var(--bx-sp-6) 0; padding: 0; list-style: none; }
.bx-plan__list li { display: flex; gap: var(--bx-sp-3); font-size: var(--bx-fs-sm); align-items: flex-start; }
.bx-plan__list svg { width: 17px; height: 17px; flex: 0 0 17px; color: var(--bx-accent); margin-top: 2px; }
.bx-plan__list li.is-off { color: var(--bx-text-subtle); }
.bx-plan__list li.is-off svg { color: var(--bx-ink-200); }
.bx-plan__foot { margin-top: auto; }

/* logo wall placeholder */
.bx-logobox {
  min-height: 72px; display: grid; place-items: center; padding: var(--bx-sp-3);
  border: 1px dashed var(--bx-border-strong);
  border-radius: var(--bx-r-md);
  background: var(--bx-bg-elevated);
  color: var(--bx-text-subtle);
  font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-semi);
  text-align: center;
}

/* quote / testimonial */
.bx-quote { display: flex; flex-direction: column; gap: var(--bx-sp-4); }
.bx-quote__text { font-size: var(--bx-fs-md); color: var(--bx-text); margin: 0; }
.bx-quote__who { display: flex; align-items: center; gap: var(--bx-sp-3); margin-top: auto; }
.bx-quote__name { font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); line-height: 1.3; }
.bx-quote__role { font-size: var(--bx-fs-xs); color: var(--bx-text-muted); }
.bx-stars { color: var(--bx-amber-600); letter-spacing: 2px; font-size: var(--bx-fs-sm); }

/* ==========================================================================
   R. PUBLIC SITE CHROME (header / footer)
   ========================================================================== */
.bx-siteheader {
  position: sticky; top: 0; z-index: var(--bx-z-sticky);
  background: var(--bx-bg-elevated);
  border-bottom: 1px solid var(--bx-border);
}
.bx-siteheader__inner {
  display: flex; align-items: center; gap: var(--bx-sp-5);
  min-height: 66px;
  flex-wrap: wrap;
  row-gap: var(--bx-sp-3);
  padding-block: var(--bx-sp-3);
}
.bx-siteheader__actions {
  display: flex; align-items: center; gap: var(--bx-sp-2);
  margin-inline-start: auto; flex: 0 1 auto; min-width: 0;
}
.bx-brand { display: inline-flex; align-items: center; gap: var(--bx-sp-3); text-decoration: none; flex: 0 0 auto; min-width: 0; }
.bx-brand__text { min-width: 0; }
.bx-brand:hover { text-decoration: none; }
.bx-brand__mark {
  width: 36px; height: 36px; flex: 0 0 36px;
  border-radius: var(--bx-r-md);
  display: grid; place-items: center;
  background: var(--bx-gradient-accent); color: #fff;
  font-size: var(--bx-fs-md); font-weight: var(--bx-fw-black); line-height: 1;
}
.bx-brand__name { font-size: var(--bx-fs-md); font-weight: var(--bx-fw-black); color: var(--bx-text-strong); letter-spacing: var(--bx-tracking-tight); line-height: 1.15; }
.bx-brand__tag { display: block; font-size: 10px; font-weight: var(--bx-fw-semi); letter-spacing: var(--bx-tracking-caps); text-transform: uppercase; color: var(--bx-text-subtle); }
.bx-sitenav { display: flex; align-items: center; gap: var(--bx-sp-1); margin-inline: auto; }
.bx-sitenav a {
  padding: var(--bx-sp-2) var(--bx-sp-3);
  border-radius: var(--bx-r-sm);
  font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-medium);
  color: var(--bx-text-muted); text-decoration: none;
  transition: background-color var(--bx-dur-fast) var(--bx-ease-out), color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-sitenav a:hover { background: var(--bx-bg-sunken); color: var(--bx-text-strong); text-decoration: none; }
.bx-sitenav a[aria-current="page"] { color: var(--bx-primary-text); background: var(--bx-primary-soft); }

.bx-sitefooter { background: var(--bx-navy-900); color: var(--bx-text-onDark-dim); padding: var(--bx-sp-14) 0 var(--bx-sp-6); font-size: var(--bx-fs-sm); }
.bx-sitefooter__grid { display: grid; grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr)); gap: var(--bx-sp-8); }
.bx-sitefooter h4 { color: #fff; font-size: var(--bx-fs-2xs); letter-spacing: var(--bx-tracking-caps); text-transform: uppercase; margin-bottom: var(--bx-sp-4); }
.bx-sitefooter a { color: var(--bx-text-onDark-dim); display: block; padding: 5px 0; text-decoration: none; }
.bx-sitefooter a:hover { color: #fff; text-decoration: none; }
.bx-sitefooter__bottom {
  margin-top: var(--bx-sp-10); padding-top: var(--bx-sp-5);
  border-top: 1px solid rgba(255,255,255,.12);
  display: flex; align-items: center; gap: var(--bx-sp-4); flex-wrap: wrap;
  font-size: var(--bx-fs-xs);
}
@media (max-width: 900px) { .bx-sitefooter__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
@media (max-width: 560px) { .bx-sitefooter__grid { grid-template-columns: minmax(0, 1fr); } }

/* ==========================================================================
   S. MISC
   ========================================================================== */
.bx-list { display: grid; gap: 0; }
.bx-list__item {
  display: flex; align-items: center; gap: var(--bx-sp-3);
  padding: var(--bx-sp-3) var(--bx-sp-4);
  border-bottom: 1px solid var(--bx-border);
  min-width: 0;
}
.bx-list__item:last-child { border-bottom: 0; }
.bx-list__item--hover:hover { background: var(--bx-bg-sunken); }

.bx-code-inline { font-family: var(--bx-font-mono); font-size: var(--bx-fs-xs); background: var(--bx-bg-sunken); border: 1px solid var(--bx-border); border-radius: var(--bx-r-xs); padding: 1px 5px; color: var(--bx-text-strong); }

.bx-method {
  display: inline-block; padding: 2px 7px; border-radius: var(--bx-r-xs);
  font-family: var(--bx-font-mono); font-size: 10px; font-weight: var(--bx-fw-bold);
  letter-spacing: .04em; background: var(--bx-accent-soft); color: var(--bx-accent-text);
}
.bx-method--post { background: var(--bx-primary-soft); color: var(--bx-primary-text); }
.bx-method--del  { background: var(--bx-danger-soft);  color: var(--bx-danger-text); }

.bx-underline-tabs { display: flex; gap: var(--bx-sp-5); border-bottom: 1px solid var(--bx-border); overflow-x: auto; }

.bx-note {
  padding: var(--bx-sp-4) var(--bx-sp-5);
  background: var(--bx-primary-soft);
  border-radius: var(--bx-r-md);
  font-size: var(--bx-fs-sm);
  color: var(--bx-primary-text);
}

.bx-watermark {
  position: absolute; inset-block-end: var(--bx-sp-3); inset-inline-end: var(--bx-sp-4);
  font-size: var(--bx-fs-2xs); font-weight: var(--bx-fw-bold);
  letter-spacing: var(--bx-tracking-caps); text-transform: uppercase;
  color: var(--bx-text-subtle); pointer-events: none;
}

.bx-divider-label {
  display: flex; align-items: center; gap: var(--bx-sp-4);
  color: var(--bx-text-muted); font-size: var(--bx-fs-xs);
  margin: var(--bx-sp-5) 0;
}
.bx-divider-label::before, .bx-divider-label::after { content: ""; height: 1px; background: var(--bx-border); flex: 1; }

.bx-scrollshadow-x { position: relative; }
.bx-scrollshadow-x::after {
  content: ""; position: absolute; inset-block: 0; inset-inline-end: 0; width: 28px;
  background: linear-gradient(to left, var(--bx-bg-elevated), transparent);
  pointer-events: none; opacity: .9;
}


/* ================= 04-layout.css ================= */
/* ==========================================================================
   BIJOY DESIGN SYSTEM — v1.0
   File 4 of 4 : APPLICATION SHELL
   Depends on: 01-tokens.css, 02-base.css, 03-components.css
   --------------------------------------------------------------------------
   One shell serves BOTH the merchant panel and the admin panel. The only
   difference between them is which nav groups they render and what colour the
   top rail uses (.bx-app--admin). No duplicated layout code.
   ========================================================================== */

.bx-app {
  display: grid;
  grid-template-columns: var(--bx-sidebar-w) minmax(0, 1fr);
  min-height: 100dvh;
  background: var(--bx-bg);
}

/* ==========================================================================
   1. SIDEBAR
   ========================================================================== */
.bx-sidebar {
  position: sticky;
  top: 0;
  height: 100dvh;
  z-index: var(--bx-z-sidebar);
  display: flex;
  flex-direction: column;
  background: var(--bx-navy-900);
  color: var(--bx-text-onDark);
  border-inline-end: 1px solid rgba(255, 255, 255, .06);
  overflow: hidden;
  transition: width var(--bx-dur-base) var(--bx-ease-out);
}

.bx-sidebar__head {
  display: flex; align-items: center; gap: var(--bx-sp-3);
  min-height: var(--bx-topbar-h);
  padding: 0 var(--bx-sp-4);
  flex: 0 0 auto;
  border-bottom: 1px solid rgba(255, 255, 255, .07);
  min-width: 0;
}
.bx-sidebar__head .bx-brand__name { color: #fff; }
.bx-sidebar__head .bx-brand__tag { color: var(--bx-text-onDark-dim); }
.bx-sidebar__head .bx-brand__mark { flex: 0 0 32px; width: 32px; height: 32px; font-size: var(--bx-fs-sm); }
.bx-sidebar__toggle { margin-inline-start: auto; flex: 0 0 auto; color: var(--bx-text-onDark-dim); }
.bx-sidebar__toggle:hover { background: rgba(255, 255, 255, .08); color: #fff; }

.bx-sidebar__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--bx-sp-4) var(--bx-sp-3);
}

.bx-sidebar__foot {
  flex: 0 0 auto;
  padding: var(--bx-sp-3);
  border-top: 1px solid rgba(255, 255, 255, .07);
}

/* --- nav groups --- */
.bx-navgroup + .bx-navgroup { margin-top: var(--bx-sp-6); }
.bx-navgroup__label {
  display: block;
  padding: 0 var(--bx-sp-3) var(--bx-sp-2);
  font-size: 10px;
  font-weight: var(--bx-fw-bold);
  letter-spacing: var(--bx-tracking-caps);
  text-transform: uppercase;
  /* was hardcoded #6C86A4, which measured 4.38:1 light / 4.08:1 dark - under AA */
  color: var(--bx-text-onDark-dim);
  white-space: nowrap;
}
.bx-navgroup__list { display: grid; gap: 2px; }

.bx-navitem {
  position: relative;
  display: flex; align-items: center; gap: var(--bx-sp-3);
  padding: var(--bx-sp-3) var(--bx-sp-3);
  border-radius: var(--bx-r-md);
  color: var(--bx-text-onDark-dim);
  font-size: var(--bx-fs-sm);
  font-weight: var(--bx-fw-medium);
  text-decoration: none;
  min-width: 0;
  transition: background-color var(--bx-dur-fast) var(--bx-ease-out), color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-navitem:hover { background: rgba(255, 255, 255, .07); color: #fff; text-decoration: none; }
.bx-navitem:focus-visible { outline: 2px solid var(--bx-blue-300); outline-offset: -2px; }
.bx-navitem svg, .bx-navitem .bx-navitem__icon { width: 18px; height: 18px; flex: 0 0 18px; color: #8BA4C0; transition: color var(--bx-dur-fast) var(--bx-ease-out); }
.bx-navitem:hover svg, .bx-navitem:hover .bx-navitem__icon { color: #fff; }
.bx-navitem__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; }
.bx-navitem__meta { margin-inline-start: auto; flex: 0 0 auto; display: flex; align-items: center; gap: var(--bx-sp-2); }

.bx-navitem.is-active {
  background: linear-gradient(90deg, rgba(47, 121, 232, .28), rgba(47, 121, 232, .08));
  color: #fff;
}
.bx-navitem.is-active svg, .bx-navitem.is-active .bx-navitem__icon { color: var(--bx-blue-300); }
.bx-navitem.is-active::before {
  content: ""; position: absolute; inset-inline-start: 0; top: 8px; bottom: 8px;
  width: 3px; border-radius: 0 3px 3px 0; background: var(--bx-blue-500);
}

.bx-navitem__count {
  display: inline-grid; place-items: center; min-width: 20px; height: 18px; padding: 0 5px;
  border-radius: var(--bx-r-full);
  background: rgba(255, 255, 255, .12); color: var(--bx-text-onDark);
  font-size: 10px; font-weight: var(--bx-fw-bold); line-height: 1;
}
.bx-navitem.is-active .bx-navitem__count { background: var(--bx-blue-600); color: #fff; }

/* custom scrollbar on the dark rail */
.bx-sidebar__body { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.18) transparent; }
.bx-sidebar__body::-webkit-scrollbar { width: 8px; }
.bx-sidebar__body::-webkit-scrollbar-track { background: transparent; }
.bx-sidebar__body::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .16); border-radius: var(--bx-r-full); border: 2px solid transparent; background-clip: content-box; }
.bx-sidebar__body::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, .28); background-clip: content-box; }

/* --- sidebar promo / support card --- */
.bx-sidecard {
  padding: var(--bx-sp-4);
  border-radius: var(--bx-r-md);
  background: rgba(255, 255, 255, .06);
  border: 1px solid rgba(255, 255, 255, .08);
  font-size: var(--bx-fs-xs);
  color: var(--bx-text-onDark-dim);
}
.bx-sidecard__title { display: block; color: #fff; font-weight: var(--bx-fw-semi); font-size: var(--bx-fs-sm); margin-bottom: 3px; }
.bx-sidecard .bx-btn { margin-top: var(--bx-sp-3); }

/* --- admin variant ---------------------------------------------------------
   Differentiated by ACCENT, not by a different layout or by a hand-picked
   colour. These rules used to hardcode the old palette (#0A1F3C for the rail,
   #0D9488 for the active gradient), which is why the admin sidebar stayed navy
   blue while every other surface had moved to the brand green. The admin rail
   takes the brand gradient and a green accent; the merchant rail keeps the teal
   accent, so the two panels are distinguishable at a glance and both on brand. */
.bx-app--admin .bx-sidebar { background: var(--bx-gradient-brand); }
.bx-app--admin .bx-sidebar__head { border-bottom-color: rgba(255, 255, 255, .12); }
.bx-app--admin .bx-navitem.is-active {
  background: linear-gradient(90deg, rgba(10, 125, 79, .34), rgba(10, 125, 79, .08));
}
.bx-app--admin .bx-navitem.is-active svg, .bx-app--admin .bx-navitem.is-active .bx-navitem__icon { color: var(--bx-blue-300); }
.bx-app--admin .bx-navitem.is-active::before { background: var(--bx-blue-500); }
.bx-app--admin .bx-navitem.is-active .bx-navitem__count { background: var(--bx-blue-700); }

/* ==========================================================================
   2. TOPBAR
   ========================================================================== */
.bx-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 100dvh;
}

.bx-topbar {
  position: sticky;
  top: 0;
  z-index: var(--bx-z-topbar);
  display: flex; align-items: center; gap: var(--bx-sp-3);
  min-height: var(--bx-topbar-h);
  padding: 0 var(--bx-sp-5);
  background: var(--bx-bg-elevated);
  border-bottom: 1px solid var(--bx-border);
}
.bx-topbar__left  { display: flex; align-items: center; gap: var(--bx-sp-3); min-width: 0; }
.bx-topbar__right { display: flex; align-items: center; gap: var(--bx-sp-2); margin-inline-start: auto; flex: 0 0 auto; }
.bx-topbar__title { font-size: var(--bx-fs-md); font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.bx-search {
  display: flex; align-items: center; gap: var(--bx-sp-2);
  width: min(340px, 100%);
  padding: 0 var(--bx-sp-3);
  min-height: 36px;
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-md);
  background: var(--bx-bg-sunken);
  transition: border-color var(--bx-dur-fast) var(--bx-ease-out), box-shadow var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-search:focus-within { border-color: var(--bx-primary); background: var(--bx-surface); box-shadow: var(--bx-shadow-focus); }
.bx-search svg { width: 16px; height: 16px; flex: 0 0 16px; color: var(--bx-text-subtle); }
.bx-search input { flex: 1 1 auto; min-width: 0; border: 0; background: none; outline: none; font-size: var(--bx-fs-sm); color: var(--bx-text-strong); }
.bx-search input::placeholder { color: var(--bx-text-subtle); }
.bx-search kbd {
  flex: 0 0 auto; font-family: var(--bx-font-mono); font-size: 10px;
  padding: 2px 5px; border: 1px solid var(--bx-border); border-radius: var(--bx-r-xs);
  background: var(--bx-bg-elevated); color: var(--bx-text-subtle);
}

/* notification bell with badge */
.bx-bell { position: relative; }
.bx-bell__badge {
  position: absolute; top: 4px; inset-inline-end: 4px;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: var(--bx-r-full);
  background: var(--bx-danger); color: #fff;
  font-size: 10px; font-weight: var(--bx-fw-bold); line-height: 16px; text-align: center;
  border: 2px solid var(--bx-bg-elevated);
}

/* user chip in the topbar */
.bx-userchip {
  display: inline-flex; align-items: center; gap: var(--bx-sp-2);
  padding: 4px var(--bx-sp-2) 4px 4px;
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-full);
  background: var(--bx-bg-elevated);
  cursor: pointer; min-width: 0;
  transition: border-color var(--bx-dur-fast) var(--bx-ease-out), background-color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-userchip:hover { border-color: var(--bx-border-strong); background: var(--bx-bg-sunken); }
.bx-userchip__name { font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); white-space: nowrap; }
/* --bx-text-subtle is ink-400, which measured 4.20:1 on the white topbar */
.bx-userchip__role { display: block; font-size: 10px; color: var(--bx-text-muted); line-height: 1.2; }
.bx-userchip__caret { width: 14px; height: 14px; color: var(--bx-text-subtle); flex: 0 0 14px; }

/* demo / environment ribbon.
   `min-width: 0` on the children is load-bearing: a flex item defaults to
   min-width:auto, which is its longest unbreakable word. A long Bengali
   sentence would then refuse to wrap and push the page sideways at 320px. */
.bx-envbar {
  display: flex; align-items: center; gap: var(--bx-sp-2); flex-wrap: wrap;
  padding: var(--bx-sp-2) var(--bx-sp-5);
  background: var(--bx-warning-soft);
  color: var(--bx-warning-text);
  font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-semi);
  border-bottom: 1px solid rgba(180, 83, 9, .18);
}
.bx-envbar > * { min-width: 0; }
.bx-envbar svg { width: 15px; height: 15px; flex: 0 0 15px; }

/* Text-holding children in horizontal bars need to be allowed to shrink below
   their intrinsic width, otherwise a long word sets a floor the bar cannot go
   under. This is applied to the TEXT slots deliberately: a blanket
   `> * { min-width: 0 }` would also let action clusters (button groups,
   segmented controls) be squeezed into an internal scroll on wide screens. */
.bx-topbar__left,
.bx-topbar__title,
.bx-pagination__meta { min-width: 0; }

/* ==========================================================================
   3. CONTENT REGION
   ========================================================================== */
.bx-content {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--bx-sp-6) var(--bx-sp-5) var(--bx-sp-12);
}
.bx-content--tight { padding: var(--bx-sp-5); }

.bx-content__inner {
  width: 100%;
  max-width: var(--bx-container-wide);
  margin-inline: auto;
  min-width: 0;
}
.bx-content__inner--narrow { max-width: var(--bx-container); }

.bx-stackgrid { display: grid; gap: var(--bx-sp-5); min-width: 0; }

/* ==========================================================================
   4. COLLAPSED RAIL  (desktop only)
   ========================================================================== */
@media (min-width: 1024px) {
  .bx-app.is-collapsed { grid-template-columns: var(--bx-sidebar-w-collapsed) minmax(0, 1fr); }
  .bx-app.is-collapsed .bx-sidebar { width: var(--bx-sidebar-w-collapsed); }
  .bx-app.is-collapsed .bx-sidebar__head { padding-inline: 0; justify-content: center; }
  .bx-app.is-collapsed .bx-brand__text,
  .bx-app.is-collapsed .bx-navgroup__label,
  .bx-app.is-collapsed .bx-navitem__text,
  .bx-app.is-collapsed .bx-navitem__meta,
  .bx-app.is-collapsed .bx-sidecard { display: none; }
  .bx-app.is-collapsed .bx-sidebar__toggle { position: absolute; top: 18px; inset-inline-end: 8px; }
  .bx-app.is-collapsed .bx-sidebar__head { position: relative; }
  .bx-app.is-collapsed .bx-navitem { justify-content: center; padding-inline: 0; }
  .bx-app.is-collapsed .bx-navgroup + .bx-navgroup { margin-top: var(--bx-sp-4); }

  /* tooltip on hover so a collapsed rail is still usable */
  .bx-app.is-collapsed .bx-navitem::after {
    content: attr(data-label);
    position: absolute; inset-inline-start: calc(100% + 10px); top: 50%;
    transform: translateY(-50%) scale(.96);
    padding: 5px var(--bx-sp-3);
    background: var(--bx-ink-900); color: #fff;
    font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-medium);
    border-radius: var(--bx-r-sm); white-space: nowrap;
    opacity: 0; pointer-events: none; z-index: var(--bx-z-tooltip);
    transition: opacity var(--bx-dur-fast) var(--bx-ease-out), transform var(--bx-dur-fast) var(--bx-ease-out);
  }
  .bx-app.is-collapsed .bx-navitem:hover::after { opacity: 1; transform: translateY(-50%) scale(1); }
}

/* ==========================================================================
   5. RESPONSIVE — off-canvas sidebar below 1024px
   ========================================================================== */

/* The scrim is a mobile-only device, and it lives INSIDE the .bx-app grid.
   Without a base rule it would still be a grid item at desktop widths, taking
   the second track and pushing .bx-main onto an implicit second row — the
   whole content region then collapses to ~228px. `display: none` outside the
   mobile query is what prevents that. */
.bx-navscrim { display: none; }

@media (max-width: 1023px) {
  .bx-app { grid-template-columns: minmax(0, 1fr); }

  .bx-sidebar {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    width: min(288px, 86vw);
    height: 100dvh;
    transform: translateX(-102%);
    transition: transform var(--bx-dur-base) var(--bx-ease-in-out);
    box-shadow: var(--bx-shadow-xl);
  }
  [dir="rtl"] .bx-sidebar { transform: translateX(102%); }

  .bx-app.is-nav-open .bx-sidebar { transform: none; }

  .bx-navscrim {
    display: block;
    position: fixed; inset: 0; z-index: calc(var(--bx-z-sidebar) - 1);
    background: var(--bx-overlay);
    opacity: 0; visibility: hidden;
    transition: opacity var(--bx-dur-base) var(--bx-ease-out), visibility var(--bx-dur-base);
  }
  .bx-app.is-nav-open .bx-navscrim { opacity: 1; visibility: visible; }

  .bx-content { padding: var(--bx-sp-5) var(--bx-sp-4) var(--bx-sp-12); }
  .bx-topbar { padding-inline: var(--bx-sp-4); }
  .bx-search kbd { display: none; }
}

/* hide the desktop collapse control on touch widths */
@media (max-width: 1023px) { .bx-sidebar__toggle { display: none; } }
@media (min-width: 1024px) { .bx-navtoggle { display: none; } }

/* ==========================================================================
   6. NARROW PHONE POLISH (down to 320px)
   ========================================================================== */
@media (max-width: 640px) {
  .bx-topbar__title { display: none; }
  .bx-search { width: 100%; }
  .bx-userchip__text { display: none; }
  .bx-userchip { padding: 4px; border-radius: var(--bx-r-full); }
  .bx-pagehead { gap: var(--bx-sp-3); }
  .bx-pagehead h1 { font-size: var(--bx-fs-xl); }
  .bx-pagehead__actions { width: 100%; }
  .bx-pagehead__actions .bx-btn { flex: 1 1 auto; }
  .bx-card__head, .bx-card__body, .bx-card__foot { padding-inline: var(--bx-sp-4); }
  .bx-modal__head, .bx-modal__body, .bx-modal__foot { padding-inline: var(--bx-sp-4); }
  .bx-pagination { padding-inline: var(--bx-sp-4); }
  .bx-pagination__meta { width: 100%; margin-bottom: var(--bx-sp-2); }
  .bx-quote, .bx-plan { padding: var(--bx-sp-5); }
  .bx-toast-region { inset-block-end: var(--bx-sp-3); }
}

/* ==========================================================================
   7. PRINT — panels should print as a clean document
   ========================================================================== */
@media print {
  .bx-app { display: block; }
  .bx-sidebar, .bx-topbar, .bx-navscrim, .bx-envbar { display: none !important; }
  .bx-content { padding: 0; }
  .bx-content__inner { max-width: none; }
}


/* ================= 06-app-shim.css ================= */
/* ==========================================================================
   BIJOY DESIGN SYSTEM — v1.0
   File 6 of 6 : APPLICATION SHIM
   --------------------------------------------------------------------------
   The bridge between the new design system and the parts of the application
   that are NOT being rewritten:
     * the existing page-loading overlay contract used by assets/js/general.js
     * rich text that comes out of the database (terms, privacy, blog posts)
     * the small reveal / counter behaviours that replaced AOS + PureCounter
   Nothing here invents a second design language; it only styles what already
   exists in the DOM.
   ========================================================================== */

/* ==========================================================================
   1. PAGE OVERLAY
   Contract: assets/js/process.js does
       $('#page-overlay').addClass('active')
       $('#page-overlay .page-loading-image').removeClass('d-none')
   so these exact ids/classes have to exist and be styled here.
   ========================================================================== */
#page-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--bx-z-modal);
  display: none;
  place-items: center;
  background: var(--bx-overlay);
  backdrop-filter: blur(2px);
}
/* ONLY `.active` may reveal the overlay.
   The markup carries `class="visible incoming"` permanently, and the legacy
   stylesheet deliberately ships `#page-overlay.visible { display: none }` so
   that nothing shows until JS opts in. Matching `.visible` here overrode that
   and pinned the spinner over every page. Both process.js (public site) and
   process2.js (panels) add `.active`, so this single rule is the whole
   contract. */
#page-overlay.active { display: grid; }
#page-overlay .page-loading-image {
  display: grid;
  place-items: center;
  gap: var(--bx-sp-4);
  padding: var(--bx-sp-6) var(--bx-sp-8);
  background: var(--bx-bg-elevated);
  border-radius: var(--bx-r-lg);
  box-shadow: var(--bx-shadow-xl);
  font-size: var(--bx-fs-sm);
  color: var(--bx-text-muted);
  text-align: center;
}
#page-overlay .page-loading-image::before {
  content: "";
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 3px solid var(--bx-blue-100);
  border-top-color: var(--bx-primary);
  animation: bx-spin .7s linear infinite;
}
/* the JS toggles Bootstrap's `.d-none`; keep that class meaningful */
.d-none { display: none !important; }

/* ==========================================================================
   2. DATABASE RICH TEXT
   Terms, privacy policy and blog bodies are stored as HTML in the options
   table. `.bx-prose` gives that arbitrary markup a readable measure without
   depending on any legacy stylesheet.
   ========================================================================== */
.bx-prose {
  font-size: var(--bx-fs-md);
  line-height: 1.75;
  color: var(--bx-text);
  max-width: 78ch;
  overflow-wrap: break-word;
}
.bx-prose > :first-child { margin-top: 0; }
.bx-prose > :last-child { margin-bottom: 0; }

.bx-prose h1, .bx-prose h2, .bx-prose h3, .bx-prose h4, .bx-prose h5, .bx-prose h6 {
  color: var(--bx-text-strong);
  margin: var(--bx-sp-8) 0 var(--bx-sp-3);
  line-height: 1.3;
}
.bx-prose h1 { font-size: var(--bx-fs-2xl); }
.bx-prose h2 { font-size: var(--bx-fs-xl); }
.bx-prose h3 { font-size: var(--bx-fs-lg); }
.bx-prose p, .bx-prose ul, .bx-prose ol, .bx-prose blockquote, .bx-prose table, .bx-prose pre {
  margin: 0 0 var(--bx-sp-4);
}
.bx-prose ul, .bx-prose ol { padding-inline-start: var(--bx-sp-6); }
.bx-prose ul { list-style: disc; }
.bx-prose ol { list-style: decimal; }
.bx-prose li { margin-bottom: var(--bx-sp-2); }
.bx-prose a { color: var(--bx-primary-text); text-decoration: underline; text-underline-offset: 2px; }
.bx-prose strong, .bx-prose b { color: var(--bx-text-strong); font-weight: var(--bx-fw-semi); }
.bx-prose blockquote {
  border-inline-start: 3px solid var(--bx-primary);
  padding: var(--bx-sp-2) 0 var(--bx-sp-2) var(--bx-sp-5);
  color: var(--bx-text-muted);
  font-style: italic;
}
.bx-prose hr { border: 0; border-top: 1px solid var(--bx-border); margin: var(--bx-sp-8) 0; }
.bx-prose img {
  max-width: 100%;
  height: auto;
  border-radius: var(--bx-r-md);
  margin: var(--bx-sp-4) 0;
}
.bx-prose code {
  font-family: var(--bx-font-mono);
  font-size: .92em;
  background: var(--bx-bg-sunken);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-xs);
  padding: 1px 5px;
}
.bx-prose pre {
  background: var(--bx-navy-900);
  color: #D7E5F5;
  border-radius: var(--bx-r-md);
  padding: var(--bx-sp-5);
  overflow-x: auto;
  font-size: var(--bx-fs-sm);
  line-height: 1.6;
}
.bx-prose pre code { background: none; border: 0; padding: 0; color: inherit; }
/* Tables inside DB content must scroll in their own box, never widen the page. */
.bx-prose table {
  display: block;
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: var(--bx-fs-sm);
}
.bx-prose th, .bx-prose td {
  border: 1px solid var(--bx-border);
  padding: var(--bx-sp-3);
  text-align: start;
  vertical-align: top;
}
.bx-prose th { background: var(--bx-bg-sunken); font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); }
.bx-prose iframe, .bx-prose video { max-width: 100%; }

/* ==========================================================================
   3. REVEAL ON SCROLL  (replaces the AOS vendor library)
   Progressive enhancement: without JS the elements are simply visible.
   ========================================================================== */
.bx-reveal { opacity: 1; }
html.bx-js .bx-reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--bx-dur-slow) var(--bx-ease-out), transform var(--bx-dur-slow) var(--bx-ease-out);
  transition-delay: var(--bx-reveal-delay, 0ms);
}
html.bx-js .bx-reveal.is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.bx-js .bx-reveal { opacity: 1; transform: none; transition: none; }
}

/* ==========================================================================
   4. COUNTER  (replaces the PureCounter vendor library)
   ========================================================================== */
.bx-counter { font-variant-numeric: tabular-nums; }

/* ==========================================================================
   4b. PUBLIC SITE HEADER BEHAVIOUR
   The desktop nav is a centred horizontal bar. Below 900px it becomes a
   full-width panel that drops out of the sticky header. Because
   .bx-siteheader is `position: sticky` it is also a containing block, so the
   absolutely-positioned panel resolves against the header itself.
   ========================================================================== */
.bx-siteheader { transition: box-shadow var(--bx-dur-base) var(--bx-ease-out); }
.bx-siteheader.is-scrolled { box-shadow: var(--bx-shadow-sm); }

.bx-sitenav-toggle { display: none; }

.bx-brand__mark img { width: 100%; height: 100%; object-fit: contain; border-radius: inherit; }
.bx-brand__mark { overflow: hidden; }

/* The uploaded site logo is usually a wide banner. Forcing it into a square
   mark squashes it, so the header shows it at its natural aspect ratio. */
.bx-brand__logo {
  display: block;
  height: 36px;
  width: auto;
  max-width: min(190px, 46vw);
  object-fit: contain;
}
@media (max-width: 480px) { .bx-brand__logo { height: 30px; } }

@media (max-width: 899px) {
  .bx-sitenav {
    position: absolute;
    top: 100%;
    inset-inline: 0;
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    margin: 0;
    padding: var(--bx-sp-3);
    background: var(--bx-bg-elevated);
    border-bottom: 1px solid var(--bx-border);
    box-shadow: var(--bx-shadow-lg);
    max-height: calc(100dvh - var(--bx-topbar-h));
    overflow-y: auto;
  }
  .bx-sitenav.is-open { display: flex; }
  .bx-sitenav a { padding: var(--bx-sp-3); font-size: var(--bx-fs-md); }
  .bx-sitenav-toggle { display: inline-grid; }
}
@media (min-width: 900px) {
  .bx-sitenav { display: flex; }
}

/* back-to-top */
.bx-backtotop {
  position: fixed;
  inset-block-end: var(--bx-sp-6);
  inset-inline-end: var(--bx-sp-6);
  z-index: var(--bx-z-sticky);
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-full);
  background: var(--bx-bg-elevated);
  color: var(--bx-text-strong);
  box-shadow: var(--bx-shadow-lg);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity var(--bx-dur-base) var(--bx-ease-out),
              transform var(--bx-dur-base) var(--bx-ease-out),
              visibility var(--bx-dur-base);
}
.bx-backtotop.is-visible { opacity: 1; visibility: visible; transform: none; }
.bx-backtotop:hover { background: var(--bx-primary); border-color: var(--bx-primary); color: #fff; }
.bx-backtotop svg { width: 18px; height: 18px; }
@media (max-width: 640px) {
  .bx-backtotop { inset-block-end: var(--bx-sp-4); inset-inline-end: var(--bx-sp-4); }
}

/* ==========================================================================
   4c. PUBLIC MARKETING EXTRAS
   Only what the public pages need on top of the shared component library.
   ========================================================================== */
.bx-hero__visual { position: relative; min-width: 0; }

/* Confirmation badge that appears to float over the bottom-right of the mock.
   It is IN FLOW with a negative top margin rather than absolutely positioned:
   an absolutely-positioned badge sitting outside the column gets clipped by
   .bx-hero's `overflow: hidden` on mid-width screens, whereas an in-flow one
   can never clip or push the page sideways. The -16px lift lands inside the
   card's own 24px padding, so no content is covered. */
.bx-hero__float {
  display: flex;
  align-items: center;
  gap: var(--bx-sp-3);
  width: fit-content;
  margin-inline-start: auto;
  margin-inline-end: var(--bx-sp-5);
  margin-top: -14px;   /* stays inside the card's 24px bottom padding */
  position: relative;
  z-index: 2;
  padding: var(--bx-sp-3) var(--bx-sp-4);
  background: var(--bx-bg-elevated);
  border-radius: var(--bx-r-md);
  box-shadow: var(--bx-shadow-lg);
}
.bx-hero__float .t1 { display: block; font-size: var(--bx-fs-2xs); color: var(--bx-text-muted); font-weight: var(--bx-fw-semi); }
.bx-hero__float .t2 { display: block; font-size: var(--bx-fs-sm); color: var(--bx-text-strong); font-weight: var(--bx-fw-bold); }
@media (max-width: 560px) {
  .bx-hero__float { margin-inline-end: var(--bx-sp-3); margin-top: var(--bx-sp-4); }
}

/* real gateway / platform logos inside the pill strip and logo tiles */
.bx-chan img { height: 20px; width: auto; max-width: 88px; object-fit: contain; }
.bx-logobox img { max-height: 30px; max-width: 100%; object-fit: contain; }
.bx-logobox--tall { min-height: 92px; }

/* horizontal scroller for long logo strips — scrolls in place, never widens
   the page, and shows snap points on touch devices */
.bx-scroller {
  display: flex;
  gap: var(--bx-sp-3);
  overflow-x: auto;
  padding-bottom: var(--bx-sp-2);
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.bx-scroller > * { flex: 0 0 auto; scroll-snap-align: start; }
.bx-scroller::-webkit-scrollbar { height: 6px; }
.bx-scroller::-webkit-scrollbar-thumb { background: var(--bx-border-strong); border-radius: var(--bx-r-full); }
.bx-scroller::-webkit-scrollbar-track { background: transparent; }
@media (min-width: 900px) {
  /* enough room on desktop: wrap instead of scrolling */
  .bx-scroller { flex-wrap: wrap; overflow: visible; }
}

/* closing call-to-action band */
.bx-ctaband {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, .7fr);
  gap: var(--bx-sp-8);
  align-items: center;
  padding: var(--bx-sp-12);
  border-radius: var(--bx-r-xl);
  background: var(--bx-gradient-brand);
  color: var(--bx-text-onDark);
}
.bx-ctaband h2 { color: #fff; }
.bx-ctaband p { margin: 0; max-width: 54ch; color: #C2D3E6; }
.bx-ctaband__actions { display: flex; gap: var(--bx-sp-3); flex-wrap: wrap; justify-content: flex-end; }
@media (max-width: 860px) {
  .bx-ctaband { grid-template-columns: minmax(0, 1fr); padding: var(--bx-sp-8) var(--bx-sp-6); }
  .bx-ctaband__actions { justify-content: flex-start; }
}

/* ==========================================================================
   4d. AUTH SHELL
   Used by sign-in, sign-up, password reset and activation. Deliberately
   framework-free: the only script contract these pages rely on is jQuery +
   $.toast + process.js + general.js for the .actionForm AJAX submit.
   ========================================================================== */
.bx-auth-page { padding: var(--bx-sp-10) 0 var(--bx-sp-14); }
.bx-auth {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: stretch;
  max-width: 1000px;
  margin-inline: auto;
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-xl);
  overflow: hidden;
  background: var(--bx-bg-elevated);
  box-shadow: var(--bx-shadow-lg);
}
.bx-auth__aside {
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: var(--bx-gradient-brand);
  color: var(--bx-text-onDark);
  padding: var(--bx-sp-10) var(--bx-sp-8);
  min-width: 0;
}
.bx-auth__aside h2 { color: #fff; font-size: var(--bx-fs-2xl); margin-bottom: var(--bx-sp-3); }
.bx-auth__aside p { color: #C2D3E6; margin: 0; }
.bx-auth__aside ul { display: grid; gap: var(--bx-sp-3); margin: var(--bx-sp-6) 0 0; padding: 0; list-style: none; }
.bx-auth__aside li { display: flex; gap: var(--bx-sp-3); font-size: var(--bx-fs-sm); align-items: flex-start; }
.bx-auth__aside li svg { width: 18px; height: 18px; flex: 0 0 18px; color: var(--bx-teal-300); margin-top: 2px; }
.bx-auth__main { padding: var(--bx-sp-10) var(--bx-sp-8); min-width: 0; }
.bx-auth__head { margin-bottom: var(--bx-sp-6); }
.bx-auth__head h1 { font-size: var(--bx-fs-2xl); margin-bottom: var(--bx-sp-2); }
.bx-auth__head p { margin: 0; color: var(--bx-text-muted); font-size: var(--bx-fs-sm); }
.bx-auth__foot { margin-top: var(--bx-sp-6); font-size: var(--bx-fs-sm); color: var(--bx-text-muted); }
@media (max-width: 820px) {
  .bx-auth { grid-template-columns: minmax(0, 1fr); border-radius: var(--bx-r-lg); }
  .bx-auth__aside { order: 2; padding: var(--bx-sp-8) var(--bx-sp-6); }
  .bx-auth__main { padding: var(--bx-sp-8) var(--bx-sp-6); }
  .bx-auth__aside h2 { font-size: var(--bx-fs-xl); }
}

/* password strength meter — replaces the Blithe .pwindicator widget.
   Same ids/classes so the markup contract is unchanged. */
.pwindicator { margin-top: var(--bx-sp-2); }
.pwindicator .bar {
  height: 5px;
  border-radius: var(--bx-r-full);
  background: var(--bx-bg-sunken);
  overflow: hidden;
  transition: background-color var(--bx-dur-base) var(--bx-ease-out);
}
.pwindicator .bar::after { content: ""; display: block; height: 100%; width: 0; transition: width var(--bx-dur-base) var(--bx-ease-out); }
.pwindicator.is-weak   .bar::after { width: 33%; background: var(--bx-danger); }
.pwindicator.is-medium .bar::after { width: 66%; background: var(--bx-warning); }
.pwindicator.is-strong .bar::after { width: 100%; background: var(--bx-success); }
.pwindicator .label { display: block; margin-top: 5px; font-size: var(--bx-fs-xs); color: var(--bx-text-muted); }
.pwindicator.is-weak   .label { color: var(--bx-danger-text); }
.pwindicator.is-medium .label { color: var(--bx-warning-text); }
.pwindicator.is-strong .label { color: var(--bx-success-text); }

/* section heading block used by the marketing pages */
.bx-head { text-align: center; max-width: 62ch; margin: 0 auto var(--bx-sp-10); }
.bx-head h2 { margin-bottom: var(--bx-sp-3); }
.bx-head p { margin: 0; color: var(--bx-text-muted); font-size: var(--bx-fs-lg); }

/* ==========================================================================
   4e. DOCUMENTATION PAGES
   ========================================================================== */
.bx-docs { display: grid; grid-template-columns: 272px minmax(0, 1fr); gap: var(--bx-sp-8); align-items: start; min-width: 0; }

/* Below 1024px there is no room for a side rail: the table of contents stacks
   above the article. Without this the 272px rail plus its content sets a floor
   of ~578px and the page scrolls sideways on every phone. */
@media (max-width: 1023px) {
  .bx-docs { grid-template-columns: minmax(0, 1fr); gap: var(--bx-sp-6); }
  .bx-docsnav {
    position: static;
    max-height: none;
    padding-bottom: var(--bx-sp-4);
    border-bottom: 1px solid var(--bx-border);
  }
}

.bx-docsnav { position: sticky; top: calc(var(--bx-topbar-h) + var(--bx-sp-5)); max-height: calc(100dvh - var(--bx-topbar-h) - var(--bx-sp-10)); overflow-y: auto; }
.bx-docsnav__group + .bx-docsnav__group { margin-top: var(--bx-sp-5); }
.bx-docsnav__label {
  display: block; padding: 0 var(--bx-sp-3) var(--bx-sp-2);
  font-size: var(--bx-fs-2xs); font-weight: var(--bx-fw-bold);
  letter-spacing: var(--bx-tracking-caps); text-transform: uppercase; color: var(--bx-text-subtle);
}
.bx-docsnav__list { display: grid; gap: 1px; border-inline-start: 1px solid var(--bx-border); }
.bx-docsnav a {
  display: block; padding: 7px var(--bx-sp-4);
  font-size: var(--bx-fs-sm); color: var(--bx-text-muted); text-decoration: none;
  border-inline-start: 2px solid transparent; margin-inline-start: -1px;
  transition: color var(--bx-dur-fast) var(--bx-ease-out), border-color var(--bx-dur-fast) var(--bx-ease-out);
}
.bx-docsnav a:hover { color: var(--bx-text-strong); text-decoration: none; }
.bx-docsnav a.is-active { color: var(--bx-primary-text); border-inline-start-color: var(--bx-primary); font-weight: var(--bx-fw-semi); }

.bx-docs__body { min-width: 0; }
.bx-docs__body > section + section { margin-top: var(--bx-sp-12); }
/* anchor targets must clear the sticky header */
.bx-docs__body [id] { scroll-margin-top: calc(var(--bx-topbar-h) + var(--bx-sp-5)); }

.bx-docs__title { font-size: var(--bx-fs-3xl); margin-bottom: var(--bx-sp-3); }
.bx-docs__section-title { font-size: var(--bx-fs-xl); margin: var(--bx-sp-8) 0 var(--bx-sp-4); padding-bottom: var(--bx-sp-2); border-bottom: 1px solid var(--bx-border); }
.bx-docs__meta { font-size: var(--bx-fs-xs); color: var(--bx-text-subtle); font-weight: var(--bx-fw-medium); }

/* endpoint callout */
.bx-endpoint {
  display: flex; align-items: center; gap: var(--bx-sp-3); flex-wrap: wrap;
  padding: var(--bx-sp-3) var(--bx-sp-4);
  border: 1px solid var(--bx-border); border-radius: var(--bx-r-md);
  background: var(--bx-bg-sunken); min-width: 0;
}
.bx-endpoint code { font-family: var(--bx-font-mono); font-size: var(--bx-fs-sm); color: var(--bx-text-strong); overflow-wrap: anywhere; min-width: 0; }
.bx-endpoint .bx-method { flex: 0 0 auto; }

/* code block with its own copy control */
.bx-code { position: relative; }
.bx-code pre {
  background: var(--bx-navy-900); color: #D7E5F5;
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 0 0 var(--bx-r-md) var(--bx-r-md);
  padding: var(--bx-sp-5); margin: 0;
  overflow-x: auto; font-size: var(--bx-fs-sm); line-height: 1.65;
  font-family: var(--bx-font-mono);
  tab-size: 2;
}
.bx-code pre code { background: none; border: 0; padding: 0; color: inherit; font-family: inherit; }
.bx-code__copy { position: absolute; top: var(--bx-sp-3); inset-inline-end: var(--bx-sp-3); z-index: 2; }
.bx-code .bx-tabs__list {
  border: 1px solid rgba(255,255,255,.08);
  border-bottom: 0;
  border-radius: var(--bx-r-md) var(--bx-r-md) 0 0;
  background: rgba(255,255,255,.04);
  padding-inline: var(--bx-sp-2);
}
.bx-code .bx-tab { color: #9FB6CE; border-bottom-color: transparent; }
.bx-code .bx-tab:hover { color: #fff; background: rgba(255,255,255,.06); }
.bx-code .bx-tab[aria-selected="true"] { color: #fff; border-bottom-color: var(--bx-teal-300); }

/* token colours for the lightweight highlighter */
.bx-tok-str  { color: #7FE3D6; }
.bx-tok-com  { color: #7E96B2; font-style: italic; }
.bx-tok-key  { color: #90B8F0; }
.bx-tok-num  { color: #F2C078; }
.bx-tok-punc { color: #A9C2DC; }

/* ==========================================================================
   4f. TOKENISED BRIDGE FOR THE API REFERENCE PARTIALS
   The code-sample partials (integration.php / integration2.php) are compiled
   from ~650 lines of hand-maintained samples. Re-typing them would risk losing
   an API field, so their outer markup keeps its original class names and this
   section styles those names with design-system tokens. No framework
   stylesheet is loaded, and every value below comes from a token, so the block
   still follows dark mode. Replace with native bx classes when the samples are
   next revised.
   ========================================================================== */
.nav-tabs { display: flex; flex-wrap: wrap; gap: 2px; border-bottom: 1px solid var(--bx-border); }
.nav-tabs .nav-item { list-style: none; }
.nav-tabs .nav-link {
  border: 0; background: none; cursor: pointer;
  padding: var(--bx-sp-3) var(--bx-sp-4);
  font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-semi);
  color: var(--bx-text-muted); border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.nav-tabs .nav-link:hover { color: var(--bx-text-strong); background: var(--bx-bg-sunken); }
.nav-tabs .nav-link.active { color: var(--bx-primary-text); border-bottom-color: var(--bx-primary); }
.tab-content > .tab-pane { display: none; }
.tab-content > .tab-pane.active { display: block; }
.tab-content > .tab-pane.show { opacity: 1; }

.table { width: 100%; border-collapse: collapse; font-size: var(--bx-fs-sm); }
.table th, .table td { border: 1px solid var(--bx-border); padding: var(--bx-sp-3); text-align: start; vertical-align: top; }
.table thead th { background: var(--bx-bg-sunken); font-weight: var(--bx-fw-semi); color: var(--bx-text-strong); }
.table-striped tbody tr:nth-of-type(odd) { background: var(--bx-bg-sunken); }
.table-responsive { max-width: 100%; overflow-x: auto; }

/* table wrappers inside the partials must scroll, never widen the page */
.bx-docs__body table { max-width: 100%; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--bx-sp-2);
  min-height: 38px; padding: var(--bx-sp-3) var(--bx-sp-5);
  border: 1px solid var(--bx-primary); border-radius: var(--bx-r-md);
  background: var(--bx-primary); color: #fff;
  font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-semi);
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.btn:hover { background: var(--bx-primary-hover); border-color: var(--bx-primary-hover); color: #fff; text-decoration: none; }
.btn-sm { min-height: 32px; padding: var(--bx-sp-2) var(--bx-sp-3); font-size: var(--bx-fs-xs); }
.btn-secondary { background: var(--bx-bg-elevated); border-color: var(--bx-border-strong); color: var(--bx-text-strong); }
.btn-secondary:hover { background: var(--bx-bg-sunken); border-color: var(--bx-ink-300); color: var(--bx-text-strong); }
.btn-light { background: var(--bx-bg-elevated); border-color: var(--bx-border); color: var(--bx-text-strong); }
.btn-primary { background: var(--bx-primary); border-color: var(--bx-primary); color: #fff; }

/* Code blocks inside the API reference partials. The partials do not use the
   .bx-code wrapper, so their bare <pre> is styled here — crucially with
   `overflow-x: auto` and `max-width: 100%`, otherwise a wide sample sets the
   page width and the whole document scrolls sideways. */
.code-container, .tab-pane { position: relative; min-width: 0; }
.code-container pre, .tab-pane pre {
  background: var(--bx-navy-900);
  color: #D7E5F5;
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: var(--bx-r-md);
  padding: var(--bx-sp-5);
  margin: 0;
  max-width: 100%;
  overflow-x: auto;
  font-family: var(--bx-font-mono);
  font-size: var(--bx-fs-sm);
  line-height: 1.65;
  tab-size: 2;
}
.code-container pre code, .tab-pane pre code {
  background: none; border: 0; padding: 0; color: inherit;
  font-family: inherit; font-size: inherit; white-space: pre;
}
/* the .table/.table-responsive block scrolls inside itself, never the page */
.table-responsive { overflow-x: auto; max-width: 100%; }

/* the docs partials place a copy control over each code block */
.copy-button { position: absolute; top: var(--bx-sp-3); inset-inline-end: var(--bx-sp-3); z-index: 2; }
.code-container { position: relative; }
.code-container:not(:hover) .copy-button { opacity: .55; }
.code-container:hover .copy-button { opacity: 1; }

.text-info    { color: var(--bx-info-text); }
.text-warning { color: var(--bx-warning-text); }
.text-danger  { color: var(--bx-danger-text); }
.text-center  { text-align: center; }
.list-unstyled { list-style: none; padding-inline-start: 0; }
.pl-0 { padding-inline-start: 0 !important; }
.my-3 { margin-block: var(--bx-sp-4); }

/* Font Awesome ships INSIDE Blithe's stylesheet, and blithe/css/app.min.css is
   where the .fas / .far / .fab @font-face and every glyph rule come from. The
   two panel shells still load Blithe; the public site and the auth shell do
   not, so a legacy glyph there would paint an empty box.

   The rule below is therefore a scope, not a blanket ban. Written unscoped it
   deleted every Font Awesome icon in both panels — 25 glyph elements across the
   inner views plus the page-header, filter and bulk-action helpers — which no
   panel screenshot makes obvious. verify-icons.mjs asserts both halves. */
.fas, .far, .fab, .fa, .fa-fw, .svg-inline--fa.fa-fw { display: none !important; }

/* Surfaces where Blithe supplies the font, so the glyphs must stay visible:
     .bx-app      both panel shells (.bx-app / .bx-app--admin)
     #modal-ajax  the shared AJAX modal host, which sits outside .bx-app
     .modal       modals it opens                                          */
.bx-app .fas, .bx-app .far, .bx-app .fab, .bx-app .fa, .bx-app .fa-fw,
#modal-ajax .fas, #modal-ajax .far, #modal-ajax .fab, #modal-ajax .fa, #modal-ajax .fa-fw,
.modal .fas, .modal .far, .modal .fab, .modal .fa, .modal .fa-fw {
  display: inline-block !important;
}
/* Blithe's own icon font (fe fe-*) is never hidden, but it is also absent from
   the public build, so the panels are the only place it may be relied on. */
/*
 * NOTE ON SCOPE
 * The rules above exist ONLY for the API reference partials. Everything else
 * on the public site uses the bx- component classes directly.
 */

/* ==========================================================================
   4g. PANEL DROPDOWN MENUS
   .bx-menu already styles the surface; this positions it under its trigger.
   ========================================================================== */
.bx-menu-wrap { position: relative; }
.bx-menu--dropdown {
  position: absolute;
  top: calc(100% + 8px);
  inset-inline-end: 0;
  z-index: var(--bx-z-topbar, 40);
  min-width: 240px;
}
.bx-menu--end { inset-inline-end: 0; inset-inline-start: auto; }
.bx-menu[hidden] { display: none !important; }

/* topbar notification list */
.bx-notif { display: grid; gap: 0; max-height: 320px; overflow-y: auto; }
.bx-notif__item {
  display: flex; gap: var(--bx-sp-3); align-items: flex-start;
  padding: var(--bx-sp-3) var(--bx-sp-4);
  border-bottom: 1px solid var(--bx-border);
  text-decoration: none; color: inherit;
}
.bx-notif__item:last-child { border-bottom: 0; }
.bx-notif__item:hover { background: var(--bx-bg-sunken); text-decoration: none; }
.bx-notif__body { min-width: 0; font-size: var(--bx-fs-sm); }

/* ==========================================================================
   4h. LIST-PAGE PIECES GENERATED BY THE SHARED HELPERS
   show_item_status(), render_table_thead() and show_pagination() in
   app/Helpers/*.php emit Blithe/Bootstrap class names that are produced on
   every row of every list page in BOTH panels. Re-styling those names with
   design tokens — rather than rewriting the helpers — changes all of them at
   once and cannot break a JavaScript contract:
     .custom-switch-input  is the class the toggle AJAX handler binds to
     .badge / .badge-*     are built from app_config('template')
   Every value below comes from a token, so these follow dark mode too.
   ========================================================================== */

/* --- status toggle ------------------------------------------------------- */
.custom-switch {
  display: inline-flex; align-items: center; gap: var(--bx-sp-2);
  margin: 0; cursor: pointer; vertical-align: middle;
}
/* the real checkbox stays in the DOM and focusable; only its box is hidden */
.custom-switch-input {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.custom-switch-indicator {
  position: relative; flex: 0 0 40px; width: 40px; height: 22px;
  border-radius: var(--bx-r-full);
  background: var(--bx-ink-200);
  transition: background-color var(--bx-dur-fast) var(--bx-ease-out);
}
.custom-switch-indicator::after {
  content: ""; position: absolute; top: 2px; inset-inline-start: 2px;
  width: 18px; height: 18px; border-radius: 50%;
  background: #fff; box-shadow: var(--bx-shadow-xs);
  transition: transform var(--bx-dur-base) var(--bx-ease-spring);
}
.custom-switch-input:checked + .custom-switch-indicator { background: var(--bx-success); }
.custom-switch-input:checked + .custom-switch-indicator::after { transform: translateX(18px); }
[dir="rtl"] .custom-switch-input:checked + .custom-switch-indicator::after { transform: translateX(-18px); }
.custom-switch-input:focus-visible + .custom-switch-indicator {
  outline: 2px solid var(--bx-focus); outline-offset: 2px;
}
.custom-switch-input:disabled + .custom-switch-indicator { opacity: .5; cursor: not-allowed; }

/* --- status / type badges ---------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px var(--bx-sp-2);
  border-radius: var(--bx-r-xs);
  background: var(--bx-neutral-soft); color: var(--bx-neutral-text);
  font-size: var(--bx-fs-2xs); font-weight: var(--bx-fw-bold);
  line-height: 1.5; letter-spacing: var(--bx-tracking-wide);
  text-transform: uppercase; white-space: nowrap; vertical-align: middle;
}
.badge-success   { background: var(--bx-success-soft); color: var(--bx-success-text); }
.badge-warning   { background: var(--bx-warning-soft); color: var(--bx-warning-text); }
.badge-danger    { background: var(--bx-danger-soft);  color: var(--bx-danger-text); }
.badge-info      { background: var(--bx-info-soft);    color: var(--bx-info-text); }
.badge-primary   { background: var(--bx-primary-soft); color: var(--bx-primary-text); }
.badge-secondary,
.badge-dark,
.badge-light     { background: var(--bx-bg-sunken); color: var(--bx-text-muted); }
.badge-pill, .badge-rounded-pill { border-radius: var(--bx-r-full); padding-inline: var(--bx-sp-3); }

/* --- pager (CodeIgniter's $pagination->links()) ------------------------- */
.pagination {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  list-style: none; padding: 0; margin: var(--bx-sp-5) 0 0;
}
.page-item { list-style: none; }
.page-link, .page-item > a, .page-item > span {
  display: inline-grid; place-items: center;
  min-width: 34px; height: 34px; padding: 0 var(--bx-sp-2);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-sm);
  background: var(--bx-bg-elevated);
  color: var(--bx-text); font-size: var(--bx-fs-xs); font-weight: var(--bx-fw-semi);
  text-decoration: none;
}
.page-link:hover, .page-item > a:hover { background: var(--bx-bg-sunken); text-decoration: none; }
.page-item.active .page-link,
.page-item.active > a,
.page-item.active > span {
  background: var(--bx-primary); border-color: var(--bx-primary); color: #fff;
}
.page-item.disabled .page-link,
.page-item.disabled > a,
.page-item.disabled > span { opacity: .45; pointer-events: none; }
/* the helper wraps the pager in a floated grid column; neutralise that */
.float-end, .float-right { float: none !important; }

/* ==========================================================================
   5. LEGACY UTILITY BRIDGE
   A few legacy layouts sprinkle one-off Bootstrap utilities through markup
   that is generated from the database. Mapping the handful that actually
   appear keeps old CMS content from collapsing without shipping Bootstrap.
   ========================================================================== */
.text-center { text-align: center; }
.text-end, .text-right { text-align: end; }
.text-muted { color: var(--bx-text-muted); }
.mt-3 { margin-top: var(--bx-sp-4); }
.mb-3 { margin-bottom: var(--bx-sp-4); }
.mb-4 { margin-bottom: var(--bx-sp-5); }
.w-100 { width: 100%; }
.img-fluid { max-width: 100%; height: auto; }

/* ==========================================================================
   6. PANEL PRIMITIVE BRIDGE

   THE PROBLEM
   Both panel shells are on the bx- design system; the module views are not.
   59 admin files and 66 merchant files still carry the previous theme's markup
   and are converted gradually, so until then the panels would read as two
   different products stitched together.

   THE APPROACH
   Blithe is Bootstrap 5, so its components are driven by the --bs-* custom
   properties declared on :root. Re-declaring those on the panel scope re-skins
   every component that consumes them without a specificity fight, and because
   each value points at a bx token the panels follow dark mode for free. The
   few components Blithe re-skins with literal colours are then overridden
   directly, again from tokens.

   DELIBERATELY NOT TOUCHED
     - `display` on .modal / .fade / .show — Bootstrap owns modal visibility,
       and a stray rule here is exactly how #page-overlay got pinned open once.
     - the class names the JavaScript binds to (.custom-switch-input,
       .actionForm, .ajaxModal, .ajaxToggleItemStatus): only surfaces change.
     - DataTables' .display / .dataTables_wrapper scaffolding, which keeps its
       own layout in blithe/css/components.css.
   ========================================================================== */

/* --- 6a. Bootstrap variable remap --------------------------------------- */
.bx-app,
#modal-ajax,
.modal {
  --bs-body-bg: var(--bx-bg-elevated);
  --bs-body-color: var(--bx-text);
  --bs-emphasis-color: var(--bx-text-strong);
  --bs-secondary-color: var(--bx-text-muted);
  --bs-secondary-bg: var(--bx-bg-sunken);
  --bs-tertiary-bg: var(--bx-bg-sunken);
  --bs-border-color: var(--bx-border);
  --bs-border-color-translucent: var(--bx-border);
  --bs-border-radius: var(--bx-r-md);
  --bs-border-radius-sm: var(--bx-r-sm);
  --bs-border-radius-lg: var(--bx-r-lg);
  --bs-border-radius-xl: var(--bx-r-xl);
  --bs-link-color: var(--bx-primary-text);
  --bs-link-hover-color: var(--bx-primary-hover);
  --bs-focus-ring-color: var(--bx-focus);
  /* mirrors --bx-primary, which is what Bootstrap composes rgba() links from */
  --bs-link-color-rgb: 2, 132, 199;

  --bs-table-bg: transparent;
  --bs-table-color: var(--bx-text);
  --bs-table-border-color: var(--bx-border);
  --bs-table-accent-bg: transparent;
  --bs-table-striped-bg: var(--bx-bg-sunken);
  --bs-table-striped-color: var(--bx-text);
  --bs-table-hover-bg: var(--bx-bg-sunken);
  --bs-table-hover-color: var(--bx-text-strong);

  --bs-modal-bg: var(--bx-bg-elevated);
  --bs-modal-color: var(--bx-text);
  --bs-modal-border-color: var(--bx-border);
  --bs-modal-border-radius: var(--bx-r-lg);
  --bs-modal-header-border-color: var(--bx-border);
  --bs-modal-footer-border-color: var(--bx-border);
  --bs-backdrop-bg: var(--bx-navy-950);
  --bs-backdrop-opacity: .55;

  --bs-dropdown-bg: var(--bx-bg-elevated);
  --bs-dropdown-border-color: var(--bx-border);
  --bs-dropdown-border-radius: var(--bx-r-md);
  --bs-dropdown-link-color: var(--bx-text);
  --bs-dropdown-link-hover-bg: var(--bx-bg-sunken);
  --bs-dropdown-link-hover-color: var(--bx-text-strong);
  --bs-dropdown-link-active-bg: var(--bx-primary);
  --bs-dropdown-link-active-color: #fff;
}

/* Blithe's .content wrapper is a leftover from the previous theme and is no
   longer defined anywhere; the card shell already provides the surface. */
.bx-content__inner > .content { padding: 0; background: none; }
.bx-content__inner > .content > .card.content { padding: 0; }

/* --- 6b. cards ---------------------------------------------------------- */
.bx-app .card,
#modal-ajax .card,
.modal .card {
  margin-bottom: var(--bx-sp-5);
  background: var(--bx-bg-elevated);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-lg);
  box-shadow: var(--bx-shadow-xs);
  color: var(--bx-text);
}
.bx-app .card:last-child { margin-bottom: 0; }

.bx-app .card-header {
  display: flex;              /* Blithe already made it flex; keep that */
  align-items: center;
  justify-content: space-between;
  gap: var(--bx-sp-3);
  width: auto;
  min-height: 0;
  padding: var(--bx-sp-4) var(--bx-sp-5);
  background: transparent;
  border-bottom: 1px solid var(--bx-border);
  line-height: 1.4;
}
.bx-app .card-header:last-child { border-bottom: 0; }
.bx-app .card-title {
  margin: 0;
  font-size: var(--bx-fs-md);
  font-weight: var(--bx-fw-semi);
  line-height: 1.35;
  color: var(--bx-text-strong);
}
.bx-app .card-title small,
.bx-app .card-subtitle {
  display: block;
  margin-top: 2px;
  font-size: var(--bx-fs-xs);
  font-weight: var(--bx-fw-regular);
  color: var(--bx-text-muted);
}
/* not defined by any shipped stylesheet, but the shared page-header helper
   emits it, so it needs a real definition to align its contents */
.bx-app .card-options {
  display: flex; align-items: center; gap: var(--bx-sp-2);
  margin-inline-start: auto; flex: 0 0 auto;
}
.bx-app .card-options a { color: var(--bx-text-muted); }
.bx-app .card-options a:hover { color: var(--bx-primary-text); }

.bx-app .card-body { padding: var(--bx-sp-5); color: var(--bx-text); }
/* Every list view nests the header INSIDE the body, so the two paddings stacked
   and the header rule drew a line above nothing. Collapse the outer padding
   instead of editing ten views. */
.bx-app .card-body > .card-header { padding-inline: 0; }
.bx-app .card-body > .card-header:first-child { padding-top: 0; }
.bx-app .card-body > .card-header:last-child { padding-bottom: 0; border-bottom: 0; }
.bx-app .card-footer {
  padding: var(--bx-sp-4) var(--bx-sp-5);
  background: transparent;
  border-top: 1px solid var(--bx-border);
}
/* a table that sits directly in a card supplies its own header row */
.bx-app .card-table .card-body { padding: 0; }
.bx-app .card-table .table { margin-bottom: 0; }

/* --- 6c. page titles ---------------------------------------------------- */
.bx-app .page-title {
  margin: 0 0 var(--bx-sp-5);
  font-size: var(--bx-fs-xl);
  font-weight: var(--bx-fw-bold);
  line-height: var(--bx-lh-tight);
  color: var(--bx-text-strong);
}
.bx-app .page-title small {
  display: block; margin-top: var(--bx-sp-1);
  font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-regular); color: var(--bx-text-muted);
}

/* --- 6d. forms ---------------------------------------------------------- */
.bx-app .form-group,
#modal-ajax .form-group,
.modal .form-group { margin-bottom: var(--bx-sp-4); }

.bx-app .form-label,
#modal-ajax .form-label,
.modal .form-label,
.bx-app .control-label {
  display: block;
  margin-bottom: var(--bx-sp-2);
  font-size: var(--bx-fs-sm);
  font-weight: var(--bx-fw-semi);
  line-height: 1.4;
  color: var(--bx-text-strong);
}
.bx-app .form-text,
.bx-app .help-block { font-size: var(--bx-fs-xs); color: var(--bx-text-muted); }

.bx-app .form-control,
#modal-ajax .form-control,
.modal .form-control,
.bx-app .form-select,
#modal-ajax .form-select,
.modal .form-select,
.bx-app .custom-select {
  display: block;
  width: 100%;
  min-height: 42px;
  padding: var(--bx-sp-2) var(--bx-sp-3);
  font-family: inherit;
  font-size: var(--bx-fs-sm);
  line-height: 1.5;
  color: var(--bx-text);
  background-color: var(--bx-bg-elevated);
  border: 1px solid var(--bx-border-strong);
  border-radius: var(--bx-r-md);
  box-shadow: none;
}
.bx-app textarea.form-control,
#modal-ajax textarea.form-control,
.modal textarea.form-control { min-height: 110px; }
.bx-app .form-control::placeholder { color: var(--bx-text-subtle); }
.bx-app .form-control:focus,
#modal-ajax .form-control:focus,
.modal .form-control:focus,
.bx-app .form-select:focus,
#modal-ajax .form-select:focus,
.modal .form-select:focus {
  border-color: var(--bx-primary);
  box-shadow: 0 0 0 3px var(--bx-primary-soft);
  outline: 0;
}
.bx-app .form-control:disabled,
.bx-app .form-control[readonly] {
  background: var(--bx-bg-sunken); color: var(--bx-text-muted); cursor: not-allowed;
}
.bx-app .form-control-sm { min-height: 34px; font-size: var(--bx-fs-xs); }
.bx-app .form-control-lg { min-height: 48px; font-size: var(--bx-fs-md); }
.bx-app .form-check-input:checked {
  background-color: var(--bx-primary); border-color: var(--bx-primary);
}
.bx-app .form-check-label { color: var(--bx-text); }

/* validation: Bootstrap keeps .invalid-feedback hidden until .is-invalid */
.bx-app .form-control.is-invalid,
.bx-app .form-select.is-invalid,
#modal-ajax .form-control.is-invalid { border-color: var(--bx-danger); }
.bx-app .form-control.is-invalid:focus,
#modal-ajax .form-control.is-invalid:focus {
  border-color: var(--bx-danger); box-shadow: 0 0 0 3px var(--bx-danger-soft);
}
.bx-app .invalid-feedback,
#modal-ajax .invalid-feedback,
.modal .invalid-feedback { margin-top: var(--bx-sp-1); font-size: var(--bx-fs-xs); color: var(--bx-danger-text); }

/* --- 6e. input groups --------------------------------------------------- */
.bx-app .input-group,
#modal-ajax .input-group,
.modal .input-group { display: flex; flex-wrap: nowrap; width: 100%; }
.bx-app .input-group > .form-control,
.bx-app .input-group > .form-select { flex: 1 1 auto; width: 1%; min-width: 0; }
.bx-app .input-group-text,
#modal-ajax .input-group-text,
.modal .input-group-text {
  display: flex; align-items: center; gap: var(--bx-sp-2);
  padding: var(--bx-sp-2) var(--bx-sp-3);
  font-size: var(--bx-fs-sm);
  color: var(--bx-text-muted);
  background: var(--bx-bg-sunken);
  border: 1px solid var(--bx-border-strong);
  border-radius: var(--bx-r-md);
  white-space: nowrap;
}
/* .input-group-append / -prepend are Bootstrap 4 spellings; the views still use
   them, so collapse the shared edge instead of leaving a doubled border */
.bx-app .input-group-append,
.bx-app .input-group-prepend { display: flex; }
.bx-app .input-group > *:not(:first-child),
.bx-app .input-group-append > * {
  border-start-start-radius: 0; border-end-start-radius: 0;
}
.bx-app .input-group > *:not(:last-child),
.bx-app .input-group-prepend > * {
  border-start-end-radius: 0; border-end-end-radius: 0;
}
.bx-app .input-group-append > .btn,
.bx-app .input-group-prepend > .btn { min-height: 42px; }

/* --- 6f. buttons -------------------------------------------------------- */
.bx-app .btn-min-width { min-width: 140px; }
.bx-app .btn-outline-primary,
#modal-ajax .btn-outline-primary,
.modal .btn-outline-primary {
  background: var(--bx-bg-elevated);
  border-color: var(--bx-border-strong);
  color: var(--bx-primary-text);
}
.bx-app .btn-outline-primary:hover,
#modal-ajax .btn-outline-primary:hover,
.modal .btn-outline-primary:hover {
  background: var(--bx-primary-soft);
  border-color: var(--bx-primary);
  color: var(--bx-primary-text);
}
.bx-app .btn-outline-secondary,
.bx-app .btn-outline-light { background: var(--bx-bg-elevated); border-color: var(--bx-border); color: var(--bx-text-strong); }
.bx-app .btn-outline-secondary:hover,
.bx-app .btn-outline-light:hover { background: var(--bx-bg-sunken); border-color: var(--bx-border-strong); color: var(--bx-text-strong); }
.bx-app .btn-success, #modal-ajax .btn-success { background: var(--bx-success); border-color: var(--bx-success); color: #fff; }
.bx-app .btn-danger,  #modal-ajax .btn-danger  { background: var(--bx-danger);  border-color: var(--bx-danger);  color: #fff; }
.bx-app .btn-warning, #modal-ajax .btn-warning { background: var(--bx-warning); border-color: var(--bx-warning); color: #fff; }
.bx-app .btn-info,    #modal-ajax .btn-info    { background: var(--bx-info);    border-color: var(--bx-info);    color: #fff; }
.bx-app .btn-dark  { background: var(--bx-navy-800); border-color: var(--bx-navy-800); color: #fff; }
.bx-app .btn-link  { background: none; border-color: transparent; color: var(--bx-primary-text); padding-inline: var(--bx-sp-2); }
.bx-app .btn-link:hover { background: var(--bx-primary-soft); color: var(--bx-primary-text); }
.bx-app .btn-lg { min-height: 46px; padding: var(--bx-sp-3) var(--bx-sp-6); font-size: var(--bx-fs-md); }

/* --- 6g. tables --------------------------------------------------------- */
.bx-app .table {
  width: 100%;
  margin-bottom: 0;
  color: var(--bx-text);
  font-size: var(--bx-fs-sm);
  vertical-align: middle;
  border-color: var(--bx-border);
}
.bx-app .table > :not(caption) > * > * {
  padding: var(--bx-sp-3) var(--bx-sp-4);
  background: transparent;
  border-bottom: 1px solid var(--bx-border);
  box-shadow: none;
}
.bx-app .table thead th {
  background: var(--bx-bg-sunken);
  font-size: var(--bx-fs-2xs);
  font-weight: var(--bx-fw-bold);
  letter-spacing: var(--bx-tracking-wide);
  text-transform: uppercase;
  color: var(--bx-text-muted);
  white-space: nowrap;
}
.bx-app .table-bordered > :not(caption) > * { border-width: 1px; }
.bx-app .table-bordered > :not(caption) > * > * { border-width: 1px; border-color: var(--bx-border); }
.bx-app .table tbody tr:last-child > * { border-bottom: 0; }
.bx-app .table-responsive { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }

/* --- 6h. modals --------------------------------------------------------- */
.modal .modal-content,
#modal-ajax .modal-content {
  background: var(--bx-bg-elevated);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-lg);
  box-shadow: var(--bx-shadow-xl);
  color: var(--bx-text);
}
.modal .modal-header,
#modal-ajax .modal-header {
  padding: var(--bx-sp-4) var(--bx-sp-5);
  border-bottom: 1px solid var(--bx-border);
}
.modal .modal-title,
#modal-ajax .modal-title {
  font-size: var(--bx-fs-md);
  font-weight: var(--bx-fw-semi);
  color: var(--bx-text-strong);
}
.modal .modal-body,
#modal-ajax .modal-body { padding: var(--bx-sp-5); }
.modal .modal-footer,
#modal-ajax .modal-footer {
  padding: var(--bx-sp-4) var(--bx-sp-5);
  gap: var(--bx-sp-2);
  border-top: 1px solid var(--bx-border);
}
/* Bootstrap 5 paints .btn-close as a dark SVG; invert it for dark mode */
[data-bx-theme="dark"] .btn-close { filter: invert(1) grayscale(1) brightness(1.9); }

/* --- 6i. tabs ----------------------------------------------------------- */
.bx-app .nav { display: flex; flex-wrap: wrap; gap: var(--bx-sp-1); padding: 0; margin: 0; list-style: none; }
.bx-app .nav-item { list-style: none; }
.bx-app .nav-link {
  display: block; padding: var(--bx-sp-2) var(--bx-sp-3);
  font-size: var(--bx-fs-sm); font-weight: var(--bx-fw-semi);
  color: var(--bx-text-muted); text-decoration: none;
  border: 0; border-radius: var(--bx-r-sm); background: none; cursor: pointer;
}
.bx-app .nav-link:hover { background: var(--bx-bg-sunken); color: var(--bx-text-strong); }
.bx-app .nav-link.active, .bx-app .nav-link.show { background: var(--bx-primary-soft); color: var(--bx-primary-text); }

/* --- 6j. alerts --------------------------------------------------------- */
.bx-app .alert {
  display: flex; align-items: flex-start; gap: var(--bx-sp-3);
  padding: var(--bx-sp-3) var(--bx-sp-4);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-md);
  background: var(--bx-bg-sunken); color: var(--bx-text);
  font-size: var(--bx-fs-sm);
}
.bx-app .alert-success { background: var(--bx-success-soft); border-color: transparent; color: var(--bx-success-text); }
.bx-app .alert-warning { background: var(--bx-warning-soft); border-color: transparent; color: var(--bx-warning-text); }
.bx-app .alert-danger  { background: var(--bx-danger-soft);  border-color: transparent; color: var(--bx-danger-text); }
.bx-app .alert-info    { background: var(--bx-info-soft);    border-color: transparent; color: var(--bx-info-text); }
.bx-app .alert-dismissible { padding-inline-end: var(--bx-sp-8); }

/* --- 6k. select2, which the panel forms rely on ------------------------- */
.select2-container--default .select2-selection--single,
.select2-container--default .select2-selection--multiple {
  min-height: 42px;
  padding: var(--bx-sp-2) var(--bx-sp-3);
  background: var(--bx-bg-elevated);
  border: 1px solid var(--bx-border-strong);
  border-radius: var(--bx-r-md);
  color: var(--bx-text);
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
  line-height: inherit; padding: 0; color: var(--bx-text);
}
.select2-container--default .select2-selection--single .select2-selection__arrow { height: 100%; }
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--single {
  border-color: var(--bx-primary); box-shadow: 0 0 0 3px var(--bx-primary-soft);
}
.select2-dropdown {
  background: var(--bx-bg-elevated);
  border: 1px solid var(--bx-border);
  border-radius: var(--bx-r-md);
  color: var(--bx-text);
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
  background: var(--bx-primary); color: #fff;
}
.select2-container--default .select2-results__option[aria-selected="true"] {
  background: var(--bx-primary-soft); color: var(--bx-primary-text);
}
.select2-search--dropdown .select2-search__field {
  background: var(--bx-bg-elevated); border: 1px solid var(--bx-border-strong);
  border-radius: var(--bx-r-sm); color: var(--bx-text); padding: var(--bx-sp-2);
}

/* --- 6l. small leftovers ------------------------------------------------ */
.bx-app .custom-switch-description {
  margin-inline-start: var(--bx-sp-3);
  font-size: var(--bx-fs-sm);
  color: var(--bx-text-muted);
}
.bx-app .cursor-pointer { cursor: pointer; }
.bx-app .modal-body .card:last-child { margin-bottom: 0; }

/* --- 6n-2. colour utilities, which Blithe ships as !important ------------
   style.css hard-codes the previous template's palette on the utility classes
   and marks them !important, so they beat every rule here regardless of order:
       .bg-primary   { background-color: #6777ef !important }
       .bg-info      { background-color: #3abaf4 !important }
       .text-muted   { color: #98a6ad !important }
   Sixty-five lines across the module views use one of these names, which is
   how the old violet kept reappearing on the admin dashboard's budget bars and
   on the "33" badge in Payment methods AFTER the components themselves were
   fixed. .text-muted mattered most: Blithe's fixed grey ignored the theme, so
   muted copy stayed a mid-grey in dark mode.
   Re-declared with !important in the sheet that loads last, so equal weight
   plus later position decides in our favour. The `-all` variants colour a whole
   card, so their inner text is set too.                                     */
/* The label colour has to come with the fill. Blithe declared `.bg-info` and
   friends as background-only, so the text inherited the body colour: the small
   teal count badge measured 1.97:1 in light and 2.91:1 in dark, failing AA in
   both. Every vivid fill therefore sets its own foreground. */
.bx-app .bg-primary,      .modal .bg-primary      { background-color: var(--bx-primary) !important; color: #fff !important; }
.bx-app .bg-secondary,    .modal .bg-secondary    { background-color: var(--bx-bg-sunken) !important; color: var(--bx-text-strong) !important; }
.bx-app .bg-success,      .modal .bg-success      { background-color: var(--bx-success) !important; color: #fff !important; }
.bx-app .bg-info,         .modal .bg-info         { background-color: var(--bx-info) !important; color: #fff !important; }
.bx-app .bg-warning,      .modal .bg-warning      { background-color: var(--bx-warning) !important; color: #fff !important; }
.bx-app .bg-danger,       .modal .bg-danger       { background-color: var(--bx-danger) !important; color: #fff !important; }
.bx-app .bg-light,        .modal .bg-light        { background-color: var(--bx-bg-sunken) !important; color: var(--bx-text) !important; }
.bx-app .bg-dark,         .modal .bg-dark         { background-color: var(--bx-navy-900) !important; color: #fff !important; }
.bx-app .bg-light-blue,   .modal .bg-light-blue   { background-color: var(--bx-info) !important; color: #fff !important; }
.bx-app .bg-light-green,  .modal .bg-light-green  { background-color: var(--bx-success) !important; color: #fff !important; }
.bx-app .bg-dark-gray,    .modal .bg-dark-gray    { background-color: var(--bx-navy-700) !important; color: #fff !important; }
.bx-app .bg-light-blue .content .text,  .bx-app .bg-light-blue .content .number,
.bx-app .bg-light-green .content .text, .bx-app .bg-light-green .content .number,
.bx-app .bg-dark-gray .content .text,   .bx-app .bg-dark-gray .content .number { color: #fff !important; }

/* The app spells its STATUSES with these classes - see
   app/Config/App_config.php:
        Success   -> bg-indigo / bg-indigo-lt
        Pending   -> bg-orange / bg-orange-lt     (also Initiated)
        Cancelled -> bg-red    / bg-red-lt
   Blithe paints them from its own palette with !important, which is how the
   "Success" badge on the transactions list stayed violet after the components
   and the .bg-primary/.bg-info utilities had been fixed. Mapped to the design
   system's status tokens so one status looks the same on every page, and the
   tinted -lt variants get the soft/tinted pair. */
.bx-app .bg-indigo,   .modal .bg-indigo   { background-color: var(--bx-success) !important; color: #fff !important; }
.bx-app .bg-orange,   .modal .bg-orange   { background-color: var(--bx-warning) !important; color: #fff !important; }
.bx-app .bg-red,      .modal .bg-red      { background-color: var(--bx-danger)  !important; color: #fff !important; }
.bx-app .bg-indigo-lt, .bx-app .bg-indigo-lightest { background-color: var(--bx-success-soft) !important; color: var(--bx-success-text) !important; }
.bx-app .bg-orange-lt, .bx-app .bg-orange-lightest { background-color: var(--bx-warning-soft) !important; color: var(--bx-warning-text) !important; }
.bx-app .bg-red-lt,    .bx-app .bg-red-lightest    { background-color: var(--bx-danger-soft)  !important; color: var(--bx-danger-text)  !important; }
/* the rest of Blithe's colour utilities, so none can resurface later */
.bx-app .bg-purple, .bx-app .bg-deep-purple, .bx-app .bg-blue, .bx-app .bg-blue-grey {
  background-color: var(--bx-primary) !important; color: #fff !important;
}
.bx-app .bg-teal, .bx-app .bg-cyan, .bx-app .bg-green, .bx-app .bg-lime {
  background-color: var(--bx-success) !important; color: #fff !important;
}
.bx-app .bg-yellow, .bx-app .bg-amber, .bx-app .bg-pink {
  background-color: var(--bx-warning) !important; color: #fff !important;
}
.bx-app .bg-grey { background-color: var(--bx-bg-sunken) !important; color: var(--bx-text) !important; }
.bx-app .bg-black, .bx-app .bg-brown { background-color: var(--bx-navy-900) !important; color: #fff !important; }
.bx-app .bg-white, .bx-app .bg-whitesmoke { background-color: var(--bx-bg-elevated) !important; color: var(--bx-text) !important; }

.bx-app .text-primary { color: var(--bx-primary-text) !important; }
/* The status text classes. Blithe ships .text-danger as the template red
   (#fc544b), which measured 3.23:1 on white on the Settings page — the one
   place oldColourCount was still non-zero after everything else was fixed. */
.bx-app .text-danger  { color: var(--bx-danger-text) !important; }
.bx-app .text-success { color: var(--bx-success-text) !important; }
.bx-app .text-warning { color: var(--bx-warning-text) !important; }
.bx-app .text-secondary, .bx-app .text-white { color: var(--bx-text-muted) !important; }
.bx-app .text-info    { color: var(--bx-info-text) !important; }
.bx-app .text-muted   { color: var(--bx-text-muted) !important; }
.bx-app .text-light   { color: var(--bx-text-onDark) !important; }
.bx-app .text-dark    { color: var(--bx-text-strong) !important; }
.bx-app .text-info-all *, .bx-app .text-info-all *::before, .bx-app .text-info-all *::after { color: var(--bx-info-text) !important; }
.bx-app .text-light-all *, .bx-app .text-light-all *::before, .bx-app .text-light-all *::after { color: var(--bx-text-onDark) !important; }
.bx-app .text-dark-all *, .bx-app .text-dark-all *::before, .bx-app .text-dark-all *::after { color: var(--bx-text-strong) !important; }

/* --- 6m. helper pieces, re-asserted above Blithe's skin -----------------
   Blithe's theme sheet styles these with COMPOUND selectors, so it beat
   section 4h on specificity even though bx.css is loaded afterwards:
       .badge.badge-success               (0,2,0)  beat  .badge-success           (0,1,0)
       .page-item.disabled .page-link     (0,3,0)  beat  .page-link               (0,1,0)
   The visible result was a solid #54ca68 plate behind green text — 1.21:1 in
   dark mode, well under WCAG AA — and a white pager button inside a dark
   panel. Re-asserting the same tokens one scope deeper outranks both, and the
   toggle needs its Blithe knob switched off or every row paints two.

   #modal-ajax carries class="modal", so the .modal scope already covers the
   AJAX modal host and needs no separate selector.                            */
.bx-app .badge.badge-success,   .modal .badge.badge-success   { background: var(--bx-success-soft); color: var(--bx-success-text); }
.bx-app .badge.badge-warning,   .modal .badge.badge-warning   { background: var(--bx-warning-soft); color: var(--bx-warning-text); }
.bx-app .badge.badge-danger,    .modal .badge.badge-danger    { background: var(--bx-danger-soft);  color: var(--bx-danger-text); }
.bx-app .badge.badge-info,      .modal .badge.badge-info      { background: var(--bx-info-soft);    color: var(--bx-info-text); }
.bx-app .badge.badge-primary,   .modal .badge.badge-primary   { background: var(--bx-primary-soft); color: var(--bx-primary-text); }
.bx-app .badge.badge-secondary, .modal .badge.badge-secondary,
.bx-app .badge.badge-dark,      .modal .badge.badge-dark,
.bx-app .badge.badge-light,     .modal .badge.badge-light     { background: var(--bx-bg-sunken);     color: var(--bx-text-muted); }

/* the toggle knob: bx.css paints it with ::after, Blithe with ::before */
.bx-app .custom-switch-indicator::before,
.modal .custom-switch-indicator::before { content: none; }

/* pager, where Blithe's skin is a compound selector */
.bx-app .page-link, .modal .page-link {
  background: var(--bx-bg-elevated);
  border-color: var(--bx-border);
  color: var(--bx-text);
}
.bx-app .page-link:hover, .modal .page-link:hover {
  background: var(--bx-bg-sunken);
  border-color: var(--bx-border-strong);
  color: var(--bx-text-strong);
}
.bx-app .page-item.active .page-link, .modal .page-item.active .page-link {
  background: var(--bx-primary);
  border-color: var(--bx-primary);
  color: #fff;
}
.bx-app .page-item.disabled .page-link, .modal .page-item.disabled .page-link {
  background: var(--bx-bg-elevated);
  border-color: var(--bx-border);
  color: var(--bx-text-subtle);
}

/* --- 6n. the theme class Blithe stamps on <body> at runtime -------------
   blithe/js/scripts.js adds `theme-white light light-sidebar` to <body> after
   load, which is why the SERVED html shows a bare <body> and the live DOM does
   not. Every colour rule that hangs off that class is a TWO-class selector, so
   it outranked the single-class rules in sections 4 and 5 despite bx.css being
   loaded last:
       .theme-white .btn-primary            (0,2,0)  beat  .btn-primary   (0,1,0)
       .theme-white .page-item.active ...   (0,4,0)  beat  .page-item ... (0,3,0)
   The measured result was the previous template's violet rgb(103,119,239) on
   every Save / Submit / Pay button and on the profile tabs.
   Restating the same declarations under .bx-app / .modal restores equal weight
   and lets document order decide - which favours bx.css. Interactive states
   need !important because Blithe ships its hovers that way.                     */

/* buttons */
.bx-app .btn-primary, .modal .btn-primary { background: var(--bx-primary); border-color: var(--bx-primary); color: #fff; }
.bx-app .btn-primary:hover, .bx-app .btn-primary:focus, .bx-app .btn-primary:active,
.modal .btn-primary:hover, .modal .btn-primary:focus, .modal .btn-primary:active {
  background: var(--bx-primary-hover) !important; border-color: var(--bx-primary-hover) !important; color: #fff;
}
.bx-app .btn-success, .modal .btn-success { background: var(--bx-success); border-color: var(--bx-success); color: #fff; }
.bx-app .btn-danger,  .modal .btn-danger  { background: var(--bx-danger);  border-color: var(--bx-danger);  color: #fff; }
.bx-app .btn-warning, .modal .btn-warning { background: var(--bx-warning); border-color: var(--bx-warning); color: #fff; }
.bx-app .btn-info,    .modal .btn-info    { background: var(--bx-info);    border-color: var(--bx-info);    color: #fff; }
.bx-app .btn-success:hover, .modal .btn-success:hover { background: var(--bx-green-700) !important; border-color: var(--bx-green-700) !important; }
.bx-app .btn-danger:hover,  .modal .btn-danger:hover  { background: var(--bx-red-700) !important;   border-color: var(--bx-red-700) !important; }

/* every outline variant, so a "clear" or "cancel" button stops rendering as a
   filled primary because section 4f gives the bare .btn a filled background */
.bx-app .btn-outline-primary, .modal .btn-outline-primary { background: var(--bx-bg-elevated); border-color: var(--bx-primary); color: var(--bx-primary-text); }
.bx-app .btn-outline-primary:hover, .modal .btn-outline-primary:hover { background: var(--bx-primary-soft) !important; border-color: var(--bx-primary) !important; color: var(--bx-primary-text) !important; }
.bx-app .btn-outline-danger, .modal .btn-outline-danger { background: var(--bx-bg-elevated); border-color: var(--bx-danger); color: var(--bx-danger-text); }
.bx-app .btn-outline-danger:hover, .modal .btn-outline-danger:hover { background: var(--bx-danger-soft) !important; border-color: var(--bx-danger) !important; color: var(--bx-danger-text) !important; }
.bx-app .btn-outline-success, .modal .btn-outline-success { background: var(--bx-bg-elevated); border-color: var(--bx-success); color: var(--bx-success-text); }
.bx-app .btn-outline-warning, .modal .btn-outline-warning { background: var(--bx-bg-elevated); border-color: var(--bx-warning); color: var(--bx-warning-text); }
.bx-app .btn-outline-info, .modal .btn-outline-info { background: var(--bx-bg-elevated); border-color: var(--bx-info); color: var(--bx-info-text); }
.bx-app .btn-outline-secondary, .bx-app .btn-outline-light, .modal .btn-outline-secondary {
  background: var(--bx-bg-elevated); border-color: var(--bx-border-strong); color: var(--bx-text-strong);
}
.bx-app .btn-outline-secondary:hover, .bx-app .btn-outline-light:hover {
  background: var(--bx-bg-sunken) !important; border-color: var(--bx-border-strong) !important; color: var(--bx-text-strong) !important;
}
.bx-app .btn-secondary, .modal .btn-secondary { background: var(--bx-bg-elevated); border-color: var(--bx-border-strong); color: var(--bx-text-strong); }
.bx-app .btn-secondary:hover, .modal .btn-secondary:hover { background: var(--bx-bg-sunken) !important; border-color: var(--bx-border-strong) !important; color: var(--bx-text-strong) !important; }
.bx-app .btn-link, .modal .btn-link { background: none; border-color: transparent; color: var(--bx-primary-text); }

/* tabs: Blithe sets these through `.theme-white .nav-tabs .nav-item .nav-link` */
.bx-app .nav-tabs .nav-item .nav-link { color: var(--bx-text-muted); background: none; border: 0; border-bottom: 2px solid transparent; border-radius: 0; }
.bx-app .nav-tabs .nav-item .nav-link:hover { color: var(--bx-text-strong); background: var(--bx-bg-sunken); }
.bx-app .nav-tabs .nav-item .nav-link.active { color: var(--bx-primary-text); background: none; border-bottom-color: var(--bx-primary); }
.bx-app .nav-pills .nav-link { color: var(--bx-text-muted); background: none; }
.bx-app .nav-pills .nav-item .nav-link { color: var(--bx-text-muted); }
.bx-app .nav-pills .nav-link.active, .bx-app .nav-pills .show > .nav-link,
.bx-app .nav-pills .nav-item .nav-link.active {
  color: var(--bx-primary-text); background: var(--bx-primary-soft); box-shadow: none;
}

/* the row status toggle. Blithe ships this as
   `.theme-white .custom-switch-input:checked ~ .custom-switch-indicator`
   which is four classes deep - one more than section 4h - so the ON track
   painted the previous template's violet even after the knob was fixed. */
.bx-app .custom-switch-input:checked ~ .custom-switch-indicator,
.bx-app .custom-switch-input:checked + .custom-switch-indicator {
  background: var(--bx-success);
}
.bx-app .custom-switch-input:focus ~ .custom-switch-indicator,
.bx-app .custom-switch-input:focus-visible + .custom-switch-indicator {
  box-shadow: 0 0 0 3px var(--bx-primary-soft);
}
/* The label beside a status toggle. Blithe ships
   `.custom-switch-input:checked ~ .custom-switch-description { color: #495057 }`
   at three classes, which outranks a two-class rule, and its only light-on-dark
   variant is gated behind Blithe's own `.dark` class that we do not use. The
   measured effect was a hard-coded dark grey in BOTH themes: 8.18:1 in light,
   2.09:1 in dark, i.e. the label was effectively invisible in dark mode. */
.bx-app .custom-switch-description,
.bx-app .custom-switch-input:checked ~ .custom-switch-description { color: var(--bx-text-muted); }

/* plain links inside legacy content. The :not() list keeps buttons, nav items
   and pagers on their own palette - a bare `.bx-content__inner a` would win
   over their single-class rules and repaint them. */
.bx-content__inner a:not([class*="btn"]):not(.nav-link):not(.page-link):not(.bx-navitem):not(.dropdown-item):not(.bx-brand) {
  color: var(--bx-primary-text);
}

/* --- 6o. form.check, which Blithe's skin leaves without a border --------- */.bx-app .form-check, .modal .form-check { display: flex; align-items: flex-start; gap: var(--bx-sp-2); padding-inline-start: 0; min-height: 0; margin-bottom: var(--bx-sp-2); }
.bx-app .form-check-input, .modal .form-check-input {
  flex: 0 0 auto;
  width: 18px; height: 18px; margin: 2px 0 0;
  background-color: var(--bx-bg-elevated);
  border: 1px solid var(--bx-border-strong);
  border-radius: var(--bx-r-xs);
  pointer-events: auto;
}
.bx-app .form-check-input:checked, .modal .form-check-input:checked { background-color: var(--bx-primary); border-color: var(--bx-primary); }
.bx-app .form-check-input:focus, .modal .form-check-input:focus { border-color: var(--bx-primary); box-shadow: 0 0 0 3px var(--bx-primary-soft); outline: 0; }
.bx-app .form-check-label, .modal .form-check-label { font-size: var(--bx-fs-sm); color: var(--bx-text); cursor: pointer; }

/* --- 6p. modal bounds ---------------------------------------------------
   A .modal-lg taller than the viewport put its footer out of reach: the
   invoice dialog measured 930px inside a 900px window with no scroller. */
/* The invoice dialog measured 868px inside a 900px window with its footer at
   bottom 945 - off-screen - and the body would not scroll (735 = 735) while
   the only overflowing box, .modal-content at 928 vs 686, was overflow:hidden.
   Every field after the fold was unreachable.

   The first attempt only flexed the CHILDREN of .modal-content, which is inert:
   this Bootstrap build does not make .modal-content a flex column, so
   flex-basis/min-height on .modal-body had nothing to resolve against. The
   container is now declared explicitly, which is what lets the body become the
   one scrolling region, and .modal scrolls too as a belt-and-braces path so
   the footer is reachable even if the flex chain is broken by something else. */
.modal { overflow-y: auto; }
.modal-dialog { max-height: calc(100vh - 2rem); margin: 1rem auto; }
.modal-content {
  display: flex; flex-direction: column;
  max-height: calc(100vh - 2rem);
  overflow: hidden;
}
.modal-header, .modal-footer { flex: 0 0 auto; }
/* The body carries its own definite bound. Flexing it was not enough: live it
   kept its full content height (735 = 735) so the footer stayed clipped at
   bottom 945 in a 900px window, whatever the flex container said. A max-height
   cannot be lost in a specificity contest the way a flex-basis can, so the body
   is guaranteed to fit between the header and the footer and to scroll the
   remainder. The 15rem reserve is the measured header + footer + dialog margin
   (~225px) plus slack for a wrapped title or footer. */
.modal-body { flex: 1 1 auto; min-height: 0; max-height: calc(100vh - 15rem); overflow-y: auto; }

/* --- 6s. Blithe's own checkbox markup -----------------------------------
   The views do not use Bootstrap's .form-check; they use Blithe's
   <div class="custom-control"><input class="custom-control-input">
   <label class="custom-control-label">. Blithe hides the real input and paints
   a fake box with the LABEL's ::before, tinted `#6777ef !important` when
   checked, so section 6o never matched and the audit still measured 13x13 with
   border-width 0. Retire the fake box and show the real control; accent-color
   then follows the brand in every browser without an image or a pseudo-element. */
.bx-app .custom-control, .modal .custom-control {
  display: flex; align-items: flex-start; gap: var(--bx-sp-2);
  padding-inline-start: 0; min-height: 0; margin-bottom: var(--bx-sp-2);
}
.bx-app .custom-control-label, .modal .custom-control-label {
  padding-inline-start: 0; font-size: var(--bx-fs-sm); color: var(--bx-text); cursor: pointer;
}
.bx-app .custom-control-label::before, .bx-app .custom-control-label::after,
.modal .custom-control-label::before, .modal .custom-control-label::after { content: none !important; }
.bx-app .custom-control-input, .modal .custom-control-input {
  position: static; opacity: 1; pointer-events: auto; z-index: auto;
  flex: 0 0 auto; width: 18px; height: 18px; margin: 2px 0 0;
  accent-color: var(--bx-primary);
}

/* --- 6q. dashboard logo in dark mode ------------------------------------
   The configured logo is a dark wordmark on a light ground and an admin can
   replace it at any time, so the asset cannot be swapped per theme. A light
   plate keeps whichever logo is set legible. */
[data-bx-theme="dark"] .bx-brand__logo { background: #fff; padding: 4px 8px; border-radius: 8px; box-sizing: content-box; }

/* --- 6r. Bootstrap display utilities ------------------------------------
   In this build of app.min.css `.d-none` is declared a SECOND time at the very
   end of the file, after the responsive block, with equal specificity and
   `!important`. Later-but-equal wins, so `d-none d-sm-block` resolves to
   display:none at every width. On /user/tickets that silently hid the entire
   "Add ticket" column on desktop, leaving a 430px hole. Re-declared here,
   inside the same breakpoints, in the sheet that loads last. */
@media (min-width: 576px) {
  .d-sm-none { display: none !important; } .d-sm-inline { display: inline !important; }
  .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; }
  .d-sm-grid { display: grid !important; } .d-sm-flex { display: flex !important; }
  .d-sm-inline-flex { display: inline-flex !important; } .d-sm-table { display: table !important; }
}
@media (min-width: 768px) {
  .d-md-none { display: none !important; } .d-md-inline { display: inline !important; }
  .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; }
  .d-md-grid { display: grid !important; } .d-md-flex { display: flex !important; }
  .d-md-inline-flex { display: inline-flex !important; } .d-md-table { display: table !important; }
}
@media (min-width: 992px) {
  .d-lg-none { display: none !important; } .d-lg-inline { display: inline !important; }
  .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; }
  .d-lg-grid { display: grid !important; } .d-lg-flex { display: flex !important; }
  .d-lg-inline-flex { display: inline-flex !important; } .d-lg-table { display: table !important; }
}
@media (min-width: 1200px) {
  .d-xl-none { display: none !important; } .d-xl-inline { display: inline !important; }
  .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; }
  .d-xl-grid { display: grid !important; } .d-xl-flex { display: flex !important; }
  .d-xl-inline-flex { display: inline-flex !important; } .d-xl-table { display: table !important; }
}
