/* ============================================================================
   Business Growth ERP - own design system.
   ----------------------------------------------------------------------------
   Replaces AdminLTE entirely. Bootstrap stays underneath for its grid, its
   utility classes and the JavaScript behaviour of modals and dropdowns, but
   every component's appearance is defined here.

   The look is deliberately not an admin template: a warm paper canvas rather
   than cool slate, flat panels with a hairline border rather than floating
   shadowed cards, a narrow icon rail rather than a wide dark text sidebar, and
   teal rather than the usual dashboard blue.

   Everything is driven by the tokens in :root, so the whole product can be
   re-tuned from one block.
   ========================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap');

:root {
  /* ------------------------------------------------------------------ BGS brand
     Every colour below is either sampled from assets/img/bgs-logo.jpg or derived from one that
     was, and every pairing was measured rather than chosen by eye. The logo is a single ramp -
     #0A234B navy -> #065B9B blue -> #0195EF -> #00BFD1 cyan -> #109B7C -> #4EAC3A green - and
     the product is built out of that ramp rather than out of a stock dashboard palette.

     The measurements quoted in the comments come from a contrast + CVD check run over the whole
     set; the two failures it caught are noted where they were fixed. Contrast is WCAG 2.1
     relative luminance, separation is CIE76 dE over a Brettel-style CVD simulation. */

  /* Surfaces - cool, so the navy chrome sits on its own family rather than against warm paper. */
  /* The ground, and it is a ground rather than almost-white on purpose. At #F5F8FC a white
     card sat on it at 1.065:1 and did not read as raised at all - the page was one sheet with
     hairlines ruled on it. At #E9EEF8 the same card separates at 1.163:1, which is what lets
     the panels float without a single one of them moving. */
  --bg-canvas:      #E9EEF8;
  --bg-surface:     #FFFFFF;
  --bg-surface-2:   #F9FBFD;
  --bg-line:        #E2E9F2;
  --bg-line-strong: #C7D3E3;

  /* Ink. Measured on all three surfaces above, not only on white: the canvas is the lightest
     thing on the screen and is what actually decides whether the faint grey passes. */
  --bg-text:        #14233B;   /* 15.75 white / 14.79 canvas */
  --bg-text-soft:   #46566F;   /*  7.44 white /  6.99 canvas */
  --bg-text-faint:  #5C6B82;   /*  5.41 white /  5.08 canvas */

  /* The sidebar, the sign-in page, and anything else that goes dark: the logo's own navy. */
  --bg-ink:         #0B1F45;
  --bg-ink-2:       #132C5C;
  --bg-ink-line:    #244A80;

  /* Accent - the logo's blue, not the generic indigo this used to be. 6.56:1 on white and
     6.16:1 on the canvas, so it carries link and button text at any size, not only as a block
     of colour. */
  --bg-accent:      #0B57C7;
  --bg-accent-dark: #08429B;
  --bg-accent-soft: #E6EEFB;

  /* The other two brand hues, at strengths that can carry text. The logo's own #4EAC3A and
     #13B8B0 are both too light for that - 4.1:1 and under - so these are their darkened forms
     and the bright originals are used only as gradient ends and marks. */
  /* Darkened from #0B7E79, which carried 4.91 on white but only 4.22 on the deeper ground
     above - under the floor the moment the canvas changed. */
  --bg-brand-teal:  #0A7571;   /* 5.53 white / 4.76 canvas */
  --bg-brand-green: #1E7A35;   /* 5.40 white */

  /* Status. Success is the brand green; the rest stay where they were, because a warning that
     is brand-coloured stops reading as a warning. */
  --bg-success:     #1E7A35;
  --bg-success-soft:#E7F4EA;
  --bg-warning:     #9A4C07;
  --bg-warning-soft:#FCF1E3;
  --bg-danger:      #B4232B;
  --bg-danger-soft: #FAE9E9;
  --bg-info:        #0B57C7;
  --bg-info-soft:   #E6EEFB;

  /* Chart marks, deliberately independent of --bg-accent: chrome and data are different jobs,
     and a series painted in the brand colour stops reading as a measurement.

     Series 2 stays amber, and that is a decision the brand lost rather than one nobody made.
     Painting it in the logo's blue was tried and measured: against the teal below it collapses
     to dE 9.0 under tritanopia - two marks a tritan reader cannot separate - while amber holds
     at 86-101 across all three simulations. The brand does not get to make a chart unreadable,
     so the second series is amber and the line is dashed as well, which is what actually carries
     it for anyone who cannot use hue at all. */
  --bg-chart-1:     #0C8286;
  --bg-chart-2:     #B45309;
  --bg-chart-grid:  #E6ECF5;

  /* Sequential ramp for the stage donut - the right half of the logo's gradient, teal running
     down into navy. The slices are a ranking, not a set of unrelated categories, so the colour
     job is sequential: one family, light to dark, darkening with the count. Validated as an
     ordinal ramp - lightness monotone, every adjacent gap >= 8 L*, lightest 1.92:1 on the card.
     Five steps and no more: a sixth would have to be lighter still, and anything past the fifth
     falls into --bg-ramp-rest, a neutral, which is what "Other" should be anyway. */
  --bg-ramp-1:      #3ECFC6;
  --bg-ramp-2:      #13B8B0;
  --bg-ramp-3:      #0E8F93;
  --bg-ramp-4:      #0B6682;
  --bg-ramp-5:      #0B3B63;
  --bg-ramp-rest:   #94A3B8;

  /* Categorical, for the source donut - sources are unrelated channels, not a scale, so they
     take distinct hues rather than one family in steps. Four plus a neutral "Other", validated
     all-pairs: worst normal-vision dE 49.5, worst CVD pair 16.3 (teal/magenta), which is better
     than the set this replaced managed at 7.4 - and the legend names every slice and a 2px gap
     separates them, so colour is never the only thing telling them apart. */
  --bg-cat-1:       #0B7E79;
  --bg-cat-2:       #1264D8;
  --bg-cat-3:       #C2410C;
  --bg-cat-4:       #A21CAF;
  --bg-cat-rest:    #94A3B8;

  /* ---- card washes.
     Not every panel is white any more. Each one takes a very light wash of its own icon's
     family, so the tint is never decoration - it says what kind of card this is, using the
     colour the header already chose. Measured: every ink token clears 4.5:1 on all five. */
  --bg-tint-blue:     #E8EFFC;
  --bg-tint-lavender: #EFEBFC;
  --bg-tint-teal:     #E4F4F2;
  --bg-tint-warm:     #F8F1E6;
  --bg-tint-mint:     #E6F4EA;

  /* Violet is the one colour here that is NOT in the logo. It is used selectively and never
     for a measurement - a lavender wash, and the accent on the brand ramp's far end - because
     a hue the mark does not contain cannot be allowed to start meaning something. */
  --bg-violet:        #6D28D9;   /* 6.11 canvas */
  --bg-violet-soft:   #F0EAFE;

  --bg-radius:      6px;
  --bg-radius-sm:   5px;
  --bg-side:        232px;
  --bg-topbar:      60px;
  --bg-font:        'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --bg-shadow-pop:  0 8px 28px rgba(18, 33, 30, .14);
}

/* ========== base ========== */

body {
  font-family: var(--bg-font);
  background: var(--bg-canvas);
  color: var(--bg-text);
  font-size: .875rem;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 { font-weight: 650; letter-spacing: -.011em; color: var(--bg-text); }
a { color: var(--bg-accent); }
a:hover { color: var(--bg-accent-dark); }
::selection { background: var(--bg-accent); color: #fff; }
hr { border-color: var(--bg-line); }
.text-muted { color: var(--bg-text-soft) !important; }

/* Figures line up in columns; this is a data product. */
.table, .bg-num, input[type="number"] { font-variant-numeric: tabular-nums; }

/* ========== shell ========== */

.bg-shell { display: flex; min-height: 100vh; }

/* ========== sidebar ==========
   One sidebar, always visible, never covering the page. A parent opens in place and its
   children stack underneath it - the "ladder". This replaced a 76px icon rail whose submenus
   flew out as a fixed panel pinned top-to-bottom: two items produced a 212px dark slab the full
   height of the window, sitting over whatever you were reading. A list that is as tall as its
   contents cannot do that.
   ========================================================================================= */

.bg-side {
  width: var(--bg-side);
  flex: 0 0 var(--bg-side);
  background: var(--bg-ink);
  color: #A8BBD6;
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; bottom: 0; left: 0;
  z-index: 1040;
  transition: transform .18s ease;
}

/* A white band across the rail, holding the real mark. See index.php for why it is a band
   rather than a boxed logo on the navy. */
.bg-side__brand {
  height: var(--bg-topbar);
  display: flex; align-items: center; justify-content: center;
  padding: 0 18px;
  background: #fff;
  border-bottom: 1px solid var(--bg-ink-line);
  text-decoration: none;
  flex: 0 0 auto;
}
.bg-side__logo {
  width: 100%; max-width: 152px; height: auto;
  /* Same reason as the sign-in page: the supplied ground is not quite white, and multiplying it
     against this band removes the seam without touching a pixel of the artwork. */
  mix-blend-mode: multiply;
}
.bg-side__brand:hover .bg-side__logo { opacity: .88; }

.bg-side__nav { flex: 1; overflow-y: auto; padding: 8px 0; }
.bg-side__nav::-webkit-scrollbar { width: 6px; }
.bg-side__nav::-webkit-scrollbar-thumb { background: var(--bg-ink-line); border-radius: 3px; }

/* A row in the ladder: a link, or the button that opens a group. */
.bg-side__item {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 16px;
  color: #9FB3D1; text-decoration: none;
  border-left: 3px solid transparent;
  font-size: .84rem;
  transition: background .12s, color .12s;
  cursor: pointer;
}
.bg-side__item i { font-size: .95rem; width: 18px; text-align: center; flex: 0 0 auto; }
.bg-side__item span { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bg-side__item:hover { background: var(--bg-ink-2); color: #fff; text-decoration: none; }
.bg-side__item.is-active {
  background: var(--bg-ink-2);
  color: #fff;
  border-left-color: var(--bg-accent);
}

/* The caret turns to point down while the group is open. */
.bg-side__caret {
  font-size: .62rem; opacity: .6; flex: 0 0 auto;
  transition: transform .18s ease;
}
.bg-side__group.is-open > .bg-side__item .bg-side__caret { transform: rotate(90deg); }

/* The children. Closed is height 0 rather than display:none so it can animate, and so a
   screen reader is not handed a list that flickers in and out of the document. */
.bg-side__sub {
  max-height: 0;
  overflow: hidden;
  transition: max-height .2s ease;
  background: var(--bg-ink-2);
}
.bg-side__group.is-open > .bg-side__sub { max-height: 60vh; }

.bg-side__sub a {
  display: block;
  padding: 8px 16px 8px 48px;
  color: #93A8C9; text-decoration: none;
  font-size: .82rem;
  border-left: 3px solid transparent;
}
.bg-side__sub a:hover { color: #fff; background: var(--bg-ink); text-decoration: none; }
.bg-side__sub a.is-active {
  color: #fff; background: var(--bg-ink);
  border-left-color: var(--bg-accent);
}

.bg-side__foot { border-top: 1px solid var(--bg-ink-line); padding: 6px 0; flex: 0 0 auto; }

/* Only drawn under the sidebar on small screens, where it slides over the page. */
.bg-side__scrim {
  display: none;
  position: fixed; inset: 0;
  background: rgba(18, 33, 30, .45);
  z-index: 1035;
}
.bg-side__toggle {
  display: none;
  background: none; border: 0; padding: 6px 8px;
  color: var(--bg-text-soft); font-size: 1.05rem; cursor: pointer;
}

.bg-frame { flex: 1; margin-left: var(--bg-side); min-width: 0; display: flex; flex-direction: column; }

.bg-topbar {
  height: var(--bg-topbar);
  background: var(--bg-surface);
  border-bottom: 1px solid var(--bg-line);
  display: flex; align-items: center;
  padding: 0 20px; gap: 14px;
  position: sticky; top: 0; z-index: 1020;
}
.bg-topbar__title { font-size: 1.02rem; font-weight: 650; margin: 0; }
.bg-topbar__crumb { font-size: .78rem; color: var(--bg-text-faint); }

/* Back. 36px so it is a real target on a phone, and it keeps its own hit area rather than
   borrowing the title's. */
.bg-topbar__back {
  flex: 0 0 auto;
  width: 36px; height: 36px; margin-right: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 1px solid var(--bg-line); border-radius: 9px;
  color: var(--bg-text-soft); font-size: .85rem; cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.bg-topbar__back:hover { background: var(--bg-surface-2); border-color: var(--bg-line-strong); color: var(--bg-text); }
.bg-topbar__back:focus-visible { outline: 2px solid var(--bg-accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .bg-topbar__back { transition: none; } }

.bg-orgchip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--bg-accent-soft); color: var(--bg-accent-dark);
  border: 1px solid #C8D5F4;
  border-radius: 999px; padding: 4px 11px; font-size: .78rem; font-weight: 550;
}
.bg-orgchip code { color: var(--bg-accent-dark); background: none; font-size: .74rem; }

.bg-user { display: flex; align-items: center; gap: 8px; text-decoration: none; color: inherit; }
.bg-user:hover { color: inherit; }
.bg-user__av {
  width: 32px; height: 32px; border-radius: 9px;
  background: var(--bg-ink); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 650; font-size: .78rem;
}
.bg-user__name { font-size: .81rem; font-weight: 600; line-height: 1.15; }
.bg-user__role { font-size: .69rem; color: var(--bg-text-faint); line-height: 1.15; }

.bg-canvas { flex: 1; padding: 20px; }

.bg-foot {
  padding: 10px 20px; border-top: 1px solid var(--bg-line);
  color: var(--bg-text-faint); font-size: .76rem;
  display: flex; justify-content: space-between;
}

/* ========== panels (the .card markup every view already uses) ========== */

.card {
  background: var(--bg-surface);
  border: 1px solid var(--bg-line);
  border-radius: var(--bg-radius);
  box-shadow: none;
  margin-bottom: 18px;
}
.card-header {
  background: none;
  border-bottom: 1px solid var(--bg-line);
  padding: 12px 16px;
  border-radius: var(--bg-radius) var(--bg-radius) 0 0;
}
.card-title { font-size: .92rem; font-weight: 650; margin: 0; }
.card-body { padding: 16px; }
.card-footer { background: var(--bg-surface-2); border-top: 1px solid var(--bg-line); padding: 12px 16px; }

/* ========== buttons ========== */

.btn {
  border-radius: var(--bg-radius-sm);
  font-weight: 550;
  font-size: .83rem;
  padding: .38rem .8rem;
  border: 1px solid transparent;
  transition: background .12s, border-color .12s, color .12s;
}
.btn:focus, .btn.focus { box-shadow: 0 0 0 3px var(--bg-accent-soft); }

.btn-primary { background: var(--bg-accent); border-color: var(--bg-accent); color: #fff; }
.btn-primary:hover, .btn-primary:focus { background: var(--bg-accent-dark); border-color: var(--bg-accent-dark); color: #fff; }

.btn-secondary { background: var(--bg-surface); border-color: var(--bg-line-strong); color: var(--bg-text); }
.btn-secondary:hover { background: var(--bg-canvas); border-color: var(--bg-text-faint); color: var(--bg-text); }

.btn-success { background: var(--bg-success); border-color: var(--bg-success); }
.btn-warning { background: var(--bg-warning); border-color: var(--bg-warning); color: #fff; }
.btn-warning:hover { background: #7E3D06; border-color: #7E3D06; color: #fff; }
.btn-danger  { background: var(--bg-danger);  border-color: var(--bg-danger); }

.btn-outline-secondary { border-color: var(--bg-line-strong); color: var(--bg-text-soft); background: var(--bg-surface); }
.btn-outline-secondary:hover { background: var(--bg-canvas); border-color: var(--bg-text-faint); color: var(--bg-text); }
.btn-outline-primary { border-color: var(--bg-accent); color: var(--bg-accent); background: var(--bg-surface); }
.btn-outline-primary:hover { background: var(--bg-accent); color: #fff; }
.btn-outline-danger { border-color: #E3C3C3; color: var(--bg-danger); background: var(--bg-surface); }
.btn-outline-danger:hover { background: var(--bg-danger); color: #fff; border-color: var(--bg-danger); }

.btn-sm { font-size: .78rem; padding: .28rem .62rem; }
.btn-xs { font-size: .72rem; padding: .16rem .46rem; border-radius: 4px; line-height: 1.4; }

/* ========== forms ========== */

.form-group label, label { font-size: .78rem; font-weight: 600; color: var(--bg-text-soft); margin-bottom: .3rem; }
.form-control {
  border: 1px solid var(--bg-line-strong);
  border-radius: var(--bg-radius-sm);
  font-size: .85rem;
  color: var(--bg-text);
  padding: .4rem .65rem;
  height: auto;
  background: var(--bg-surface);
}
.form-control:focus {
  border-color: var(--bg-accent);
  box-shadow: 0 0 0 3px var(--bg-accent-soft);
  background: var(--bg-surface);
}
.form-control::placeholder { color: var(--bg-text-faint); }
.form-control-sm { font-size: .8rem; padding: .3rem .55rem; }
select.form-control:not([size]):not([multiple]) { height: auto; }
.form-text { font-size: .74rem; }
textarea.form-control { line-height: 1.5; }

.custom-control-label { font-weight: 500; color: var(--bg-text); font-size: .84rem; }
.custom-control-input:checked ~ .custom-control-label::before {
  background: var(--bg-accent); border-color: var(--bg-accent);
}
.custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 3px var(--bg-accent-soft); }

.is-invalid, .parsley-error { border-color: var(--bg-danger) !important; }
.invalid-feedback, .parsley-errors-list {
  color: var(--bg-danger); font-size: .74rem; list-style: none; padding: 0; margin: .25rem 0 0;
}

/* ========== tables ========== */

.table { color: var(--bg-text); margin-bottom: 0; }
.table thead th {
  border-bottom: 1px solid var(--bg-line-strong);
  border-top: 0;
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--bg-text-faint);
  padding: 9px 12px;
  white-space: nowrap;
}
.table td { border-top: 1px solid var(--bg-line); padding: 10px 12px; vertical-align: middle; }
.table-sm td, .table-sm th { padding: 7px 10px; }
.table-hover tbody tr:hover { background: var(--bg-surface-2); }
.table tbody tr:last-child td { border-bottom: 0; }

/* ========== badges ========== */

.badge {
  font-weight: 600; font-size: .7rem; letter-spacing: .01em;
  padding: .3em .6em; border-radius: 4px;
}
.badge-primary   { background: var(--bg-accent-soft);  color: var(--bg-accent-dark); }
.badge-secondary { background: #E7EDF5;                color: var(--bg-text-soft); }
.badge-success   { background: var(--bg-success-soft); color: var(--bg-success); }
.badge-info      { background: var(--bg-info-soft);    color: var(--bg-info); }
.badge-warning   { background: var(--bg-warning-soft); color: var(--bg-warning); }
.badge-danger    { background: var(--bg-danger-soft);  color: var(--bg-danger); }
.badge-light     { background: var(--bg-canvas); color: var(--bg-text-soft); border: 1px solid var(--bg-line); }

/* ========== alerts ========== */

.alert { border: 1px solid transparent; border-radius: var(--bg-radius); font-size: .85rem; padding: .7rem 1rem; }
.alert-success { background: var(--bg-success-soft); border-color: #CBE5D4; color: var(--bg-success); }
.alert-info    { background: var(--bg-info-soft);    border-color: #CBD8F7; color: var(--bg-info); }
.alert-warning { background: var(--bg-warning-soft); border-color: #EFD9BC; color: var(--bg-warning); }
.alert-danger  { background: var(--bg-danger-soft);  border-color: #EBCDCD; color: var(--bg-danger); }
.alert-light   { background: var(--bg-surface-2);    border-color: var(--bg-line); color: var(--bg-text); }

/* The lapsed-subscription strip sits flush under the topbar. */
.bg-banner { border-radius: 0; border-left: 0; border-right: 0; border-top: 0; margin: 0; }

/* ========== modals ========== */

.modal-content {
  border: 1px solid var(--bg-line);
  border-radius: var(--bg-radius);
  box-shadow: var(--bg-shadow-pop);
}
.modal-header { border-bottom: 1px solid var(--bg-line); padding: 14px 18px; }
.modal-title { font-size: .98rem; font-weight: 650; }
.modal-body { padding: 18px; }
.modal-footer { border-top: 1px solid var(--bg-line); background: var(--bg-surface-2); padding: 12px 18px; }
.modal-backdrop.show { opacity: .35; }
.close { font-weight: 400; color: var(--bg-text-faint); text-shadow: none; opacity: 1; }
.close:hover { color: var(--bg-text); }

/* ========== dropdowns ========== */

.dropdown-menu {
  border: 1px solid var(--bg-line);
  border-radius: var(--bg-radius);
  box-shadow: var(--bg-shadow-pop);
  font-size: .85rem;
  padding: 6px;
}
.dropdown-item { border-radius: var(--bg-radius-sm); padding: .45rem .7rem; color: var(--bg-text); }
.dropdown-item:hover { background: var(--bg-canvas); }
.dropdown-divider { border-color: var(--bg-line); }

/* ========== stat tiles (replaces AdminLTE's small-box) ========== */

.bg-stat {
  background: var(--bg-surface);
  border: 1px solid var(--bg-line);
  border-radius: var(--bg-radius);
  padding: 14px 16px;
  margin-bottom: 18px;
  position: relative;
  overflow: hidden;
}
.bg-stat::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--bg-accent);
}
.bg-stat--success::before { background: var(--bg-success); }
.bg-stat--warning::before { background: var(--bg-warning); }
.bg-stat--danger::before  { background: var(--bg-danger); }
.bg-stat__value { font-size: 2rem; font-weight: 700; line-height: 1; letter-spacing: -.03em;
                  font-variant-numeric: tabular-nums; }
.bg-stat__label { font-size: .78rem; color: var(--bg-text); margin-top: 6px; font-weight: 600; }
/* A money figure carries a currency and separators, so it needs about twice the room a count
   does and wrapped to two lines in a quarter-width tile. Smaller, and told not to break. */
.bg-stat__value--money { font-size: 1.4rem; white-space: nowrap; }
.bg-stat__note  { font-size: .72rem; color: var(--bg-text-faint); margin-top: 1px; }

/* A sparkline sitting in the tile's top-right corner: the headline number says where the book
   is now, this says which way it has been moving. Absolute, so it never pushes the figure
   around, and low-contrast, because the number is the thing being read. */
.bg-stat__spark { position: absolute; top: 12px; right: 12px; width: 76px; height: 24px;
                  opacity: .5; pointer-events: none; }
.bg-stat__spark path { fill: none; stroke: var(--bg-chart-1); stroke-width: 1.75;
                       stroke-linecap: round; stroke-linejoin: round; }

/* A stat that opens the records behind its own number. Used by the stage boxes and the four
   headline tiles, which all lead to the lead register filtered to exactly what they counted.
   The whole box is the target, not the figure inside it - a 3-digit number is a small thing to
   ask somebody to hit. */
a.bg-stat,
a.bg-stat:hover,
a.bg-stat:focus { display: block; color: inherit; text-decoration: none; }
a.bg-stat { transition: border-color .12s ease, transform .12s ease; }
a.bg-stat:hover { border-color: var(--bg-accent); transform: translateY(-1px); }
a.bg-stat:focus-visible { outline: 2px solid var(--bg-accent); outline-offset: 2px; }
/* Nothing to open, so it should not invite a click. */
a.bg-stat.is-empty { opacity: .62; }
a.bg-stat.is-empty:hover { border-color: var(--bg-line); transform: none; }

/* ========== the stage funnel (M9) ==========
   Bars are relative to the busiest stage rather than to the total: the question this answers is
   where the open work is piling up, so the fullest bar should be full. */

.bg-funnel__row { display: flex; align-items: center; gap: 12px; padding: 5px 0; }
.bg-funnel__name {
  flex: 0 0 34%; font-size: .82rem; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bg-funnel__track { flex: 1; background: var(--bg-canvas); border-radius: 3px; height: 16px; }
/* --bg-chart-1, not --bg-accent. Every bar, line, ring and segment on a dashboard is drawn
   from the chart palette and every link, button and active state from the brand - so navy means
   "you can click this" and teal means "this is a measurement". These bars were the one place
   still painting data in the brand colour. */
.bg-funnel__bar { height: 100%; background: var(--bg-chart-1); border-radius: 3px; }
.bg-funnel__bar.is-late { background: var(--bg-warning); }
.bg-funnel__count {
  flex: 0 0 88px; text-align: right; font-size: .8rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.bg-funnel__late { display: block; color: var(--bg-danger); font-size: .69rem; font-weight: 600; }

/* ========== DataTables ========== */

.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select {
  border: 1px solid var(--bg-line-strong);
  border-radius: var(--bg-radius-sm);
  padding: .25rem .5rem;
  font-size: .8rem;
}
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter { font-size: .78rem; color: var(--bg-text-soft); }
.dataTables_wrapper .dataTables_paginate .paginate_button {
  border-radius: var(--bg-radius-sm) !important;
  border: 1px solid transparent !important;
  font-size: .79rem;
  padding: .28rem .6rem !important;
  color: var(--bg-text-soft) !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current {
  background: var(--bg-accent) !important;
  border-color: var(--bg-accent) !important;
  color: #fff !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
  background: var(--bg-canvas) !important;
  border-color: var(--bg-line-strong) !important;
  color: var(--bg-text) !important;
}
table.dataTable thead .sorting:after,
table.dataTable thead .sorting_asc:after,
table.dataTable thead .sorting_desc:after { opacity: .3; }

/* ========== the pipeline ==========
   The product's signature screen: a lead's run drawn as a track you read left to right, with the
   money and the SLA on it, rather than a table of rows. The sequence IS the product - Process to
   Subprocess to result - so it is worth drawing rather than tabulating. */

.bg-run {
  background: var(--bg-surface);
  border: 1px solid var(--bg-line);
  border-radius: var(--bg-radius);
  margin-bottom: 16px;
  overflow: hidden;
}
.bg-run__head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 16px;
  border-bottom: 1px solid var(--bg-line);
  background: var(--bg-surface-2);
}
.bg-run__product { font-weight: 650; font-size: .92rem; }
.bg-run__process { font-size: .78rem; color: var(--bg-text-soft); }
.bg-run__money { font-size: .82rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.bg-run__note { padding: 0 16px; margin-top: 10px; font-size: .82rem; }

/* --- the track --- */

/* A long ladder (the Business Growth flow is 19 steps) runs off the right of the card with
   nothing to say so, so the track carries a fade that stops at the end of the scroll. */
.bg-pipe {
  display: flex; overflow-x: auto; padding: 20px 10px 14px;
  background:
    linear-gradient(to right, var(--bg-surface), transparent) left center / 24px 100% no-repeat,
    linear-gradient(to left,  var(--bg-surface), transparent) right center / 24px 100% no-repeat,
    radial-gradient(farthest-side at 0 50%, rgba(18,33,30,.10), transparent) left center / 12px 100% no-repeat,
    radial-gradient(farthest-side at 100% 50%, rgba(18,33,30,.10), transparent) right center / 12px 100% no-repeat;
  background-attachment: local, local, scroll, scroll;
}
.bg-pipe::-webkit-scrollbar { height: 6px; }
.bg-pipe::-webkit-scrollbar-thumb { background: var(--bg-line-strong); border-radius: 3px; }

.bg-pipe__node {
  flex: 0 0 128px;
  position: relative;
  text-align: center;
  padding: 0 6px;
}
/* The connector runs from the previous node's centre to this one's. */
.bg-pipe__node::before {
  content: ''; position: absolute; top: 13px; left: -50%;
  width: 100%; height: 2px; background: var(--bg-line-strong); z-index: 0;
}
.bg-pipe__node:first-child::before { display: none; }
.bg-pipe__node.is-passed::before { background: var(--bg-accent); }

.bg-pipe__dot {
  position: relative; z-index: 1;
  width: 28px; height: 28px; border-radius: 50%;
  margin: 0 auto 9px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-surface);
  border: 2px solid var(--bg-line-strong);
  color: var(--bg-text-faint);
  font-size: .68rem; font-weight: 700;
}
.bg-pipe__name {
  font-size: .78rem; font-weight: 600; line-height: 1.25;
  margin-bottom: 3px; color: var(--bg-text);
}
.bg-pipe__meta { font-size: .68rem; color: var(--bg-text-faint); line-height: 1.35; }
.bg-pipe__amt  { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--bg-text-soft); }

.bg-pipe__node.is-done    .bg-pipe__dot { background: var(--bg-accent); border-color: var(--bg-accent); color: #fff; }
.bg-pipe__node.is-skipped .bg-pipe__dot { border-style: dashed; }
.bg-pipe__node.is-skipped .bg-pipe__name { color: var(--bg-text-faint); font-weight: 500; }
.bg-pipe__node.is-current .bg-pipe__dot {
  border-color: var(--bg-accent); color: var(--bg-accent);
  box-shadow: 0 0 0 4px var(--bg-accent-soft);
}
.bg-pipe__node.is-current .bg-pipe__name { color: var(--bg-accent-dark); }
.bg-pipe__node.is-overdue .bg-pipe__dot {
  border-color: var(--bg-danger); color: var(--bg-danger);
  box-shadow: 0 0 0 4px var(--bg-danger-soft);
}
.bg-pipe__node.is-overdue .bg-pipe__name { color: var(--bg-danger); }
.bg-pipe__flag { color: var(--bg-danger); font-weight: 700; }

/* --- what you act on: the current step, spelled out under the track --- */

.bg-now {
  border-top: 1px solid var(--bg-line);
  background: var(--bg-accent-soft);
  padding: 13px 16px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.bg-now--late { background: var(--bg-danger-soft); }
.bg-now__label {
  font-size: .66rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--bg-accent-dark);
}
.bg-now--late .bg-now__label { color: var(--bg-danger); }
.bg-now__name { font-weight: 650; font-size: .92rem; }
.bg-now__facts { font-size: .78rem; color: var(--bg-text-soft); }
.bg-now__task {
  width: 100%; font-size: .8rem; color: var(--bg-text-soft);
  white-space: pre-wrap; border-top: 1px dashed var(--bg-line); padding-top: 9px;
}

/* ========== activity timeline ========== */

.bg-tl { position: relative; padding-left: 22px; }
.bg-tl::before {
  content: ''; position: absolute; left: 6px; top: 6px; bottom: 6px;
  width: 2px; background: var(--bg-line);
}
.bg-tl__item { position: relative; padding: 0 0 15px; }
.bg-tl__item:last-child { padding-bottom: 0; }
.bg-tl__dot {
  position: absolute; left: -22px; top: 3px;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--bg-surface); border: 2px solid var(--bg-line-strong);
}
.bg-tl__item.is-note .bg-tl__dot { border-color: var(--bg-accent); }
.bg-tl__head { font-size: .82rem; font-weight: 600; }
.bg-tl__when { font-size: .7rem; color: var(--bg-text-faint); }
.bg-tl__text { font-size: .82rem; color: var(--bg-text-soft); white-space: pre-wrap; margin-top: 2px; }
.bg-tl__next {
  display: inline-block; margin-top: 5px; font-size: .72rem; font-weight: 600;
  background: var(--bg-warning-soft); color: var(--bg-warning);
  border-radius: 4px; padding: 2px 7px;
}
/* A follow-up that has been dealt with stops shouting; the date stays, readable, as a record. */
.bg-tl__next.is-done {
  background: var(--bg-canvas); color: var(--bg-text-faint); text-decoration: line-through;
}

/* One field's move, used by the edit trail and by the popup that asks why - the same shape in
   both, so what you are asked about is what you later read back. */
.bg-edit { margin-top: 7px; }
.bg-edit__field { font-size: .74rem; font-weight: 650; color: var(--bg-text-soft); }
.bg-edit__why {
  font-size: .76rem; color: var(--bg-text); margin-top: 2px;
  border-left: 2px solid var(--bg-accent); padding-left: 7px;
}
.bg-diff { font-size: .8rem; display: flex; align-items: baseline; flex-wrap: wrap; }
.bg-diff__old { color: var(--bg-text-faint); text-decoration: line-through; }
.bg-diff__new { color: var(--bg-text); font-weight: 600; }

/* The row of things to do with a run once it has been lost. */
.bg-after {
  border-top: 1px solid var(--bg-line);
  background: var(--bg-surface-2);
  padding: 11px 16px;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.bg-after__label { font-size: .78rem; color: var(--bg-text-soft); margin-right: 4px; }

/* ========== sign-in pages ==========
   These live outside the shell, so they carry the identity on their own. A split field: the
   brand on the left, the work on the right.

   The mark is supplied as a JPEG on a white ground, which decides this layout more than taste
   does. It cannot go on the navy without either a white box around it or its background keyed
   out, and keying it out is redrawing somebody's logo. So it sits on the white half, where its
   own ground disappears into the panel, and the navy half is branded with the wordmark's three
   words and the climbing line the mark is built from. Below 992px the brand half is dropped
   rather than stacked - on a phone it would be a screen of decoration above the only thing
   anybody came here to do. */

.bg-auth {
  min-height: 100vh;
  min-height: 100dvh;   /* mobile toolbars: 100vh overshoots and pushes the form under them */
  background: var(--bg-surface);
  color: var(--bg-text);
}
.bg-auth__split { display: flex; min-height: 100vh; min-height: 100dvh; }

/* ---- the brand half */
.bg-auth__brandside {
  flex: 0 0 46%;
  position: relative;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 56px;
  overflow: hidden;
  background:
    radial-gradient(760px 420px at 18% 8%, #16397A 0%, transparent 62%),
    radial-gradient(620px 420px at 95% 100%, #0A3F6E 0%, transparent 58%),
    var(--bg-ink);
}
/* A hairline of the brand ramp down the seam, so the two halves meet on purpose. */
.bg-auth__brandside::after {
  content: ''; position: absolute; top: 0; right: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, #0195EF 0%, #00BFD1 52%, #83C541 100%);
}

.bg-auth__motif {
  position: absolute; top: 8%; right: 6%; width: min(74%, 440px); height: auto;
  opacity: .9; pointer-events: none;
}
.bg-auth__motif-grid line { stroke: rgba(255, 255, 255, .09); stroke-width: 1; }

.bg-auth__brandcopy { position: relative; max-width: 30ch; }
.bg-auth__eyebrow {
  font-size: .72rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: #6FD6DA; margin: 0 0 14px;
}
.bg-auth__headline {
  font-size: clamp(1.6rem, 2.4vw, 2.15rem); font-weight: 700; line-height: 1.18;
  letter-spacing: -.022em; color: #fff; margin: 0 0 12px;
}
.bg-auth__blurb { font-size: .95rem; line-height: 1.55; color: #9FB3D1; margin: 0; }

/* ---- the form half */
.bg-auth__formside {
  flex: 1 1 auto;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 40px 24px 20px;
  background: var(--bg-surface);
}
.bg-auth__form { width: 100%; max-width: 380px; }

/* Width only, height auto: the mark keeps its own 2:1 whatever happens to this file later.

   multiply, because the supplied JPEG's ground is not quite #FFFFFF and left a faint grey
   rectangle around the mark on the white panel. Multiplying against white leaves every pixel of
   the artwork exactly as it is and takes the near-white ground to nothing - it is compositing
   the mark onto the background it was drawn for, not recolouring it. It is only ever placed on
   white here; on anything darker multiply would dim it, which is the other half of why the mark
   does not go on the navy. */
.bg-auth__logo {
  display: block; width: 205px; height: auto; margin: 0 0 30px;
  mix-blend-mode: multiply;
}

.bg-auth__welcome {
  font-size: 1.55rem; font-weight: 700; letter-spacing: -.025em;
  margin: 0 0 6px; color: var(--bg-text);
}
.bg-auth__sub { font-size: .9rem; color: var(--bg-text-soft); margin: 0 0 26px; }

.bg-auth__alert {
  display: flex; align-items: flex-start; gap: .55rem;
  font-size: .84rem; line-height: 1.45; padding: .7rem .85rem; margin-bottom: 18px;
}
.bg-auth__alert i { margin-top: .12rem; flex: 0 0 auto; }

.bg-auth .form-group { margin-bottom: 18px; }
.bg-auth label {
  font-size: .8rem; font-weight: 600; color: var(--bg-text); margin-bottom: 7px;
}

/* ---- the field.
   A bordered row with the icon inside it rather than Bootstrap's input-group, whose appended
   box draws a second bordered rectangle beside every control. One shape per field. */
.bg-field { position: relative; display: flex; align-items: center; }
.bg-field__icon {
  position: absolute; left: 14px; font-size: .88rem;
  color: var(--bg-text-faint); pointer-events: none;
}
.bg-field .form-control {
  height: 48px; padding: 0 14px 0 40px;
  border-radius: 10px; border: 1px solid var(--bg-line-strong);
  background: var(--bg-surface-2); font-size: .92rem; color: var(--bg-text);
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.bg-field:focus-within .bg-field__icon { color: var(--bg-accent); }
.bg-field .form-control::placeholder { color: #93A0B4; }
.bg-field .form-control:hover { border-color: #A9B9CE; }
.bg-field .form-control:focus {
  background: var(--bg-surface);
  border-color: var(--bg-accent);
  box-shadow: 0 0 0 3px rgba(11, 87, 199, .16);
}
/* A password manager filling this form is the normal way it is used, and the browser repaints
   an autofilled control with its own yellow - losing the surface, the radius and the focus ring
   on both fields at once. A 100px inset shadow is the only way to put the background back:
   background-color is ignored on an autofilled control. The focus rule restates the ring,
   because that shadow replaces it. */
.bg-field .form-control:-webkit-autofill,
.bg-field .form-control:-webkit-autofill:hover {
  -webkit-box-shadow: 0 0 0 100px var(--bg-surface-2) inset;
  -webkit-text-fill-color: var(--bg-text);
  caret-color: var(--bg-text);
}
.bg-field .form-control:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 100px var(--bg-surface) inset, 0 0 0 3px rgba(11, 87, 199, .16);
}

/* The password field keeps clear of its own toggle. */
#password.form-control { padding-right: 46px; }

/* 44x44 as the skill's touch rule asks, with the glyph centred inside it. */
.bg-field__toggle {
  position: absolute; right: 2px;
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: 9px; cursor: pointer;
  color: var(--bg-text-faint); font-size: .9rem;
  transition: color .15s ease, background .15s ease;
}
.bg-field__toggle:hover { color: var(--bg-accent); background: var(--bg-accent-soft); }
.bg-field__toggle:focus-visible { outline: 2px solid var(--bg-accent); outline-offset: 1px; }

/* Parsley marks the control; the field has to show it, because the border is the only edge the
   reader can see. The message sits under the field it belongs to, not at the top of the form. */
.bg-auth .parsley-error { border-color: var(--bg-danger) !important; background: var(--bg-surface); }
.bg-auth .parsley-error:focus { box-shadow: 0 0 0 3px rgba(180, 35, 43, .16); }
.bg-auth .parsley-errors-list {
  list-style: none; margin: 7px 0 0; padding: 0;
  font-size: .78rem; color: var(--bg-danger);
}

/* ---- the button */
.bg-auth__submit {
  position: relative;
  height: 48px; border-radius: 10px;
  font-size: .92rem; font-weight: 650; letter-spacing: .005em;
  margin-top: 4px;
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  background: linear-gradient(135deg, #0B57C7 0%, #0A4AAE 100%);
  border: 0;
  box-shadow: 0 6px 16px -6px rgba(11, 87, 199, .65);
  transition: transform .15s ease, box-shadow .15s ease, filter .15s ease;
}
.bg-auth__submit:hover:not(:disabled) {
  filter: brightness(1.07);
  box-shadow: 0 10px 22px -8px rgba(11, 87, 199, .72);
  transform: translateY(-1px);
}
.bg-auth__submit:active:not(:disabled) { transform: translateY(0); }
.bg-auth__submit:focus-visible { outline: 3px solid rgba(11, 87, 199, .45); outline-offset: 2px; }
.bg-auth__submit:disabled { opacity: 1; filter: saturate(.55) brightness(.92); cursor: default; }
.bg-auth__submit-arrow { font-size: .8rem; transition: transform .15s ease; }
.bg-auth__submit:hover:not(:disabled) .bg-auth__submit-arrow { transform: translateX(2px); }

/* Working. The label stays put and the arrow is swapped for a spinner, so the button does not
   change width and the row does not jump at the moment of submitting. */
.bg-auth__spinner { display: none; width: 15px; height: 15px; }
.bg-auth__submit.is-loading .bg-auth__submit-arrow { display: none; }
.bg-auth__submit.is-loading .bg-auth__spinner {
  display: block;
  border: 2px solid rgba(255, 255, 255, .35);
  border-top-color: #fff; border-radius: 50%;
  animation: bg-spin .6s linear infinite;
}
@keyframes bg-spin { to { transform: rotate(360deg); } }

/* forgot.php: the same page without the brand half. It is a detour, and a full brand wall on a
   detour makes it look like a destination - so the form half simply takes the whole width and
   centres itself. */
.bg-auth--solo .bg-auth__formside { padding-top: 56px; }
.bg-auth--solo .bg-auth__form { margin: 0 auto; }
.bg-auth__step {
  font-size: 1.05rem; font-weight: 650; letter-spacing: -.015em;
  margin: 0 0 4px; color: var(--bg-text);
}

.bg-auth__foot { text-align: center; margin: 20px 0 0; font-size: .84rem; }
.bg-auth__foot a { color: var(--bg-accent); font-weight: 600; }
.bg-auth__foot a:hover { color: var(--bg-accent-dark); text-decoration: underline; }
.bg-auth__legal {
  margin: 32px 0 0; font-size: .74rem; color: var(--bg-text-faint); text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .bg-auth__submit, .bg-auth__submit-arrow, .bg-field .form-control { transition: none; }
  .bg-auth__submit:hover:not(:disabled) { transform: none; }
  .bg-auth__submit.is-loading .bg-auth__spinner { animation-duration: 1.6s; }
}

/* Tablet: the brand half narrows before it goes. */
@media (max-width: 1199.98px) {
  .bg-auth__brandside { flex-basis: 40%; padding: 40px; }
  .bg-auth__motif { width: min(86%, 330px); }
}

/* Phone and small tablet: brand half gone, and a thin band of the brand ramp across the top in
   its place so the page is still unmistakably BGS. */
@media (max-width: 991.98px) {
  .bg-auth__brandside { display: none; }
  .bg-auth__split { flex-direction: column; }
  .bg-auth__formside {
    justify-content: flex-start;
    padding: 56px 22px 28px;
    border-top: 4px solid transparent;
    border-image: linear-gradient(90deg, #0B1F45 0%, #0195EF 38%, #00BFD1 68%, #83C541 100%) 1;
  }
  .bg-auth__logo { width: 168px; margin-bottom: 26px; }
  .bg-auth__welcome { font-size: 1.4rem; }
}

@media (max-width: 400px) {
  .bg-auth__formside { padding: 44px 16px 24px; }
  .bg-auth__logo { width: 150px; }
}

/* Short, wide windows - a laptop at 1366x768 with the browser chrome taking its share - must not
   trap the form under the fold. */
@media (max-height: 680px) {
  .bg-auth__formside { justify-content: flex-start; padding-top: 36px; }
  .bg-auth__logo { margin-bottom: 20px; }
  .bg-auth__sub { margin-bottom: 20px; }
}

.input-group-text {
  background: var(--bg-surface-2);
  border-color: var(--bg-line-strong);
  color: var(--bg-text-faint);
  border-radius: 0 var(--bg-radius-sm) var(--bg-radius-sm) 0;
}

/* ========== misc ========== */

.bg-empty { text-align: center; padding: 34px 16px; color: var(--bg-text-faint); }
.bg-empty i { font-size: 1.7rem; display: block; margin-bottom: 10px; opacity: .45; }

.bg-sectionlabel {
  font-size: .7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--bg-text-faint); margin-bottom: .5rem;
}

/* Below this the sidebar would eat a third of the window, so it slides over the page instead
   and the topbar grows a button to call it. The ladder itself is unchanged - it is the same
   markup and the same open/close - only its position and a scrim differ. */
@media (max-width: 991.98px) {
  .bg-side {
    transform: translateX(-100%);
    box-shadow: 0 0 40px rgba(0, 0, 0, .35);
  }
  .bg-side.is-shown { transform: translateX(0); }
  .bg-side.is-shown ~ .bg-side__scrim { display: block; }

  .bg-side__toggle { display: inline-block; }
  .bg-frame { margin-left: 0; }
}

@media (max-width: 767.98px) {
  .bg-canvas { padding: 14px; }
  .bg-user__name, .bg-user__role { display: none; }
}


/* ------------------------------------------------------------------ charts
   Hand-drawn SVG. The project carries no charting library and does not need one for a line and
   a few bars; everything here is marks plus the tokens above, so it themes with the rest. */

.bg-chart            { position: relative; }
.bg-chart svg        { display: block; width: 100%; height: auto; }
.bg-chart__grid      { stroke: var(--bg-chart-grid); stroke-width: 1; }
.bg-chart__axis      { fill: var(--bg-text-faint); font-size: 11px; }
/* 2px, round joins: a thin mark that stays legible where the line doubles back. */
.bg-chart__line      { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.bg-chart__area      { stroke: none; opacity: .10; }
/* A surface ring, so a dot sitting on the other series stays its own shape. */
.bg-chart__dot       { r: 4; stroke: var(--bg-surface); stroke-width: 2; }
.bg-chart__hit       { fill: transparent; cursor: pointer; }
.bg-chart__cross     { stroke: var(--bg-line-strong); stroke-width: 1; stroke-dasharray: 3 3; opacity: 0; }
.bg-chart__col:hover .bg-chart__cross { opacity: 1; }
.bg-chart__col:hover .bg-chart__dot   { r: 6; }
.bg-chart__end       { font-size: 11px; font-weight: 600; }

.bg-chart__tip {
  position: absolute; pointer-events: none; opacity: 0; transform: translate(-50%, -100%);
  background: var(--bg-ink); color: #fff; border-radius: var(--bg-radius-sm);
  padding: .4rem .55rem; font-size: .76rem; line-height: 1.35; white-space: nowrap;
  box-shadow: var(--bg-shadow-pop); transition: opacity .09s ease;
}
.bg-chart__tip b     { font-weight: 600; }
.bg-chart__tip i     { display: inline-block; width: 8px; height: 8px; border-radius: 2px;
                       margin-right: .35rem; vertical-align: baseline; }

/* Legend: always present for two series, and the swatch carries the identity so the text can
   stay in ink like every other label on the screen. */
.bg-legend           { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap;
                       font-size: .78rem; color: var(--bg-text-soft); }
.bg-legend span      { display: inline-flex; align-items: center; gap: .35rem; }
.bg-legend i         { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }


/* The stage donut: part-to-whole of the open runs, one segment per step of the ladder. */
.bg-donut            { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.bg-donut__fig       { position: relative; flex: 0 0 160px; }
.bg-donut svg        { display: block; width: 160px; height: 160px; }
/* Drawn as a stroked circle rather than wedges: the ring width is one number, the 2px gap
   between segments is just a shorter dash, and there is no arc maths to get wrong. */
.bg-donut__seg       { fill: none; stroke-width: 18; transition: stroke-width .1s ease; }
.bg-donut__seg:hover { stroke-width: 22; cursor: pointer; }
.bg-donut__hole      { position: absolute; inset: 0; display: flex; flex-direction: column;
                       align-items: center; justify-content: center; pointer-events: none; }
.bg-donut__total     { font-size: 1.5rem; font-weight: 700; line-height: 1; color: var(--bg-text); }
.bg-donut__caption   { font-size: .7rem; color: var(--bg-text-faint); margin-top: .15rem; }

.bg-donut__key       { flex: 1 1 150px; min-width: 0; margin: 0; }
.bg-donut__key li    { display: flex; align-items: baseline; gap: .45rem; font-size: .8rem;
                       padding: .2rem 0; line-height: 1.3; }
.bg-donut__key i     { width: 10px; height: 10px; border-radius: 2px; flex: 0 0 auto;
                       position: relative; top: 1px; }
/* Wraps rather than ellipsing. Step names are a sentence - "Advance and work order" - and
   "Advance and w..." tells the reader nothing the colour had not already told them. */
.bg-donut__key span  { flex: 1 1 auto; min-width: 0; }
.bg-donut__key b     { font-weight: 600; }
.bg-donut__key em    { font-style: normal; color: var(--bg-text-faint); font-size: .74rem; }


/* ---------------------------------------------------------------- work list density
   "On you now" is the longest thing on this screen and most of its ink was repetition: an
   organisation running one product through one process printed the same two lines on every
   row, four wrapped lines deep, pushing the whole analysis band off the bottom of the page.
   The cell is now written only when it changes, which costs nothing when it varies and
   collapses to a single line when it does not. */
.bg-worklist td        { vertical-align: middle; }
.bg-worklist .is-same  { color: transparent; }
.bg-worklist .is-same::before { content: '\2013'; color: var(--bg-line-strong); }
.bg-worklist__proc     { font-size: .78rem; line-height: 1.25; }
.bg-worklist__proc em  { font-style: normal; color: var(--bg-text-faint); font-size: .74rem;
                         display: block; }

/* Rounded data-ends on the status bars: a 4px cap anchored to the baseline, so a bar reads as
   a measured length rather than a block of colour. */
.bg-funnel__bar        { border-radius: 0 4px 4px 0; }

/* The funnel count, with the "not started" note under it rather than beside it. */
.bg-funnel__count em { display: block; font-style: normal; font-weight: 400;
                       font-size: .7rem; color: var(--bg-text-faint); line-height: 1.2;
                       margin-top: 1px; }


/* ---------------------------------------------------------------- card states
   A card has three states besides content, and before this it only really had one: every panel
   on the dashboard printed "Loading..." and, if the request failed, printed it for ever. The
   toast that announced the failure is gone in four seconds and the card still says Loading, so
   the screen reads as hung rather than broken. */
.bg-load            { display: flex; align-items: center; gap: .5rem; padding: .4rem 0;
                      color: var(--bg-text-faint); font-size: .82rem; }
.bg-load__bar       { height: 8px; border-radius: 4px; flex: 1 1 auto;
                      background: linear-gradient(90deg, var(--bg-line) 25%,
                                  var(--bg-surface-2) 37%, var(--bg-line) 63%);
                      background-size: 400% 100%; animation: bg-shimmer 1.3s ease infinite; }
@keyframes bg-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) { .bg-load__bar { animation: none; } }

.bg-fail            { text-align: center; padding: 1.1rem .75rem; color: var(--bg-text-soft); }
.bg-fail i          { display: block; font-size: 1.3rem; color: var(--bg-danger); margin-bottom: .4rem; }
.bg-fail p          { font-size: .82rem; margin: 0 0 .6rem; }


/* ---------------------------------------------------------------- depth
   Gradients, used sparingly and only where they do a job: a card has to lift off the canvas,
   and the sidebar has to read as one surface rather than a flat slab. Everything is within two
   or three steps of its base colour - a gradient you can name is a gradient that has gone too
   far, and the numbers on top of these still have to be the loudest thing in the tile. */

.bg-stat {
  background: linear-gradient(180deg, var(--bg-surface) 0%, var(--bg-surface-2) 100%);
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
}
a.bg-stat:hover {
  box-shadow: 0 4px 14px rgba(11, 87, 199, .12);
}

.card {
  box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
}

/* The sidebar: navy, with the top a shade lighter so the brand sits on its own ground. */
.bg-side, .main-sidebar {
  background: linear-gradient(180deg, var(--bg-ink-2) 0%, var(--bg-ink) 220px);
}


/* ---------------------------------------------------------------- filled KPI tiles
   The headline tiles as solid colour with white text, which is the enterprise-SaaS convention
   and what the client asked for by example. Every pairing was measured against white text
   before being used: navy 8.7:1, red 6.5:1, teal 5.5:1, green and amber 5.0:1 - all clear of
   the 4.5:1 floor, so the label and the note are readable, not just the big figure.

   Only the four headline tiles are filled. Filling every tile on the page would make the screen
   a block of colour with the numbers competing against each other; these four are the headline
   and the rest stay quiet so they can be read after it. */
.bg-stat--filled {
  border-color: transparent;
  color: #fff;
  background: linear-gradient(140deg, var(--tile) 0%, var(--tile-2) 100%);
}
.bg-stat--filled::before { display: none; }            /* the left rule is redundant when filled */
.bg-stat--filled .bg-stat__value,
.bg-stat--filled .bg-stat__label { color: #fff; }
.bg-stat--filled .bg-stat__note  { color: rgba(255, 255, 255, .82); }
.bg-stat--filled .bg-stat__spark path { stroke: #fff; }
.bg-stat--filled .bg-stat__spark { opacity: .65; }

/* The icon sits behind the figure, large and barely there - decoration, not a second thing to
   read, so it never competes with the number. */
.bg-stat__icon {
  position: absolute; right: 10px; bottom: 4px;
  font-size: 2.6rem; opacity: .16; pointer-events: none;
}

a.bg-stat--filled:hover { border-color: transparent; box-shadow: 0 6px 18px rgba(15, 23, 42, .18); }

/* Pushed as chromatic as each hue can go and still clear 4.5:1 against the white text on it.
   Every value below was measured, not picked: the bright end is the worst case, because it is the
   lightest point the label and the note ever sit on.

   Teal and amber do NOT move, and that is the measurement talking rather than taste. Teal's end
   is 4.61:1 as it stands and the next step up the chroma ramp lands at 4.06; amber's is 5.02 and
   gains three points of chroma for half a point of contrast. Both are already at their ceiling,
   so the only thing left to take there was legibility. Navy, green and red had real room and have
   been spent to it. */
.bg-tile-navy  { --tile: #0B1F45; --tile-2: #1B52BE; }   /* end 7.01:1, chroma 117 -> 163 */
.bg-tile-blue  { --tile: #0B4FA8; --tile-2: #1266DE; }   /* end 5.27:1, chroma 198 -> 204 */
.bg-tile-teal  { --tile: #0A6E72; --tile-2: #0C8286; }   /* end 4.61:1 - at the ceiling, unchanged */
.bg-tile-amber { --tile: #92400E; --tile-2: #B45309; }   /* end 5.02:1 - at the ceiling, unchanged */
.bg-tile-green { --tile: #166128; --tile-2: #158438; }   /* end 4.78:1, chroma  92 -> 111 */
.bg-tile-red   { --tile: #9F1D24; --tile-2: #D1323B; }   /* end 4.96:1, chroma 147 -> 159 */

/* ---------------------------------------------------------------- team performance
   One row per person: who owns the leads, how many, and how many they have closed. */
.bg-team            { margin: 0; }
.bg-team li         { display: flex; align-items: center; gap: .6rem; padding: .5rem 0; }
.bg-team li + li    { border-top: 1px solid var(--bg-line); }
.bg-team__who       { flex: 0 0 34px; height: 34px; border-radius: 50%; display: flex;
                      align-items: center; justify-content: center; font-size: .78rem;
                      font-weight: 600; color: #fff; background: var(--bg-ink-2); }
.bg-team__body      { flex: 1 1 auto; min-width: 0; }
.bg-team__name      { font-size: .84rem; font-weight: 600; }
.bg-team__track     { height: 7px; border-radius: 4px; background: var(--bg-surface-2);
                      border: 1px solid var(--bg-line); overflow: hidden; margin-top: .3rem; }
.bg-team__bar       { height: 100%; border-radius: 0 4px 4px 0; background: var(--bg-chart-1); }
.bg-team__num       { flex: 0 0 auto; text-align: right; font-size: .82rem; font-weight: 600;
                      font-variant-numeric: tabular-nums; }
.bg-team__num em    { display: block; font-style: normal; font-weight: 400; font-size: .72rem;
                      color: var(--bg-text-faint); }

/* Revenue columns. Flat fill, rounded top only: the bar grows from the axis, so the end that
   carries the value is the one that gets the radius. */
.bg-chart__col-bar { fill: var(--bg-chart-1); }
.bg-chart__col-bar:hover { fill: var(--bg-accent); }

/* The ageing bands: a sub-label under the band name, and an empty band dimmed rather than
   dropped so its bar can be seen filling up later. */
.bg-funnel__name em  { display: block; font-style: normal; font-size: .7rem;
                       color: var(--bg-text-faint); line-height: 1.2; }
.bg-funnel__row.is-empty { opacity: .55; }


/* ================================================================= polish pass
   Softer geometry and a little depth, applied through the existing tokens and class names so
   no screen needed editing to receive it. Everything here is appearance only - no element moved
   and nothing became a different size - which is why it reaches the Leads register and the lead
   profile as well, and why it can be reverted by deleting this block. */

:root {
  --bg-radius:    10px;
  --bg-radius-sm: 8px;
  /* Two shadows rather than one: a tight dark edge that reads as a border at any zoom, and a
     wide soft one that lifts the card off the canvas. A single large blur just looks smudged. */
  --bg-lift:      0 1px 2px rgba(15, 23, 42, .05), 0 6px 16px -6px rgba(15, 23, 42, .10);
  --bg-lift-hi:   0 1px 2px rgba(15, 23, 42, .06), 0 14px 28px -10px rgba(15, 23, 42, .16);
}

.card {
  box-shadow: var(--bg-lift);
  transition: box-shadow .16s ease, transform .16s ease;
}
/* Only cards that DO something lift. A card that rises under the cursor and then cannot be
   clicked is a promise the screen does not keep, so this is scoped to the ones holding links. */
.card:has(a:hover) { box-shadow: var(--bg-lift-hi); }

.card-header {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}
.card-title { font-size: .95rem; letter-spacing: -.01em; }
/* The title takes the slack. Several headers already carried a right-hand note under
   justify-content: between, and making the header a flex row added the icon as a third child -
   which pushed every one of those titles into the middle of its own card. */
.card-header .card-title { flex: 1 1 auto; }

/* A small tinted glyph before the title: the cards are told apart at a glance by shape and
   colour before any of the words are read, which is most of what makes a long screen scannable.
   Decorative, so it is hidden from the accessibility tree - the heading already says the name. */
.card-ico {
  flex: 0 0 26px; height: 26px; border-radius: 7px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .76rem; color: var(--bg-accent); background: var(--bg-accent-soft);
}
.card-ico--teal  { color: var(--bg-brand-teal);  background: #E2F4F3; }
.card-ico--amber { color: var(--bg-warning);     background: var(--bg-warning-soft); }
.card-ico--green { color: var(--bg-brand-green); background: var(--bg-success-soft); }
.card-ico--red   { color: var(--bg-danger);      background: var(--bg-danger-soft); }

/* The header's own subtitle sits under the title, not beside it, so the row stays one line. */
.card-header .card-sub {
  flex: 1 0 100%; font-size: .78rem; color: var(--bg-text-faint);
  margin: 2px 0 0 34px;
}

.bg-stat { border-radius: var(--bg-radius); }
.bg-stat--filled { box-shadow: var(--bg-lift); }

/* Charts: let the area under the line fade out rather than sit as a flat wash, and give the
   revenue columns the same vertical falloff, so the ink is heaviest where the value is read. */
.bg-chart__area { opacity: 1; fill: url(#bgAreaFade); }
.bg-chart__col-bar { fill: url(#bgBarFade); }
.bg-chart__col-bar:hover { fill: var(--bg-accent); }

/* The donut sits on the card rather than in it. */
.bg-donut svg { filter: drop-shadow(0 6px 14px rgba(15, 23, 42, .12)); }


/* ================================================================= consistency pass
   The polish applied to the Lead Analysis dashboard never reached the other two screens built
   on the same components, so the product read as three different ages of itself: filled tiles
   on one, outline tiles on the others; header icons on one, none elsewhere. Everything below is
   appearance only and lives on the shared class names, so the platform dashboard and Reports
   inherit it without their markup moving. */

/* ---- cards in a row share a height, OPT-IN.
   Bootstrap's columns stretch but the card inside does not, so a short card beside a tall one
   leaves a step at the bottom of the row. Applied globally this was worse than the problem: a
   column holding one card beside a column holding three stretched that single card to the
   height of all three, which on the Lead Analysis screen left the Lead status card as a tall
   box half full of nothing. CSS cannot tell a peer column from a stack, so the row says. */
.row--even > [class*="col-"] { display: flex; flex-direction: column; }
.row--even > [class*="col-"] > .card { flex: 1 1 auto; margin-bottom: 0; }

/* ---- the KPI strip.
   Tiles in a row line up whatever their notes wrap to. One tile whose note runs to two lines -
   "closed without an order", "from the steps customers have switched on" - made its whole row
   ragged at the bottom, and which tile that was changed with the window width, so it was
   invisible at the width you happened to be testing. Measured: the headline row was 86, 86, 86,
   104 at 1200px.

   The column is made a flex container only where it actually holds a tile, so this cannot reach
   the card rows - stretching a lone card to match a column of three stacked ones is the mistake
   this stylesheet already made once. The note is pushed to the bottom so the labels above it sit
   on a common line rather than floating at different heights. */
.row > [class*="col-"]:has(> .bg-stat) { display: flex; flex-direction: column; }
.row > [class*="col-"] > .bg-stat { flex: 1 1 auto; display: flex; flex-direction: column; }
.bg-stat__note { margin-top: auto; }

/* ---- tables.
   Headers were already quiet; this adds the spacing and the rhythm that make a long list
   readable - a touch more air per row, a hairline under the head, and a hover that does not
   shout. */
.table thead th {
  text-transform: uppercase;
  letter-spacing: .055em;
  font-size: .68rem;
  white-space: nowrap;
  border-bottom: 1px solid var(--bg-line-strong);
}
.table td { padding: 11px 12px; }
.table-sm td, .table-sm th { padding: 8px 11px; }
.table-hover tbody tr { transition: background .12s ease; }
.table-hover tbody tr:hover { background: var(--bg-accent-soft); }
/* A table that fills its card edge to edge should not also carry the card's border. */
.card-body.p-0 > .table tbody tr:last-child td { border-bottom: 0; }

/* ---- status badges: a little more presence, same colours. */
.badge {
  padding: .3em .6em;
  border-radius: 999px;
  font-weight: 600;
  letter-spacing: .01em;
}

/* ---- empty states.
   The glyph now sits in a soft disc rather than floating as a large grey character, which is
   what made an empty card read as a missing one. */
.bg-empty { padding: 28px 16px; font-size: .84rem; line-height: 1.5; }
.bg-empty i {
  width: 42px; height: 42px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 1.05rem; margin: 0 auto 10px;
  color: var(--bg-text-soft); background: var(--bg-surface-2);
  border: 1px solid var(--bg-line); opacity: 1;
}

/* ---- sidebar: a touch more room per row and a clearer active state. */
.bg-side__link { transition: background .14s ease, color .14s ease; }

@media (max-width: 575.98px) {
  /* Two tiles per row rather than one tall column, and the big figure comes down a step so a
     four-digit count still fits on one line on a phone. */
  .bg-stat { padding: 12px 13px; }
  .bg-stat__value { font-size: 1.6rem; }
  .bg-stat__icon { font-size: 2rem; right: 6px; bottom: 2px; }
  .card-body { padding: 13px; }
  .card-header { padding: 11px 13px; }
}


/* ================================================================= premium pass
   One more pass over the three dashboards for the client demonstration: the same components,
   given the spacing, the hierarchy and the restraint a commercial analytics product has. Nothing
   below moves an element or changes a figure - it is all surface - so it reaches the Leads
   register and the lead profile too, and deleting this block returns the product to the look it
   had at ac1d8f0.

   Two rules behind every change here: colour is spent where it carries meaning and nowhere else,
   and the number is always the loudest thing in its tile. */

:root {
  /* 12 rather than 10. At 10 a card reads as a box with the corners taken off; at 12 it reads
     as a panel, which is what the rest of the geometry on these screens already says. */
  --bg-radius:    12px;
  --bg-radius-sm: 9px;
}


/* ---------------------------------------------------------------- the frame
   The header is the first thing in the demonstration and it was the least considered thing on
   the screen: 56px of flat white holding a title, a chip and an avatar at three unrelated
   weights. */

.bg-topbar {
  /* Translucent over the canvas rather than opaque. Content passing under a sticky bar should
     still be faintly there - an opaque strip reads as a lid closing over the page. */
  background: rgba(255, 255, 255, .82);
  -webkit-backdrop-filter: saturate(170%) blur(14px);
  backdrop-filter: saturate(170%) blur(14px);
  padding: 0 24px;
  gap: 16px;
}
.bg-topbar__title { font-size: 1.06rem; letter-spacing: -.018em; line-height: 1.2; }
.bg-topbar__crumb { font-size: .72rem; line-height: 1.3; margin-top: 1px; }

/* Organisation selector. It was bordered in a teal left over from the palette before this one,
   against a navy-tinted fill - the one chip on the screen whose border and background disagreed. */
.bg-orgchip {
  border-color: #C8D5F4;
  padding: 5px 12px 5px 10px;
  font-weight: 600;
  gap: 7px;
}
.bg-orgchip code { font-weight: 600; opacity: .72; letter-spacing: .02em; }

/* The user block closes the bar, so it gets a hairline to sit against rather than floating off
   the right edge beside the org chip at the same weight. */
.bg-user { padding-left: 16px; border-left: 1px solid var(--bg-line); }
.bg-user__av { border-radius: 10px; box-shadow: 0 2px 6px -1px rgba(15, 23, 42, .30); }

/* A little more air around the content, and a floor under the last card. */
.bg-canvas { padding: 24px 24px 32px; }

/* The rail's active row: a navy wash fading out to the right, rather than a flat slab of
   --bg-ink-2 - which is the colour the open submenu behind it is already using. */
.bg-side__item.is-active {
  background: linear-gradient(90deg, rgba(11, 87, 199, .40) 0%, rgba(11, 87, 199, .05) 100%);
}


/* ---------------------------------------------------------------- KPI tiles
   The headline row is what the screen is judged on in the first two seconds. The figures were
   already right; what was missing was hierarchy - the icon was a 2.6rem watermark bleeding off
   the corner at roughly the visual weight of the number, and the label sat at the same size and
   case as the note under it, so a tile read as three similar lines rather than one figure with
   two captions. */

.bg-stat { padding: 16px 18px; margin-bottom: 20px; }

/* Primary (filled) against secondary (outlined): the gap is now carried by size as well as by
   colour, so the hierarchy survives a greyscale print and a colour-blind reader. */
.bg-stat__value { font-size: 1.85rem; padding-right: 44px; }
.bg-stat--filled .bg-stat__value { font-size: 2.3rem; letter-spacing: -.035em; }
.bg-stat__value--money { font-size: 1.35rem; }
.bg-stat--filled .bg-stat__value--money { font-size: 1.55rem; }

/* Micro-caps for the label and a quieter note under it: the convention every analytics product
   uses, and the one that lets the figure above it be read on its own. */
.bg-stat__label {
  font-size: .715rem; font-weight: 650;
  text-transform: uppercase; letter-spacing: .055em;
  margin-top: 9px; line-height: 1.25;
}
.bg-stat__note { font-size: .7rem; line-height: 1.3; padding-top: 3px; }

/* The icon becomes a contained chip in the corner instead of a giant faded glyph. A watermark
   has to be guessed at, sits half-cropped whenever a tile has no note to grow it - which is
   every tile on Reports - and competes with the figure for the eye at exactly the moment the
   figure should win. The chip is small, deliberate, and speaks the same language as .card-ico. */
.bg-stat__icon {
  right: 14px; top: 14px; bottom: auto;
  width: 34px; height: 34px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-size: .92rem; opacity: 1;
  color: var(--bg-accent); background: var(--bg-accent-soft);
}
.bg-stat--success .bg-stat__icon { color: var(--bg-success); background: var(--bg-success-soft); }
.bg-stat--warning .bg-stat__icon { color: var(--bg-warning); background: var(--bg-warning-soft); }
.bg-stat--danger  .bg-stat__icon { color: var(--bg-danger);  background: var(--bg-danger-soft); }
.bg-stat--filled  .bg-stat__icon { color: #fff; background: rgba(255, 255, 255, .17); }

/* ---------------------------------------------------------------- elevation
   The one thing the tiles still lacked. Every surface carried the same 1px neutral shadow at 4%,
   which under a saturated tile is invisible - so four strong colours sat on the canvas like
   stickers rather than like cards above it. The fix is to tint the shadow with the tile's OWN
   colour, which is already to hand as --tile: a navy tile drops a navy shadow, a red one a red
   shadow, and each tile reads as lifted off the page in its own light rather than under a grey
   one borrowed from somewhere else.

   Deliberately outside the tile. The gradients in here were each measured against white text
   (navy 8.7:1, red 6.5:1, teal 5.5:1, green and amber 5.0:1) and a bloom or highlight laid over
   them would quietly spend that margin - amber and green have only half a step of room before
   4.5:1. A shadow cannot touch the text, so the contrast stays exactly as measured. */
.bg-stat--filled {
  box-shadow: 0 10px 22px -14px var(--tile), 0 2px 6px -2px rgba(15, 23, 42, .10);
}
a.bg-stat--filled:hover {
  box-shadow: 0 16px 30px -14px var(--tile), 0 4px 10px -3px rgba(15, 23, 42, .14);
}

/* The quiet tiles and the panels lift by much less, which is the point: the headline row should
   sit above them, and a page where everything floats equally has no depth at all. */
.bg-stat { box-shadow: 0 1px 2px rgba(15, 23, 42, .05), 0 6px 14px -10px rgba(15, 23, 42, .16); }
.card    { box-shadow: 0 1px 2px rgba(15, 23, 42, .05), 0 8px 18px -14px rgba(15, 23, 42, .18); }

@media (prefers-reduced-motion: reduce) {
  a.bg-stat--filled:hover { box-shadow: 0 10px 22px -14px var(--tile), 0 2px 6px -2px rgba(15, 23, 42, .10); }
}

/* ---------------------------------------------------------------- colour on the quiet tiles
   The filled row is held at its contrast ceiling, so the colour this page was short of had to
   come from the tiles that were white. These carry DARK text, which is the opposite problem: a
   tint can be laid on without spending any legibility, and every figure below was measured on
   its own tint rather than on white - 7.95:1 accent, 5.57 danger, 5.52 warning, 4.76 success.
   All four clear 4.5 as SMALL text, and these are 1.85rem.

   The wash fades out by two thirds across, so the tile still reads as a card on the canvas
   rather than as a block of flat colour, and the note at the bottom keeps a near-white ground. */
.bg-stat:not(.bg-stat--filled) {
  background: linear-gradient(135deg, var(--tint, var(--bg-accent-soft)) 0%, var(--bg-surface) 66%);
  border-color: var(--tint-line, var(--bg-line));
}
.bg-stat:not(.bg-stat--filled) .bg-stat__value { color: var(--tint-ink, var(--bg-accent-dark)); }

.bg-stat--success { --tint: var(--bg-success-soft); --tint-ink: var(--bg-success); --tint-line: #CBE6D2; }
.bg-stat--warning { --tint: var(--bg-warning-soft); --tint-ink: var(--bg-warning); --tint-line: #F0DCC2; }
.bg-stat--danger  { --tint: var(--bg-danger-soft);  --tint-ink: var(--bg-danger);  --tint-line: #F0CFCF; }

/* Nothing behind it to open, so it should not be wearing a colour either. */
a.bg-stat.is-empty { background: var(--bg-surface); }
a.bg-stat.is-empty .bg-stat__value { color: var(--bg-text-soft); }

/* The stage grid keeps its white ground. Its boxes are toned from the DATA - danger as soon as a
   step holds anything overdue - so on a real book most of them carry the same tone at once, and
   washing each one turned a nine-box grid into a sheet of pink that said nothing. The tone is
   worth more as an edge than as a fill when there are nine of them side by side. The figure
   still takes the colour, so the grid did not lose it entirely. */
#anStages .bg-stat:not(.bg-stat--filled) {
  background: var(--bg-surface);
  border-color: var(--bg-line);
}

/* The sparkline moves to the bottom corner, where the chip is not. */
.bg-stat__spark { top: auto; bottom: 14px; right: 14px; opacity: .55; }

/* A diagonal highlight over the fill. Two or three per cent of white across the top corner is
   the whole effect - enough that the tile has a light source, not enough to name. */
.bg-stat--filled {
  background:
    radial-gradient(125% 105% at 100% 0%, rgba(255, 255, 255, .20) 0%, rgba(255, 255, 255, 0) 58%),
    linear-gradient(140deg, var(--tile) 0%, var(--tile-2) 100%);
  /* Reports' tiles carry no note and the dashboard's carry one or two lines. Without a floor the
     same four tiles are three different heights on three screens. */
  min-height: 118px;
}

/* An outlined tile with a status takes a wash of its own colour rather than only a 3px rule.
   Overdue has to be findable in a glance across a row of eight tiles; it does not have to make
   the screen look like an incident. The wash is gone by 58% of the tile's height, so the figure
   is still read on white. */
.bg-stat--danger  { background: linear-gradient(170deg, var(--bg-danger-soft)  0%, var(--bg-surface) 58%); }
.bg-stat--warning { background: linear-gradient(170deg, var(--bg-warning-soft) 0%, var(--bg-surface) 58%); }
.bg-stat--success { background: linear-gradient(170deg, var(--bg-success-soft) 0%, var(--bg-surface) 58%); }
.bg-stat::before  { border-radius: var(--bg-radius) 0 0 var(--bg-radius); }

/* The Stage boxes are the one place a tile gets really narrow: a quarter of a half-width card
   is about 100px, and an organisation running three processes now draws twelve of them. At that
   width the uppercase, letter-spaced label breaks inside its own words - "SUSPECTIN / G",
   "REFERENC / ES" - so there it drops back to sentence case with no tracking, which is narrower
   and wraps where the spaces are. */
#anStages .bg-stat__label {
  text-transform: none;
  letter-spacing: 0;
  font-size: .765rem;
}
#anStages .bg-stat__value { font-size: 1.6rem; padding-right: 0; }
#anStages .bg-stat__icon { display: none; }
#anStages .bg-stat { padding: 14px 15px; }

a.bg-stat:hover { transform: translateY(-2px); }
a.bg-stat--filled:hover { box-shadow: 0 10px 26px -8px rgba(15, 23, 42, .38); }


/* ---------------------------------------------------------------- panels */

.card { margin-bottom: 20px; }
.card-header { padding: 14px 18px; }
.card-body { padding: 18px; }
/* The header's right-hand note - "last 6 months", "which channel converts" - is a caption, not a
   second title, and it was being set at the colour and size of body copy. */
.card-header > .text-muted { font-size: .76rem !important; color: var(--bg-text-faint) !important; }
.card-ico { flex: 0 0 28px; height: 28px; border-radius: 8px; font-size: .78rem; }
.card-header .card-sub { margin-left: 36px; }


/* ---------------------------------------------------------------- charts
   Sizing, labels, legend and grid. The marks themselves, and every colour they are drawn in,
   are left exactly as the validated palette at the top of this file set them. */

/* A measured grid should be felt, not read: dashed and lighter, so the line sits in front of it
   rather than in it. */
.bg-chart__grid { stroke-dasharray: 2 6; stroke-linecap: round; }
.bg-chart__axis { font-size: 10.5px; letter-spacing: .015em; }
.bg-chart__line { stroke-width: 2.25; }

/* Legend entries as chips. A bare swatch and a word, repeated, reads as a sentence that got
   broken up; a chip reads as a key. */
.bg-legend { gap: .5rem; }
.bg-legend span {
  background: var(--bg-surface-2); border: 1px solid var(--bg-line);
  border-radius: 999px; padding: .22rem .6rem .22rem .5rem;
  font-size: .75rem; font-weight: 600; color: var(--bg-text);
}
.bg-legend i { width: 9px; height: 9px; border-radius: 50%; }

.bg-chart__tip {
  padding: .45rem .6rem; border-radius: 9px;
  background: rgba(15, 23, 42, .96);
  box-shadow: 0 12px 26px -10px rgba(15, 23, 42, .55);
  margin-top: -9px;
}
/* The tooltip points at the thing it describes. */
.bg-chart__tip::after {
  content: ''; position: absolute; left: 50%; top: 100%; transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: rgba(15, 23, 42, .96);
}
.bg-chart__tip i { border-radius: 50%; width: 9px; height: 9px; }

/* Donut. The ring is the figure's frame, so the total inside it grows to match, and a legend row
   lights up to say it belongs to the segment it names. */
.bg-donut { gap: 1.25rem; }
.bg-donut__total { font-size: 1.75rem; letter-spacing: -.03em; }
.bg-donut__key li {
  padding: .3rem .45rem; border-radius: 7px;
  transition: background .12s ease;
}
.bg-donut__key li:hover { background: var(--bg-surface-2); }

/* Bars: a rounded track, and a fill that runs the teal ramp, so a long bar and a short one are
   still the same measurement read in the same place. */
.bg-funnel__row { padding: 7px 0; }
.bg-funnel__track {
  height: 10px; border-radius: 999px;
  background: var(--bg-surface-2); border: 1px solid var(--bg-line);
  overflow: hidden;
}
.bg-funnel__bar {
  border-radius: 999px;
  background: linear-gradient(90deg, var(--bg-ramp-2) 0%, var(--bg-chart-1) 100%);
  transition: width .5s cubic-bezier(.4, 0, .2, 1);
}
.bg-funnel__bar.is-late { background: linear-gradient(90deg, #92400E 0%, var(--bg-warning) 100%); }
.bg-team__track { height: 8px; border-radius: 999px; }
.bg-team__bar   { border-radius: 999px;
                  background: linear-gradient(90deg, var(--bg-ramp-2), var(--bg-chart-1)); }
@media (prefers-reduced-motion: reduce) { .bg-funnel__bar { transition: none; } }


/* ---------------------------------------------------------------- tables
   A date and a money amount are single tokens and were being allowed to wrap: "2026-10-" over
   "05", "Rs." over "1500.00" - two lines where there is one value, in the columns a reader
   scans straight down. */
.table td.text-right, .table th.text-right { white-space: nowrap; }
.bg-worklist td:nth-child(4) { white-space: nowrap; }
.table thead th { color: var(--bg-text-faint); }
/* A four-column table in a 305px card is wider than the card - "Upcoming follow-ups" was
   pushing the whole document 28px sideways, so every dashboard carried a horizontal scrollbar
   and the page slid under the cursor. The table takes its own scrollbar instead. */
.card-body.p-0 { overflow-x: auto; }
/* The row under the cursor should be marked, not highlighted: a full-width tint on every hover
   in a forty-row list is a lot of colour for something that only means "you are here". */
.table-hover tbody tr:hover {
  background: var(--bg-surface-2);
  box-shadow: inset 2px 0 0 var(--bg-accent);
}


/* ---------------------------------------------------------------- card states
   A single 8px bar was standing in for a whole panel of content. Three bars of unequal length
   read as text about to arrive, which is what a skeleton is for. */
.bg-load { flex-direction: column; align-items: stretch; gap: .5rem; padding: .5rem 0 .6rem; }
.bg-load::before, .bg-load::after {
  content: ''; display: block; height: 8px; border-radius: 4px;
  background: linear-gradient(90deg, var(--bg-line) 25%, var(--bg-surface-2) 37%, var(--bg-line) 63%);
  background-size: 400% 100%; animation: bg-shimmer 1.3s ease infinite;
}
.bg-load::before { width: 68%; }
.bg-load::after  { width: 42%; }
@media (prefers-reduced-motion: reduce) {
  .bg-load::before, .bg-load::after { animation: none; }
}

/* An empty panel should look finished, not broken. The glyph belongs above the sentence, and
   `margin: 0 auto` on an inline-flex box does not centre it - which is why every empty panel on
   these three screens was drawing a disc with the sentence stuck to its right. */
.bg-empty { padding: 32px 18px; color: var(--bg-text-soft); }
.bg-empty i {
  display: flex; width: 46px; height: 46px;
  font-size: 1.15rem; margin: 0 auto 12px;
}


/* ---------------------------------------------------------------- small screens */
@media (max-width: 575.98px) {
  .bg-canvas { padding: 14px 14px 22px; }
  .bg-stat { padding: 14px 15px; }
  .bg-stat__value { font-size: 1.55rem; padding-right: 38px; }
  .bg-stat--filled .bg-stat__value { font-size: 1.75rem; }
  .bg-stat__value--money,
  .bg-stat--filled .bg-stat__value--money { font-size: .95rem; padding-right: 34px; }
  .bg-stat--filled { min-height: 104px; }
  .bg-stat__icon { width: 30px; height: 30px; right: 11px; top: 11px; font-size: .82rem; }
  .bg-stat__spark { display: none; }   /* 76px of trend in a 150px tile is noise, not a chart */
  .bg-topbar { padding: 0 14px; }
  .bg-user { padding-left: 10px; }

  /* The charts are a fixed 720-unit viewBox scaled to the container, so on a 345px phone every
     mark is drawn at about half size - an 11px axis label lands at 5px and cannot be read. The
     marks are sized in user units, so scaling them up here is the whole fix: no re-render, no
     resize listener, and the desktop chart is untouched. */
  .bg-chart__axis { font-size: 19px; }
  .bg-chart__end  { font-size: 19px; }
  .bg-chart__line { stroke-width: 4; }
  .bg-chart__dot  { r: 7; }
  .bg-chart__col:hover .bg-chart__dot { r: 10; }
  /* The first month label is centred on the y-axis and at this size it is wider than the gutter
     the viewBox leaves for it, so it was arriving as "lay 2026". It hangs into the card's own
     padding instead of being cut. */
  .bg-chart svg { overflow: visible; }
}


/* ================================================================= shared polish
   Phase 5. The sign-in page got a field, a button and a focus ring that the rest of the product
   did not have, which would have left the best-looking screen in the application behind the
   front door. Everything below puts the same language on the shared components, through the
   class names the views already use, so no screen needed editing to receive it. */

/* ---- focus.
   One visible ring, everywhere, on whatever the keyboard is actually on. :focus-visible rather
   than :focus so a mouse click does not leave a ring behind, and :focus is kept as the fallback
   for anything that predates it. Nothing in this stylesheet is allowed to set outline: none
   without putting something else in its place. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible,
.btn:focus-visible,
.form-control:focus-visible,
.custom-control-input:focus-visible + .custom-control-label::before {
  outline: 2px solid var(--bg-accent);
  outline-offset: 2px;
  border-radius: var(--bg-radius-sm);
}
.btn:focus { box-shadow: none; }

/* ---- forms.
   The same field the sign-in page uses, at the density the rest of the product needs: a 38px
   control rather than 48px, because these sit in tables and filter rows rather than alone on a
   page, and the same focus ring so the two never look like two different products. */
.form-control {
  border-radius: 9px;
  border-color: var(--bg-line-strong);
  color: var(--bg-text);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.form-control:focus {
  border-color: var(--bg-accent);
  box-shadow: 0 0 0 3px rgba(11, 87, 199, .14);
  outline: none;                       /* the ring above IS the focus indicator here */
}
.form-control::placeholder { color: #93A0B4; }
label { font-weight: 600; font-size: .82rem; color: var(--bg-text); }
.form-text { font-size: .76rem; }
select.form-control:not([size]):not([multiple]) { height: calc(1.9rem + 10px); }

/* Parsley, product-wide - it was only styled on the sign-in page. */
.parsley-error { border-color: var(--bg-danger) !important; }
.parsley-errors-list {
  list-style: none; margin: 6px 0 0; padding: 0;
  font-size: .76rem; color: var(--bg-danger);
}

/* ---- buttons.
   Weight and a little lift on the primary only. Secondary actions stay flat: if every button
   lifts, none of them is the one to press. */
.btn { font-weight: 600; transition: background .15s ease, box-shadow .15s ease, transform .15s ease; }
.btn-primary {
  background: linear-gradient(135deg, var(--bg-accent) 0%, var(--bg-accent-dark) 100%);
  border: 0;
  box-shadow: 0 2px 8px -2px rgba(11, 87, 199, .5);
}
.btn-primary:hover, .btn-primary:focus {
  background: linear-gradient(135deg, #0C5ED8 0%, #0A4AAE 100%);
  box-shadow: 0 5px 14px -4px rgba(11, 87, 199, .58);
  transform: translateY(-1px);
}
.btn-primary:active { transform: translateY(0); }
.btn-outline-secondary {
  border-color: var(--bg-line-strong); color: var(--bg-text-soft); background: var(--bg-surface);
}
.btn-outline-secondary:hover {
  border-color: var(--bg-accent); color: var(--bg-accent);
  background: var(--bg-accent-soft);
}
.btn-sm { border-radius: 8px; }

/* ---- a filter bar.
   Reports' export row and the register's filters are a line of controls above a result set, and
   they were reading as a form to fill in. Grouped on their own tinted strip they read as what
   they are: a way to narrow what is already on the screen. */
.bg-filters {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: .75rem;
  padding: 14px 16px;
  background: var(--bg-surface-2);
  border: 1px solid var(--bg-line);
  border-radius: var(--bg-radius);
}
.bg-filters .form-group { margin-bottom: 0; }
.bg-filters label {
  font-size: .7rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--bg-text-faint); margin-bottom: 5px;
}

/* ---- dropdowns, modals, alerts: brand-side details the token change does not reach. */
.dropdown-item:hover { background: var(--bg-accent-soft); color: var(--bg-accent-dark); }
.dropdown-item:focus-visible { outline-offset: -2px; }
.modal-header { align-items: center; gap: .6rem; }
.alert { display: flex; align-items: flex-start; gap: .55rem; line-height: 1.45; }
.alert > i { margin-top: .12rem; flex: 0 0 auto; }
/* The lapsed-subscription strip spans the page, so it keeps its own box model. */
.bg-banner { display: block; }

/* ---- the rail.
   A brand hairline down the active row, so "where am I" is carried by shape as well as by the
   wash behind it - the wash alone is the kind of thing that disappears on a dim projector in a
   client meeting. */
.bg-side__item.is-active { border-left-color: #00BFD1; }
.bg-side__sub a.is-active { border-left-color: #00BFD1; }

/* ---- motion, once, for everything.
   The individual blocks above already opt out where they animate; this is the backstop for any
   transition added later that forgets to. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* The second series is dashed as well as amber - see renderTrend. 7-5 at 2.25px reads as a
   dashed line at the size this chart is drawn without turning into dots. */
.bg-chart__line--alt { stroke-dasharray: 7 5; }

/* The key draws line segments rather than dots, because that is what it is naming - and the
   second one is dashed, so the legend carries the same distinction the chart does. The colour
   arrives as `color` rather than `background` so the repeating gradient below can use it; an
   inline `background` would have blown the gradient away. */
.bg-legend i {
  width: 16px; height: 3px; border-radius: 2px;
  background-color: currentColor;
}
.bg-legend span:first-child i { color: var(--bg-chart-1); }
.bg-legend__dash {
  background-color: transparent !important;
  background-image: repeating-linear-gradient(90deg, currentColor 0 5px, transparent 5px 9px);
}

/* Search takes the slack; the button sits on the baseline with the controls, not under them.
   Both selectors are scoped to .bg-filters so the growing one is not out-specified by the
   general one that follows it. */
.bg-filters .form-group { flex: 0 1 auto; }
.bg-filters .form-group.bg-filters__grow { flex: 1 1 240px; min-width: 180px; }
.bg-filters .form-group.bg-filters__action { margin-left: auto; }
.bg-filters__action .btn { height: 34px; }
@media (max-width: 575.98px) {
  .bg-filters { flex-direction: column; align-items: stretch; }
  .bg-filters__action { margin-left: 0; }
  .bg-filters__action .btn { width: 100%; }
}


/* ================================================================= colour pass
   The product read as one sheet of white. The ground is deeper now (see --bg-canvas), and the
   panels on it are washed rather than uniformly white.

   Nothing below moves anything. Every rule is a surface, a fill or a radius, applied through the
   class names the views already carry, so the layout, the section order and the card positions
   are exactly where they were. */

/* ---------------------------------------------------------------- the panels
   A card takes a light wash of ITS OWN icon's family, keyed off .card-ico--*, which the headers
   already carry. That is the whole reason this needs no markup: the tint is not decoration
   sprinkled over the page, it is the colour the header already chose, carried down the panel and
   fading out before the content starts.

   A red-icon card is deliberately NOT washed red. "On you now" and "Needs attention" are the two
   busiest panels on their screens, and a page with a red panel on it reads as a page with
   something wrong with it. */
.card {
  background:
    linear-gradient(180deg, var(--card-wash, var(--bg-surface)) 0%, var(--bg-surface) 190px);
  border-radius: 14px;
}
.card:has(> .card-header .card-ico)            { --card-wash: var(--bg-tint-blue); }
.card:has(> .card-header .card-ico--teal)      { --card-wash: var(--bg-tint-teal); }
.card:has(> .card-header .card-ico--amber)     { --card-wash: var(--bg-tint-warm); }
.card:has(> .card-header .card-ico--green)     { --card-wash: var(--bg-tint-mint); }
.card:has(> .card-header .card-ico--red)       { --card-wash: var(--bg-surface); }

/* The header sits on the wash, so its own hairline is all that separates it. */
.card-header { background: none; border-bottom-color: rgba(20, 35, 59, .07); }

/* The blue wash lands within 1.01:1 of the ground, which is fine for the body of the card - it
   fades to white long before the content - but it leaves the top edge with nothing to sit
   against. The border does that job now rather than the fill. */
.card, .bg-stat { border-color: #D3DCEC; }

/* A deeper ground wants a softer, wider shadow under the card, or the panel looks stuck on. */
:root {
  --bg-lift:    0 1px 2px rgba(16, 29, 56, .06), 0 10px 24px -12px rgba(16, 29, 56, .22);
  --bg-lift-hi: 0 1px 2px rgba(16, 29, 56, .07), 0 18px 36px -14px rgba(16, 29, 56, .30);
}

/* ---------------------------------------------------------------- the headline tiles
   Four unrelated primaries became one family. "In process" is the one that changed meaning as
   well as colour: it was amber, and amber is caution - but a lead running its process is a lead
   behaving normally, so it now reads as electric blue like the rest of the ladder. Red is left
   on exactly one tile, Failed, which is the only one of the four that is actually bad news.

   The radial highlight is stronger than it was and sits in the top-right, which is what gives
   these a light source rather than a flat fill. */
.bg-stat--filled {
  border-radius: 14px;
  background:
    radial-gradient(130% 110% at 100% 0%, rgba(255, 255, 255, .26) 0%, rgba(255, 255, 255, 0) 60%),
    linear-gradient(140deg, var(--tile) 0%, var(--tile-2) 100%);
}
.bg-tile-emerald { --tile: #116138; --tile-2: #13823F; }   /* white 7.52 -> 4.89 */
.bg-tile-violet  { --tile: #4C1D95; --tile-2: #6D28D9; }   /* white 10.95 -> 7.10 */

/* The note on a filled tile becomes a pill, the way the reference carries its trend chips. It is
   the same text the tile always had - no figure here is new or computed. */
/* A chip rather than a lozenge, because these notes are not all one line. "from the steps
   customers have switched on" wraps to three on a phone, and a 999px radius around three lines
   of text reads as a mistake - a 9px one reads as a chip at any height. */
.bg-stat--filled .bg-stat__note {
  display: inline-block;
  background: rgba(255, 255, 255, .16);
  border-radius: 9px;
  padding: 3px 9px;
  line-height: 1.35;
  color: #fff;
  font-weight: 600;
}
.bg-stat--filled .bg-stat__icon { background: rgba(255, 255, 255, .20); }

/* The outlined tiles get the same wash treatment as the panels, so the second row belongs to the
   first rather than looking like leftovers. */
.bg-stat:not(.bg-stat--filled) {
  border-radius: 14px;
  background: linear-gradient(170deg, var(--tint, var(--bg-tint-blue)) 0%, var(--bg-surface) 76%);
}
.bg-stat--success { --tint: var(--bg-tint-mint); }
.bg-stat--warning { --tint: var(--bg-tint-warm); }
.bg-stat--danger  { --tint: var(--bg-danger-soft); }

/* ---------------------------------------------------------------- charts
   Depth where the reference has it: the bars and the ring. The hues are untouched - every one of
   them was validated for contrast and colour-blind separation and none of that changes here. */

/* Status and ageing bars: a gradient along the bar and a rounded cap, so a measured length reads
   as a measured length rather than a block. */
.bg-funnel__bar {
  background: linear-gradient(90deg, var(--bg-ramp-3) 0%, var(--bg-chart-1) 70%, var(--bg-ramp-1) 100%);
}
.bg-funnel__track { background: rgba(16, 29, 56, .05); border-color: transparent; }
.bg-team__track   { background: rgba(16, 29, 56, .05); border-color: transparent; }
.bg-team__bar     { background: linear-gradient(90deg, var(--bg-ramp-3), var(--bg-chart-1)); }

/* A heavier ring with rounded ends, which is most of what makes the reference's donut look
   finished. The gap between segments is already a dash, so rounding the cap shortens it
   slightly - that is why the ring grows rather than just rounding. */
.bg-donut__seg       { stroke-width: 20; stroke-linecap: round; }
.bg-donut__seg:hover { stroke-width: 24; }

/* The legend rows sit on their own tint on hover, matching the card they are in. */
.bg-donut__key li:hover { background: rgba(11, 87, 199, .06); }

/* ---------------------------------------------------------------- everything else
   The radii move together or they look like two products. */
.btn, .form-control, .bg-field .form-control, .badge { border-radius: 10px; }
.badge { border-radius: 999px; }
.bg-filters { border-radius: 12px; background: rgba(255, 255, 255, .6); }
.modal-content { border-radius: 16px; }
.dropdown-menu { border-radius: 12px; }

/* The topbar is translucent over a tinted ground now, so it needs to be tinted too or it reads
   as a white bar floating above a blue page. */
.bg-topbar { background: rgba(233, 238, 248, .82); }

/* Tables inside a washed card keep a white body, so a long list is still read on white. */
.card-body.p-0 > .table { background: var(--bg-surface); }
.table thead th { background: var(--bg-surface); }

@media (max-width: 575.98px) {
  /* The wash is set in pixels from the top, so on a phone - where every card is narrow and tall -
     it has to stop sooner or it never reaches white. */
  .card { background: linear-gradient(180deg, var(--card-wash, var(--bg-surface)) 0%, var(--bg-surface) 120px); }
}

/* ---- long lists, capped.
   See Dashboard.capRows(). The hidden rows stay in the document so opening them costs nothing;
   this is the only thing that makes them hidden. */
.bg-rowcap__hidden { display: none; }
.bg-rowcap {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  padding: 12px 16px;
  border-top: 1px solid var(--bg-line);
  background: var(--bg-surface-2);
}
.bg-rowcap__count { font-size: .78rem; color: var(--bg-text-faint); }


/* ================================================================= charts and bars
   The bar lists were thirteen identical rows: one colour, one weight, a long grey slot behind
   each, and the figure parked at the far right of it. Length was the only thing doing any work.

   What changed, and what deliberately did not: colour now carries rank as well as length, but
   ONLY in the two lists that are actually ordered by size. The drop-off funnel under Stage is in
   ladder order across two processes (10, 8, 4, 19 ...), so a ramp down it would be reading a
   ranking into a sequence that has none, and it keeps the single brand gradient. */

/* ---- the bar itself. Thicker, fully rounded, and on a track that is barely there - thirteen
   empty slots at 5% ink was most of what made the panel look like a form. */
.bg-funnel__row   { padding: 6px 0; border-radius: 8px; transition: background .12s ease; }
.bg-funnel__row:hover { background: rgba(11, 87, 199, .045); }
.bg-funnel__track { height: 12px; background: rgba(16, 29, 56, .035); }
.bg-funnel__bar   { border-radius: 999px; }

/* More of the row goes to the bar: the name column was a third of it, and a status name is two
   words. */
.bg-funnel__name  { flex-basis: 29%; }
.bg-funnel__count { flex-basis: 76px; }
.bg-funnel__count em,
.bg-funnel__late  { font-size: .68rem; }

/* ---- rank, in two lists that are sorted by it.
   Lead status is ORDER BY leads DESC and Team performance is ordered the same way, so position
   in the list IS the ranking - and fading the bar down the list says the same thing the length
   says, twice. Redundant encoding on purpose: it survives being printed in grey, and it gives a
   thirteen-row list a shape you can read without comparing ends.
   Written general-to-specific so any row count works, not just thirteen. */
#anStatuses .bg-funnel__bar,
#anTeam     .bg-team__bar                                     { opacity: .58; }
#anStatuses .bg-funnel__row:nth-child(-n+10) .bg-funnel__bar,
#anTeam     .bg-team li:nth-child(-n+10) .bg-team__bar        { opacity: .68; }
#anStatuses .bg-funnel__row:nth-child(-n+8)  .bg-funnel__bar,
#anTeam     .bg-team li:nth-child(-n+8)  .bg-team__bar        { opacity: .78; }
#anStatuses .bg-funnel__row:nth-child(-n+6)  .bg-funnel__bar,
#anTeam     .bg-team li:nth-child(-n+6)  .bg-team__bar        { opacity: .88; }
#anStatuses .bg-funnel__row:nth-child(-n+3)  .bg-funnel__bar,
#anTeam     .bg-team li:nth-child(-n+3)  .bg-team__bar        { opacity: 1; }

/* ---- ageing runs the other way, and means something else.
   Its four rows are bands in time order, not a ranking, so the ramp is the band itself: fresh
   leads light, stale leads dark. That is the one list here where the colour is the measurement
   rather than a second opinion about the length. */
#anAgeing .bg-funnel__row:nth-child(1) .bg-funnel__bar { background: var(--bg-ramp-1); }
#anAgeing .bg-funnel__row:nth-child(2) .bg-funnel__bar { background: var(--bg-ramp-2); }
#anAgeing .bg-funnel__row:nth-child(3) .bg-funnel__bar { background: var(--bg-ramp-4); }
#anAgeing .bg-funnel__row:nth-child(4) .bg-funnel__bar { background: var(--bg-ramp-5); }

/* ---- the line chart.
   A soft shadow in the series' own colour, so the line sits above its grid rather than in it.
   Kept small: a line that glows stops being a measurement. */
.bg-chart__line { filter: drop-shadow(0 2px 3px rgba(12, 130, 134, .28)); }
.bg-chart__line--alt { filter: drop-shadow(0 2px 3px rgba(180, 83, 9, .22)); }
.bg-chart__dot { filter: drop-shadow(0 1px 2px rgba(16, 29, 56, .25)); }

/* The revenue columns are deliberately left alone. rx on a <rect> rounds all four corners, and
   this file already decided the other way - "the bar grows from the axis, so the end that
   carries the value is the one that gets the radius". Rounding the foot would lift the column
   off its own baseline. */

/* ---- the donut's key, as rows that line up with the ring. */
.bg-donut__key li { padding: .34rem .45rem; }
.bg-donut__key i  { width: 11px; height: 11px; border-radius: 3px; }

/* 29% of a phone is about 90px, and "Quotation Sent" arrives as "Quotation S...". The bar can
   spare the room there - it is the only thing on the row that scales. */
@media (max-width: 575.98px) {
  .bg-funnel__name  { flex-basis: 38%; }
  /* Sized to its own content rather than to a guess: a fixed basis wide enough for "4 not
     started" steals room from the name, and one narrow enough for the name wraps the sub-label.
     Letting it be as wide as it needs to be settles both. */
  .bg-funnel__count { flex-basis: auto; white-space: nowrap; }
}

@media (prefers-reduced-motion: reduce) {
  .bg-funnel__row { transition: none; }
}

/* The folded "Other" row in Where the leads are: a real count, but not a place, so it reads as
   the remainder rather than as the seventh city. */
#anCities .bg-funnel__row.is-rest .bg-funnel__name { color: var(--bg-text-faint); font-style: italic; }
#anCities .bg-funnel__row.is-rest .bg-funnel__bar  { background: var(--bg-ramp-rest); }


/* ================================================================= the process chain
   The dashboard draws its stages with the same .proc-step-card as the process builder, so the
   two read as one thing. The group heading above each chain is all that is still needed here;
   the old clip-path chevron rules went when the markup did. */

.proc-flow__group + .proc-flow__group { margin-top: 18px; }

.proc-flow__label {
  display: flex; align-items: baseline; gap: .5rem;
  font-size: .78rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  color: var(--bg-text-soft);
  margin-bottom: 8px;
}
.proc-flow__label span {
  font-weight: 500; letter-spacing: 0; text-transform: none;
  font-size: .76rem; color: var(--bg-text-faint);
}

@media (prefers-reduced-motion: reduce) {
  .proc-card, .proc-card:hover,
  .proc-def__card, .proc-def__card:hover, .proc-def__chev,
  .proc-step-card, .proc-step-card:hover { transition: none; transform: none; }
}
/* ==== Process Workflow UI Improvements ==== */
/* A step in the standard process, shown as written. Not a link: an unset step has no leads
   to open, and switching it on is a priced decision that belongs in Product Setting. */
.proc-step-card--def { cursor: default; }
.proc-step-card--def:hover { transform: none; box-shadow: 0 2px 6px rgba(0,0,0,.08); border-color: var(--bg-line); }

/* Not switched on here: still legible, clearly not live. Carries the badge as well as the
   fade, so it never depends on colour alone. */
.proc-step-card--def.is-off { opacity: .62; }
.proc-step-card--def.is-off .proc-step-header { filter: grayscale(.65); }

.proc-step-task {
  font-size: .78rem;
  color: var(--bg-text-soft);
  margin-bottom: 6px;
}

.proc-step-card__name { font-weight: 600; line-height: 1.25; }

.proc-card {
  border: 2px solid var(--bg-line);
  transition: box-shadow .2s ease, border-color .2s ease, transform .2s ease;
}

.proc-card:hover {
  box-shadow: 0 4px 12px rgba(11, 87, 199, .25);
  border-color: var(--bg-accent);
  transform: translateY(-2px);
}

.proc-card__header {
  background: linear-gradient(135deg, var(--bg-accent) 0%, var(--bg-accent-dark) 100%);
  color: #fff;
  border-bottom: none;
  padding: 12px 14px;
  border-radius: 6px 6px 0 0;
}

.proc-flow {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  gap: 8px;
  padding: 16px 8px;
  align-items: stretch;
}

.proc-step-card {
  flex: 0 0 240px;
  min-width: 200px;
  background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  border: 2px solid #e3e6f0;
  border-radius: 10px;
  box-shadow: 0 2px 6px rgba(0,0,0,0.08);
  transition: all 0.25s ease;
  cursor: pointer;
  position: relative;
  margin-right: 20px;
}

.proc-step-card:hover {
  box-shadow: 0 4px 12px rgba(78, 115, 223, 0.25);
  border-color: #4e73df;
  transform: translateY(-4px) scale(1.02);
  z-index: 10;
}

.proc-step-card:after {
  content: "\2192";
  position: absolute;
  right: -24px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 24px;
  font-weight: bold;
  color: #4e73df;
  z-index: 5;
}

.proc-step-card:last-child:after {
  display: none;
}

.proc-step-header {
  background: linear-gradient(135deg, #4e73df 0%, #224abe 100%);
  color: white;
  padding: 12px 14px;
  border-radius: 8px 8px 0 0;
  font-weight: 600;
  font-size: 0.95rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.proc-step-body {
  padding: 12px 14px;
  color: #5a5c69;
  font-size: 0.85rem;
  min-height: 70px;
}

.proc-step-num {
  background: rgba(255,255,255,0.25);
  border-radius: 50%;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.85rem;
}

.proc-subproc-container {
  margin-top: 12px;
  padding: 4px 12px 12px;
  background: linear-gradient(135deg, var(--bg-surface-2) 0%, var(--bg-canvas) 100%);
  border-radius: 10px;
  border: 2px dashed var(--bg-line-strong);
}

/* A standard process, as one card you open. Clicking it reveals its steps below. */
.proc-def + .proc-def { margin-top: 14px; }

.proc-def__card {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 14px 16px;
  text-align: left;
  color: #fff;
  border: 0;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--bg-ink-2) 0%, var(--bg-ink) 100%);
  box-shadow: 0 2px 8px rgba(11, 31, 69, .18);
  transition: box-shadow .2s ease, transform .2s ease;
  cursor: pointer;
}

.proc-def__card:hover {
  box-shadow: 0 5px 16px rgba(11, 31, 69, .28);
  transform: translateY(-2px);
}

.proc-def__card:focus-visible {
  outline: 3px solid var(--bg-accent);
  outline-offset: 2px;
}

.proc-def__ico {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px;
  border-radius: 9px;
  background: rgba(255, 255, 255, .16);
  font-size: 1rem;
}

.proc-def__text  { display: flex; flex-direction: column; min-width: 0; }
.proc-def__name  { font-weight: 700; font-size: .98rem; line-height: 1.25; }
.proc-def__meta  { font-size: .76rem; opacity: .82; }

.proc-def__chev {
  margin-left: auto;
  transition: transform .2s ease;
}
.proc-def__card.is-open .proc-def__chev { transform: rotate(180deg); }

/* The card you are reading about, and the button that opens it. */
.proc-step-card.is-selected {
  border-color: var(--bg-brand-teal);
  box-shadow: 0 0 0 3px rgba(10, 117, 113, .25);
}

.proc-step-info {
  min-width: 44px;
  min-height: 44px;
  padding: 0 10px;
  border: 0;
  border-radius: 6px;
  background: rgba(255, 255, 255, .18);
  color: #fff;
  font-size: .95rem;
  cursor: pointer;
}

.proc-step-info:hover  { background: rgba(255, 255, 255, .32); }
.proc-step-info:focus-visible,
.proc-step-card:focus-within {
  outline: 3px solid var(--bg-accent);
  outline-offset: 2px;
}

.proc-details-panel {
  margin-top: 16px;
  background: var(--bg-surface);
  border: 2px solid var(--bg-brand-teal);
  border-radius: 10px;
  box-shadow: 0 2px 8px rgba(10, 117, 113, .15);
  overflow: hidden;
}

.proc-details-header {
  background: linear-gradient(135deg, var(--bg-brand-teal) 0%, #065754 100%);
  color: white;
  padding: 12px 16px;
  font-weight: 600;
  font-size: 0.95rem;
}

.proc-details-body {
  padding: 14px 16px;
}

.proc-details-row {
  margin-bottom: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--bg-line);
  font-size: 0.85rem;
}

.proc-details-row:last-child {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
}

.proc-details-label {
  font-weight: 600;
  color: var(--bg-text);
  margin-right: 6px;
}

.proc-details-value {
  color: var(--bg-text-soft);
}

.proc-flow-container {
  position: relative;
  padding: 20px 10px;
}

@media (max-width: 768px) {
  .proc-flow {
    flex-direction: column;
    overflow-x: visible;
  }
  .proc-step-card {
    flex: 1 1 auto;
    margin-right: 0;
    margin-bottom: 30px;
  }
  .proc-step-card:after {
    content: "\2193";
    right: 50%;
    top: auto;
    bottom: -28px;
    transform: translateX(50%);
    font-size: 24px;
  }
  .proc-step-card:last-child {
    margin-bottom: 0;
  }
  .proc-step-card:last-child:after {
    display: none;
  }
  .proc-subproc-card {
    flex: 1 1 100%;
    max-width: 100%;
  }
}
