/* =============================================================================
   app.css — thin override layer on top of the WebAdmin theme (themed Bootstrap 5).
   ---------------------------------------------------------------------------
   The bought theme (assets/theme/css/{bootstrap,icons,app}.min.css) owns the shell,
   sidebar, topbar, cards, palette and dark mode (via data-bs-theme). This file only
   carries the few app-specific hooks the theme doesn't provide.
   ============================================================================= */

/* Inline SVG icons (our icon() helper) inherit text color + size with the font. */
.cb-ico-inline { width: 1em; height: 1em; vertical-align: -0.125em; flex: 0 0 auto; }
.cb-tip { cursor: help; }
.cb-tip__ico { width: 0.9em; height: 0.9em; vertical-align: -0.08em; }

/* Widget-list avatar tile. */
.cb-wcard__avatar {
  width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; background: var(--bs-tertiary-bg); flex: 0 0 auto;
}
.cb-wcard__avatar img { width: 100%; height: 100%; object-fit: cover; }
.cb-wcard__avatar .cb-ico-inline { width: 22px; height: 22px; color: var(--bs-secondary-color); }

/* Topbar dark/light toggle button (theme's header-item, our behaviour). */
.cb-theme-toggle .cb-theme-icon { font-size: 1.25rem; line-height: 1; vertical-align: middle; }

/* --- Brand: icon SVG + Asap wordmark. Theme shows logo-lg (icon+text) when expanded,
       logo-sm (icon only) when collapsed. Icon variant swaps with the theme (dark icon on
       light bg, light icon on dark bg). Asap is self-hosted (CSP 'self', no CDN). --- */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/poppins/poppins-700.woff2') format('woff2');
}
/* Brand box. We don't use the theme's logo-lg/logo-sm spans (wired for a different
   layout) — just one icon + a wordmark, and we hide the wordmark on collapse.
   Flex-centered at 75px so it lines up with the hamburger (a 75px .header-item
   pinned top:0). */
.navbar-brand-box .logo { display: flex; align-items: center; gap: 0.25rem; height: 75px; line-height: normal; }
.cb-logo-icon { height: 34px; width: auto; }
.cb-logo-icon--dark { display: none; }
[data-bs-theme="dark"] .cb-logo-icon--light { display: none; }
[data-bs-theme="dark"] .cb-logo-icon--dark { display: inline-block; }
/* Brand mark — inline mono SVG (see partials/shared/brand-mark). currentColor lets it recolour
   per theme OR take a fixed brand color — whichever --cb-logo-color resolves to below.
   `--cb-logo-size` (set by shared/brand-lockup on its wrapper) is the size knob, 38px by default. */
/* Pinned to the theme's own text-ink colors: --bs-dark (near-black) on light theme,
   --bs-emphasis-color (near-white) on dark theme. (Tried --bs-light for dark theme first, but
   this admin theme repurposes --bs-light/--bs-dark as component SURFACE colors — e.g. sidebar/
   card backgrounds — not text ink, so in dark mode --bs-light is itself a dark charcoal and the
   mark nearly vanished. --bs-emphasis-color is the theme's actual near-white text ink instead.)
   TO REVERT to the plain single-var adaptive default: delete BOTH of the next two rules —
   .cb-logo-mark's own var() fallback (--bs-emphasis-color) is already theme-adaptive by itself. */
:root { --cb-logo-color: var(--bs-dark); }
[data-bs-theme="dark"] { --cb-logo-color: var(--bs-emphasis-color); }
.cb-logo-mark { display: inline-flex; align-items: center; color: var(--cb-logo-color, var(--bs-emphasis-color)); flex: 0 0 auto; }
.cb-logo-mark svg { height: var(--cb-logo-size, 38px); width: auto; display: block; }
/* shared/brand-lockup's own span: `display:contents` so its mark+text children lay out as if
   direct children of whatever flex container wraps the partial (sidebar .logo, .cb-topbar-logo,
   or an auth page's own centered link) — no gap/alignment duplicated here. CSS vars (size) still
   cascade to descendants through it. */
.cb-logo-lockup { display: contents; }
.cb-logo-text {
  font-family: 'Poppins', system-ui, -apple-system, "Segoe UI", sans-serif;
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.02em;
  line-height: 1;
  white-space: nowrap;
  color: var(--bs-emphasis-color);
}
/* Collapsed rail (70px): icon only, centered, no padding so it fits cleanly. */
[data-sidebar-size="sm"] .navbar-brand-box { padding: 0; }
[data-sidebar-size="sm"] .navbar-brand-box .logo { justify-content: center; gap: 0; }
[data-sidebar-size="sm"] .cb-logo-text { display: none; }

/* Mobile topbar brand (sidebar hidden ≤lg): icon + wordmark, left of the hamburger. */
.cb-topbar-logo { display: inline-flex; align-items: center; gap: 0.5rem; height: 75px; padding-right: 0.5rem; text-decoration: none; }


/* Footer: use the THEME's own placement — position:absolute; bottom:0 — but the theme ships
   NO positioned ancestor for it, so on a tall (scrolling) page the footer anchors to the
   viewport and drifts up the page instead of sitting under the content. Give .main-content
   position:relative (the ancestor the theme forgot) and the absolute footer pins to the bottom
   of the content on BOTH short and tall pages (main-content has min-height:100vh + grows with
   content). Our footer also carries an extra processor-disclosure row, so let it size to its
   content, drop the theme's right:270px inset (main-content is already inset from the sidebar
   by its own margin), and reserve matching room above it. */
.main-content { position: relative; }
/* left:0 + right:0 — the theme's footer uses left:270px (clearing the sidebar RELATIVE TO THE
   VIEWPORT), but our footer is anchored to .main-content, which is already inset by its own
   margin-left:270px; keeping the theme's 270px would double-count and the footer wouldn't stretch
   the full content width. */
.footer { position: absolute; height: auto; left: 0; right: 0; }

/* Panel titles: the theme's titled panels use a .card-header (title + divider) with a .card-title
   at 16px/600. Bootstrap's .card-title carries no size/weight, so pin it to the theme's. Used where
   we convert a single-title panel to the header pattern; multi-section cards keep inline sub-headings. */
.card-title { font-size: 16px; font-weight: 600; margin-bottom: 0; }
.card-title-desc { color: var(--bs-secondary-color); font-size: .8125rem; margin-bottom: 0; margin-top: .35rem; }
.page-content { padding-bottom: 7rem; }

/* The theme's topbar dropdowns use .dropdown-menu-xl / -lg but ship no width rule for them
   (Bootstrap otherwise sizes a dropdown to its content, which left the notifications panel
   cramped). Give them a comfortable fixed width, capped on small screens. */
.dropdown-menu-xl { width: 22rem; max-width: 94vw; }
.dropdown-menu-lg { width: 20rem; max-width: 94vw; }

/* Topbar user avatar: size to match the adjacent header icons; readable in both themes. */
.header-item.user .avatar-xs { height: 2.1rem; width: 2.1rem; }
.header-item.user .avatar-title { font-size: 0.95rem; }

/* Grid.js (theme's mermaid theme is light-only) → repaint with Bootstrap vars so the table matches
   the admin theme in BOTH light and dark. Scoped under .cb-conversations to outrank mermaid's rules. */
.cb-conversations .gridjs-container { color: var(--bs-body-color); }
.cb-conversations .gridjs-wrapper { box-shadow: none; border: 1px solid var(--bs-border-color); border-bottom: 0; border-radius: .375rem .375rem 0 0; }
.cb-conversations .gridjs-table { background: var(--bs-body-bg); }
.cb-conversations .gridjs-th { background: var(--bs-tertiary-bg); border-color: var(--bs-border-color); }
.cb-conversations .gridjs-th, .cb-conversations .gridjs-th-content { color: var(--bs-body-color); }
.cb-conversations .gridjs-td { background: var(--bs-body-bg); color: var(--bs-body-color); border-color: var(--bs-border-color); }
.cb-conversations .gridjs-tr:hover .gridjs-td { background: var(--bs-tertiary-bg); }
.cb-conversations .gridjs-search-input, .cb-conversations input.gridjs-input {
  background: var(--bs-body-bg); color: var(--bs-body-color); border-color: var(--bs-border-color); }
.cb-conversations .gridjs-search-input::placeholder { color: var(--bs-secondary-color); }
.cb-conversations .gridjs-footer { background: transparent; border-color: var(--bs-border-color); box-shadow: none; border-radius: 0 0 .375rem .375rem; }
.cb-conversations .gridjs-summary { color: var(--bs-secondary-color); }
.cb-conversations .gridjs-pagination .gridjs-pages button {
  background: var(--bs-body-bg); color: var(--bs-body-color); border-color: var(--bs-border-color);
  display: inline-flex; align-items: center; justify-content: center; line-height: 1.5; }
.cb-conversations .gridjs-pagination .gridjs-pages button:hover:not(:disabled) { background: var(--bs-tertiary-bg); }
.cb-conversations .gridjs-pagination .gridjs-pages button.gridjs-currentPage { background: var(--bs-primary); color: #fff; border-color: var(--bs-primary); }
/* mermaid's sort-arrow glyphs are dark SVGs — invert them so they show on the dark header. */
[data-bs-theme="dark"] .cb-conversations .gridjs-th button.gridjs-sort { filter: invert(.85); }

/* =============================================================================
   Widgets v2 — premium plan-aware list (templates/members/widgets/v2.php).
   Each card takes its accent from the widget's own primary color (--cb-w2-accent).
   ============================================================================= */
.cb-w2-usage { width: 140px; height: 5px; }
.cb-w2-setup { height: 5px; }

/* Card: soft elevation, hover lift, per-widget accent strip. */
.cb-w2-card { border-top: 3px solid var(--cb-w2-accent, var(--bs-primary));
  transition: transform .15s ease, box-shadow .15s ease; }
.cb-w2-card:hover { transform: translateY(-2px); box-shadow: 0 .5rem 1.5rem rgba(0,0,0,.10); }
[data-bs-theme="dark"] .cb-w2-card:hover { box-shadow: 0 .5rem 1.5rem rgba(0,0,0,.45); }

/* Avatar tile: bigger than v1, subtle ring in the accent color. */
.cb-w2-avatar { width: 56px; height: 56px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  background: var(--bs-tertiary-bg); flex: 0 0 auto; font-size: 1.25rem;
  box-shadow: 0 0 0 2px var(--bs-body-bg), 0 0 0 4px var(--cb-w2-accent, var(--bs-border-color)); }
.cb-w2-avatar img { width: 100%; height: 100%; object-fit: cover; }
.cb-w2-avatar .cb-ico-inline { width: 26px; height: 26px; color: var(--bs-secondary-color); }
.cb-w2-avatar--sm { width: 40px; height: 40px; font-size: 1rem; box-shadow: none; }

/* Status pill with a pulse dot when live. */
.cb-w2-status { display: inline-flex; align-items: center; gap: .4rem;
  padding: .25rem .6rem; border-radius: 2rem; font-size: .78rem; font-weight: 600; flex: 0 0 auto; }
.cb-w2-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
.cb-w2-status .bg-success { animation: cb-w2-pulse 2s ease-out infinite; }
@keyframes cb-w2-pulse {
  0% { box-shadow: 0 0 0 0 rgba(var(--bs-success-rgb), .5); }
  70% { box-shadow: 0 0 0 6px rgba(var(--bs-success-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--bs-success-rgb), 0); }
}

/* Setup checklist: quiet pill links; done = green tick, todo invites the click. */
.cb-w2-checks { display: flex; flex-wrap: wrap; gap: .35rem; }
.cb-w2-check { display: inline-flex; align-items: center; gap: .3rem;
  padding: .2rem .55rem; border-radius: 2rem; font-size: .78rem; text-decoration: none;
  color: var(--bs-body-color); background: var(--bs-tertiary-bg); border: 1px solid transparent; }
.cb-w2-check:hover { border-color: var(--cb-w2-accent, var(--bs-primary)); color: var(--bs-body-color); }
.cb-w2-check.is-done { color: var(--bs-success); background: rgba(var(--bs-success-rgb), .08); }
.cb-w2-check i { font-size: .95rem; }

/* Feature chips: on = tinted, locked = dimmed with lock, still clickable → upgrade. */
.cb-w2-chips { display: flex; flex-wrap: wrap; gap: .35rem; }
.cb-w2-chip { display: inline-flex; align-items: center; gap: .3rem;
  padding: .2rem .55rem; border-radius: 2rem; font-size: .78rem; border: 1px solid var(--bs-border-color);
  background: transparent; color: var(--bs-secondary-color); }
.cb-w2-chip i { font-size: .95rem; }
.cb-w2-chip.is-on { color: var(--bs-primary); border-color: rgba(var(--bs-primary-rgb), .35);
  background: rgba(var(--bs-primary-rgb), .06); }
.cb-w2-chip.is-locked { opacity: .65; cursor: pointer; }
.cb-w2-chip.is-locked:hover { opacity: 1; border-color: var(--bs-warning); color: var(--bs-body-color); }

/* Feature catalog rows (Plan & features panel). */
.cb-w2-feature { display: flex; gap: .75rem; padding: .75rem; border-radius: .5rem; height: 100%;
  border: 1px solid var(--bs-border-color); background: var(--bs-body-bg); }
.cb-w2-feature.is-locked { background: var(--bs-tertiary-bg); }
.cb-w2-feature.is-locked .cb-w2-feature-icon { opacity: .55; }
.cb-w2-feature-icon { width: 38px; height: 38px; border-radius: .5rem; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center; font-size: 1.25rem;
  color: var(--bs-primary); background: rgba(var(--bs-primary-rgb), .08); }

/* Empty-state hero + upgrade modal icon. */
.cb-w2-hero-icon, .cb-w2-up-icon { width: 72px; height: 72px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-size: 2.2rem;
  color: var(--bs-primary); background: rgba(var(--bs-primary-rgb), .1); }

/* ── Tables: the same rounded-card treatment as every other surface. Apply
      .cb-table on the .table-responsive wrapper; add [data-cb-list] and theme.js
      injects search + pagination once the table is big enough. ── */
.cb-table { border: 1px solid var(--bs-border-color); border-radius: .5rem;
  overflow-x: auto; background: var(--bs-body-bg); }
.cb-table > .table { margin-bottom: 0; }
.cb-table > .table > thead { background: var(--bs-tertiary-bg); }
.cb-table > .table > thead th { border-bottom-width: 1px; padding-top: .6rem; padding-bottom: .6rem; }
.cb-table > .table td, .cb-table > .table th { padding-left: .75rem; padding-right: .75rem; }
.cb-table > .table > tbody > tr:last-child > td { border-bottom: 0; }
.cb-hide { display: none !important; }
.cb-table-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-bottom: .5rem; }
.cb-table-toolbar .cb-table-search { max-width: 16rem; }
.cb-table-pager { display: flex; align-items: center; gap: .5rem; margin-top: .5rem; }

/* ── Message center rows (0053). The theme's .col-mail grid is a fixed-50px absolute-
      positioning layout built for its exact demo markup (photo + "23 threads" + short
      times) and its .unread colour is a hardcoded light grey that goes white in dark mode.
      Ours is a robust flex row in the same visual language, theme-var-driven so dark mode
      is correct. ── */
.cb-inbox .message-list { display: block; }
.cb-inbox .cb-msg { display: flex; align-items: center; gap: .85rem; padding: .7rem 1.15rem;
  border-bottom: 1px solid var(--bs-border-color); text-decoration: none; color: var(--bs-body-color);
  transition: background-color .15s; }
.cb-inbox .cb-msg:last-child { border-bottom: 0; }
.cb-inbox .cb-msg:hover { background: var(--bs-tertiary-bg); }
.cb-inbox .cb-msg.unread { background: rgba(var(--bs-primary-rgb), .06); }
.cb-inbox .cb-msg .avatar-sm { flex: 0 0 auto; }
.cb-inbox .cb-msg-main { flex: 1 1 auto; min-width: 0; }
.cb-inbox .cb-msg-from { font-size: .78rem; color: var(--bs-secondary-color); line-height: 1.2; }
.cb-inbox .cb-msg-subject { font-size: .92rem; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; color: var(--bs-body-color); }
.cb-inbox .cb-msg.unread .cb-msg-subject { font-weight: 600; }
.cb-inbox .cb-msg-date { flex: 0 0 auto; font-size: .78rem; color: var(--bs-secondary-color); white-space: nowrap; }
/* Read-message body spacing */
.cb-inbox-body p:last-child { margin-bottom: 0; }

/* Message-thread email body: normal (non-pre) wrapping, comfortable line height. */
.cb-inbox .cb-mail-body { line-height: 1.6; white-space: normal; }
.cb-inbox .cb-mail-body br + br { display: block; content: ""; margin-top: .5rem; }
.cb-inbox .cb-inbox-body { line-height: 1.6; }
.cb-inbox .cb-inbox-body p:last-child { margin-bottom: 0; }

/* ── Ask AI right-side panel (reuses the theme .right-bar slide mechanism, wider). ── */
.right-bar.cb-askai { width: 420px; right: -430px; background: var(--bs-body-bg); }
.right-bar-enabled .right-bar.cb-askai { right: 0; }
@media (max-width: 480px) { .right-bar.cb-askai { width: 100%; right: -100%; } }
.cb-askai .rightbar-title h5 { font-weight: 600; }
.cb-askai-spark, .cb-askai-hero { color: var(--bs-primary); }
.cb-askai-hero { width: 56px; height: 56px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; font-size: 1.8rem; background: rgba(var(--bs-primary-rgb), .1); }
.cb-askai-btn { font-weight: 500; color: var(--bs-primary); }
.cb-askai-btn .mdi { font-size: 1.05rem; }
.cb-askai-scroll { overflow-y: auto; }
.cb-askai-sugg { border: 1px solid var(--bs-border-color); border-radius: .6rem; padding: .6rem .8rem;
  background: var(--bs-body-bg); cursor: pointer; transition: background-color .15s; text-decoration: none; color: inherit; }
.cb-askai-sugg:hover { background: var(--bs-tertiary-bg); }
.cb-askai-sugg .t { font-weight: 500; font-size: .85rem; display: block; }
.cb-askai-sugg .s { font-size: .78rem; color: var(--bs-secondary-color); }
.cb-askai-msg { display: flex; margin-bottom: .75rem; }
.cb-askai-msg .b { padding: .55rem .85rem; border-radius: .8rem; max-width: 85%; font-size: .88rem; line-height: 1.5; white-space: pre-wrap; }
.cb-askai-msg.user { justify-content: flex-end; }
.cb-askai-msg.user .b { background: var(--bs-primary); color: #fff; border-bottom-right-radius: .2rem; }
.cb-askai-msg.ai .b { background: var(--bs-tertiary-bg); border-bottom-left-radius: .2rem; }
.cb-askai-msg.ai.pending .b { color: var(--bs-secondary-color); font-style: italic; }
.cb-askai-input textarea { resize: none; padding-right: 3rem; border-radius: .8rem; max-height: 8rem; }
.cb-askai-send { position: absolute; right: .4rem; bottom: .4rem; width: 2rem; height: 2rem; border-radius: 50%;
  padding: 0; display: flex; align-items: center; justify-content: center; }

/* Conversation transcript on the theme chat markup (buyer↔widget). */
.cb-chat { padding-top: .5rem; }
.cb-chat li { clear: both; margin-bottom: 1.25rem; }
.cb-chat .avatar-xs { height: 1.75rem; width: 1.75rem; }
.cb-chat .avatar-title { font-size: .9rem; }
.cb-chat .conversation-name { margin-bottom: .35rem; }

/* ── Quill composer (shared/quill-editor.php) ─────────────────────────────────────────────────
   Match the theme's form controls (border colour, 12px radius, our font size) and make the snow
   theme work in dark mode (it ships light-only: black toolbar icons + white surfaces). */
.cb-quill .ql-toolbar.ql-snow,
.cb-quill .ql-container.ql-snow { border-color: var(--bs-border-color); }
.cb-quill .ql-toolbar.ql-snow { border-radius: 12px 12px 0 0; background: var(--bs-tertiary-bg); }
.cb-quill .ql-container.ql-snow { border-radius: 0 0 12px 12px; font-family: inherit; font-size: 14.8px; }
.cb-quill .ql-editor { background: var(--bs-body-bg); color: var(--bs-body-color); }
.cb-quill .ql-editor.ql-blank::before { color: var(--bs-secondary-color); font-style: normal; left: 12px; right: 12px; }
.cb-quill .ql-editor img { max-width: 100%; height: auto; border-radius: 6px; }
/* dark mode: recolour Quill's SVG toolbar glyphs + picker surfaces to theme vars */
[data-bs-theme="dark"] .cb-quill .ql-snow .ql-stroke { stroke: var(--bs-body-color); }
[data-bs-theme="dark"] .cb-quill .ql-snow .ql-fill { fill: var(--bs-body-color); }
[data-bs-theme="dark"] .cb-quill .ql-snow .ql-picker,
[data-bs-theme="dark"] .cb-quill .ql-snow .ql-picker-label { color: var(--bs-body-color); }
[data-bs-theme="dark"] .cb-quill .ql-snow .ql-picker-options { background: var(--bs-tertiary-bg); border-color: var(--bs-border-color); }
[data-bs-theme="dark"] .cb-quill .ql-snow.ql-toolbar button:hover .ql-stroke { stroke: var(--bs-primary); }

/* Rich (Quill-composed) message bodies inside chat bubbles / mail rows: trim the trailing block
   margin so the bubble hugs its content, and keep links legible on the primary (blue) bubble. */
.cb-msg-body > :last-child, .cb-mail-body > :last-child { margin-bottom: 0; }
.cb-msg-body p, .cb-mail-body p { margin-bottom: .5rem; }
.text-bg-primary .cb-msg-body a { color: #fff; text-decoration: underline; }

/* Insert-tag: a real toolbar button (tag icon) that opens a small popup menu — replaces a native
   <select> that rendered its text unreadably in dark mode and clashed with the rest of the toolbar. */
.cb-tag-wrap { position: relative; }
.cb-quill .cb-tag-btn { width: 28px; height: 24px; padding: 0; background: none; border: 0; cursor: pointer;
  color: var(--bs-body-color); font-size: 16px; line-height: 1; vertical-align: middle; border-radius: 4px; }
.cb-quill .cb-tag-btn:hover, .cb-quill .cb-tag-btn.cb-active { color: var(--bs-primary); background: var(--bs-tertiary-bg); }
.cb-tag-menu { position: absolute; z-index: 1080; top: 100%; left: 0; margin-top: 4px; min-width: 210px;
  background: var(--bs-body-bg); border: 1px solid var(--bs-border-color); border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0,0,0,.18); padding: 4px; }
.cb-tag-menu-head { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--bs-secondary-color); padding: 4px 8px; }
/* High specificity (+ !important on the box metrics) to beat Quill's `.ql-toolbar button { width:28px;
   height:24px; float:none }`, which otherwise crushes each menu item into a 28px column. */
.cb-quill .cb-tag-menu .cb-tag-item { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; width: 100% !important; height: auto !important; float: none; background: none; border: 0;
  border-radius: 6px; padding: 6px 10px; cursor: pointer; text-align: left; color: var(--bs-body-color); font-size: 13px; }
.cb-quill .cb-tag-menu .cb-tag-item:hover { background: var(--bs-tertiary-bg); }
.cb-quill .cb-tag-menu .cb-tag-item code { color: var(--bs-secondary-color); font-size: 11px; }

/* Quill's link editor (snow .ql-tooltip) ships unstyled → invisible in dark mode. Theme it to the app
   (it's a control, not email content, so app-theme reads well over either editor surface). */
.cb-quill .ql-snow .ql-tooltip { background: var(--bs-body-bg); border: 1px solid var(--bs-border-color);
  color: var(--bs-body-color); border-radius: 8px; box-shadow: 0 4px 14px rgba(0,0,0,.18); }
.cb-quill .ql-snow .ql-tooltip::before { color: var(--bs-secondary-color); }
.cb-quill .ql-snow .ql-tooltip input[type=text] { background: var(--bs-body-bg); border: 1px solid var(--bs-border-color);
  color: var(--bs-body-color); border-radius: 4px; }
.cb-quill .ql-snow .ql-tooltip a.ql-action, .cb-quill .ql-snow .ql-tooltip a.ql-preview,
.cb-quill .ql-snow .ql-tooltip a.ql-remove { color: var(--bs-primary); }

/* WYSIWYG email preview (admin/system composer): show the editor surface as the RECIPIENT sees it —
   a light card — regardless of the app's dark/light theme. The "what you see" has to match the send. */
.cb-quill--email .ql-container.ql-snow,
.cb-quill--email .ql-editor { background: #ffffff; color: #1a1d21; }
.cb-quill--email .ql-editor.ql-blank::before { color: #98a0ab; }
.cb-quill--email .ql-editor a { color: #2b6cb0; }

/* ── Members dashboard (charts + world map + drag-to-reorder cards) ── */
.cb-map { height: 340px; position: relative; }
.cb-map svg { width: 100%; height: 100%; }
.cb-spark { margin-left: auto; }
.cb-toplist li + li { border-top: 1px solid var(--bs-border-color); }
.cb-bar-row + .cb-bar-row { margin-top: .55rem; }
.cb-bar { height: 8px; background: var(--bs-tertiary-bg); border-radius: 6px; }
/* The card heading IS the drag handle — grab anywhere on it to reorder. Move cursor on hover hints
   it's draggable; grabbing cursor takes over (everywhere) during an active drag. */
.cb-drag-handle { cursor: move; user-select: none; }
.cb-dash-card { transition: opacity .15s ease; }
.gu-mirror { cursor: grabbing; z-index: 1090; }
.gu-mirror .card { box-shadow: 0 12px 30px rgba(0,0,0,.22); border-color: var(--bs-primary); }
.gu-transit { opacity: .25; }
body.cb-dragging, body.cb-dragging * { cursor: grabbing !important; }
/* jsVectorMap tooltip → match theme (it appends .jvm-tooltip to <body>). */
.jvm-tooltip { background: var(--bs-body-bg) !important; color: var(--bs-body-color) !important;
  border: 1px solid var(--bs-border-color); box-shadow: 0 4px 14px rgba(0,0,0,.18); font-family: inherit; }
.jvm-zoom-btn { background: var(--bs-secondary-bg); color: var(--bs-body-color); border-radius: 4px; }

/* Brand-chrome preview: clickable logo thumbnails + a live email frame (logo header + compliance
   footer) around the editor, so staff see exactly what each brand's recipients get. Display only. */
.cb-brand-thumbs { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.cb-brand-thumbs-label { font-size: 12px; color: var(--bs-secondary-color); }
.cb-brand-thumb { display: inline-flex; align-items: center; justify-content: center; min-width: 46px; height: 34px;
  padding: 3px 8px; background: var(--bs-body-bg); border: 1px solid var(--bs-border-color); border-radius: 7px;
  cursor: pointer; color: var(--bs-body-color); font-size: 12px; font-weight: 600; }
.cb-brand-thumb img { max-height: 22px; max-width: 96px; object-fit: contain; }
.cb-brand-thumb:hover { border-color: var(--bs-primary); }
.cb-brand-thumb.cb-active { border-color: var(--bs-primary); box-shadow: 0 0 0 2px rgba(var(--bs-primary-rgb), .25); }
/* The framed email card. In email mode the toolbar sits on top; the white card holds header+body+footer. */
.cb-quill--framed .cb-quill-frame { background: #f5f6f8; border: 1px solid var(--bs-border-color);
  border-top: 0; border-radius: 0 0 12px 12px; padding: 18px; }
.cb-quill--framed .ql-toolbar.ql-snow { border-radius: 12px 12px 0 0; }
.cb-quill-brandhead { background: #fff; border: 1px solid #e2e5ea; border-bottom: 0; border-radius: 10px 10px 0 0;
  padding: 18px; text-align: center; }
.cb-quill--framed .ql-container.ql-snow { border-radius: 0 !important; border-color: #e2e5ea; }
.cb-quill-brandfoot { background: #fff; border: 1px solid #e2e5ea; border-top: 1px solid #eef0f3;
  border-radius: 0 0 10px 10px; padding: 14px 18px; text-align: center; font-size: 12px; color: #8a909a; }
.cb-quill-brandfoot a { color: #8a909a; text-decoration: underline; }
.cb-quill-brandfoot > div { margin-bottom: 6px; }
.cb-quill-brandfoot .cb-dot { margin: 0 6px; }
.cb-quill-brandfoot .cb-quill-footaddr { white-space: normal; }

/* ── Helpdesk queue (admin/tickets) ── */
.cb-min0 { min-width: 0; }
.cb-search { position: relative; }
.cb-search > .bx { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--bs-secondary-color); pointer-events: none; }
.cb-search input { padding-left: 34px; }
/* Clickable status stat cards */
.cb-statcard { transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease; border: 1px solid var(--bs-border-color); }
.cb-statcard:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(0,0,0,.08); }
.cb-statcard--active { box-shadow: 0 0 0 1px currentColor inset; }
/* Requester / agent avatars */
.cb-av { width: 40px; height: 40px; display: inline-flex; }
.cb-av .avatar-title { width: 40px; height: 40px; font-size: 14px; }
.cb-av-xs { width: 22px; height: 22px; }
.cb-av-sm { width: 32px; height: 32px; font-size: 12px; }
.cb-av-xs .avatar-title { width: 22px; height: 22px; font-size: 10px; }
/* Ticket rows: two-line, scannable, priority accent on the left edge */
.cb-tickets .cb-ticket { border-left: 3px solid transparent; padding: .8rem 1rem; }
.cb-tickets .cb-ticket:hover { background: var(--bs-tertiary-bg); }
.cb-ticket--urgent { border-left-color: var(--bs-danger); }
.cb-ticket--high { border-left-color: var(--bs-warning); }
.cb-ticket-subject { font-size: .95rem; }
.cb-ticket-preview { max-width: 100%; }

/* Ticket conversation: newest-first, scrollable beyond a sensible height (long threads). */
.cb-thread { max-height: 560px; overflow-y: auto; }

/* ── Integration install-guide tiles ── */
.cb-guide-tile { transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease; cursor: pointer; }
.cb-guide-tile:hover { transform: translateY(-3px); border-color: var(--bs-primary) !important;
  box-shadow: 0 10px 24px rgba(0, 0, 0, .10); }
.cb-guide-tile:hover .cb-guide-arrow { opacity: 1; transform: translateX(0); }
.cb-guide-arrow { opacity: 0; transform: translateX(-4px); transition: all .12s ease; color: var(--bs-primary); }
.cb-guide-ico { width: 42px; height: 42px; border-radius: 10px; flex: none;
  display: inline-flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 700; }
/* Brand logos are drawn for LIGHT backgrounds — the chip stays white in both themes so dark
   marks (Square, Ghost, WordPress…) never disappear in dark mode. */
.cb-guide-logo { width: 56px; height: 56px; border-radius: 12px; flex: none;
  background: #fff; border: 1px solid var(--bs-border-color);
  display: inline-flex; align-items: center; justify-content: center; }
.cb-guide-logo img { width: 32px; height: 32px; border-radius: 7px; /* softens full-bleed square favicon PNGs; no visible effect on transparent SVG marks */ }
.cb-guide-logo.cb-guide-letter { font-size: 24px; font-weight: 700; }
.cb-guide-blurb { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.35; min-height: 4.05em; }

/* ── Widget picker (Choices.js) — avatar chip per option ─────────────────── */
.cb-wsel-opt { display: flex; align-items: center; gap: 8px; }
.cb-wsel-av { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; flex: none;
  background: var(--bs-tertiary-bg); }
.cb-wsel-initial { display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: var(--bs-primary);
  background: var(--bs-primary-bg-subtle); }
.cb-wsel-iconchip { display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; color: var(--bs-secondary-color); background: var(--bs-tertiary-bg); }
/* inline usage next to labels: kill the plugin's default block margin, keep it compact */
.choices:has(select[data-cb-widgetselect]) { margin-bottom: 0; min-width: 200px; }
.cb-wsel-opt span { white-space: nowrap; }
/* let the open list size to its longest name instead of wrapping mid-word */
.choices:has(select[data-cb-widgetselect]) .choices__list--dropdown { width: max-content; min-width: 100%; }

/* ── Secondary buttons → the theme's SOFT look (btn-subtle): quiet primary-tinted chip that
   fills solid on hover/active. Solid gray (default AND my darker attempt) reads dead in both
   modes; the tint tracks --bs-primary so both themes and rebrands follow automatically. The
   solid active state doubles as the selected state for toggle groups (Light/Dark, devices). ── */
/* The theme's bootstrap build sets btn-secondary with LITERAL props + !important states, so
   this must match that weight — Bootstrap's CSS-var button API is bypassed there. */
.btn-secondary {
  color: var(--bs-primary);
  background-color: rgba(var(--bs-primary-rgb), .12);
  border-color: transparent;
}
.btn-secondary:hover, .btn-secondary:focus, .btn-secondary:active, .btn-secondary.active, .btn-secondary.show {
  color: #fff !important;
  background-color: var(--bs-primary) !important;
  border-color: transparent !important;
}
.btn-secondary:focus { box-shadow: 0 0 0 .15rem rgba(var(--bs-primary-rgb), .35) !important; }
.btn-secondary:disabled, .btn-secondary.disabled {
  color: var(--bs-secondary-color);
  background-color: var(--bs-tertiary-bg);
  border-color: transparent;
}

/* ── Appearance editor: preset cards (rendered by appearance-editor.js) ── */
.cb-preset-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .75rem; }
.cb-preset { display: flex; flex-direction: column; align-items: flex-start; gap: .25rem;
  padding: .75rem .9rem; text-align: left; cursor: pointer;
  border: 1px solid var(--bs-border-color); border-radius: .6rem;
  background: var(--bs-body-bg); color: var(--bs-body-color);
  transition: border-color .12s, box-shadow .12s; }
.cb-preset:hover { border-color: var(--bs-primary); }
.cb-preset.active { border-color: var(--bs-primary); box-shadow: 0 0 0 .15rem rgba(var(--bs-primary-rgb), .25); }
.cb-preset .sw { display: flex; gap: 4px; margin-bottom: .15rem; }
.cb-preset .sw i { width: 18px; height: 18px; border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, .12); display: block; }
.cb-preset .nm { font-weight: 600; font-size: .9rem; }
.cb-preset .ds { font-size: .78rem; color: var(--bs-secondary-color); }
/* delete badge on saved (custom) preset cards — click once to arm, again to confirm */
.cb-preset { position: relative; }
.cb-preset .cb-preset-del { position: absolute; top: .35rem; right: .5rem; font-size: .95rem;
  line-height: 1; padding: .1rem .3rem; border-radius: .35rem; color: var(--bs-secondary-color); }
.cb-preset .cb-preset-del:hover { color: #fff; background: var(--bs-danger); }
.cb-preset .cb-preset-del[data-arm="1"] { color: #fff; background: var(--bs-danger); font-size: .72rem; font-weight: 600; }

/* ── Dark-mode usability lift (system-wide) ─────────────────────────────────
   The theme's dark palette gives form controls the SAME background as the
   cards they sit in and near-invisible borders. Subtle, variable-driven
   adjustments: inputs read as inputs, nothing changes stylistically.
   Applies everywhere the shells load this sheet (members/admin/editors). */
[data-bs-theme="dark"] .form-control,
[data-bs-theme="dark"] .form-select,
[data-bs-theme="dark"] textarea.form-control {
  background-color: color-mix(in srgb, var(--bs-body-color) 4%, var(--bs-body-bg));
  border-color: color-mix(in srgb, var(--bs-body-color) 22%, transparent);
}
[data-bs-theme="dark"] .form-control:focus,
[data-bs-theme="dark"] .form-select:focus {
  background-color: color-mix(in srgb, var(--bs-body-color) 6%, var(--bs-body-bg));
  border-color: var(--bs-primary);
}
[data-bs-theme="dark"] .form-control::placeholder {
  color: color-mix(in srgb, var(--bs-body-color) 45%, transparent);
}
[data-bs-theme="dark"] .input-group-text {
  background-color: color-mix(in srgb, var(--bs-body-color) 7%, var(--bs-body-bg));
  border-color: color-mix(in srgb, var(--bs-body-color) 22%, transparent);
}
[data-bs-theme="dark"] .form-check-input:not(:checked) {
  background-color: color-mix(in srgb, var(--bs-body-color) 6%, var(--bs-body-bg));
  border-color: color-mix(in srgb, var(--bs-body-color) 30%, transparent);
}
/* Bordered choice cards (studio destination/palette tiles, preset cards):
   labels and icons get a touch more presence against dark card fills. */
[data-bs-theme="dark"] .cb-pal-tile,
[data-bs-theme="dark"] .cb-studio-dest {
  border-color: color-mix(in srgb, var(--bs-body-color) 18%, transparent) !important;
}
[data-bs-theme="dark"] .cb-pal-tile span,
[data-bs-theme="dark"] .cb-pal-tile i {
  color: color-mix(in srgb, var(--bs-body-color) 88%, var(--bs-primary));
}
[data-bs-theme="dark"] .cb-pal-tile:hover span,
[data-bs-theme="dark"] .cb-pal-tile:hover i {
  color: var(--bs-body-color);
}

/* ── Studio editor v3 (task #63): full-viewport workspace ─────────────────────
   The editor takes the whole screen over the admin chrome; the canvas gets every
   pixel by default. One right side panel slides in for whatever's being worked on
   (inspector / elements palette / theme) — closed until needed. */
.cb-sped-full { position: fixed; inset: 0; z-index: 1045; display: flex; flex-direction: column; background: var(--bs-body-bg); }
.cb-sped-top { display: flex; align-items: center; gap: .5rem; padding: .45rem .75rem; border-bottom: 1px solid var(--bs-border-color); background: var(--bs-body-bg); position: relative; z-index: 2; }
.cb-sped-top-center { position: absolute; left: 50%; transform: translateX(-50%); }
.cb-sped-body { flex: 1; display: flex; min-height: 0; position: relative; }
.cb-sped-canvasarea { flex: 1; min-width: 0; background: var(--bs-secondary-bg); }
.cb-sped-canvasarea #sped-canvas { display: block; width: 100%; height: 100%; border: 0; background: #fff; margin: 0 auto; }
.cb-sped-side { width: 340px; flex-shrink: 0; display: flex; flex-direction: column; border-left: 1px solid var(--bs-border-color); background: var(--bs-body-bg); margin-right: -340px; transition: margin-right .18s ease; overflow: hidden; }
.cb-sped-side.open { margin-right: 0; }
.cb-sped-side-head { display: flex; align-items: center; padding: .5rem .85rem; border-bottom: 1px solid var(--bs-border-color); }
.cb-sped-side-body { flex: 1; overflow-y: auto; padding: .85rem; }
@media (max-width: 900px) { .cb-sped-side { position: absolute; right: 0; top: 0; bottom: 0; box-shadow: -8px 0 24px rgba(0,0,0,.18); } }

/* Editor chrome buttons: neutral, readable in both modes. The theme styles
   .btn-secondary with LITERAL colors (not --bs-btn-* vars), so these must be concrete
   properties too — variable overrides silently lose. */
.cb-sped-top .btn-secondary,
[data-bs-theme=dark] .cb-sped-top .btn-secondary {
  background-color: transparent; border-color: transparent; color: var(--bs-body-color);
}
.cb-sped-top .btn-secondary:hover, .cb-sped-top .btn-secondary:focus, .cb-sped-top .btn-secondary:active,
[data-bs-theme=dark] .cb-sped-top .btn-secondary:hover, [data-bs-theme=dark] .cb-sped-top .btn-secondary:focus {
  background-color: var(--bs-secondary-bg); border-color: transparent; color: var(--bs-body-color);
}
/* Palette tiles: quiet neutral fill + SUBTLE border (borderless read wrong; it was the
   heavy dark-blue coloring that dated them) — primary tint + border on hover. */
.cb-sped-side .cb-pal-tile,
[data-bs-theme=dark] .cb-sped-side .cb-pal-tile {
  background-color: transparent; border: 1px solid var(--bs-border-color);
  color: var(--bs-secondary-color); border-radius: .6rem;
}
.cb-sped-side .cb-pal-tile:hover, .cb-sped-side .cb-pal-tile:focus,
[data-bs-theme=dark] .cb-sped-side .cb-pal-tile:hover, [data-bs-theme=dark] .cb-sped-side .cb-pal-tile:focus {
  background-color: var(--bs-primary-bg-subtle); border-color: var(--bs-primary);
  color: var(--bs-primary);
}


/* Funnel builder nodes (task #69) */
/* overflow VISIBLE: the ENTRY badge (top:-9px) and the yes/no ports (right:-6px) hang
   outside the card — the thumb clips its own oversized iframe, so nothing else needs it. */
.fnl-node { position: absolute; width: 190px; height: 152px; background: var(--bs-body-bg); border: 1.5px solid var(--bs-border-color); border-radius: .7rem; padding: 0; cursor: grab; user-select: none; box-shadow: 0 3px 10px -4px rgba(0,0,0,.25); }
.fnl-node-thumb { border-radius: .7rem .7rem 0 0; }
.fnl-node-thumb { position: relative; height: 104px; background: var(--bs-secondary-bg); overflow: hidden; border-bottom: 1px solid var(--bs-border-color); }
.fnl-node-thumb iframe { width: 1200px; height: 660px; border: 0; transform: scale(0.1567); transform-origin: top left; pointer-events: none; background: #fff; }
.fnl-node-thumb-empty { display: flex; align-items: center; justify-content: center; height: 100%; color: var(--bs-secondary-color); font-size: 1.6rem; opacity: .6; }
.fnl-node-info { padding: .4rem .75rem; }
.fnl-node:active { cursor: grabbing; }
.fnl-node.sel { border-color: var(--bs-primary); box-shadow: 0 0 0 3px var(--bs-primary-bg-subtle); }
.fnl-node.entry { border-left: 4px solid var(--bs-success); }
.fnl-node-title { font-weight: 600; font-size: .85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fnl-node-sub { font-size: .72rem; color: var(--bs-secondary-color); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fnl-node-badge { position: absolute; top: -9px; left: 8px; background: var(--bs-success); color: #fff; font-size: .58rem; font-weight: 700; letter-spacing: .06em; border-radius: 99px; padding: 1px 7px; }

/* Funnel nodes: real flow-chart feel. */
.fnl-node { touch-action: none; }
.fnl-node.dragging { cursor: grabbing; box-shadow: 0 10px 26px -10px rgba(0,0,0,.45); z-index: 3; transition: none; }
.fnl-port { position: absolute; right: -6px; width: 11px; height: 11px; border-radius: 50%;
  border: 2px solid var(--bs-body-bg); }
.fnl-port-yes { top: 46px; background: #22c55e; }
.fnl-port-no { bottom: 46px; background: #ef4444; }

/* Funnel node affordances: pencil-to-edit on hover, port cursors, wire-drop target glow. */
.fnl-node-edit { position: absolute; top: 5px; right: 6px; border: 1px solid var(--bs-border-color);
  background: var(--bs-body-bg); color: var(--bs-secondary-color); font-size: 14px; line-height: 1;
  padding: 3px 5px; border-radius: 6px; cursor: pointer; opacity: .85; box-shadow: 0 2px 6px -2px rgba(0,0,0,.3); }
.fnl-node:hover .fnl-node-edit, .fnl-node.sel .fnl-node-edit { opacity: 1; }
.fnl-node-edit:hover { color: var(--bs-primary); background: var(--bs-primary-bg-subtle); }
.fnl-port { cursor: crosshair; }
.fnl-port:hover { transform: scale(1.35); }
.fnl-node.target { border-color: var(--bs-primary); box-shadow: 0 0 0 4px var(--bs-primary-bg-subtle); }

/* Editor-inside-the-funnel overlay: the editor comes to you. */
.fnl-editor-overlay { position: fixed; inset: 0; z-index: 1060; background: var(--bs-body-bg); }
.fnl-editor-overlay iframe { width: 100%; height: 100%; border: 0; display: block; }
.fnl-editor-back { position: fixed; left: 50%; transform: translateX(-50%); bottom: 14px; z-index: 1061;
  display: inline-flex; align-items: center; gap: .4rem; border: 1px solid var(--bs-border-color);
  background: var(--bs-body-bg); color: var(--bs-body-color); font-size: .85rem; font-weight: 600;
  padding: .45rem 1.2rem; border-radius: 99px; box-shadow: 0 6px 20px -8px rgba(0,0,0,.4); cursor: pointer; }
.fnl-editor-back:hover { border-color: var(--bs-primary); color: var(--bs-primary); }

/* Funnel shelf: collapsed rail by default; opens to a slim tray. */
.fnl-shelf { width: 34px; flex-shrink: 0; border-right: 1px solid var(--bs-border-color);
  background: var(--bs-body-bg); display: flex; transition: width .15s ease; overflow: hidden; }
.fnl-shelf.open { width: 216px; }
.fnl-shelf-tab { flex: 0 0 34px; border: 0; background: transparent; color: var(--bs-secondary-color);
  cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: .5rem;
  padding-top: .8rem; font-size: .68rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.fnl-shelf-tab span { writing-mode: vertical-rl; }
.fnl-shelf-tab:hover, .fnl-shelf.open .fnl-shelf-tab { color: var(--bs-primary); }
.fnl-shelf-panel { width: 182px; overflow-y: auto; padding: .7rem .7rem .7rem 0; }
.fnl-shelf-hint { font-size: .72rem; color: var(--bs-secondary-color); margin-bottom: .7rem; }
.fnl-shelf-card { position: relative; border: 1.5px dashed var(--bs-border-color); border-radius: .6rem;
  overflow: hidden; margin-bottom: .6rem; cursor: grab; background: var(--bs-body-bg); }
.fnl-shelf-card:hover { border-color: var(--bs-primary); }
.fnl-shelf-thumb { height: 64px; overflow: hidden; background: var(--bs-secondary-bg); pointer-events: none; }
.fnl-shelf-thumb iframe { width: 1200px; height: 400px; border: 0; transform: scale(0.157); transform-origin: top left; background: #fff; }
.fnl-shelf-name { font-size: .78rem; font-weight: 600; padding: .3rem 1.6rem .35rem .55rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fnl-shelf-del { position: absolute; right: 4px; bottom: 3px; border: 0; background: transparent;
  color: var(--bs-secondary-color); font-size: 13px; padding: 2px; cursor: pointer; border-radius: 4px; }
.fnl-shelf-del:hover { color: var(--bs-danger); background: var(--bs-danger-bg-subtle); }
.fnl-shelf-empty { font-size: .75rem; color: var(--bs-secondary-color); }
.fnl-shelf-ghost { position: fixed; z-index: 1070; pointer-events: none; background: var(--bs-body-bg);
  border: 1.5px solid var(--bs-primary); border-radius: .5rem; padding: .3rem .7rem; font-size: .8rem;
  font-weight: 600; box-shadow: 0 8px 22px -8px rgba(0,0,0,.4); }
