/* =========================================================================
   beautiful.css — BridgeBI design layer
   =========================================================================

   Ported from the component study at https://beautiful-ui-five.vercel.app
   (turbodesign.co). What was taken is the CRAFT, not the palette:

     1. A LAYERED SURFACE SCALE. page < canvas < surface < inset, plus two
        hover steps and three ink weights. Every panel picks a layer instead
        of inventing a grey. This is the single biggest reason that reference
        UI reads as one system and BridgeBI's older cards do not.
     2. HAIRLINE-FIRST SHADOWS. Every elevation starts with `0 0 0 1px line`
        and only then adds blur. A 1px ring reads crisp at any zoom where a
        blurred shadow reads muddy — so borders and shadows are ONE token,
        never two competing declarations.
     3. A THREE-STOP RADIUS SCALE. chip 6 / control 8 / card 10. Nothing else.
        Pills are reserved for toggles and status capsules, never for tags —
        DESIGN.md already says flag tags are 6px, and this keeps that honest.
     4. COLOR-MIX TAGS. A tag takes ONE colour and derives its text, fill and
        border from it against the current surface, so the same markup works
        in light and dark with no second palette.

   The colours themselves stay Northbridge: navy #0D2A5E, gold #C9A43F, warm
   off-white #F5F3EE. The dark theme is a deep navy-black built from the same
   hues, not a neutral grey — so it still reads as Northbridge with the lights
   off.

   NAMESPACING. Everything here is `--bb-*` (tokens) or `.bb-*` (components).
   index.html carries ~50k lines with its own `--navy` / `.card` / `.stat-card`
   vocabulary; a shared name would have this file silently restyling surfaces
   nobody asked it to touch. The one deliberate exception is the CRAFT PASS at
   the bottom, which upgrades existing chrome on purpose and is fenced off in
   its own section.

   THEME. `html[data-bb-theme="dark"|"light"]` — set by beautiful.js before
   first paint. Absent the attribute the light palette applies, so an old cache
   or a JS failure still renders the app it always rendered.
   ========================================================================= */

/* =========================================================================
   1. TOKENS — light (default)
   ========================================================================= */

:root {
  /* --- surfaces, back to front ------------------------------------------ */
  --bb-page:        #F5F3EE;   /* app background, behind everything */
  --bb-canvas:      #EFEDE6;   /* a well/recess inside the page */
  --bb-surface:     #FFFFFF;   /* cards, tables, menus */
  --bb-inset:       #FAF9F6;   /* a well inside a surface (footers, code) */
  --bb-hover:       #F4F2EC;   /* row / item hover */
  --bb-hover-2:     #E7E3D8;   /* pressed, or hover on an already-tinted row */

  /* --- ink, heaviest to lightest --------------------------------------- */
  --bb-ink:         #1A1A1A;   /* primary text */
  --bb-ink-2:       #5A564F;   /* secondary text, table headers */
  --bb-ink-3:       #8A8578;   /* captions, placeholders, disabled */

  /* --- lines ----------------------------------------------------------- */
  --bb-line:        #E6E1D8;   /* default hairline */
  --bb-line-strong: #D4CFC4;   /* a line that has to survive on a tint */

  /* --- fields ---------------------------------------------------------- */
  --bb-field:       #F1EFE8;   /* input / select fill */
  --bb-stripe:      rgba(13, 42, 94, .035);
  --bb-stripe-bg:   #F7F5F0;

  /* --- accents --------------------------------------------------------- */
  --bb-accent:      #0D2A5E;   /* Northbridge navy — the interactive colour */
  --bb-accent-ink:  #11326D;   /* navy on a tint (link text) */
  --bb-accent-tint: #EAEFF8;
  --bb-gold:        #C9A43F;   /* brand highlight, never a link */
  --bb-gold-ink:    #A8842C;
  --bb-gold-tint:   #FBF4E2;

  /* --- status ---------------------------------------------------------- */
  --bb-green:       #2E7D52;  --bb-green-tint:  #E9F3ED;
  --bb-orange:      #C77D1B;  --bb-orange-tint: #FBF2E3;
  --bb-red:         #B23B3B;  --bb-red-tint:    #F9EBEB;
  --bb-cyan:        #16788F;  --bb-cyan-tint:   #E5F1F4;
  --bb-violet:      #6B4FA8;  --bb-violet-tint: #F0EBF9;

  /* --- tooltips (always the dark treatment, both themes) --------------- */
  --bb-tip-bg:      #12283C;
  --bb-tip-fg:      #F5F3EE;
  --bb-tip-muted:   #9AA8B8;
  --bb-tip-line:    #24405C;

  /* --- elevation. hairline first, blur second -------------------------- */
  --bb-sh-hairline:   0 0 0 1px var(--bb-line);
  --bb-sh-btn:        0 0 0 1px var(--bb-line-strong), 0 1px 2px rgba(13, 42, 94, .05);
  --bb-sh-card:       0 0 0 1px var(--bb-line), 0 1px 2px rgba(13, 42, 94, .04), 0 2px 6px rgba(13, 42, 94, .035);
  --bb-sh-raised:     0 0 0 1px var(--bb-line), 0 2px 10px rgba(13, 42, 94, .05);
  --bb-sh-overlay:    0 0 0 1px var(--bb-line), 0 8px 28px rgba(13, 42, 94, .10);
  --bb-sh-inset:      inset 0 1px 2px rgba(13, 42, 94, .10);
  --bb-sh-focus:      0 0 0 2px var(--bb-page), 0 0 0 4px color-mix(in srgb, var(--bb-accent) 45%, transparent);

  /* --- radii. three stops, nothing else -------------------------------- */
  --bb-r-chip:    6px;
  --bb-r-control: 8px;
  --bb-r-card:    10px;

  /* --- motion ---------------------------------------------------------- */
  --bb-ease-strong: cubic-bezier(.23, 1, .32, 1);   /* enters, pops */
  --bb-ease-link:   cubic-bezier(.16, 1, .30, 1);   /* underlines, slides */
  --bb-t-fast:      .12s;
  --bb-t-base:      .16s;
  --bb-t-slow:      .28s;
}

/* =========================================================================
   2. TOKENS — dark
   -------------------------------------------------------------------------
   Deep navy-black, not neutral grey: every surface keeps a trace of #0D2A5E's
   hue so gold and navy still look like they belong to it. Accents brighten
   because navy-on-navy has no contrast — the interactive colour becomes a lit
   blue while gold stays the brand highlight.
   ========================================================================= */

html[data-bb-theme="dark"] {
  --bb-page:        #0B1220;
  --bb-canvas:      #0E1626;
  --bb-surface:     #131C2E;
  --bb-inset:       #101828;
  --bb-hover:       #1A2438;
  --bb-hover-2:     #223047;

  --bb-ink:         #EEF1F6;
  --bb-ink-2:       #A3AEC0;
  --bb-ink-3:       #6C7890;

  --bb-line:        #1F2B3F;
  --bb-line-strong: #2B3A52;

  --bb-field:       #172134;
  --bb-stripe:      rgba(255, 255, 255, .045);
  --bb-stripe-bg:   #0F1727;

  --bb-accent:      #6FA8F5;
  --bb-accent-ink:  #9CC5FF;
  --bb-accent-tint: rgba(111, 168, 245, .16);
  --bb-gold:        #D8B65A;
  --bb-gold-ink:    #E8CE84;
  --bb-gold-tint:   rgba(216, 182, 90, .16);

  --bb-green:       #3FBE7A;  --bb-green-tint:  rgba(63, 190, 122, .16);
  --bb-orange:      #F0A044;  --bb-orange-tint: rgba(240, 160, 68, .16);
  --bb-red:         #EF6B6B;  --bb-red-tint:    rgba(239, 107, 107, .16);
  --bb-cyan:        #45C3DC;  --bb-cyan-tint:   rgba(69, 195, 220, .16);
  --bb-violet:      #A78BE0;  --bb-violet-tint: rgba(167, 139, 224, .16);

  --bb-tip-bg:      #060B14;
  --bb-tip-fg:      #EEF1F6;
  --bb-tip-muted:   #8894A8;
  --bb-tip-line:    #1F2B3F;

  --bb-sh-btn:      0 0 0 1px var(--bb-line-strong), 0 1px 2px rgba(0, 0, 0, .35);
  --bb-sh-card:     0 0 0 1px var(--bb-line), 0 1px 2px rgba(0, 0, 0, .25), 0 2px 6px rgba(0, 0, 0, .22);
  --bb-sh-raised:   0 0 0 1px var(--bb-line), 0 2px 10px rgba(0, 0, 0, .30);
  --bb-sh-overlay:  0 0 0 1px var(--bb-line-strong), 0 8px 28px rgba(0, 0, 0, .45);
  --bb-sh-inset:    inset 0 1px 2px rgba(0, 0, 0, .40);
  --bb-sh-focus:    0 0 0 2px var(--bb-page), 0 0 0 4px color-mix(in srgb, var(--bb-accent) 55%, transparent);
}

/* Colour-scheme hint so native widgets (scrollbars, date pickers, the caret)
   follow the theme. Without this a dark page still gets a white scrollbar. */
html[data-bb-theme="dark"]  { color-scheme: dark; }
html[data-bb-theme="light"] { color-scheme: light; }

/* =========================================================================
   3. KEYFRAMES
   ========================================================================= */

@keyframes bb-pop-in     { from { opacity: 0; transform: scale(.95); }        to { opacity: 1; transform: scale(1); } }
@keyframes bb-fade-up    { from { opacity: 0; transform: translateY(8px); }   to { opacity: 1; transform: translateY(0); } }
@keyframes bb-fade-in    { from { opacity: 0; }                                to { opacity: 1; } }
@keyframes bb-stream-in  { from { opacity: 0; filter: blur(4px); }            to { opacity: 1; filter: blur(0); } }
@keyframes bb-caret      { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
@keyframes bb-spin       { to { transform: rotate(360deg); } }
@keyframes bb-shimmer    { from { background-position: 150% 0; } to { background-position: -50% 0; } }
@keyframes bb-pixel      { 0%, 100% { opacity: .15; } 18%, 42% { opacity: 1; } 62% { opacity: .15; } }
@keyframes bb-eq         { 0%, 100% { transform: scaleY(.35); } 50% { transform: scaleY(1); } }
@keyframes bb-slide-up   { from { opacity: 0; transform: translate(-50%, 10px); } to { opacity: 1; transform: translate(-50%, 0); } }

@media (prefers-reduced-motion: reduce) {
  .bb-shimmer, .bb-pix i, .bb-caret, .bb-eq i, .bb-spinner {
    animation: none !important;
  }
}

/* =========================================================================
   4. PRIMITIVES — buttons, fields, chips, keys
   ========================================================================= */

.bb-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 30px; padding: 0 11px;
  border: 0; border-radius: var(--bb-r-control);
  background: var(--bb-surface); color: var(--bb-ink);
  box-shadow: var(--bb-sh-btn);
  font: 500 12.5px/1 inherit; cursor: pointer;
  transition: background-color var(--bb-t-fast) ease-out,
              box-shadow var(--bb-t-fast) ease-out,
              transform var(--bb-t-fast) var(--bb-ease-strong);
}
.bb-btn:hover  { background: var(--bb-hover); }
.bb-btn:active { transform: scale(.975); }
.bb-btn:focus-visible { outline: 0; box-shadow: var(--bb-sh-btn), var(--bb-sh-focus); }
.bb-btn[disabled] { opacity: .5; cursor: not-allowed; }

.bb-btn.is-primary {
  background: var(--bb-accent); color: #fff;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--bb-accent) 70%, #000), 0 1px 2px rgba(13, 42, 94, .18);
}
.bb-btn.is-primary:hover { background: color-mix(in srgb, var(--bb-accent) 88%, #000); }
html[data-bb-theme="dark"] .bb-btn.is-primary { color: #08111F; }

.bb-btn.is-quiet { background: transparent; box-shadow: none; color: var(--bb-ink-2); }
.bb-btn.is-quiet:hover { background: var(--bb-hover); color: var(--bb-ink); }

.bb-btn.is-danger { color: var(--bb-red); box-shadow: 0 0 0 1px color-mix(in srgb, var(--bb-red) 32%, var(--bb-surface)); background: var(--bb-red-tint); }
.bb-btn.is-danger:hover { background: color-mix(in srgb, var(--bb-red) 20%, var(--bb-surface)); }

/* Square icon button — 28px is the reference's control height for a bare icon. */
.bb-iconbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  border: 0; border-radius: var(--bb-r-control);
  background: transparent; color: var(--bb-ink-2); cursor: pointer;
  transition: background-color var(--bb-t-fast) ease-out, color var(--bb-t-fast) ease-out,
              transform var(--bb-t-fast) var(--bb-ease-strong);
}
.bb-iconbtn:hover  { background: var(--bb-hover); color: var(--bb-ink); }
.bb-iconbtn:active { transform: scale(.94); }
.bb-iconbtn:focus-visible { outline: 0; box-shadow: var(--bb-sh-focus); }
.bb-iconbtn svg { width: 15px; height: 15px; flex: none; }

.bb-field {
  width: 100%; height: 32px; padding: 0 10px;
  border: 0; border-radius: var(--bb-r-control);
  background: var(--bb-field); color: var(--bb-ink);
  box-shadow: var(--bb-sh-inset);
  font: 400 12.5px/1 inherit;
  transition: box-shadow var(--bb-t-fast) ease-out;
}
.bb-field::placeholder { color: var(--bb-ink-3); }
.bb-field:focus { outline: 0; box-shadow: var(--bb-sh-inset), var(--bb-sh-focus); }

.bb-kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 5px;
  border-radius: var(--bb-r-chip);
  background: var(--bb-surface); color: var(--bb-ink-3);
  box-shadow: var(--bb-sh-hairline);
  font: 500 11px/1 'JetBrains Mono', ui-monospace, monospace;
}

/* Underline that grows from the left on hover — cheap, and it makes plain
   text links feel deliberate instead of default-blue. */
.bb-ul { display: inline-block; position: relative; }
.bb-ul::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: 0 50%;
  transition: transform var(--bb-t-slow) var(--bb-ease-link);
}
a:hover .bb-ul::after, a:focus-visible .bb-ul::after,
.bb-ul:hover::after { transform: scaleX(1); }

/* Scroll container with no visible bar and a fade at the bottom edge, so a
   long list reads as "there is more" without a scrollbar rail. */
.bb-scroll { scrollbar-width: none; -ms-overflow-style: none; overscroll-behavior: contain; }
.bb-scroll::-webkit-scrollbar { display: none; }
.bb-scroll.is-masked {
  -webkit-mask-image: linear-gradient(#000 0 calc(100% - 3rem), transparent 100%);
          mask-image: linear-gradient(#000 0 calc(100% - 3rem), transparent 100%);
}

/* =========================================================================
   5. TAGS + STATUS CHIPS
   -------------------------------------------------------------------------
   One custom property (`--tag`) drives text, fill and border. That is what
   lets the SAME tag markup survive a theme flip: the mix is against
   `--bb-surface`, which moved, so the tag moves with it.
   ========================================================================= */

.bb-tags { display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; }

.bb-tag {
  --tag: var(--bb-ink-2);
  display: inline-flex; align-items: center; flex-shrink: 0;
  max-width: 160px; height: 23px; padding: 0 7px;
  border: 1px solid color-mix(in srgb, var(--tag) 24%, var(--bb-surface));
  border-radius: var(--bb-r-chip);
  background: color-mix(in srgb, var(--tag) 13%, var(--bb-surface));
  color: color-mix(in srgb, var(--tag) 82%, var(--bb-ink));
  font: 500 11px/1 inherit;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bb-tag::before {
  content: ''; flex: 0 0 5px; width: 5px; height: 5px; margin-right: 5px;
  border-radius: 50%; background: var(--tag);
}
.bb-tag.no-dot::before { display: none; }
.bb-tag.is-strong { background: color-mix(in srgb, var(--tag) 22%, var(--bb-surface)); }

.bb-tag.t-navy   { --tag: var(--bb-accent); }
.bb-tag.t-gold   { --tag: var(--bb-gold); }
.bb-tag.t-green  { --tag: var(--bb-green); }
.bb-tag.t-orange { --tag: var(--bb-orange); }
.bb-tag.t-red    { --tag: var(--bb-red); }
.bb-tag.t-cyan   { --tag: var(--bb-cyan); }
.bb-tag.t-violet { --tag: var(--bb-violet); }
.bb-tag.t-grey   { --tag: var(--bb-ink-3); }

/* "+2" overflow tag — deliberately colourless so it never competes with a
   real tag for attention. */
.bb-tag-more {
  display: inline-flex; align-items: center; flex-shrink: 0;
  height: 23px; padding: 0 7px;
  border: 1px solid var(--bb-line-strong); border-radius: var(--bb-r-chip);
  background: var(--bb-inset); color: var(--bb-ink-3);
  font: 500 11px/1 inherit;
}

/* Filter chip row: label + count, the count in a recessed pill. The active
   chip is the only one with a surface. */
.bb-chips { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }
.bb-chip {
  display: inline-flex; align-items: center; gap: 7px;
  height: 30px; padding: 0 11px;
  border: 0; border-radius: 99px;
  background: transparent; color: var(--bb-ink-2);
  font: 500 12.5px/1 inherit; cursor: pointer;
  transition: background-color var(--bb-t-fast) ease-out, color var(--bb-t-fast) ease-out;
}
.bb-chip:hover { background: var(--bb-hover); color: var(--bb-ink); }
.bb-chip.is-active {
  background: var(--bb-surface); color: var(--bb-ink);
  box-shadow: var(--bb-sh-btn);
}
.bb-chip .bb-chip-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.bb-chip .bb-chip-n {
  color: var(--bb-ink-3); font: 500 11.5px/1 'JetBrains Mono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
}
.bb-chip.is-active .bb-chip-n {
  padding: 2px 5px; border-radius: var(--bb-r-chip);
  background: var(--bb-field); color: var(--bb-ink-2);
}

/* Segmented control — the "Capsules | List" toggle. */
.bb-seg {
  display: inline-flex; align-items: center; gap: 2px; padding: 3px;
  border-radius: 99px; background: var(--bb-field);
}
.bb-seg button {
  height: 26px; padding: 0 13px; border: 0; border-radius: 99px;
  background: transparent; color: var(--bb-ink-3);
  font: 500 12px/1 inherit; cursor: pointer;
  transition: background-color var(--bb-t-fast) ease-out, color var(--bb-t-fast) ease-out;
}
.bb-seg button:hover { color: var(--bb-ink-2); }
.bb-seg button.is-active { background: var(--bb-surface); color: var(--bb-ink); box-shadow: var(--bb-sh-btn); }

/* 20px monogram square used in front of a name. */
.bb-mark {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 20px; width: 20px; height: 20px;
  border-radius: var(--bb-r-chip);
  background: var(--bb-field); color: var(--bb-ink-2);
  font: 650 10px/1 inherit; text-transform: uppercase;
}

.bb-dot { display: inline-block; flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; }
.bb-dot.d-green  { background: var(--bb-green); }
.bb-dot.d-orange { background: var(--bb-orange); }
.bb-dot.d-red    { background: var(--bb-red); }
.bb-dot.d-cyan   { background: var(--bb-cyan); }
.bb-dot.d-grey   { background: var(--bb-ink-3); }

/* =========================================================================
   6. SHELL + TOOLBAR + DATA GRID
   -------------------------------------------------------------------------
   The reference's records table, ported. Three sticky planes cooperate:
   thead (top), the first column (left), and tfoot (bottom). Their z-indexes
   are NOT arbitrary — the corner cells must outrank both planes they belong
   to or they get painted over while scrolling diagonally:

       tfoot sticky first cell  6   <- corner, bottom-left
       thead sticky first cell  7   <- corner, top-left
       thead th                 5
       tfoot td                 4
       body sticky first cell   2

   Every numeric cell is JetBrains Mono + tabular-nums, per DESIGN.md.
   ========================================================================= */

.bb-shell {
  width: 100%; min-width: 0; overflow: hidden;
  border-radius: var(--bb-r-card);
  background: var(--bb-surface);
  box-shadow: var(--bb-sh-card);
}

.bb-toolbar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 52px; padding: 8px 10px;
  border-bottom: 1px solid var(--bb-line-strong);
  background: var(--bb-surface);
}
.bb-toolbar-l, .bb-toolbar-r { display: inline-flex; align-items: center; gap: 4px; }
.bb-toolbar-r { flex-shrink: 0; }
.bb-toolbar-title { font: 600 13px/1.2 inherit; color: var(--bb-ink); margin-right: 6px; }

.bb-grid-scroll { width: 100%; overflow: auto; }

.bb-grid {
  width: 100%; border-collapse: separate; border-spacing: 0;
  table-layout: fixed; font-size: 12px; color: var(--bb-ink);
}
.bb-grid th, .bb-grid td {
  text-align: left; vertical-align: middle;
  border-right:  1px solid color-mix(in srgb, var(--bb-line) 78%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--bb-line) 78%, transparent);
}
.bb-grid tr > :last-child { border-right: 0; }

.bb-grid thead th {
  position: sticky; top: 0; z-index: 5;
  height: 42px; padding: 0;
  background: var(--bb-surface); color: var(--bb-ink-2);
  font: 600 12px/1 inherit;
}
.bb-grid thead th.bb-sticky-cell { z-index: 7; }

/* Header cells are buttons so sorting is keyboard-reachable. The sort arrow
   is hidden until hover/active — a column of always-visible arrows is noise. */
.bb-hbtn {
  display: inline-flex; align-items: center; gap: 6px;
  width: 100%; height: 42px; padding: 0 12px;
  border: 0; background: transparent; color: inherit;
  font: inherit; text-align: left; cursor: pointer;
  transition: background-color var(--bb-t-fast) ease-out;
}
.bb-hbtn:hover { background: var(--bb-hover); }
.bb-hbtn .bb-sort {
  display: inline-flex; margin-left: auto; flex-shrink: 0; opacity: 0;
  transition: opacity var(--bb-t-fast) ease-out, transform var(--bb-t-base) var(--bb-ease-strong);
}
.bb-hbtn:hover .bb-sort, .bb-sort.is-visible { opacity: 1; }
.bb-sort.is-desc { transform: rotate(180deg); }
.bb-hbtn .bb-hicon { width: 13px; height: 13px; color: var(--bb-ink-3); flex: none; }

.bb-cell {
  height: 42px; padding: 0 12px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bb-cell.is-num {
  text-align: right;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
}
.bb-cell.is-num.pos { color: var(--bb-green); }
.bb-cell.is-num.neg { color: var(--bb-red); }

/* Sticky first column. The right-edge shadow is a one-sided spread trick:
   a negative blur radius clips the shadow to the right side only, so the
   column casts onto the scrolling body without a halo above and below. */
.bb-sticky-cell {
  position: sticky; left: 0; z-index: 2;
  background: var(--bb-surface);
  box-shadow: 5px 0 8px -10px rgba(0, 0, 0, .4);
}

.bb-row > .bb-cell {
  transition: background-color var(--bb-t-fast) ease-out, color var(--bb-t-fast) ease-out;
}
.bb-row:hover > .bb-cell { background: var(--bb-hover); }
.bb-row.is-selected > .bb-cell { background: color-mix(in srgb, var(--bb-accent) 7%, var(--bb-surface)); }
.bb-grid tbody tr:last-child > td { border-bottom: 0; }

/* Zebra is opt-in per table: `.bb-grid.is-striped`. */
.bb-grid.is-striped tbody tr:nth-child(2n) > .bb-cell { background: var(--bb-stripe); }
.bb-grid.is-striped tbody tr:nth-child(2n):hover > .bb-cell { background: var(--bb-hover); }

/* tfoot = the calculation row. Recessed, sticky to the bottom, numbers in
   mono — it reads as a summary plane, not as one more data row. */
.bb-grid tfoot td {
  position: sticky; bottom: 0; z-index: 4;
  height: 38px; padding: 0 12px;
  background: var(--bb-inset); color: var(--bb-ink-2);
  font-size: 11.5px;
}
.bb-grid tfoot .bb-sticky-cell { z-index: 6; background: var(--bb-inset); }
.bb-calc-label  { color: var(--bb-ink-2); font-weight: 550; }
.bb-calc-number {
  color: var(--bb-ink); margin-right: 3px;
  font-family: 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums;
}

.bb-shell-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 38px; padding: 0 12px;
  color: var(--bb-ink-3); font-size: 11.5px;
}
.bb-shell-foot strong { color: var(--bb-ink-2); font-weight: 600; }
/* A hint that only appears while the pointer is in the shell. Keeps the
   resting state clean but still teaches the shortcut. */
.bb-shell-foot .bb-hint {
  display: inline-flex; align-items: center; gap: 5px; opacity: 0;
  transition: opacity var(--bb-t-base) ease-out;
}
.bb-shell:hover .bb-shell-foot .bb-hint { opacity: 1; }

/* Checkbox with a real input behind it, so focus and label clicks work. */
.bb-check { display: inline-flex; position: relative; cursor: pointer; }
.bb-check input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.bb-check-box {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px;
  border: 1px solid var(--bb-line-strong); border-radius: var(--bb-r-chip);
  background: var(--bb-surface); color: transparent;
  transition: border-color var(--bb-t-base) ease-out, background-color var(--bb-t-base) ease-out,
              transform var(--bb-t-base) var(--bb-ease-strong);
}
.bb-check:hover .bb-check-box  { background: var(--bb-hover); }
.bb-check:active .bb-check-box { transform: scale(.96); }
.bb-check input:focus-visible + .bb-check-box { outline: 2px solid var(--bb-accent); outline-offset: 2px; }
.bb-check input:checked + .bb-check-box {
  background: var(--bb-accent); border-color: var(--bb-accent); color: #fff;
}
html[data-bb-theme="dark"] .bb-check input:checked + .bb-check-box { color: #08111F; }
.bb-check-box svg { width: 12px; height: 12px; }

.bb-link {
  display: inline-flex; align-items: center; gap: 5px; max-width: 100%;
  color: var(--bb-accent-ink);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
  overflow: hidden; text-overflow: ellipsis;
  transition: color var(--bb-t-fast) ease-out, text-decoration-color var(--bb-t-fast) ease-out;
}
.bb-link:hover, .bb-link:focus-visible { color: var(--bb-ink); text-decoration-color: currentColor; }

/* =========================================================================
   7. DIFF ROWS
   -------------------------------------------------------------------------
   For anything BridgeBI is PROPOSING: a budget shift, a campaign to cut, a
   keyword to negative. Red = leaving, green = arriving, untinted = untouched.
   The strike-through is on the value, never the row, so the row stays readable.
   ========================================================================= */

.bb-grid tr.bb-diff-del > .bb-cell {
  background: color-mix(in srgb, var(--bb-red) 12%, var(--bb-surface));
  color: var(--bb-red);
}
.bb-grid tr.bb-diff-add > .bb-cell {
  background: color-mix(in srgb, var(--bb-green) 12%, var(--bb-surface));
  color: var(--bb-green);
}
.bb-grid tr.bb-diff-del:hover > .bb-cell { background: color-mix(in srgb, var(--bb-red) 18%, var(--bb-surface)); }
.bb-grid tr.bb-diff-add:hover > .bb-cell { background: color-mix(in srgb, var(--bb-green) 18%, var(--bb-surface)); }
.bb-strike { text-decoration: line-through; text-decoration-thickness: 1px; }

/* =========================================================================
   8. TASK ROWS (capsules)
   -------------------------------------------------------------------------
   A pill per step with a leading state glyph. BridgeBI's long jobs — sync
   Meta, sync Google, ingest, classify — are exactly this shape, and a capsule
   list reads as progress where a log line reads as noise.
   ========================================================================= */

.bb-tasks { display: flex; flex-direction: column; gap: 8px; }

.bb-task {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px;
  border-radius: 99px;
  background: var(--bb-surface);
  box-shadow: var(--bb-sh-card);
  animation: bb-fade-up var(--bb-t-slow) var(--bb-ease-strong) both;
}
.bb-task-name { flex: 1; min-width: 0; font: 500 13px/1.3 inherit; color: var(--bb-ink);
                overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bb-task-meta { color: var(--bb-ink-3); font-size: 12px; flex: none;
                font-family: 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums; }

.bb-task-glyph {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 24px; width: 24px; height: 24px; border-radius: 50%;
  font: 600 11px/1 inherit;
}
.bb-task-glyph.g-done    { background: var(--bb-green); color: #fff; }
.bb-task-glyph.g-done svg { width: 13px; height: 13px; }
.bb-task-glyph.g-fail    { background: var(--bb-red); color: #fff; }
.bb-task-glyph.g-wait    { background: var(--bb-field); color: var(--bb-ink-3); }
/* Running: the number stays legible inside a rotating ring. */
.bb-task-glyph.g-run     { background: var(--bb-field); color: var(--bb-ink-2); position: relative; }
.bb-task-glyph.g-run::after {
  content: ''; position: absolute; inset: -1px; border-radius: 50%;
  border: 2px solid transparent; border-top-color: var(--bb-accent);
  animation: bb-spin .8s linear infinite;
}

.bb-status {
  display: inline-flex; align-items: center; flex: none;
  height: 24px; padding: 0 10px; border-radius: 99px;
  font: 500 11.5px/1 inherit;
  --tag: var(--bb-ink-3);
  background: color-mix(in srgb, var(--tag) 16%, var(--bb-surface));
  color: color-mix(in srgb, var(--tag) 85%, var(--bb-ink));
}
.bb-status.s-done { --tag: var(--bb-green); }
.bb-status.s-run  { --tag: var(--bb-cyan); }
.bb-status.s-wait { --tag: var(--bb-orange); }
.bb-status.s-fail { --tag: var(--bb-red); }

/* =========================================================================
   9. STAT / DELTA BLOCK
   -------------------------------------------------------------------------
   The insight card's number treatment: label with a series dot, a large
   signed percent, and the dollar figure underneath in the same colour. Sign
   colour carries the meaning so the reader never has to parse the number to
   know if it is good news.
   ========================================================================= */

.bb-deltas { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 4px 24px; }

.bb-delta-label {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--bb-ink-2); font: 500 13px/1.3 inherit; margin-bottom: 4px;
}
.bb-delta-value {
  font: 700 26px/1.1 'JetBrains Mono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.bb-delta-sub {
  margin-top: 2px;
  font: 500 13px/1.2 'JetBrains Mono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
}
.bb-delta.is-up   .bb-delta-value, .bb-delta.is-up   .bb-delta-sub { color: var(--bb-green); }
.bb-delta.is-down .bb-delta-value, .bb-delta.is-down .bb-delta-sub { color: var(--bb-red); }
.bb-delta.is-flat .bb-delta-value, .bb-delta.is-flat .bb-delta-sub { color: var(--bb-ink-2); }

/* Inline highlight for a number quoted mid-sentence. */
.bb-num { font-family: 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums; }
.bb-num.pos { color: var(--bb-green); }
.bb-num.neg { color: var(--bb-red); }

/* An @mention-style entity reference: dot + name, for a division or campaign. */
.bb-ent { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; color: var(--bb-ink); }
.bb-ent::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--tag, var(--bb-accent)); }

/* =========================================================================
   10. INSIGHT CARD + CHART STAGE + TOOLTIP
   ========================================================================= */

.bb-insight { padding: 14px; border-radius: var(--bb-r-card); background: var(--bb-surface); box-shadow: var(--bb-sh-card); }
.bb-insight-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.bb-insight-title { display: inline-flex; align-items: center; gap: 8px; font: 600 14px/1 inherit; color: var(--bb-ink); }
.bb-insight-title .bb-count { color: var(--bb-ink-3); font-weight: 500; }
.bb-insight-lede { color: var(--bb-ink); font: 400 14px/1.55 inherit; margin-bottom: 12px; }
.bb-insight-body {
  padding: 12px; border-radius: var(--bb-r-control);
  background: var(--bb-inset); box-shadow: var(--bb-sh-hairline);
}
.bb-insight-foot { margin-top: 12px; }

.bb-chart-stage {
  position: relative; margin-top: 10px;
  border-radius: var(--bb-r-control); background: var(--bb-canvas);
  box-shadow: var(--bb-sh-hairline);
  overflow: hidden;
}
.bb-chart-stage-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 8px 10px; border-bottom: 1px solid var(--bb-line);
  color: var(--bb-ink-3); font-size: 12px;
}
.bb-chart-stage-body { position: relative; padding: 10px; }
.bb-chart-stage svg { display: block; width: 100%; height: auto; overflow: visible; }

/* Vertical scrub line. Non-interactive so it never eats the pointer. */
.bb-chart-cursor {
  position: absolute; top: 0; bottom: 0; width: 1px; z-index: 4;
  background: var(--bb-ink); opacity: .26; pointer-events: none;
}
.bb-tip-anchor { position: absolute; top: 8px; z-index: 5; transform: translateX(-50%); pointer-events: none; }
.bb-tip {
  min-width: 154px; padding: 9px 10px;
  border: 1px solid var(--bb-tip-line); border-radius: var(--bb-r-card);
  background: var(--bb-tip-bg); color: var(--bb-tip-fg);
  box-shadow: var(--bb-sh-overlay); font-size: 12px;
}
.bb-tip-time { display: block; margin-bottom: 7px; color: var(--bb-tip-muted); font-size: 11px; }
.bb-tip-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; line-height: 1.65; }
.bb-tip-row > span { display: inline-flex; align-items: center; gap: 7px; }
.bb-tip-row strong {
  color: var(--bb-tip-muted); font-weight: 500;
  font-family: 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums;
}
.bb-tip-dot { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; }

/* Series swatch legend. */
.bb-legend { display: inline-flex; align-items: center; gap: 4px; }
.bb-legend button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 20px; padding: 0; border: 0; border-radius: var(--bb-r-chip);
  background: var(--bb-field); cursor: pointer;
  transition: opacity var(--bb-t-fast) ease-out;
}
.bb-legend button.is-off { opacity: .35; }
.bb-legend button i { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }

/* =========================================================================
   11. RECOMMENDATION CARD + CONFIDENCE METER
   -------------------------------------------------------------------------
   The shape for "BridgeBI thinks you should do X". A question, the proposal
   with its operands as code chips, then a footer that pairs a confidence
   reading with the two actions. Confidence lives NEXT TO the accept button on
   purpose — it is the thing you weigh right before clicking.
   ========================================================================= */

.bb-rec { border-radius: var(--bb-r-card); background: var(--bb-surface); box-shadow: var(--bb-sh-card); overflow: hidden; }
.bb-rec-body { padding: 14px; }
.bb-rec-q { font: 600 14.5px/1.4 inherit; color: var(--bb-ink); margin-bottom: 6px; }
.bb-rec-p { font: 400 13.5px/1.6 inherit; color: var(--bb-ink-2); }
.bb-rec-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 12px;
  border-top: 1px solid var(--bb-line); background: var(--bb-inset);
}
.bb-rec-actions { display: inline-flex; align-items: center; gap: 8px; }

/* Operand chip — mono, tinted, so a value pulled from data is visibly not prose. */
.bb-code {
  display: inline-flex; align-items: center; padding: 2px 6px;
  border-radius: var(--bb-r-chip);
  background: var(--bb-accent-tint); color: var(--bb-accent-ink);
  font: 500 12.5px/1.5 'JetBrains Mono', ui-monospace, monospace;
}

.bb-conf { display: inline-flex; align-items: center; gap: 8px; color: var(--bb-ink-2); font: 500 12.5px/1 inherit; }
.bb-conf-bars { display: inline-flex; align-items: flex-end; gap: 2px; height: 13px; }
.bb-conf-bars i { width: 4px; border-radius: 1px; background: var(--bb-line-strong); }
.bb-conf-bars i:nth-child(1) { height: 60%; }
.bb-conf-bars i:nth-child(2) { height: 80%; }
.bb-conf-bars i:nth-child(3) { height: 100%; }
.bb-conf.c-low  .bb-conf-bars i:nth-child(-n+1) { background: var(--bb-red); }
.bb-conf.c-med  .bb-conf-bars i:nth-child(-n+2) { background: var(--bb-orange); }
.bb-conf.c-high .bb-conf-bars i                 { background: var(--bb-green); }

/* =========================================================================
   12. CONTEXT / SOURCE CARD
   -------------------------------------------------------------------------
   Evidence, shown as evidence. The agent's HARD RULE says every number cites
   a source; this is that citation rendered — claim on top, source chip at the
   bottom, file type colour-coded.
   ========================================================================= */

.bb-ctx { border-radius: var(--bb-r-card); background: var(--bb-surface); box-shadow: var(--bb-sh-card); overflow: hidden; }
.bb-ctx + .bb-ctx { margin-top: 8px; }
.bb-ctx-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 12px; border-bottom: 1px solid var(--bb-line);
}
.bb-ctx-title { display: inline-flex; align-items: center; gap: 8px; font: 500 13px/1.3 inherit; color: var(--bb-ink); }
.bb-ctx-title svg { width: 14px; height: 14px; color: var(--bb-ink-3); flex: none; }
.bb-ctx-meta { color: var(--bb-ink-3); font-size: 12px; flex: none;
               font-family: 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums; }
.bb-ctx-body { padding: 12px; color: var(--bb-ink-2); font: 400 13px/1.6 inherit; }

.bb-src {
  display: inline-flex; align-items: center; gap: 8px;
  height: 30px; padding: 0 10px 0 6px;
  border-radius: 99px; background: var(--bb-inset);
  box-shadow: var(--bb-sh-hairline);
  color: var(--bb-ink-2); font: 500 12.5px/1 inherit;
  transition: background-color var(--bb-t-fast) ease-out, color var(--bb-t-fast) ease-out;
}
a.bb-src:hover { background: var(--bb-hover); color: var(--bb-ink); }
.bb-src-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 20px; border-radius: var(--bb-r-chip);
  color: #fff; font: 700 8.5px/1 inherit; letter-spacing: .02em; flex: none;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .10);
}
.bb-src-badge.f-pdf { background: #E0484D; }
.bb-src-badge.f-csv { background: #1E9E5A; }
.bb-src-badge.f-xls { background: #1D7044; }
.bb-src-badge.f-crm { background: var(--bb-accent); }
.bb-src-badge.f-meta { background: #1877F2; }
.bb-src-badge.f-goog { background: #C77D1B; }
.bb-src-badge.f-bi  { background: #C9A43F; color: #1A1A1A; }
.bb-src-out { width: 12px; height: 12px; color: var(--bb-ink-3); flex: none; }

/* =========================================================================
   13. AI STATES — thinking, streaming, tool chips, loader
   ========================================================================= */

/* "Thought for 4 seconds" — collapsed by default, sparkle + shimmering label. */
.bb-think { border-radius: var(--bb-r-control); }
.bb-think-toggle {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 8px; border: 0; border-radius: var(--bb-r-control);
  background: transparent; color: var(--bb-ink-2);
  font: 500 13px/1 inherit; cursor: pointer;
  transition: background-color var(--bb-t-fast) ease-out;
}
.bb-think-toggle:hover { background: var(--bb-hover); color: var(--bb-ink); }
.bb-think-toggle svg { width: 14px; height: 14px; flex: none; }
.bb-think-toggle .bb-chev { transition: transform var(--bb-t-base) var(--bb-ease-strong); }
.bb-think.is-open .bb-think-toggle .bb-chev { transform: rotate(180deg); }
.bb-think-body { display: none; padding: 4px 8px 8px 30px; color: var(--bb-ink-2); font: 400 13px/1.65 inherit; }
.bb-think.is-open .bb-think-body { display: block; animation: bb-fade-up var(--bb-t-base) var(--bb-ease-strong) both; }

/* Shimmer for a label that is actively working. background-clip on text with
   a moving gradient — no layout cost, and it reads as "alive" where a spinner
   reads as "stuck". */
.bb-shimmer {
  background: linear-gradient(90deg,
    var(--bb-ink-3) 0%, var(--bb-ink) 45%, var(--bb-ink) 55%, var(--bb-ink-3) 100%);
  background-size: 200% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: bb-shimmer 2.2s linear infinite;
}

/* Streaming text: each chunk fades in from blur, the caret blinks until done. */
.bb-stream > * { animation: bb-stream-in var(--bb-t-slow) var(--bb-ease-strong) both; }
.bb-caret {
  display: inline-block; width: 2px; height: 1.05em; margin-left: 2px;
  vertical-align: text-bottom; translate: 0 -.5px;
  border-radius: 1px; background: var(--bb-ink);
  animation: bb-caret 1s step-end infinite;
}
.bb-caret.is-streaming { animation: none; }
/* Trailing blur on the newest characters — the detail that makes streaming
   feel like generation instead of a timer revealing pre-written text. */
.bb-stream-tail {
  filter: blur(1.6px);
  -webkit-mask-image: linear-gradient(90deg, #000 20%, rgba(0, 0, 0, .2));
          mask-image: linear-gradient(90deg, #000 20%, rgba(0, 0, 0, .2));
}

/* Tool call chips: verb + operand, operand in mono. Compresses an agent
   trace to one scannable line per call. */
.bb-tool-list { display: flex; flex-direction: column; gap: 6px; }
.bb-tool {
  display: flex; align-items: center; gap: 10px;
  font: 500 13px/1 inherit; color: var(--bb-ink);
}
.bb-tool svg { width: 14px; height: 14px; color: var(--bb-ink-3); flex: none; }
.bb-tool-arg {
  flex: 1; min-width: 0; padding: 7px 10px;
  border-radius: var(--bb-r-chip); background: var(--bb-field); color: var(--bb-ink-2);
  font: 400 12.5px/1 'JetBrains Mono', ui-monospace, monospace;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bb-difflist { display: flex; flex-wrap: wrap; gap: 8px; padding-top: 10px; border-top: 1px solid var(--bb-line); }
.bb-diffchip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 10px; border-radius: var(--bb-r-control);
  background: var(--bb-inset); box-shadow: var(--bb-sh-hairline);
  font: 400 12.5px/1 'JetBrains Mono', ui-monospace, monospace; color: var(--bb-ink);
}
.bb-diffchip .add { color: var(--bb-green); }
.bb-diffchip .del { color: var(--bb-red); }

/* Pixel-grid loader. Nine cells on staggered delays: it looks like work being
   done in parallel, which is what a sync actually is. */
.bb-loading { display: inline-flex; align-items: center; gap: 10px; color: var(--bb-ink-2); font: 500 13px/1 inherit; }
.bb-pix { display: grid; grid-template-columns: repeat(3, 4px); gap: 2px; flex: none; }
.bb-pix i { width: 4px; height: 4px; border-radius: 1px; background: currentColor; animation: bb-pixel 1.5s ease-in-out infinite; }
.bb-pix i:nth-child(1) { animation-delay: 0s; }
.bb-pix i:nth-child(2) { animation-delay: .10s; }
.bb-pix i:nth-child(3) { animation-delay: .20s; }
.bb-pix i:nth-child(4) { animation-delay: .30s; }
.bb-pix i:nth-child(5) { animation-delay: .40s; }
.bb-pix i:nth-child(6) { animation-delay: .50s; }
.bb-pix i:nth-child(7) { animation-delay: .60s; }
.bb-pix i:nth-child(8) { animation-delay: .70s; }
.bb-pix i:nth-child(9) { animation-delay: .80s; }
.bb-elapsed {
  color: var(--bb-ink-3);
  font: 400 12.5px/1 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums;
}

/* Equaliser bars — a compact "live" marker for a running sync. */
.bb-eq { display: inline-flex; align-items: flex-end; gap: 2px; height: 12px; }
.bb-eq i { width: 3px; height: 100%; border-radius: 1px; background: currentColor; transform-origin: 50% 100%; animation: bb-eq 1s ease-in-out infinite; }
.bb-eq i:nth-child(2) { animation-delay: .15s; }
.bb-eq i:nth-child(3) { animation-delay: .30s; }
.bb-eq i:nth-child(4) { animation-delay: .45s; }

.bb-spinner {
  display: inline-block; width: 14px; height: 14px; flex: none;
  border: 2px solid color-mix(in srgb, var(--bb-ink-3) 40%, transparent);
  border-top-color: var(--bb-accent); border-radius: 50%;
  animation: bb-spin .7s linear infinite;
}

/* Skeleton block for a value that has not landed yet. */
.bb-skel {
  border-radius: var(--bb-r-chip);
  background: linear-gradient(90deg, var(--bb-field) 0%, var(--bb-hover-2) 50%, var(--bb-field) 100%);
  background-size: 200% 100%; animation: bb-shimmer 1.4s linear infinite;
  color: transparent; user-select: none;
}

/* =========================================================================
   14. COMMAND SEARCH
   ========================================================================= */

.bb-cmd { border-radius: var(--bb-r-card); background: var(--bb-surface); box-shadow: var(--bb-sh-overlay); overflow: hidden; }
.bb-cmd-input {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px; border-bottom: 1px solid var(--bb-line);
}
.bb-cmd-input svg { width: 16px; height: 16px; color: var(--bb-ink-3); flex: none; }
.bb-cmd-input input {
  flex: 1; min-width: 0; border: 0; background: transparent; color: var(--bb-ink);
  font: 400 14px/1 inherit; outline: 0;
}
.bb-cmd-input input::placeholder { color: var(--bb-ink-3); }
.bb-cmd-list { max-height: 320px; overflow-y: auto; padding: 6px; }
.bb-cmd-label {
  padding: 6px 8px; color: var(--bb-ink-3);
  font: 650 10.5px/1 inherit; letter-spacing: .04em; text-transform: uppercase;
}
.bb-cmd-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 8px; border: 0; border-radius: var(--bb-r-chip);
  background: transparent; color: var(--bb-ink);
  font: 400 13.5px/1.3 inherit; text-align: left; cursor: pointer;
  transition: background-color var(--bb-t-fast) ease-out;
}
.bb-cmd-item:hover, .bb-cmd-item.is-active { background: var(--bb-hover); }
.bb-cmd-item .bb-cmd-hint { margin-left: auto; color: var(--bb-ink-3); font-size: 12px; flex: none; }
.bb-cmd-empty { padding: 28px 14px; text-align: center; color: var(--bb-ink-3); font-size: 13px; }

/* Dropdown menu, shared by filter/sort/overflow. Pops from its own corner. */
.bb-menu {
  position: absolute; z-index: 30; top: calc(100% + 7px); left: 0;
  width: 200px; padding: 6px;
  border: 1px solid var(--bb-line-strong); border-radius: var(--bb-r-card);
  background: var(--bb-surface); box-shadow: var(--bb-sh-overlay);
  transform-origin: 0 0; animation: bb-pop-in var(--bb-t-base) var(--bb-ease-strong) both;
}
.bb-menu.is-right { left: auto; right: 0; transform-origin: 100% 0; }
.bb-menu-label {
  padding: 5px 8px 6px; color: var(--bb-ink-3);
  font: 650 10.5px/1 inherit; letter-spacing: .04em; text-transform: uppercase;
}
.bb-menu button {
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 7px 8px; border: 0; border-radius: var(--bb-r-chip);
  background: transparent; color: var(--bb-ink-2);
  font: 400 12px/1.3 inherit; text-align: left; cursor: pointer;
  transition: background-color var(--bb-t-fast) ease-out, color var(--bb-t-fast) ease-out;
}
.bb-menu button:hover, .bb-menu button.is-selected { background: var(--bb-hover); color: var(--bb-ink); }
.bb-menu-check { width: 13px; text-align: center; color: var(--bb-accent-ink); font-weight: 700; font-size: 12px; flex: none; }

/* =========================================================================
   15. SELECTION ACTION BAR
   -------------------------------------------------------------------------
   Floating pill that appears when rows are selected: a free-text instruction
   plus the two or three verbs that apply. Divided by hairlines rather than
   spaced apart, so it reads as one control.
   ========================================================================= */

.bb-selbar {
  position: fixed; left: 50%; bottom: 24px; z-index: 900;
  display: flex; align-items: stretch;
  border-radius: 99px; background: var(--bb-surface);
  box-shadow: var(--bb-sh-overlay), 0 12px 32px rgba(0, 0, 0, .10);
  overflow: hidden;
  animation: bb-slide-up var(--bb-t-slow) var(--bb-ease-strong) both;
}
.bb-selbar input {
  min-width: 190px; padding: 0 16px; border: 0;
  background: transparent; color: var(--bb-ink); font: 400 13px/1 inherit; outline: 0;
}
.bb-selbar input::placeholder { color: var(--bb-ink-3); }
.bb-selbar > * + * { border-left: 1px solid var(--bb-line); }
.bb-selbar button {
  display: inline-flex; align-items: center; gap: 7px;
  height: 44px; padding: 0 14px; border: 0;
  background: transparent; color: var(--bb-ink); font: 500 13px/1 inherit; cursor: pointer;
  transition: background-color var(--bb-t-fast) ease-out;
}
.bb-selbar button:hover { background: var(--bb-hover); }
.bb-selbar button svg { width: 15px; height: 15px; color: var(--bb-ink-2); flex: none; }
.bb-selbar .bb-selcount {
  display: inline-flex; align-items: center; height: 44px; padding: 0 14px;
  color: var(--bb-ink-2); font: 500 13px/1 inherit;
}
.bb-selbar .bb-selcount strong {
  color: var(--bb-ink); margin-right: 4px;
  font-family: 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums;
}

/* =========================================================================
   16. THEME TOGGLE
   ========================================================================= */

.bb-theme-btn { position: relative; }
.bb-theme-btn .bb-sun, .bb-theme-btn .bb-moon {
  transition: opacity var(--bb-t-base) ease-out, transform var(--bb-t-base) var(--bb-ease-strong);
}
.bb-theme-btn .bb-moon { position: absolute; opacity: 0; transform: rotate(-90deg) scale(.6); }
html[data-bb-theme="dark"] .bb-theme-btn .bb-sun  { opacity: 0; transform: rotate(90deg) scale(.6); }
html[data-bb-theme="dark"] .bb-theme-btn .bb-moon { opacity: 1; transform: none; }

/* =========================================================================
   17. CRAFT PASS — existing BridgeBI chrome
   -------------------------------------------------------------------------
   Everything above is opt-in. This section is NOT: it re-shadows and re-rounds
   the chrome that already ships, so the whole app inherits the hairline-first
   elevation and the 10/8/6 radius scale without touching 50k lines of markup.

   Deliberately narrow. It changes elevation, radius and hover feedback only —
   never a colour, never a layout dimension. A colour change here would fight
   the light theme it is trying to leave alone.
   ========================================================================= */

.card,
.stat-card,
.summary-card {
  box-shadow: var(--bb-sh-card) !important;
  border-radius: var(--bb-r-card) !important;
}
.card:hover, .stat-card:hover { box-shadow: var(--bb-sh-raised) !important; }

/* Inputs and selects get the inset field treatment: a field should look
   recessed and a button should look raised. Most UIs give both the same
   border, which is why they read as flat. */
input[type="text"], input[type="search"], input[type="number"],
input[type="date"], input[type="email"], input[type="password"],
select, textarea {
  border-radius: var(--bb-r-control);
}
input[type="text"]:focus, input[type="search"]:focus, input[type="number"]:focus,
input[type="date"]:focus, input[type="email"]:focus, input[type="password"]:focus,
select:focus, textarea:focus {
  outline: 0;
  box-shadow: var(--bb-sh-focus);
}

/* Sidebar: section labels get the reference's uppercase micro-caps, and the
   active tab's gold marker gets a real inset rail instead of a border that
   shifts the label. */
.sidebar-section {
  letter-spacing: .06em !important;
  text-transform: uppercase;
  font-size: 10.5px !important;
  font-weight: 650 !important;
}
.sidebar-nav-tab {
  border-radius: var(--bb-r-control) !important;
  transition: background-color var(--bb-t-fast) ease-out,
              color var(--bb-t-fast) ease-out,
              transform var(--bb-t-fast) var(--bb-ease-strong) !important;
}
.sidebar-nav-tab:active { transform: scale(.985); }

/* Count badge on a nav tab, matching the reference's recessed pill. */
.sidebar-nav-tab .bb-navcount {
  margin-left: auto; padding: 2px 6px; border-radius: var(--bb-r-chip);
  background: rgba(255, 255, 255, .08); color: rgba(255, 255, 255, .72);
  font: 500 10.5px/1.4 'JetBrains Mono', ui-monospace, monospace;
  font-variant-numeric: tabular-nums; flex: none;
}

/* Every number in the app gets tabular figures. DESIGN.md already requires
   this; declaring it once here means a new table cannot forget. */
td, th, .bb-num, .stat-value, .kpi-value {
  font-variant-numeric: tabular-nums;
}

/* =========================================================================
   18. DARK MODE FOR THE EXISTING APP SHELL
   -------------------------------------------------------------------------
   index.html carries ~2,000 hardcoded colour literals, so a complete dark
   theme is a tokenisation sweep, not a stylesheet. What IS available cheaply
   is this: the app's neutral scale already goes through five variables, and
   those five are used ~1,300 times. Remapping them flips the shell.

   THE SWEEP IS SAFE, AND THAT WAS CHECKED RATHER THAN ASSUMED:

     - `--off-white`, `--warm-2`, `--warm-3` are used as BACKGROUNDS and
       BORDERS only, never as a text colour. Verified by grepping for
       `color: var(--off-white…)` — zero hits across index.html and all six
       stylesheets. So darkening them cannot turn text invisible.
     - `--text` / `--text-muted` are used as a background in four places, all
       of them small dots and severity chips. Those invert to a light dot on a
       dark surface, which still reads.
     - `--warm-white` is a text colour in exactly ONE rule
       (`.report-card-seal`, white-on-navy), overridden below.

   `--navy` is deliberately NOT remapped. It is the app's identity, it is used
   both as a fill and as a text colour, and the header and sidebar are supposed
   to stay navy — they already read as the dark chrome of a light app, so in
   dark mode they simply stop being the only dark thing on screen.

   Anything still light after this is a hardcoded literal. That is the follow-up
   sweep, not a bug in this file.
   ========================================================================= */

html[data-bb-theme="dark"] {
  --off-white:  #0B1220;   /* body background */
  --warm-white: #101828;   /* raised surface */
  --warm-2:     #0E1626;
  --warm-3:     #131C2E;
  --text:       #EEF1F6;
  --text-muted: #A3AEC0;
  --border:     #1F2B3F;
  --shadow:     rgba(0, 0, 0, .55);
}

/* Cards and panels: agent.css and index.html both paint `#fff` literally in
   many places, and white is the one literal that cannot survive dark mode.
   These are the containers that hold the app's content. */
html[data-bb-theme="dark"] .card,
html[data-bb-theme="dark"] .stat-card,
html[data-bb-theme="dark"] .summary-card,
html[data-bb-theme="dark"] .modal,
html[data-bb-theme="dark"] .modal-content,
html[data-bb-theme="dark"] .dropdown,
html[data-bb-theme="dark"] .notification-dropdown {
  background: var(--bb-surface);
  color: var(--bb-ink);
}

html[data-bb-theme="dark"] table { color: var(--bb-ink); }
html[data-bb-theme="dark"] thead th { background: var(--bb-inset); color: var(--bb-ink-2); }
html[data-bb-theme="dark"] tbody tr:hover > td { background: var(--bb-hover); }
html[data-bb-theme="dark"] td, html[data-bb-theme="dark"] th { border-color: var(--bb-line); }

html[data-bb-theme="dark"] input[type="text"], html[data-bb-theme="dark"] input[type="search"],
html[data-bb-theme="dark"] input[type="number"], html[data-bb-theme="dark"] input[type="date"],
html[data-bb-theme="dark"] input[type="email"], html[data-bb-theme="dark"] input[type="password"],
html[data-bb-theme="dark"] select, html[data-bb-theme="dark"] textarea {
  background: var(--bb-field); color: var(--bb-ink); border-color: var(--bb-line-strong);
}
html[data-bb-theme="dark"] ::placeholder { color: var(--bb-ink-3); }

/* The one text-on-fill usage of --warm-white. Remapping the variable would
   otherwise put a dark letter on the navy seal. */
html[data-bb-theme="dark"] .report-card-seal { color: #F5F3EE; }

/* Page titles are `--navy`, which is now nearly the page background. They take
   the ink token instead — this is the rule that stops every page heading from
   disappearing the moment the lights go out. */
html[data-bb-theme="dark"] h1,
html[data-bb-theme="dark"] h2,
html[data-bb-theme="dark"] h3,
html[data-bb-theme="dark"] .page-title,
html[data-bb-theme="dark"] .card-title,
html[data-bb-theme="dark"] .section-title,
html[data-bb-theme="dark"] .stat-value,
html[data-bb-theme="dark"] .kpi-value {
  color: var(--bb-ink);
}

/* Header and sidebar keep their navy, but the header's translucent fill is
   mixed against a light page in the original rule — it needs the dark ground
   or it washes out into a grey band. */
html[data-bb-theme="dark"] header { background: rgba(9, 20, 40, .82); }

/* =========================================================================
   19. RESPONSIVE
   -------------------------------------------------------------------------
   Keyed off `html[data-cw]` (content width) to match responsive.css, with a
   viewport fallback for the case where responsive.js has not booted yet.
   ========================================================================= */

@media (max-width: 720px) {
  .bb-toolbar { flex-direction: column; align-items: flex-start; }
  .bb-toolbar-l, .bb-toolbar-r { width: 100%; }
  .bb-toolbar-r { justify-content: flex-end; }
  .bb-shell-foot .bb-hint { display: none; }
  .bb-deltas { grid-template-columns: 1fr 1fr; gap: 4px 12px; }
  .bb-delta-value { font-size: 22px; }
  .bb-selbar { left: 12px; right: 12px; bottom: 12px; transform: none; animation: bb-fade-up var(--bb-t-slow) var(--bb-ease-strong) both; }
  .bb-selbar input { min-width: 0; flex: 1; }
  .bb-task { border-radius: var(--bb-r-card); }
}

html[data-cw="xs"] .bb-deltas,
html[data-cw="sm"] .bb-deltas { grid-template-columns: 1fr 1fr; }
html[data-cw="xs"] .bb-toolbar { flex-direction: column; align-items: flex-start; }

/* Any box that clips its own content must refuse to shrink.
   `overflow: hidden` sets an element's automatic minimum size to 0. Inside a
   flex container that overflows — a chat log, a scrolling column, a card stack
   — the default `flex-shrink: 1` then crushes it toward zero height, and it
   crushes SILENTLY: the element is in the DOM, it has no height, and nothing
   errors. This cost the analyst's follow-up card its entire existence on any
   conversation long enough to scroll.

   Fixed once, here, for every clipping component in this file. Add `flex: none`
   to any new one that also carries `overflow: hidden`. */
.bb-shell, .bb-rec, .bb-ctx, .bb-insight, .bb-cmd, .bb-selbar, .bb-task, .bb-chart-stage {
  flex: none;
}

/* Icon SVGs inside a flex row must not be allowed to collapse. responsive.css
   sets `svg { max-width: 100% }`, which resolves to 0 for an icon whose flex
   basis is auto — an explicit width plus flex:none is the only reliable fix
   (flex:none alone does NOT do it). Keep both declarations. */
.bb-btn svg, .bb-iconbtn svg, .bb-tool svg, .bb-src-out,
.bb-ctx-title svg, .bb-cmd-input svg, .bb-selbar button svg {
  flex: none; max-width: none;
}
