/* ──────────────────────────────────────────────────────────────────────────
   Field 2 Service × Velzon — page-widget styles ONLY.
   Deliberately does NOT override Bootstrap .card/.table/.btn/.form-control/body —
   Velzon's app.min.css owns those so the whole app inherits the theme (incl. dark).
   Custom Field 2 Service widgets are themed with Velzon CSS variables (--vz-*) so they
   adapt to light/dark automatically.
   ────────────────────────────────────────────────────────────────────────── */

:root {
    --rfs-primary: var(--vz-primary, var(--vz-primary));
    --rfs-radius: var(--vz-border-radius, .375rem);
    /* Sidebar 10% narrower (Velzon default 250px → 225px); cascades to menu,
       content margin, topbar offset and footer since the lg layout reads this var */
    --vz-vertical-menu-width: 225px;
}

/* ── DESIGN-SYSTEM token foundation (consistency sweep, 2026-06-30) ─────────────
   Global SSOT for the consistency lane (DESIGN-SYSTEM.md §2 spacing · §3 radius ·
   §4 type). This is the one stylesheet linked on every page (layouts/velzon.php),
   so rfs-dispatch / rfs-settings / portal-calendar — all linked AFTER it — inherit
   these. Values ARE the SSOT's; pixels don't change, references do.
   NB: the page-scoped --set-r-* scale (rfs-settings.css) is deliberately NOT aliased
   here — its --set-r-md is 10px whereas this --r-md is 8px (DESIGN-SYSTEM §3).
   Off-scale font sizes (8.5/9/10/10.5/11.5/12.5/13.5/21/22/23px etc.) throughout this
   file are intentional design choices for dense UIs, micro-labels, and display numbers
   where the 8-step token scale has no exact match — owner-accepted WONTFIX (A-205/A-206/
   A-318/A-320/A-321). Do NOT snap these to the nearest --fs-* token. */
:root {
    /* Spacing (§2) — mirrors the settings --set-1..8 */
    --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
    --space-5: 20px; --space-6: 24px; --space-7: 32px; --space-8: 40px;
    --hair: 1px;  /* the 1px hairline border token (§2) */
    /* Accent (§1) — promote the scattered --disp-orange / bare #fb7a3c to ONE global accent */
    --rfs-accent: #fb7a3c;
    --rfs-accent-rgb: 251, 122, 60;  /* for rgba(var(--rfs-accent-rgb), α) */
    /* Radius (§3) — form controls use --r-md (8px)
       Off-scale accepted (owner 2026-06-30, A-325 WONTFIX): 12px = card/icon-box family;
       .55rem = .input-group-text (Bootstrap alignment). Do NOT snap these to the nearest token. */
    --r-sm: 6px; --r-md: 8px; --r-lg: 10px; --r-xl: 14px; --r-pill: 999px;
    /* Type scale (§4) */
    --fs-xs: .75rem; --fs-sm: .8rem; --fs-base: .875rem; --fs-lg: 1rem;
    --fs-xl: 1.125rem; --fs-xxl: 1.3rem; --fs-hero: 1.75rem;
}

/* ── Sidebar brand ─────────────────────────────────────────────────
   NB: do NOT set display on .logo-lg/.logo-sm — Velzon toggles those to collapse the brand in icon view */
.navbar-brand-box .logo-lg { white-space: nowrap; }

/* ── Sidebar menu hover/active highlight ──────────────────────────────────────
   NOTE: use DESCENDANT (`.navbar-nav li`) not direct-child (`.navbar-nav > li`).
   Velzon wraps the menu in SimpleBar (#navbar-nav > .simplebar-wrapper > … > .simplebar-content > li),
   so `.navbar-nav > li` no longer matches and the highlight silently stops working. */
.navbar-menu .navbar-nav li > .nav-link { border-radius: var(--r-sm); transition: background-color .15s ease, color .15s ease; }
.navbar-menu .navbar-nav li > .nav-link:hover { background-color: rgba(255,255,255,.12); color: #fff !important; }
.navbar-menu .navbar-nav li > .nav-link:hover i { color: #fff !important; }
.navbar-menu .navbar-nav li > .nav-link.active { background-color: rgba(255,255,255,.16); color: #fff !important; }
.navbar-menu .navbar-nav li > .nav-link.active i { color: #fff !important; }

/* ── Brand logo (RYKAI Field Pro) ─────────────────────────────────────────────
   The artwork is a wide canvas on a #071633 navy bg, so it blends into the sidebar.
   We crop to the wordmark with background-size/position rather than shrinking the
   whole canvas (which would make the text tiny). Extra top/bottom margin = padding. */
/* Brand marks: the real SVGs, no crop-from-one-JPG trickery. Wordmark when expanded, icon when collapsed. */
.rfs-brand-logo { display:block; background-repeat:no-repeat; background-position:50% 50%; background-size:contain; }
.navbar-brand-box .logo-lg .rfs-brand-logo { width:150px; height:26px; margin:22px auto; background-image:url('../images/f2s-wordmark.svg'); }
.navbar-brand-box .logo-sm .rfs-brand-logo { width:38px; height:38px; margin:16px auto; background-image:url('../images/f2s-icon.svg'); }
.horizontal-logo .logo-lg .rfs-brand-logo { width:38px; height:38px; margin:0; background-image:url('../images/f2s-icon.svg'); }

/* ── Quick-add "+" on creatable sidebar items ─────────────────────────────────
   A small add button at the right of a top-level nav row, shown on row hover. */
/* Descendant `#navbar-nav .nav-item` (not `>`) so it survives SimpleBar's wrapper divs (see note above).
   `.rfs-nav-add` is still a direct child of its own .nav-item, so the `> .rfs-nav-add` step is kept. */
#navbar-nav .nav-item { position:relative; }
.rfs-nav-add { position:absolute; top:9px; right:9px; width:26px; height:26px; display:none; align-items:center; justify-content:center;
    border-radius:7px; color:var(--rfs-accent); font-size:20px; line-height:1; text-decoration:none; z-index:3; transition:background .15s, color .15s; }
#navbar-nav .nav-item:hover > .rfs-nav-add { display:inline-flex; }
#navbar-nav .nav-item:hover > .nav-link .rfs-nav-badge { opacity:0; }
.rfs-nav-add:hover { background:rgba(var(--rfs-accent-rgb),.18); color:var(--rfs-accent) !important; }
/* Hide it when the sidebar is collapsed to the icon rail (no labels). */
[data-sidebar-size="sm"] .rfs-nav-add, [data-sidebar-size="sm-hover"] .vertical-menu .rfs-nav-add { display:none !important; }

/* ── Inline cell editing + column-picker rows ───────────────────────────── */
/* A cell is only interactive once its column's Columns→Edit box is on (.rfs-editable added by JS). */
.rfs-cell-edit { border-radius:4px; padding:1px 4px; }
.rfs-cell-edit.rfs-editable { cursor:pointer; border-bottom:var(--hair) dashed rgba(var(--vz-primary-rgb),.35); transition:background .12s, border-color .12s; }
.rfs-cell-edit.rfs-editable:hover { background:rgba(var(--vz-primary-rgb),.08); border-bottom-color:rgba(var(--vz-primary-rgb),.7); }
.rfs-cell-edit.rfs-editable input, .rfs-cell-edit.rfs-editable select { margin:-2px 0; }
/* Engineers multi-select panel (position:fixed coords set in JS so the table overflow can't clip it) */
.rfs-multi-pick { position:fixed; z-index:1090; min-width:184px; max-width:248px; background:var(--vz-secondary-bg); border:var(--hair) solid var(--vz-border-color); border-radius:var(--r-md); box-shadow:0 8px 24px rgba(16,24,40,.18); padding:6px; }
.rfs-multi-list { max-height:210px; overflow-y:auto; display:flex; flex-direction:column; gap:1px; }
.rfs-multi-opt { display:flex; align-items:center; gap:7px; font-size:13px; padding:var(--space-1) 7px; border-radius:5px; cursor:pointer; white-space:nowrap; margin:0; font-weight:500; }
.rfs-multi-opt:hover { background:rgba(var(--vz-primary-rgb),.08); }
/* Columns dropdown rows: label | View | Edit | reorder (Edit column drops out when nothing's editable) */
.rfs-cols-head, .rfs-col-row { display:grid; grid-template-columns:1fr 44px 44px 54px; align-items:center; column-gap:var(--space-1); }
.rfs-cols-head.rfs-no-edit, .rfs-col-row.rfs-no-edit { grid-template-columns:1fr 44px 54px; }
.rfs-cols-head { font-size:10.5px; font-weight:600; text-transform:uppercase; letter-spacing:.03em; }
.rfs-col-row { border-radius:var(--r-sm); padding-top:2px; padding-bottom:2px; }
.rfs-col-row:hover { background:rgba(var(--vz-primary-rgb),.05); }
/* Keep the whole picker within the viewport so it can't bleed into the top bar. */
.rfs-cols .dropdown-menu { max-height:calc(100vh - 90px); overflow-y:auto; }
.rfs-col-label { cursor:default; font-size:13px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rfs-col-row .rfs-col-view, .rfs-col-row .rfs-col-edit { justify-self:center; cursor:pointer; }
.rfs-col-row .rfs-col-view:disabled, .rfs-col-row .rfs-col-edit:disabled { cursor:not-allowed; opacity:.4; }
.rfs-col-reorder { display:flex; gap:2px; justify-self:end; }
.rfs-col-row .btn-icon { width:24px; height:24px; min-width:24px; padding:0; font-size:var(--fs-base); }

/* ── Reusable fixed-layout list tables (consistent width · truncation · drag-resize · sticky head) ──
   A list opts in by: (1) add `rfs-table-fixed` to the <table> and `rfs-table-wrap` to its
   `.table-responsive`; (2) give any 2-line / long-text cell a `title=` tooltip so nothing is lost
   (multi-line cells wrap their text block in `.rfs-trunc`); (3) supply per-column widths on the
   rfs-cols host via data-rfs-cols-widths '{"<colKey>":{"w":<px>,"min":<px>}, …}'. The resize+persist
   +reset engine lives once in initRfsCols() (field2service.js); widths ride the same rfs_cols_<listKey>
   store as show/hide/reorder, and the existing Reset clears them too. */
.rfs-table-fixed { table-layout:fixed; min-width:100%; }
/* Fixed layout makes the table width content-INDEPENDENT (identical every page); clip each cell so
   no content can widen its column — long text truncates to an ellipsis (full value in the title=). */
.rfs-table-fixed > thead > tr > th,
.rfs-table-fixed > tbody > tr > td { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* While a cell is inline-edited its editor may be wider than the column — let it escape the clip. */
.rfs-table-fixed > tbody > tr > td:focus-within { overflow:visible; }
/* 2-line cells (e.g. Job number + subtitle): the flex text block must be allowed to shrink so the
   subtitle ellipsises instead of widening the column (the usual offender). */
.rfs-table-fixed .rfs-trunc { min-width:0; }
.rfs-table-fixed .rfs-trunc > p { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Drag-to-resize grip on the right edge of each resizable <th> (added by initRfsCols). */
.rfs-table-fixed th.rfs-col-resizable { position:relative; }
.rfs-col-resizer { position:absolute; top:0; right:0; width:9px; height:100%; cursor:col-resize; touch-action:none; user-select:none; z-index:1; }
/* A light-grey hairline shown AT REST so the header reads as a resizable grid; it thickens + takes the
   brand colour on hover / while dragging so the grip obviously signals "draggable". Header cells only. */
.rfs-col-resizer::after { content:""; position:absolute; top:22%; right:3px; width:1px; height:56%; border-radius:2px; background:var(--vz-border-color); transition:background .12s, width .12s; }
.rfs-col-resizer:hover::after, body.rfs-col-resizing .rfs-col-resizer::after { width:2px; background:rgba(var(--vz-primary-rgb),.6); }
body.rfs-col-resizing { cursor:col-resize; user-select:none; }
/* ONE scrollbar (the owner's non-negotiable): the list flows in the page — no inner scroll box — so the
   whole page scrolls with the single browser scrollbar. The wrapper stays overflow:visible and the width
   engine (initRfsCols) fits the table to the card so it never needs a horizontal inner scroll either;
   only if a page's min column widths genuinely can't fit does the engine add .rfs-x-scroll for a graceful
   horizontal scroll on that page alone (phones likewise).
   No sticky header: page-relative sticky on the header <th> renders unreliably in Chromium for these
   list tables (only some cells stick — verified in-browser across border-collapse / table-layout /
   overflow permutations), so per the owner's stated priority (single scrollbar ≫ sticky header) the
   header scrolls with the page rather than reintroduce a second scroll box just to host it. */
.rfs-table-wrap { overflow:visible; }
.rfs-table-wrap.rfs-x-scroll { overflow-x:auto; }
@media (max-width:575.98px){ .rfs-table-wrap { overflow-x:auto; } }

/* ── Tighter sidebar: −1px text + slightly less padding so it fits without scrolling ── */
.navbar-menu .navbar-nav .nav-link { font-size: 15px; padding-top: .45rem; padding-bottom: .45rem; }
.navbar-menu .navbar-nav .nav-sm .nav-link { font-size: var(--fs-xs); padding-top: .3rem; padding-bottom: .3rem; }
.navbar-menu .navbar-nav .menu-title { padding-top: .9rem; padding-bottom: .3rem; }

/* ── Sidebar visual hierarchy (2026-07-05): section labels + a secondary tier ──
   .rfs-nav-2nd = secondary items sit back a step; the daily drivers (Hub / Dashboard / Jobs /
   Calendar / Customers) keep full weight. Opacity, not colour, so the per-company menu font
   colour still applies; hover / active / open submenu restore full weight. The class is only
   emitted for office users — field users' short menu is all drivers (and has no menu-titles). */
#navbar-nav .nav-link.rfs-nav-2nd { opacity: .72; }
#navbar-nav .nav-link.rfs-nav-2nd:hover,
#navbar-nav .nav-link.rfs-nav-2nd.active,
#navbar-nav .nav-link.rfs-nav-2nd[aria-expanded="true"] { opacity: 1; }

/* ── Command palette (Ctrl+K, rfs-palette.js) ─────────────────────────────
   Surfaces use --vz-secondary-bg / --vz-body-color so the panel follows the app theme AND the
   Hub command-center skin (the palette mounts inside .rfs-hub-cc on Hub pages; --vz-card-bg /
   --vz-light are undefined there — the known landmine — so they are never used here). */
.rfs-palette-overlay { position:fixed; inset:0; z-index:1080; display:none; background:rgba(15,23,42,.45);
  align-items:flex-start; justify-content:center; padding:10vh 16px 16px; }
.rfs-palette-overlay.show { display:flex; }
.rfs-palette { width:100%; max-width:620px; background:var(--vz-secondary-bg,#fff); color:var(--vz-body-color,#212529);
  border:1px solid var(--vz-border-color,#e9ebec); border-radius:var(--r-md,10px); box-shadow:0 18px 50px rgba(15,23,42,.35);
  display:flex; flex-direction:column; max-height:70vh; overflow:hidden; }
.rfs-palette-head { display:flex; align-items:center; gap:10px; padding:12px 16px; border-bottom:1px solid var(--vz-border-color,#e9ebec); }
.rfs-palette-head > i { font-size:18px; opacity:.6; }
.rfs-palette-input { flex:1; border:0; outline:0; background:transparent; color:inherit; font-size:15px; }
.rfs-palette-input:focus-visible { outline:2px solid var(--vz-primary,#405189); outline-offset:3px; border-radius:var(--r-sm,6px); }
.rfs-palette-head kbd { font-size:11px; padding:2px 7px; border-radius:5px; background:rgba(127,127,127,.14); color:inherit; opacity:.7; }
.rfs-palette-list { overflow-y:auto; padding:6px; }
.rfs-palette-sec { font-size:11px; letter-spacing:.05em; text-transform:uppercase; opacity:.55; padding:10px 12px 4px; }
.rfs-palette-row { display:flex; align-items:center; gap:11px; padding:8px 12px; border-radius:var(--r-sm,6px); cursor:pointer; }
.rfs-palette-row.active { background:rgba(var(--rfs-accent-rgb,79,70,229),.14); }
.rfs-palette-ic { font-size:17px; opacity:.65; flex:0 0 auto; }
.rfs-palette-body { min-width:0; flex:1; }
.rfs-palette-lbl { font-size:14px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rfs-palette-sub { font-size:12px; opacity:.6; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rfs-palette-badge { font-size:11px; opacity:.55; flex:0 0 auto; }

/* ── Roomier list tables (less squashed/busy) ─────────────────── */
.table.align-middle > tbody > tr > td { padding-top: .9rem; padding-bottom: .9rem; }
.table > thead > tr > th { padding-top: .75rem; padding-bottom: .75rem; font-size: 11px; letter-spacing: .03em; text-transform: uppercase; }
.table > tbody > tr { border-color: var(--vz-border-color); }
.card-header .nav-tabs-custom { margin-bottom: -1px; }

/* ── Record-detail sub-tab strips: one scrolling line, visually separate ──────
   The Overview/Items/Notes/… tabs on the job, customer, team-member and vehicle
   detail pages can run to a dozen tabs and used to WRAP onto two lines. Keep them
   on ONE line — scroll horizontally if they overflow — and give each tab a hairline
   divider so they read as distinct. Scoped via .rfs-detail-tabs so the list-page
   status tabs (also .nav-tabs-custom) stay as-is. Velzon's active-underline
   indicator (::after at bottom:0, inside the content box) is preserved;
   overflow-y:hidden only kills the phantom y-scrollbar that overflow-x:auto would
   otherwise imply. Long strips add `.rfs-tabscroll` on top for chevron scrolling
   (below) — the thin scrollbar here is the JS-off fallback. */
.rfs-detail-tabs { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
.rfs-detail-tabs::-webkit-scrollbar { height: 6px; }
.rfs-detail-tabs::-webkit-scrollbar-thumb { background: var(--vz-border-color); border-radius: 6px; }
.rfs-detail-tabs .nav-item + .nav-item { border-left: var(--hair) solid var(--vz-border-color); }
.rfs-detail-tabs .nav-link { white-space: nowrap; }

/* ── Detail sub-tabs · arrow-scroll enhancement (+328, Jobs preview) ──────────
   Replaces the horizontal scrollbar on the long detail strips with left/right
   chevrons (owner: the scrollbar "is ugly"). Opt-in via `.rfs-tabscroll`; the
   wrapper + buttons are built by initDetailTabScroll() in field2service.js, which adds
   `.is-enhanced` once wired — so with JS off the strip keeps its scrollbar (never a
   dead un-scrollable strip). Arrows appear only while the strip overflows, per
   usable direction only: a chevron (`.is-on`) shows ONLY for a side you can still
   scroll (right by default, left once scrolled) and takes NO space otherwise — so
   at the start the strip is flush-left, its first tab lined up with the content
   columns, and it returns there when you scroll back. Transparent buttons sit on
   the page bg — no colour to match. Scoped to Jobs for sign-off before Customers. */
.rfs-tabscroll-wrap { display: flex; align-items: stretch; margin-bottom: 1rem; }
/* !important beats Bootstrap's .mb-3 utility — otherwise the strip keeps a 1rem
   bottom margin that inflates the flex-row height, dropping the chevrons (and
   their underline) below the tab labels. Spacing is carried by the wrapper. */
.rfs-tabscroll-wrap > .rfs-detail-tabs { flex: 1 1 auto; min-width: 0; margin-bottom: 0 !important; }
.rfs-detail-tabs.rfs-tabscroll.is-enhanced { scrollbar-width: none; }
.rfs-detail-tabs.rfs-tabscroll.is-enhanced::-webkit-scrollbar { display: none; }
.rfs-tabscroll-btn {
  flex: 0 0 auto; width: 30px; padding: 0; display: none;
  align-items: center; justify-content: center;
  border: 0; border-bottom: var(--hair) solid var(--vz-border-color);
  background: transparent; color: var(--vz-secondary-color);
  font-size: 20px; line-height: 1; cursor: pointer; transition: color .15s;
}
.rfs-tabscroll-btn.is-on { display: inline-flex; }
.rfs-tabscroll-btn:hover { color: var(--vz-primary); }

/* ── Detail sub-tabs · darker/bolder active tab (+328, Jobs preview) ──────────
   The active tab read LIGHTER than its neighbours — Velzon hardcodes the active at
   a muted #405189 while inactive tabs are near-black #212529. Pull the active text
   + its underline to the brand primary and bump the weight so the selected tab is
   clearly the strongest. The `.nav-item` in the chain lifts specificity above
   Velzon's hardcode. Scoped to `.rfs-tabscroll` (Jobs) for sign-off. */
.rfs-detail-tabs.rfs-tabscroll .nav-item .nav-link.active { color: var(--vz-primary); font-weight: 600; }
.rfs-detail-tabs.rfs-tabscroll .nav-item .nav-link.active::after { background-color: var(--vz-primary); }

/* ── Table action buttons ─────────────────────────────────────── */
.table-actions { display: flex; gap: var(--space-1); justify-content: flex-end; }
.table-actions .btn { padding: var(--space-1) 8px; font-size: var(--fs-xs); }

/* ── §5 Button loading state (A-220) ──────────────────────────── */
.btn-loading { pointer-events: none; opacity: .72; cursor: not-allowed; position: relative; }
.btn-loading::after {
  content: ''; display: inline-block; width: .75em; height: .75em; margin-left: .45em;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; animation: rfs-spin .55s linear infinite; vertical-align: -.1em;
}
@keyframes rfs-spin { to { transform: rotate(360deg); } }

/* ══════════════════════════════════════════════════════════════════════════
   BUTTON SYSTEM — house SSOT for how buttons SIT TOGETHER  (2026-07-06)
   ──────────────────────────────────────────────────────────────────────────
   Velzon owns the base `.btn` look (see file header — we don't override it, so
   every variant keeps ONE uniform height/padding/radius/font/focus/disabled).
   This block owns the ROW: a cluster of actions must always align and read as
   one family. Full spec + variant taxonomy + copy-paste snippets → DESIGN-SYSTEM.md §5A.

   VARIANT TAXONOMY (map semantics onto Velzon's classes — never fork parallel ones):
     PRIMARY    the one main action ....... btn btn-primary
     SECONDARY  related, lower-emphasis ... btn btn-soft-primary
     POSITIVE   convert / confirm ......... btn btn-success  ·  btn btn-soft-success
     DANGER     destructive .............. btn btn-danger    ·  btn btn-soft-danger
     NEUTRAL    cancel / back / dismiss ... btn btn-light border
     ICON-ONLY  dense-row action .......... btn btn-icon btn-soft-*
   SIZE RULE: every button in ONE row shares ONE size — all default `.btn`, or all
   `.btn-sm` (dense/table rows). NEVER mix `.btn-sm` with full-size `.btn` in a row.

   ROW WRAPPER `.rfs-actions`: wrap any cluster of ≥2 buttons in it (add
   `.rfs-actions-end` to right-align). It vertically centres the row AND kills the
   #1 misalignment cause — a `<form class="d-inline">` wrapper's UA bottom-margin
   throwing the baseline of its bare-button siblings in a flex row.
   ══════════════════════════════════════════════════════════════════════════ */
.rfs-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.rfs-actions-end { justify-content: flex-end; }
/* Inline forms add no vertical space inside an action row (consolidated SSOT —
   was patched twice locally: rfs-settings §17 .rfs-autopage + .rfs-alert-actions). */
.rfs-actions form { margin-bottom: 0; }
/* Global safety net: a `d-inline` form is always an inline single-button wrapper,
   so it must never add a bottom margin, even in rows not wrapped in .rfs-actions. */
form.d-inline { margin-bottom: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   LIST ROW SYSTEM — house SSOT for list-table row typography + actions (2026-07-07)
   ──────────────────────────────────────────────────────────────────────────
   Ends the "random text sizes throughout" drift: every office list row uses ONE
   title / subtitle / action-cluster look, derived from the owner-approved Jobs
   list (`jobs/_list.php`). Sibling of the BUTTON SYSTEM block above —
   `.rfs-row-actions` is the dense table-cell twin of `.rfs-actions` (same
   vertical-centre + zero-form-margin invariant). Full spec → DESIGN-SYSTEM.md §5B.

     .rfs-row-title    primary-cell name/ref (link OR plain). Cell-sized (inherits
                       the table font-size — NO bare `<p>`/heading blowing it up,
                       which was the recurring/index.php drift), weight 600, body
                       colour. A LINK stays body-colour → primary on hover (mirrors
                       the Jobs `<a class="fw-semibold text-body">`).
     .rfs-row-sub      muted 12px second line; single-line, truncates to an ellipsis
                       (full text in a title="" on the same element or the .rfs-trunc
                       wrapper). Mirrors the Jobs `<p class="text-muted fs-12">`.
     .rfs-row-actions  dense right-aligned icon-button cluster, ALWAYS vertically
                       centred on a 1- OR 2-line row; a bare/`d-inline` <form> child
                       adds no margin (the off-centre-icons cause). Buttons inside
                       share ONE size (all `.btn-sm .btn-icon`) per the §5A size rule.
   ══════════════════════════════════════════════════════════════════════════ */
.rfs-row-title { font-weight: 600; color: var(--vz-body-color); line-height: 1.3; }
a.rfs-row-title, .rfs-row-title a { color: var(--vz-body-color); text-decoration: none; }
a.rfs-row-title:hover, .rfs-row-title a:hover { color: var(--vz-primary); }
.rfs-row-sub {
  margin: 0; font-size: var(--fs-xs); color: var(--vz-secondary-color); line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rfs-row-actions { display: inline-flex; align-items: center; justify-content: flex-end; gap: var(--space-1); }
.rfs-row-actions form { margin-bottom: 0; }

/* ── Status badge (dot + label) ───────────────────────────────── */
.status-badge { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; border-radius: 20px; font-size: var(--fs-xs); font-weight: 600; }
.status-badge::before { content: ''; display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: currentColor; opacity: .8; }

/* ── KPI gradient cards (legacy, still used in a few places) ───── */
.kpi-card { border: none; border-radius: 12px; padding: var(--space-5); color: #fff; }
.kpi-card .kpi-value { font-size: var(--fs-hero); font-weight: 700; line-height: 1; }
.kpi-card .kpi-label { font-size: var(--fs-xs); opacity: .85; margin-top: 4px; }
.kpi-card .kpi-sub   { font-size: var(--fs-xs); opacity: .7; margin-top: 6px; }
.kpi-blue   { background: linear-gradient(135deg, var(--vz-primary), #6366f1); }
.kpi-red    { background: linear-gradient(135deg, #ef4444, #f87171); }
.kpi-green  { background: linear-gradient(135deg, #22c55e, #4ade80); }
.kpi-purple { background: linear-gradient(135deg, #8b5cf6, #a78bfa); }
.kpi-amber  { background: linear-gradient(135deg, #f59e0b, #fbbf24); }

/* ── Line-items table (quotes / invoices) ─────────────────────── */
.line-items-table { width: 100%; }
.line-items-table th { font-size: 11px; font-weight: 700; color: var(--vz-secondary-color); text-transform: uppercase; padding: var(--space-2); background: var(--vz-light); border: var(--hair) solid var(--vz-border-color); }
.line-items-table td { padding: 6px; border: var(--hair) solid var(--vz-border-color); vertical-align: middle; }
.line-items-table input, .line-items-table select { font-size: var(--fs-base) !important; }
.line-items-total { background: var(--vz-light); padding: var(--space-3) 16px; border-radius: 0 0 var(--rfs-radius) var(--rfs-radius); border: var(--hair) solid var(--vz-border-color); border-top: 2px solid var(--vz-border-color); }

/* ── Detail rows (key/value on show pages) ────────────────────── */
.detail-row { display: flex; padding: 10px 0; border-bottom: var(--hair) solid var(--vz-border-color); font-size: var(--fs-base); }
.detail-row:last-child { border-bottom: none; }
.detail-label { color: var(--vz-secondary-color); width: 140px; flex-shrink: 0; font-size: var(--fs-sm); }
.detail-value { color: var(--vz-body-color); font-weight: 500; }

/* ── Priority colours ─────────────────────────────────────────── */
.priority-urgent { color: #ef4444; font-weight: 700; }
.priority-high   { color: #f59e0b; font-weight: 600; }
.priority-normal { color: var(--vz-secondary-color); }
.priority-low    { color: #94a3b8; }

/* ── Dashboard stat tiles (legacy fallback) ───────────────────── */
.stat-tile { position: relative; background: var(--vz-secondary-bg); border: var(--hair) solid var(--vz-border-color); border-radius: var(--r-xl); padding: 18px 20px; height: 100%; box-shadow: 0 1px 2px rgba(16,24,40,.04); transition: box-shadow .15s ease, transform .15s ease; overflow: hidden; }
.stat-tile::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--accent, var(--vz-primary)); opacity: .9; }
.stat-tile:hover { box-shadow: 0 6px 18px rgba(16,24,40,.10); transform: translateY(-2px); }
.stat-top { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 10px; }
.stat-icon { width: 40px; height: 40px; border-radius: 11px; display: flex; align-items: center; justify-content: center; font-size: 19px; flex-shrink: 0; }
.stat-label { font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--vz-secondary-color); padding-top: 4px; }
.stat-value { font-size: var(--fs-hero); font-weight: 700; line-height: 1.05; color: var(--vz-body-color); letter-spacing: -.02em; }
.stat-sub { font-size: 12.5px; margin-top: 6px; }
a.stat-link { display: block; text-decoration: none; color: inherit; cursor: pointer; }
a.stat-link:hover { text-decoration: none; color: inherit; }
.stat-tile.stat-active { border-color: var(--accent, var(--vz-primary)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent, var(--vz-primary)) 25%, transparent), 0 4px 12px rgba(16,24,40,.08); }
@media (max-width: 575px) { .stat-tile { padding: 14px 16px; border-radius: 12px; } .stat-value { font-size: 23px; } .stat-icon { width: 36px; height: 36px; font-size: 17px; } }

/* ── Assignee selection chips ─────────────────────────────────── */
.assignee-chip { display: flex; align-items: center; width: 100%; padding: var(--space-2) 12px; border: var(--hair) solid var(--vz-border-color); border-radius: var(--r-lg); cursor: pointer; font-size: var(--fs-base); transition: border-color .12s, background .12s; margin: 0; }
.assignee-chip:hover { border-color: var(--vz-primary); background: rgba(var(--vz-primary-rgb),.05); }
.assignee-chip:focus-visible { outline: 2px solid var(--vz-primary); outline-offset: 2px; }
.assignee-chip:has(input:checked) { border-color: var(--vz-primary); background: rgba(var(--vz-primary-rgb),.1); }
.assignee-chip .form-check-input { margin-top: 0; }

/* ── Job reference badge ──────────────────────────────────────── */
.job-ref-badge { display: inline-flex; align-items: center; gap: var(--space-1); background: rgba(var(--vz-primary-rgb),.1); color: var(--vz-primary); font-weight: 700; font-size: var(--fs-lg); letter-spacing: .01em; padding: 6px 14px; border-radius: var(--r-md); border: var(--hair) solid rgba(var(--vz-primary-rgb),.25); }
.job-ref-badge i { font-size: var(--fs-base); opacity: .7; }

/* ── Wizard steps (job/customer create) ───────────────────────── */
.wizard-steps { display: flex; align-items: center; justify-content: center; gap: 0; }
.wizard-step { display: flex; flex-direction: column; align-items: center; gap: 6px; opacity: .5; transition: opacity .2s; }
.wizard-step.active, .wizard-step.done { opacity: 1; }
.wizard-step-num { width: 38px; height: 38px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; background: var(--vz-light); color: var(--vz-secondary-color); transition: background .2s, color .2s; }
.wizard-step.active .wizard-step-num { background: var(--vz-primary); color: #fff; }
.wizard-step.done .wizard-step-num { background: var(--vz-success, #059669); color: #fff; }
.wizard-step.done .wizard-step-num { font-size: 0; }
.wizard-step.done .wizard-step-num::before { content: "\2713"; font-size: var(--fs-lg); }
.wizard-step-label { font-size: var(--fs-sm); font-weight: 600; color: var(--vz-body-color); }
.wizard-step-line { flex: 1; max-width: 80px; height: 2px; background: var(--vz-border-color); margin: 0 8px 22px; }
.wizard-nav { position: sticky; bottom: 0; display: flex; align-items: center; gap: var(--space-2); background: var(--vz-secondary-bg); border-top: var(--hair) solid var(--vz-border-color); padding: var(--space-3) 16px; margin: 0 -4px; border-radius: 0 0 12px 12px; box-shadow: 0 -2px 8px rgba(16,24,40,.04); }

/* ── Type toggle (Individual / Business) ──────────────────────── */
.type-toggle { display: flex; gap: 10px; }
.type-option { flex: 1; border: var(--hair) solid var(--vz-border-color); border-radius: var(--r-lg); padding: var(--space-3) 16px; text-align: center; cursor: pointer; font-weight: 600; color: var(--vz-body-color); transition: border-color .12s, background .12s; margin: 0; }
.type-option input { display: none; }
.type-option:hover { border-color: var(--vz-primary); }
.type-option:focus-visible { outline: 2px solid var(--vz-primary); outline-offset: 2px; }
.type-option.selected { border-color: var(--vz-primary); background: rgba(var(--vz-primary-rgb),.1); color: var(--vz-primary); }

/* ── Job view page widgets ────────────────────────────────────── */
.job-hero { background: linear-gradient(180deg, rgba(var(--vz-primary-rgb),.06), rgba(var(--vz-primary-rgb),.015)), var(--vz-card-bg, #fff); border: var(--hair) solid rgba(var(--vz-primary-rgb),.18); border-left: 5px solid var(--pcol, var(--vz-primary)); border-radius: var(--r-xl); padding: 22px 24px; box-shadow: none; }
.job-pill { display: inline-flex; align-items: center; gap: 2px; font-size: var(--fs-xs); font-weight: 600; padding: 3px 10px; border-radius: 20px; border: var(--hair) solid var(--vz-border-color); background: var(--vz-light); color: var(--vz-secondary-color); }
.assignee-avatar { width: 32px; height: 32px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; color: #fff; font-size: var(--fs-xs); font-weight: 700; }
.info-tile { display: flex; align-items: center; gap: var(--space-3); background: var(--vz-secondary-bg); border: var(--hair) solid var(--vz-border-color); border-radius: 12px; padding: 14px 16px; height: 100%; box-shadow: 0 1px 2px rgba(16,24,40,.04); }
.info-tile-icon { width: 42px; height: 42px; border-radius: 11px; display: flex; align-items: center; justify-content: center; font-size: 20px; flex-shrink: 0; }
.info-tile-body { min-width: 0; }
.info-tile-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--vz-secondary-color); }
.info-tile-value { font-size: var(--fs-xl); font-weight: 700; color: var(--vz-body-color); line-height: 1.2; }
.info-tile-sub { font-size: var(--fs-xs); color: var(--vz-secondary-color); }
/* Embedded location map (in the Location card, left half of the job-show stat row). */
.job-hero-map iframe { width: 100%; height: 170px; border: 0; border-radius: var(--r-lg); display: block; }
/* Detail-page primary heading — allows long unbroken tokens (URLs, part refs, model strings) to wrap
   rather than expanding the heading to force a full-page horizontal scroll. */
.rfs-hd-title { overflow-wrap:anywhere; word-break:break-word; }

/* In-card edge-to-edge tables (card-body.p-0): pad the OUTER cells so the row
   content lines up with the card header / padded cards around it, instead of
   sitting flush against the card edge. Uses the card's own spacer so it matches. */
.rfs-card-table > :not(caption) > * > *:first-child { padding-left: var(--vz-card-spacer-x, 1.25rem); }
.rfs-card-table > :not(caption) > * > *:last-child  { padding-right: var(--vz-card-spacer-x, 1.25rem); }

/* Job-show stat tiles as an equal-height grid. Mobile = 1 col (thin strips); ≥768 = 2×2
   with equal rows; ≥992 it fills its column height so it lines up with the Location card
   beside it. `--full` (no location) spreads to 4-up on desktop. */
.job-stat-grid { display: grid; grid-template-columns: 1fr; gap: 1rem; }
.job-stat-grid > .info-tile { height: 100%; }
@media (min-width: 768px) {
    .job-stat-grid { grid-template-columns: 1fr 1fr; grid-auto-rows: 1fr; }
    .job-stat-grid--full { grid-template-columns: repeat(4, 1fr); }
}
@media (min-width: 992px) {
    /* Full-column stretch is job-hero-ONLY: there the grid sits beside the full-height Location card and must
       match it. Scoped to `.job-hero` so pages that reuse `.job-stat-grid` on its own (e.g. customers/show.php)
       keep their natural ~90px tile height instead of stretching to the page's full content height (blank tiles). */
    .job-hero .job-stat-grid { height: 100%; }
    .job-hero-eng { min-width: 168px; }
}
/* `--2up`: force a 2×2 grid on phones (e.g. customer show stat tiles) with the chunky
   stacked tile (icon + label + value), instead of the default 1-up thin strips. Equal
   rows via grid-auto-rows. Overrides the global `.info-tile` mobile strip rules. */
@media (max-width: 767.98px) {
    .job-stat-grid--2up { grid-template-columns: 1fr 1fr; grid-auto-rows: 1fr; }
    .job-stat-grid--2up .info-tile { padding: var(--space-3) 14px; }
    .job-stat-grid--2up .info-tile-body { display: block; }
    .job-stat-grid--2up .info-tile-vals { text-align: left; }
    .job-stat-grid--2up .info-tile-value { font-size: 17px; }
}

@media (max-width: 767.98px) {
    /* Job hero was a tall, squashed block on phones — tighten padding + title, and stop
       the "Assigned Engineers" block being a forced right-aligned column (sit it left). */
    .job-hero { padding: 14px 14px; }
    .job-hero h3 { font-size: 1.2rem; line-height: 1.25; }
    .job-hero .text-end { text-align: left !important; min-width: 0 !important; }
    .job-hero .text-end .align-items-end { align-items: flex-start !important; }

    /* Job info-tiles → compact strips on phones (one per row). The 2×2 chunky
       tiles wrapped their values ("Fixed Price", "Est. 0h 30m") awkwardly; now
       it's icon · LABEL (left) · value + sub (right-aligned, stacked) — full
       width so nothing wraps mid-word, and the sub-line is KEPT. */
    .info-tile { padding: 9px 14px; gap: var(--space-3); }
    .info-tile-icon { width: 34px; height: 34px; font-size: var(--fs-lg); border-radius: 9px; }
    .info-tile-body { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex: 1; min-width: 0; }
    .info-tile-label { font-size: 11px; white-space: nowrap; flex-shrink: 0; }
    .info-tile-vals { text-align: right; min-width: 0; }
    .info-tile-value { font-size: 15px; line-height: 1.25; }
    .info-tile-sub { font-size: 11px; line-height: 1.2; }
}
.checkin-bar { display: flex; align-items: center; gap: var(--space-3); background: var(--vz-secondary-bg); border: var(--hair) solid var(--vz-border-color); border-radius: 12px; padding: var(--space-3) 16px; }
.checkin-bar.checked-in { border-color: var(--vz-success, #22c55e); background: rgba(34,197,94,.08); }

/* ── Notes / timeline ─────────────────────────────────────────── */
.note-item { background: var(--vz-secondary-bg); border: var(--hair) solid var(--vz-border-color); border-left: 3px solid var(--vz-primary); border-radius: var(--r-lg); padding: var(--space-3) 14px; margin-bottom: 10px; }
.note-item .note-text, .note-text { font-size: var(--fs-base); color: var(--vz-body-color); }
.note-item .note-meta, .note-meta { font-size: var(--fs-xs); color: var(--vz-secondary-color); margin-top: 4px; }

/* ── Dashboard list rows (legacy dashboard, kept) ─────────────── */
.dash-list .dl-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-3) 18px; border-bottom: var(--hair) solid var(--vz-border-color); }
.dash-list .dl-row:last-child { border-bottom: 0; }
.dash-list .dl-row:hover { background: var(--vz-light); }
.dash-list .dl-title { font-weight: 600; font-size: var(--fs-base); color: var(--vz-body-color); text-decoration: none; }
.dash-list .dl-title:hover { color: var(--vz-primary); }
.dash-list .dl-sub { font-size: var(--fs-xs); color: var(--vz-secondary-color); margin-top: 1px; }
.dash-empty { padding: 28px; text-align: center; color: var(--vz-secondary-color); font-size: var(--fs-base); }
.dash-empty i { display: block; font-size: 26px; margin-bottom: 6px; }
.activity-row { display: flex; align-items: center; gap: var(--space-3); padding: 11px 18px; border-bottom: var(--hair) solid var(--vz-border-color); font-size: var(--fs-base); }
.activity-row:last-child { border-bottom: 0; }
.activity-row .ar-ico { flex-shrink: 0; width: 30px; height: 30px; border-radius: var(--r-md); display: flex; align-items: center; justify-content: center; background: var(--vz-light); }
.activity-row .ar-desc { flex: 1; color: var(--vz-body-color); }
.activity-row .ar-meta { font-size: var(--fs-xs); color: var(--vz-secondary-color); white-space: nowrap; }

/* ─────────────────────────── Mobile polish ─────────────────────────── */
@media (max-width: 767.98px) {
    /* Never let a stray wide element push the whole page sideways */
    body { overflow-x: hidden; }
    /* De-clutter the top bar on phones: hide the non-essential AI-usage chip so Add / bell / avatar breathe */
    #rfs-ai-usage { display: none !important; }
    /* Tighter card padding so content gets more width on phones */
    .card-body { padding: 1rem; }
    .page-content { padding-left: 12px; padding-right: 12px; padding-bottom: 5.5rem; }
    /* Action bars / button groups always wrap instead of overflowing */
    .d-flex.gap-2, .d-flex.gap-3 { flex-wrap: wrap; }
    /* Tables: scroll inside their wrapper + a touch smaller */
    .table-responsive { -webkit-overflow-scrolling: touch; }
    .table { font-size: 13px; }
    .table > :not(caption) > * > * { padding-left: .5rem; padding-right: .5rem; }
    /* Modals breathe to the screen edges */
    .modal-dialog { margin: .5rem; }
    /* Detail rows stack their label above the value */
    .detail-row { flex-direction: column; align-items: flex-start; gap: 1px; }
    /* The sticky wizard nav stays usable + lifts its buttons WELL off the screen edge (gesture bar /
       rounded corners). 14px felt jammed against the bottom — give the primary button real breathing room. */
    .wizard-nav { flex-wrap: wrap; gap: var(--space-2); margin-top: 14px; padding-top: 14px; padding-bottom: calc(28px + env(safe-area-inset-bottom, 0px)); }
    /* Big page headings scale down a little */
    h1, .h1 { font-size: 1.5rem; } h2, .h2 { font-size: var(--fs-xxl); }
    /* Line-items table → stacked cards on mobile (v0.9). Was min-width:560px (h-scroll).
       The table is unreadable squashed on a phone; reflow each row to a labelled card.
       Pure CSS via the fixed 7-col order — works for static + JS-added rows on all 5
       invoice/quote/job-create forms (they share `.line-items-table` + `.line-item-row`). */
    .line-items-table { min-width: 0 !important; }
    .line-items-table thead { display: none; }
    .line-items-table tbody, .line-items-table tr.line-item-row, .line-items-table tr.line-item-row td { display: block; width: 100% !important; }
    .line-items-table tr.line-item-row { border: var(--hair) solid var(--vz-border-color); border-radius: var(--r-lg); padding: 10px 12px; margin: 0 12px 12px; }
    .line-items-table tr.line-item-row td { border: none !important; padding: 5px 0 !important; }
    .line-items-table tr.line-item-row td::before {
        display: block; font-size: 10.5px; font-weight: 600; text-transform: uppercase;
        letter-spacing: .03em; color: var(--vz-secondary-color); margin-bottom: 3px;
    }
    .line-items-table tr.line-item-row td:nth-child(1)::before { content: "Description"; }
    .line-items-table tr.line-item-row td:nth-child(2)::before { content: "Quantity"; }
    .line-items-table tr.line-item-row td:nth-child(3)::before { content: "Unit Price"; }
    .line-items-table tr.line-item-row td:nth-child(4)::before { content: "Discount"; }
    .line-items-table tr.line-item-row td:nth-child(5)::before { content: "Tax Rate"; }
    .line-items-table tr.line-item-row td:nth-child(6)::before { content: "Line Total"; }
    .line-items-table tr.line-item-row td:nth-child(6) { border-top: var(--hair) dashed var(--vz-border-color) !important; margin-top: 4px; padding-top: 8px !important; }
    .line-items-table tr.line-item-row td:nth-child(7) { text-align: right; padding-top: 4px !important; }
    .line-items-table tr.line-item-row td:nth-child(7)::before { display: none; content: ""; }
    /* totals summary: the gap-5 overflows on phones */
    .line-items-total .d-flex.gap-5 { gap: 0 !important; justify-content: space-between !important; }
    /* Dropdown menus never spill past the screen edge */
    .dropdown-menu { max-width: calc(100vw - 24px); }

    /* ── Tabs (Active / Completed / Deleted …) on phones ──────────────────
       They wrapped to a 2nd row and the `ms-auto` "Deleted" got bumped to its
       own right-aligned line — looked broken. Make the tab strip a single
       horizontally-scrollable row; drop the ms-auto bump so Deleted sits inline. */
    .nav-tabs-custom {
        flex-wrap: nowrap !important;
        overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .nav-tabs-custom::-webkit-scrollbar { display: none; }
    .nav-tabs-custom .nav-item { flex-shrink: 0; }
    .nav-tabs-custom .nav-item.ms-auto { margin-left: 0 !important; }
    /* slightly smaller text + tighter padding so more tabs fit on screen (most users
       see them all without scrolling); horizontal scroll stays as a backstop. */
    .nav-tabs-custom .nav-link { padding-left: .42rem; padding-right: .42rem; white-space: nowrap; font-size: 13px; }
    .nav-tabs-custom .nav-link .badge { font-size: 9px; padding: .14em .36em; margin-left: 3px !important; }

    /* ── List tables → stacked cards on phones (v0.9) ────────────────────
       `table.rfs-tcards` is tagged by the field2service.js enhancer (list tables only).
       Each row becomes a card; each cell is a "Label — value" line. Kills the
       horizontal table scroll (content was cut at the screen edge). */
    table.rfs-tcards { min-width: 0 !important; }
    table.rfs-tcards thead { display: none; }
    table.rfs-tcards, table.rfs-tcards tbody { display: block; width: 100%; }
    table.rfs-tcards tbody tr { display: block; border: var(--hair) solid var(--vz-border-color); border-radius: var(--r-lg); padding: var(--space-1) 12px; margin: 0 0 10px; }
    table.rfs-tcards tbody td {
        display: flex; justify-content: space-between; align-items: center; gap: var(--space-3);
        border: 0 !important; padding: 6px 0 !important; text-align: right; white-space: normal;
    }
    table.rfs-tcards tbody td::before {
        content: attr(data-label); font-size: 11px; font-weight: 600; text-transform: uppercase;
        letter-spacing: .02em; color: var(--vz-secondary-color); text-align: left; white-space: nowrap; flex-shrink: 0;
    }
    table.rfs-tcards tbody td:not([data-label]) { justify-content: flex-end; }
    table.rfs-tcards tbody td:not([data-label])::before { display: none; }
    table.rfs-tcards .table-actions { justify-content: flex-end; }

    /* Tables that opt OUT of the card reflow (`rfs-no-tcards`, e.g. the Jobs list)
       scroll left/right on phones. Keep cells on one line so the row scrolls
       instead of wrapping (covers tables without the Bootstrap `table-nowrap`
       class), and give the rows a bit more vertical padding than Bootstrap's
       tight .5rem so they're not cramped while scrolling. */
    table.rfs-no-tcards { white-space: nowrap; }
    table.rfs-no-tcards thead th,
    table.rfs-no-tcards tbody td { padding-top: .95rem !important; padding-bottom: .95rem !important; }
}

/* ── Compact stat / KPI tiles on mobile (v0.9) ───────────────────────────
   `.card-animate` is used ONLY by stat tiles across the whole app (dashboard,
   jobs, customers, quotes, invoices, leads, tasks, time, price book, reports),
   so compacting it here slims EVERY page's tiles with no side effects.
   Goal: 2-up everywhere (col-6 handles that) + MUCH shorter tiles (number +
   small label, minimal padding) + even heights when one label wraps. */
@media (max-width: 767.98px) {
    /* height:100% makes paired tiles in a row match even when one tile's sub-line
       (e.g. "0 today · 0 this week") wraps to 2 lines and the neighbour's doesn't —
       kills the ragged-bottom-edge look. The .row already stretches the columns. */
    .card-animate { margin-bottom: .5rem; height: 100%; }
    /* …and CENTRE the content vertically. Without this, the label+number sit at the top of the
       stretched tile with dead space below — which made the active-filter tile's selected RING look
       like an oversized empty box bleeding past its neighbour on the list pages. Balanced now. */
    .card-animate .card-body { padding: .6rem .72rem; min-height: 4.3rem; display: flex; flex-direction: column; justify-content: center; }
    /* kill the big label→value spacers (mt-3 / mt-4) so the tile is a slim strip */
    .card-animate .card-body .mt-2,
    .card-animate .card-body .mt-3,
    .card-animate .card-body .mt-4 { margin-top: .3rem !important; }
    .card-animate .card-body .mb-1,
    .card-animate .card-body .mb-2 { margin-bottom: .1rem !important; }
    /* label: clamp to 2 lines so 1- and 2-line neighbours keep EQUAL height */
    .card-animate .text-uppercase {
        font-size: .66rem !important; line-height: 1.14; letter-spacing: .02em;
        display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
    }
    /* the big number — smaller so the whole tile is a compact strip */
    .card-animate h4, .card-animate .fs-22 { font-size: 1.15rem !important; line-height: 1.1; }
    /* sub-text (e.g. "0 today · 0 this week") */
    .card-animate .fs-12 { font-size: .66rem !important; }
    /* icon avatar shrinks so it never drives the tile height */
    .card-animate .avatar-sm { height: 1.9rem; width: 1.9rem; }
    .card-animate .avatar-sm .avatar-title { font-size: .95rem !important; }
    /* Labels using Bootstrap `text-truncate` (Reports KPIs, dashboard tiles) clip to
       "Revenue Collect…". On mobile, wrap them to 2 lines instead of truncating. */
    .card-animate .card-body .text-truncate {
        white-space: normal;
        display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
    }
    /* Active (selected-filter) tile: the bare 1px `border border-{tone}` reads like a stray
       focus outline on mobile. Make it a deliberate "selected" look — soft tint + soft ring. */
    .card-animate.border {
        border-color: transparent !important;
        background: rgba(var(--vz-primary-rgb), .055) !important;
        /* INSET ring (drawn inside the tile edge) so the selected highlight can never paint past
           the tile / bleed past its neighbour the way an outset 0 0 0 1.5px ring did. */
        box-shadow: inset 0 0 0 1.5px rgba(var(--vz-primary-rgb), .38) !important;
    }
}

/* ── Condensed stat tiles (mobile) — the 8 "stats" list pages ────────────
   Applied via `.rfs-stats-tight` on the stat .row of jobs/customers/quotes/
   invoices/pricebook/tasks/leads/time (NOT dashboard or reports — those keep
   the standard taller tile). Drops the min-height, tightens padding + the
   label→number gap, shrinks the icon + number so the 2×2 grid is shorter.
   Iterate the numbers here; remove the class from a row to opt that page out. */
@media (max-width: 767.98px) {
    .rfs-stats-tight .card-animate .card-body { padding: .45rem .6rem; min-height: 0; }
    .rfs-stats-tight .card-animate .card-body .mt-2,
    .rfs-stats-tight .card-animate .card-body .mt-3,
    .rfs-stats-tight .card-animate .card-body .mt-4 { margin-top: .1rem !important; }
    .rfs-stats-tight .card-animate h4,
    .rfs-stats-tight .card-animate .fs-22 { font-size: 1.05rem !important; line-height: 1.05; }
    .rfs-stats-tight .card-animate .avatar-sm { height: 1.55rem; width: 1.55rem; }
    .rfs-stats-tight .card-animate .avatar-sm .avatar-title { font-size: var(--fs-sm) !important; }
}

/* ── AI launcher hidden on form pages (v0.9) ─────────────────────────────
   The floating AI sparkle (#rfs-ai-launch) sat ON TOP of the primary submit
   button in `.wizard-nav` (Next / Create Invoice / Save) on every create/edit
   form, and even when raised it covered nearby fields. On any page with a
   sticky form footer, hide the FAB — the assistant is still one tap away via
   the topbar usage pill (which opens the same chat). */
body:has(.wizard-nav) #rfs-ai-launch { display: none !important; }

/* …and whenever ANY modal is open, the FAB floated on top of the modal (lead/task/
   email/record-payment/quick-add-customer). Bootstrap puts `modal-open` on <body>
   while a modal is showing — hide the FAB for the duration so it never overlaps. */
body.modal-open #rfs-ai-launch { display: none !important; }

/* Hide-on-scroll (phones): the FAB overlapped right-aligned card values (status badge,
   date) on list/show pages while scrolling. field2service.js adds .rfs-fab-tuck while scrolling
   DOWN and removes it on scroll-up / near the top. transform rides the base .15s transition. */
#rfs-ai-launch.rfs-fab-tuck { transform: translateY(160%); pointer-events: none; }

/* On very small phones, keep stat tiles 2-up (NOT 1-up) — just trim the number a touch */
@media (max-width: 359.98px) {
    .stat-value { font-size: 20px; }
    .card-animate h4, .card-animate .fs-22 { font-size: 1.05rem !important; }
    .card-animate .text-uppercase { font-size: .62rem !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   MOBILE DESIGN SYSTEM — Phase 1 (2026-07-24)
   Reusable phone layer so mobile polish lives ONCE, not as per-page hacks.
   THE phone breakpoint (SSOT): 767.98px — the value already used by every
   mobile block above (card reflow, stat compacting, tap sizing). Reuse it;
   don't introduce a second phone breakpoint.
   Pieces: .rfs-stat-grid (2×2 KPI grid) · .rfs-hscroll (snap rail for 5+
   tiles / chip strips) · the tap-target floor · .rfs-mcards (priority-column
   list cards). Spec: rykai-fs-dev/MOBILE-UX-REPORT-2026-07-24.md §"foundational move".
   ══════════════════════════════════════════════════════════════════════════ */

/* ── .rfs-stat-grid — the KPI container ───────────────────────────────────
   Desktop: an auto-fit row that never squashes below a comfortable tile width.
   Phone (≤767.98px): a clean 2×2 grid (the owner's explicit ask) with a min
   tile height so a 1-line and a 2-line tile stay equal and nothing crushes.
   Drop-in: replace a `.row g-3` of stat columns with this on the container and
   let the tiles be direct children (no col-* needed). */
.rfs-stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--space-3); }
.rfs-stat-grid > * { margin: 0; min-width: 0; }
@media (max-width: 767.98px) {
    .rfs-stat-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
    .rfs-stat-grid > * { min-height: 4.2rem; }
}

/* ── .rfs-hscroll — opt-in horizontal SNAP rail ───────────────────────────
   For 5+ stat tiles, filter-chip strips or timeline rails: a deliberate
   sideways scroll with a peek of the next card as the swipe affordance and a
   hidden scrollbar. A horizontal grid rail sizes itself — it only scrolls when
   the children genuinely don't fit (so it's a normal row on desktop, a snap
   rail on a phone). Children are the tiles/chips directly. */
.rfs-hscroll {
    display: grid; grid-auto-flow: column; grid-auto-columns: minmax(200px, 1fr);
    gap: var(--space-3); overflow-x: auto; scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.rfs-hscroll::-webkit-scrollbar { display: none; }
.rfs-hscroll > * { scroll-snap-align: start; min-width: 0; margin: 0; }
@media (max-width: 767.98px) {
    /* ~1.8 tiles in view on a phone so the next-card peek reads as "swipe me" */
    .rfs-hscroll { grid-auto-columns: 56%; gap: 10px; }
}

/* ── Tap-target floor (≤767.98px) ─────────────────────────────────────────
   Scoped to the surfaces that measured sub-38px (list action icons + inline-
   edit cells) — NOT a blanket bump of every .btn-icon (that would bloat the
   topbar). ≥40px is the comfortable thumb-tap floor. */
@media (max-width: 767.98px) {
    .rfs-row-actions .btn-icon,
    .rfs-mcards td .btn-icon { min-width: 40px; min-height: 40px; }
    .table .rfs-cell-edit { display: inline-flex; align-items: center; min-height: 34px; }
    .rfs-mcards .rfs-cell-edit { min-height: 40px; }
}

/* ── .rfs-mcards — priority-column list CARDS (≤767.98px) ──────────────────
   The middle path the owner asked for: NOT a sideways 12-column data-grid, NOT
   a label-every-cell dump. Each row → a 2-line card showing only the fields
   that matter. The field2service.js engine adds `.rfs-mcards` when a list partial
   tags its identity cell [data-mobile-primary]; the meta cells carry
   [data-mobile-secondary]; every other cell is hidden on phones. The whole
   card is tappable to the record (JS); the action icons stay top-right.
   (On phone the fixed-column width engine releases its px widths for these
   tables — see rfsReleaseColWidths in field2service.js — so the card CSS governs.) */
@media (max-width: 767.98px) {
    table.rfs-mcards { display: block; width: 100%; min-width: 0 !important; }
    table.rfs-mcards > thead { display: none; }
    table.rfs-mcards > tbody { display: block; }
    table.rfs-mcards > tbody > tr {
        display: flex; flex-wrap: wrap; align-items: flex-start;
        column-gap: 10px; row-gap: 5px; position: relative;
        border: var(--hair) solid var(--vz-border-color); border-radius: var(--r-lg);
        padding: 12px 14px; margin: 0 0 10px; cursor: pointer;
    }
    table.rfs-mcards > tbody > tr:hover { background: var(--vz-light); }
    /* Every cell hidden by default; primary / secondary / actions opt back in.
       Override the fixed-layout clip (nowrap/ellipsis/overflow) inherited from
       .rfs-table-fixed so card content can wrap. */
    table.rfs-mcards > tbody > tr > td {
        display: none; border: 0 !important; padding: 0 !important;
        white-space: normal; overflow: visible; max-width: 100%;
    }
    /* Line 1 — identity block. flex-basis:0 so line-collection ignores its (wide)
       content and the action cluster always shares line 1; grow then fills the rest,
       pinning actions hard-right. (flex:1 1 62% let the 62% hypothetical width push a
       4-icon action cluster onto its own line — fixed.) */
    table.rfs-mcards > tbody > tr > td[data-mobile-primary] {
        display: block; flex: 1 1 0; min-width: 0; order: 1;
    }
    /* Actions — top-right of the card on line 1. */
    table.rfs-mcards > tbody > tr > td[data-col="_actions"] {
        display: block; flex: 0 0 auto; order: 2; text-align: right;
    }
    table.rfs-mcards > tbody > tr > td[data-col="_actions"] .rfs-row-actions { flex-wrap: wrap; justify-content: flex-end; }
    /* Forced line break after the identity+actions row so the whole meta strip drops to
       line 2 together (a 0-height, full-width flex item — without it a short meta chip
       can back-fill line 1 next to the shrunk primary). */
    table.rfs-mcards > tbody > tr::after { content: ""; flex: 0 0 100%; height: 0; order: 3; }
    /* Line 2 — the meta strip: status / date / value / customer chips flow inline + wrap.
       min-width:0 + wrap + overflow-wrap so a long free-text chip (customer/company name)
       wraps instead of bleeding past the card edge (never re-introduces horizontal scroll). */
    table.rfs-mcards > tbody > tr > td[data-mobile-secondary] {
        display: inline-flex; align-items: center; gap: 4px; flex: 0 1 auto; order: 4;
        min-width: 0; max-width: 100%; white-space: normal; overflow-wrap: anywhere;
        font-size: 13px; color: var(--vz-secondary-color); line-height: 1.5;
    }
    table.rfs-mcards > tbody > tr > td[data-mobile-secondary] .rfs-cell-edit { color: var(--vz-body-color); }
    /* the primary title/subtitle already carry .rfs-row-title / .rfs-row-sub;
       let the subtitle wrap to 2 lines in a card rather than ellipsise to one. */
    table.rfs-mcards .rfs-trunc > p.rfs-row-sub { white-space: normal; }
    /* Keep the identity block to name + subtitle on a phone card: hide the desktop-only
       detail extras (ref line, tag row, category / linked-customer badges) tagged
       `.rfs-m-min` so a tagged customer / lead / ticket card stays crisp, not 4-5 lines
       tall. Desktop is untouched (rule is inside the phone media query). */
    table.rfs-mcards .rfs-m-min { display: none !important; }
}

/* ─────────────────────── Dark-mode safety net ───────────────────────
   Bootstrap's FIXED light utilities (.bg-light / .table-light / .text-dark)
   don't adapt, so panels, table heads and badges glow white in dark mode.
   Remap them onto Velzon's theme-aware --vz-light surface. Every rule is
   scoped to [data-bs-theme="dark"] so LIGHT MODE IS COMPLETELY UNTOUCHED. */
[data-bs-theme="dark"] .bg-light { background-color: var(--vz-light) !important; }
[data-bs-theme="dark"] .bg-light.text-dark,
[data-bs-theme="dark"] .bg-dark-subtle.text-dark { color: var(--vz-body-color) !important; }
[data-bs-theme="dark"] .table-light,
[data-bs-theme="dark"] .table > thead.table-light th {
    --bs-table-bg: var(--vz-light);
    --bs-table-color: var(--vz-body-color);
    color: var(--vz-body-color);
}
/* Search-result dropdowns & popovers sit on bg-body — give them a clear edge in dark */
[data-bs-theme="dark"] .shadow-sm { box-shadow: 0 2px 10px rgba(0,0,0,.5) !important; }

/* ─────────────────── Mobile menu / hamburger ───────────────────
   Desktop (≥1025px): full sidebar always visible → NO hamburger.
   Below that: sidebar is an off-canvas overlay, toggled by the hamburger. */
#topnav-hamburger-icon { display: none !important; }
@media (max-width: 1024.98px) {
    #topnav-hamburger-icon { display: inline-flex !important; align-items: center; justify-content: center; }
}
.app-menu { transition: margin-left .25s ease; }
.vertical-overlay { transition: opacity .2s ease; }

/* ─── Sidebar scroll + bottom user block layout ───
   .app-menu is position:fixed (no SimpleBar in this build) and now ends in a pinned user block.
   Make .app-menu a flex COLUMN: brand box (top) → #scrollbar (fills the middle + scrolls) →
   .rfs-side-user (bottom, natural height). This guarantees the scroll list always sits ABOVE the
   user block at every sidebar size, so the lower items (Settings, Recycle Bin, Price Book…) can
   never be clipped or hidden behind it. */
.app-menu { display: flex; flex-direction: column; padding-bottom: 0; }
/* Velzon reserves ~95px (calc(70px + 25px)) padding-bottom on .navbar-menu for its old footer.
   In our flex column that padding pushes the user block up off the true bottom AND steals menu
   height — zero it so #scrollbar fills the full height and .rfs-side-user pins to the very bottom. */
.app-menu.navbar-menu { padding-bottom: 0; }
.app-menu .navbar-brand-box { flex: 0 0 auto; }
.app-menu #scrollbar {
    flex: 1 1 auto;
    min-height: 0;
    height: auto;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,.28) transparent;
}
.app-menu #scrollbar::-webkit-scrollbar { width: 6px; }
.app-menu #scrollbar::-webkit-scrollbar-thumb { background: rgba(255,255,255,.28); border-radius: 3px; }
.app-menu #scrollbar::-webkit-scrollbar-track { background: transparent; }

/* ─────────────────────────── Activity timeline ─────────────────────────── */
.act-timeline { position: relative; }
.act-day { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--vz-secondary-color); margin: 18px 0 10px; display: flex; align-items: center; gap: var(--space-2); }
.act-day::after { content: ''; flex: 1; height: 1px; background: var(--vz-border-color); }
.act-day:first-child { margin-top: 0; }
.act-item { position: relative; display: flex; gap: var(--space-3); padding-bottom: 16px; }
.act-item:not(:last-child)::before { content: ''; position: absolute; left: 17px; top: 38px; bottom: -2px; width: 2px; background: var(--vz-border-color); }
.act-ico { flex-shrink: 0; width: 36px; height: 36px; border-radius: var(--r-lg); display: flex; align-items: center; justify-content: center; font-size: var(--fs-lg); z-index: 1; box-shadow: 0 0 0 4px var(--vz-secondary-bg); }
.act-body { flex: 1; min-width: 0; padding-top: 3px; }
.act-desc { font-size: var(--fs-base); color: var(--vz-body-color); line-height: 1.45; }
.act-desc .act-strong { font-weight: 600; }
.act-meta { font-size: var(--fs-xs); color: var(--vz-secondary-color); margin-top: 3px; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.act-meta .act-avatar { width: 18px; height: 18px; border-radius: 50%; color: #fff; font-size: 9px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.act-desc .act-actor { width: 18px; height: 18px; border-radius: 50%; color: #fff; font-size: 9px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; vertical-align: middle; margin-right: 5px; position: relative; top: -1px; }
.act-time { white-space: nowrap; }
.act-link { font-size: var(--fs-xs); text-decoration: none; }
/* Bootstrap badges are nowrap, so a long job-title tag ("JOB-38494 — Stairlift Service
   & Battery Change ›") ran right up to the phone's edge. Let the tag wrap instead. */
.act-link.badge { white-space: normal; text-align: left; max-width: 100%; line-height: 1.3; }
.act-timeline.act-compact .act-item { padding-bottom: 12px; }
.act-timeline.act-compact .act-ico { width: 32px; height: 32px; font-size: var(--fs-base); }
.act-timeline.act-compact .act-item:not(:last-child)::before { left: 15px; top: 34px; }

/* ── Premium form polish (v0.9) — scoped to .rfs-form so it only touches create/edit pages ── */
.rfs-form .card { border: var(--hair) solid var(--vz-border-color); border-radius: .85rem; box-shadow: 0 1px 2px rgba(15,23,42,.05), 0 12px 32px -20px rgba(15,23,42,.30); margin-bottom: 1.25rem; }
.rfs-form .card-header { background: linear-gradient(180deg, rgba(var(--vz-primary-rgb),.05), transparent); border-bottom: var(--hair) solid var(--vz-border-color); padding: .95rem 1.3rem; border-top-left-radius: .85rem; border-top-right-radius: .85rem; }
.rfs-form .card-header h6 { font-size: .74rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--vz-secondary-color); }
.rfs-form .card-body { padding: 1.35rem 1.4rem; }
.rfs-form .form-label { font-size: .78rem; /* intentional off-scale, owner-accepted A-320/A-321 */ font-weight: 600; color: var(--vz-body-color); margin-bottom: .35rem; }
.rfs-form .form-control, .rfs-form .form-select { border-radius: var(--r-md); }
.rfs-form .form-control:focus:not(.is-invalid), .rfs-form .form-select:focus:not(.is-invalid) { border-color: var(--vz-primary); box-shadow: 0 0 0 .2rem rgba(var(--vz-primary-rgb),.13); }
.rfs-form .input-group-text { border-radius: .55rem; /* intentional off-scale, owner-accepted A-325 */ }
/* Uniform, iOS-safe field text on forms (the dense line-item & contact -sm controls stay compact). */
.rfs-form .form-control:not(.form-control-sm):not(.form-control-lg), .rfs-form .form-select:not(.form-select-sm) { font-size: var(--fs-lg); }
/* Phone-number rows (anywhere): type / dial-code / number all the same size, with room for the dial code + country. */
.phone-row .form-select, .phone-row .form-control { font-size: var(--fs-lg); }
.phone-row select[name$="[type]"] { width: 110px !important; }
.phone-row select[name$="[cc]"]   { width: 205px !important; }
@media (max-width: 480px) {
    .phone-row { flex-wrap:wrap; }
    .phone-row select[name$="[type]"],
    .phone-row select[name$="[cc]"],
    .phone-row .form-control { width:100% !important; flex:1 1 100% !important; }
    .rfs-clock-reason-group { display:flex; flex-direction:column; }
    .rfs-clock-reason-group > .form-control,
    .rfs-clock-reason-group > .btn { width:100%; min-height:44px; border-radius:var(--vz-border-radius,4px) !important; }
}

/* ── Reusable polished modal + form pattern (the Task popup is the reference) ──
   Apply `rfs-modal` to the .modal wrapper and `rfs-form` to the body content.
   Section headers use .rfs-section-label; the upload area uses .rfs-dropzone. */
.rfs-modal .modal-content { border:none; border-radius:var(--r-xl); box-shadow:0 24px 60px rgba(0,0,0,.20); }
.rfs-modal .modal-header { padding:1.05rem 1.35rem; border-bottom:var(--hair) solid var(--vz-border-color); border-radius:var(--r-xl) 14px 0 0; }
.rfs-modal .modal-title { font-size:1.02rem; font-weight:600; display:flex; align-items:center; gap:.5rem; }
.rfs-modal .modal-title i { color:var(--vz-primary); }
.rfs-modal .modal-body { padding:1.35rem; }
.rfs-modal .modal-footer { padding:.85rem 1.35rem; border-top:var(--hair) solid var(--vz-border-color); background:var(--vz-light); border-radius:0 0 14px 14px; }
/* Field styling auto-applies to EVERY .rfs-modal body (one class unifies every popup) */
.rfs-modal .modal-body .form-label { font-size:.8125rem; /* intentional off-scale, owner-accepted A-320/A-321 */ font-weight:500; color:var(--vz-secondary-color); margin-bottom:.3rem; }
.rfs-modal .modal-body .rfs-title-input { font-size:1.05rem; font-weight:500; padding:.55rem .85rem; }
.rfs-modal .modal-body .form-control, .rfs-modal .modal-body .form-select { padding-top:.5rem; padding-bottom:.5rem; }
.rfs-modal .modal-body .input-group-text { background:var(--vz-light); color:var(--vz-secondary-color); }
.rfs-section-label { font-size:11px; text-transform:uppercase; letter-spacing:.06em; font-weight:600; color:var(--vz-secondary-color); margin:1.15rem 0 .65rem; padding-bottom:.35rem; border-bottom:var(--hair) dashed var(--vz-border-color); }
.rfs-dropzone { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:.2rem; text-align:center; width:100%; padding:1.35rem; border:1.5px dashed var(--vz-border-color); border-radius:var(--r-lg); cursor:pointer; transition:border-color .15s ease, background .15s ease; margin-bottom:0; }
.rfs-dropzone:hover { border-color:var(--vz-primary); background:rgba(var(--vz-primary-rgb),.045); }
.rfs-dropzone i { font-size:1.7rem; color:var(--vz-primary); }
.rfs-dropzone-files:empty { display:none; }

/* ── Modal backdrop: darker + frosted glass (uniform across every popup) ── */
.modal-backdrop.show { opacity:.6; }
.modal-backdrop { backdrop-filter:blur(5px); -webkit-backdrop-filter:blur(5px); }

/* ── Sexier modal header: icon chip + title + subtitle ── */
.rfs-modal .modal-header { align-items:center; gap:.75rem; }
.rfs-modal-head { display:flex; align-items:center; gap:.8rem; min-width:0; }
.rfs-modal-ico { width:42px; height:42px; border-radius:12px; flex-shrink:0; display:flex; align-items:center; justify-content:center; font-size:21px; background:rgba(var(--vz-primary-rgb),.12); color:var(--vz-primary); }
.rfs-modal-head .modal-title { margin:0; line-height:1.15; }
.rfs-modal-sub { margin:2px 0 0; font-size:var(--fs-xs); color:var(--vz-secondary-color); line-height:1.2; }

/* Tall scrollable modals (e.g. New/Edit Task) — guarantee the footer (Cancel / Add / Save
   buttons) stays ON-SCREEN on shorter viewports. Without this cap a long body pushes the
   footer below the fold and the action button looks "missing". Capping the scrollable body
   to the viewport minus header+footer+margins (~205px, +buffer) forces it to scroll instead. */
.rfs-modal .modal-dialog-scrollable .modal-body { max-height: calc(100vh - 220px); }

/* ── Smart Assist — guardrails / live-notice strip (red/yellow/blue) ───────── */
.rfs-assist-strip { display:flex; flex-direction:column; gap:var(--space-2); }
.rfs-assist-strip:not(:empty) { margin-bottom:14px; }
.rfs-assist-item { display:flex; align-items:flex-start; gap:10px; padding:10px 12px; border-radius:var(--r-lg); border:var(--hair) solid; font-size:13px; line-height:1.35; }
.rfs-assist-ico { font-size:var(--fs-xl); line-height:1.2; flex-shrink:0; margin-top:1px; }
.rfs-assist-body { flex:1 1 auto; min-width:0; }
.rfs-assist-title { font-weight:600; }
.rfs-assist-actions { margin-top:6px; display:flex; flex-wrap:wrap; gap:6px; }
.rfs-assist-action { display:inline-block; padding:2px 9px; border-radius:var(--r-sm); font-size:var(--fs-xs); font-weight:500; text-decoration:none; background:rgba(0,0,0,.06); }
.rfs-assist-action:hover { background:rgba(0,0,0,.12); }
.rfs-assist-x { border:0; background:transparent; font-size:20px; line-height:1; color:inherit; opacity:.5; cursor:pointer; padding:0 2px; flex-shrink:0; }
.rfs-assist-x:hover { opacity:1; }
/* 🔴 block */
.rfs-assist-item.is-block { color:#b42318; background:rgba(240,68,56,.08); border-color:rgba(240,68,56,.35); }
/* 🟡 warn */
.rfs-assist-item.is-warn  { color:#93600b; background:rgba(247,144,9,.10); border-color:rgba(247,144,9,.38); }
/* 🔵 nudge */
.rfs-assist-item.is-nudge { color:var(--vz-info); background:rgba(41,112,219,.08); border-color:rgba(41,112,219,.30); }
.rfs-assist-disabled { opacity:.55; cursor:not-allowed !important; }

/* Phase 7 — AI form-assist panel (rfs-ai-assist.js). SEPARATE, non-blocking layer
   from the rules strip above: a soft "manager beside you" card with gentle suggestions.
   Never disables submit; purely advisory. */
.rfs-ai-assist-panel { display:flex; flex-direction:column; gap:var(--space-2); }
.rfs-ai-assist-panel:not(:empty) { margin:14px 0; padding:var(--space-3) 14px; border-radius:12px;
    border:var(--hair) solid rgba(var(--vz-primary-rgb),.28); background:rgba(var(--vz-primary-rgb),.05); }
.rfs-ai-assist-head { display:flex; align-items:center; gap:7px; font-size:var(--fs-xs); font-weight:600;
    letter-spacing:.02em; text-transform:uppercase; color:var(--vz-primary); opacity:.85; }
.rfs-ai-assist-head i { font-size:15px; }
.rfs-ai-assist-item { display:flex; align-items:flex-start; gap:10px; padding:9px 11px; border-radius:var(--r-lg);
    border:var(--hair) solid; font-size:13px; line-height:1.4; background:var(--vz-card-bg, #fff); }
.rfs-ai-assist-ico { font-size:17px; line-height:1.2; flex-shrink:0; margin-top:1px; }
.rfs-ai-assist-body { flex:1 1 auto; min-width:0; }
.rfs-ai-assist-msg { display:block; }
.rfs-ai-assist-actions { margin-top:7px; display:flex; flex-wrap:wrap; gap:6px; }
.rfs-ai-assist-btn { display:inline-flex; align-items:center; padding:3px 11px; border-radius:7px; border:var(--hair) solid rgba(0,0,0,.12);
    font-size:var(--fs-xs); font-weight:500; cursor:pointer; background:rgba(0,0,0,.04); color:inherit; }
.rfs-ai-assist-btn:hover:not(:disabled) { background:rgba(0,0,0,.10); }
.rfs-ai-assist-btn:disabled { opacity:.65; cursor:default; }
.rfs-ai-assist-apply { border-color:rgba(var(--vz-primary-rgb),.45); color:var(--vz-primary); background:rgba(var(--vz-primary-rgb),.08); }
.rfs-ai-assist-x { border:0; background:transparent; font-size:19px; line-height:1; color:inherit; opacity:.45; cursor:pointer; padding:0 2px; flex-shrink:0; }
.rfs-ai-assist-x:hover { opacity:1; }
.rfs-ai-assist-item.is-info { color:var(--vz-info); border-color:rgba(41,112,219,.28); }
.rfs-ai-assist-item.is-warn { color:#93600b; border-color:rgba(247,144,9,.40); background:rgba(247,144,9,.06); }

/* Field 2 Service Draft — "restored your unsaved draft" banner (rfs-draft.js) */
.rfs-draft-banner { display:flex; align-items:center; gap:var(--space-2); margin-bottom:12px; padding:var(--space-2) 12px; border-radius:var(--r-lg); font-size:13px; color:var(--vz-info); background:rgba(41,112,219,.08); border:var(--hair) solid rgba(41,112,219,.30); }
.rfs-draft-banner i { font-size:var(--fs-lg); line-height:1; }
.rfs-draft-discard { margin-left:auto; border:0; background:transparent; color:var(--vz-info); font-weight:600; text-decoration:underline; cursor:pointer; padding:0; }

/* Google Places predictions dropdown — must sit ABOVE Bootstrap modals.
   Google appends .pac-container to <body> with a default z-index of 1000, so inside a
   modal (z-index ~1055) the address suggestions render BEHIND the modal and look "dead"
   (you type but nothing clickable appears). Lift it above the modal so address search
   works in the quick-add-customer modal and any other modal-hosted address field. */
.pac-container { z-index: 1100 !important; }

/* ── Reports hub ─────────────────────────────────────────────────────────── */
.rfs-reports { display:flex; gap:18px; align-items:flex-start; }
.rfs-reports[data-layout="top"] { display:block; }
.rfs-rep-rail { flex:0 0 208px; width:208px; position:sticky; top:90px; align-self:flex-start; }
.rfs-reports[data-layout="top"] .rfs-rep-rail { position:static; width:auto; flex:none; margin-bottom:14px; }
.rfs-rep-main { flex:1; min-width:0; }
.rfs-rep-rail-head { font-size:11px; text-transform:uppercase; letter-spacing:.04em; color:var(--vz-secondary-color); font-weight:600; padding:0 8px 6px; }
.rfs-reports[data-layout="top"] .rfs-rep-rail-head { display:none; }
.rfs-rep-search { position:relative; margin-bottom:8px; }
.rfs-rep-search > i { position:absolute; left:10px; top:50%; transform:translateY(-50%); color:var(--vz-secondary-color); font-size:15px; pointer-events:none; }
.rfs-rep-search input { width:100%; height:34px; padding:0 10px 0 30px; border:var(--hair) solid var(--vz-border-color); border-radius:var(--r-md); background:var(--vz-secondary-bg); color:var(--vz-body-color); font-size:13px; }
.rfs-reports[data-layout="top"] .rfs-rep-search { max-width:240px; }
.rfs-rep-nav { display:flex; flex-direction:column; gap:2px; }
.rfs-reports[data-layout="top"] .rfs-rep-nav { flex-direction:row; flex-wrap:wrap; gap:6px; }
.rfs-rep-link { display:flex; align-items:center; gap:9px; padding:var(--space-2) 10px; border-radius:9px; color:var(--vz-body-color); font-size:var(--fs-base); font-weight:500; text-decoration:none; cursor:pointer; transition:background .12s, color .12s; }
.rfs-rep-link:hover { background:rgba(var(--vz-primary-rgb),.06); color:var(--vz-body-color); }
.rfs-rep-link.active { background:rgba(var(--vz-primary-rgb),.12); color:var(--vz-primary); }
.rfs-rep-link-ic { font-size:17px; flex-shrink:0; }
.rfs-rep-link-tx { flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rfs-reports[data-layout="top"] .rfs-rep-link { border:var(--hair) solid var(--vz-border-color); padding:6px 12px; }
.rfs-reports[data-layout="top"] .rfs-rep-link.active { border-color:var(--vz-primary); }
.rfs-rep-pin { border:none; background:transparent; color:var(--vz-secondary-color); font-size:var(--fs-base); padding:0 2px; line-height:1; opacity:0; transition:opacity .12s, color .12s; cursor:pointer; }
.rfs-rep-link:hover .rfs-rep-pin, .rfs-rep-link.rfs-pinned .rfs-rep-pin { opacity:1; }
.rfs-rep-link.rfs-pinned .rfs-rep-pin { color:#f7b84b; }
/* Customise overlays on each tile / card */
.rfs-rep-item .card { position:relative; }
.rfs-cust-ov { display:none; position:absolute; top:6px; right:8px; z-index:4; align-items:center; gap:5px; background:var(--vz-secondary-bg); border:var(--hair) solid var(--vz-border-color); border-radius:7px; padding:2px 6px; }
.rfs-customising .rfs-cust-ov { display:inline-flex; }
.rfs-cust-grip { cursor:grab; color:var(--vz-secondary-color); font-size:15px; }
.rfs-cust-eye { border:none; background:transparent; padding:0; color:var(--vz-secondary-color); font-size:15px; line-height:1; cursor:pointer; }
.rfs-cust-eye:hover { color:var(--vz-primary); }
.rfs-customising .rfs-rep-item .card { outline:1px dashed transparent; transition:outline-color .12s; }
.rfs-customising .rfs-rep-item:hover .card { outline-color:rgba(var(--vz-primary-rgb),.45); }
.rfs-rep-item.rfs-dragging { opacity:.45; }
.rfs-rep-item.rfs-dragging .card { outline:2px solid var(--vz-primary) !important; }
/* Hidden widgets: gone in normal mode, dimmed-and-shown while customising */
.rfs-rep-item.rfs-hidden { display:none; }
.rfs-customising .rfs-rep-item.rfs-hidden { display:block; opacity:.45; }
.rfs-customising .rfs-rep-item.rfs-hidden .rfs-cust-eye { color:var(--vz-primary); }
.rfs-rep-item { transition:opacity .18s ease; }
/* Needs-attention panel */
.rfs-na-grid { display:grid; grid-template-columns:1fr 1fr; gap:var(--space-1) 18px; }
@media (max-width:640px){ .rfs-na-grid { grid-template-columns:1fr; } }
.rfs-na-item { display:flex; align-items:center; gap:10px; padding:7px 6px; border-radius:var(--r-md); text-decoration:none; color:var(--vz-body-color); }
.rfs-na-item:hover { background:rgba(var(--vz-primary-rgb),.06); color:var(--vz-body-color); }
.rfs-na-tx { flex:1; font-size:13.5px; }
/* Skeleton: dim the data zones while a new range loads */
.rfs-loading #kpiGrid, .rfs-loading #widgetGrid { opacity:.5; pointer-events:none; transition:opacity .15s; }

/* ════════════════════════════════════════════════════════════════════
   Operations day planner (rfs-ops-*) — per-engineer columns, travel
   sanity chips, day map pins, unassigned tray, tracking teaser.
   ════════════════════════════════════════════════════════════════════ */
/* Clean & modern (#routeplanner 2026-06-19). Surfaces use --vz-secondary-bg (--vz-card-bg is undefined in this
   Velzon build → was white-in-dark; repointed 2026-06-20 by the Smart Dispatch contract reconcile). */
.rfs-ops-kpis { display:flex; flex-wrap:wrap; gap:var(--space-3); margin-bottom:18px; }
.rfs-ops-kpi { flex:1 1 150px; min-width:150px; display:flex; align-items:center; gap:var(--space-3); padding:14px 16px;
    background:var(--vz-secondary-bg); border:var(--hair) solid var(--vz-border-color); border-radius:var(--r-xl);
    box-shadow:0 1px 2px rgba(0,0,0,.04); transition:transform .14s ease, box-shadow .14s ease; }
.rfs-ops-kpi:hover { transform:translateY(-2px); box-shadow:0 6px 18px rgba(0,0,0,.08); }
.rfs-ops-kpi-alert { border-color:rgba(var(--vz-danger-rgb),.35); }
.rfs-ops-kpi-ic { width:42px; height:42px; border-radius:11px; display:inline-flex; align-items:center; justify-content:center; font-size:20px; flex-shrink:0; }
.rfs-ops-kpi-primary { background:rgba(var(--vz-primary-rgb),.12); color:var(--vz-primary); }
.rfs-ops-kpi-info    { background:rgba(var(--vz-info-rgb),.12);    color:var(--vz-info); }
.rfs-ops-kpi-success { background:rgba(var(--vz-success-rgb),.12); color:var(--vz-success); }
.rfs-ops-kpi-danger  { background:rgba(var(--vz-danger-rgb),.12);  color:var(--vz-danger); }
.rfs-ops-kpi-warning { background:rgba(var(--vz-warning-rgb),.14); color:var(--vz-warning); }
.rfs-ops-kpi-n { font-size:21px; font-weight:700; line-height:1.1; }
.rfs-ops-kpi-l { font-size:11.5px; color:var(--vz-secondary-color); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

.rfs-ops-board { display:flex; gap:var(--space-4); overflow-x:auto; padding:2px 2px 10px; align-items:flex-start; }
.rfs-ops-col { flex:0 0 278px; max-width:278px; background:var(--vz-secondary-bg); border:var(--hair) solid var(--vz-border-color);
    border-radius:var(--r-xl); padding:var(--space-3); transition:box-shadow .14s ease, border-color .14s ease; }
.rfs-ops-col.rfs-ops-coldrop { border-color:rgba(var(--vz-primary-rgb),.65); box-shadow:0 0 0 3px rgba(var(--vz-primary-rgb),.14) inset; }
.rfs-ops-colhead { display:flex; align-items:center; gap:10px; padding:2px 2px 11px; border-bottom:var(--hair) dashed var(--vz-border-color); margin-bottom:11px; }
.rfs-ops-load { height:4px; border-radius:3px; background:var(--vz-border-color); margin-top:5px; overflow:hidden; max-width:160px; }
.rfs-ops-load-bar { display:block; height:100%; border-radius:3px; transition:width .2s ease; }
/* Timeline / Gantt day view */
.rfs-ops-viewtoggle .btn.active { background:rgba(var(--vz-primary-rgb),.14); color:var(--vz-primary); border-color:transparent; }
.rfs-ops-tl { border:var(--hair) solid var(--vz-border-color); border-radius:12px; overflow:hidden; }
.rfs-ops-tl-axis, .rfs-ops-tl-lane { display:flex; align-items:stretch; }
.rfs-ops-tl-axis { height:26px; border-bottom:var(--hair) solid var(--vz-border-color); background:var(--vz-secondary-bg); }
.rfs-ops-tl-lane { border-top:var(--hair) solid var(--vz-border-color); }
.rfs-ops-tl-lane:first-of-type { border-top:0; }
.rfs-ops-tl-lane-label { flex:0 0 140px; max-width:140px; display:flex; align-items:center; gap:7px; padding:6px 10px; border-right:var(--hair) solid var(--vz-border-color); background:var(--vz-secondary-bg); }
.rfs-ops-tl-track { position:relative; flex:1 1 auto; min-height:56px; touch-action:none; }
.rfs-ops-tl-hour { position:absolute; top:6px; transform:translateX(-50%); font-size:10.5px; color:var(--vz-secondary-color); white-space:nowrap; }
.rfs-ops-tl-grid { position:absolute; top:0; bottom:0; width:1px; background:var(--vz-border-color); opacity:.45; }
.rfs-ops-tl-job { position:absolute; top:7px; bottom:7px; min-width:36px; border-radius:7px; color:#fff; text-decoration:none; padding:var(--space-1) 7px; overflow:hidden; cursor:grab; box-shadow:0 1px 3px rgba(0,0,0,.22); display:flex; flex-direction:column; justify-content:center; line-height:1.15; user-select:none; touch-action:none; }
.rfs-ops-tl-job:hover { box-shadow:0 5px 12px rgba(0,0,0,.3); color:#fff; z-index:3; }
.rfs-ops-tl-job.rfs-ops-dragging { opacity:.75; z-index:5; cursor:grabbing; box-shadow:0 8px 18px rgba(0,0,0,.35); }
.rfs-ops-tl-job.rfs-ops-done { opacity:.55; }
.rfs-ops-tl-job-t { font-size:9.5px; font-weight:700; opacity:.95; }
.rfs-ops-tl-job-c { font-size:11px; font-weight:600; }
.rfs-ops-tl-lane.rfs-ops-tl-drop .rfs-ops-tl-track { background:rgba(var(--vz-primary-rgb),.08); }
.rfs-ops-tl-untimed { position:absolute; right:7px; top:50%; transform:translateY(-50%); font-size:10px; color:var(--vz-secondary-color); pointer-events:none; }
@media (max-width:640px){ .rfs-ops-tl-lane-label { flex-basis:90px; max-width:90px; } }
.rfs-ops-avatar { width:34px; height:34px; border-radius:50%; color:#fff; font-size:var(--fs-xs); font-weight:600; display:inline-flex; align-items:center; justify-content:center; flex-shrink:0; box-shadow:0 2px 6px rgba(0,0,0,.18); }
.rfs-ops-job { display:flex; gap:10px; align-items:flex-start; background:var(--vz-secondary-bg); border:var(--hair) solid var(--vz-border-color);
    border-radius:11px; padding:10px 11px; text-decoration:none; color:var(--vz-body-color); cursor:grab;
    box-shadow:0 1px 2px rgba(0,0,0,.05); transition:transform .12s ease, border-color .12s ease, box-shadow .12s ease; }
.rfs-ops-job + .rfs-ops-job { margin-top:9px; }
.rfs-ops-job:hover { transform:translateY(-2px); border-color:rgba(var(--vz-primary-rgb),.5); box-shadow:0 6px 16px rgba(0,0,0,.10); color:var(--vz-body-color); }
.rfs-ops-job:active { cursor:grabbing; }
.rfs-ops-job.rfs-ops-dragging { opacity:.5; transform:scale(.98); box-shadow:none; }
.rfs-ops-job.rfs-ops-done { opacity:.6; }
.rfs-ops-pin { width:24px; height:24px; border-radius:50%; color:#fff; font-size:11px; font-weight:700; display:inline-flex; align-items:center; justify-content:center; flex-shrink:0; margin-top:1px; box-shadow:0 2px 5px rgba(0,0,0,.22); }
.rfs-ops-pin-ghost { background:transparent; border:var(--hair) dashed var(--vz-border-color); color:var(--vz-secondary-color); box-shadow:none; }
.rfs-ops-leg { position:relative; margin:7px 0 7px 34px; font-size:11.5px; color:var(--vz-secondary-color); display:inline-flex; align-items:center; gap:3px;
    padding:2px 9px; background:var(--vz-secondary-bg); border:var(--hair) solid var(--vz-border-color); border-radius:20px; }
.rfs-ops-leg::before { content:""; position:absolute; left:-18px; top:50%; width:14px; border-top:2px dotted var(--vz-border-color); }
.rfs-ops-leg-bad { color:var(--vz-danger); background:rgba(var(--vz-danger-rgb),.1); border-color:rgba(var(--vz-danger-rgb),.3); font-weight:600; }
.rfs-ops-empty { padding:18px 4px; text-align:center; color:var(--vz-secondary-color); }
.rfs-ops-map { height:440px; width:100%; border-radius:0 0 6px 6px; }
.rfs-ops-dot { display:inline-block; width:10px; height:10px; border-radius:50%; margin-right:5px; vertical-align:-1px; }
.rfs-ops-tray { max-height:440px; overflow-y:auto; }
.rfs-ops-trayrow { display:flex; align-items:center; gap:10px; padding:9px 4px; border-bottom:var(--hair) dashed var(--vz-border-color); }
.rfs-ops-trayrow:last-child { border-bottom:0; }
.rfs-ops-teaser { opacity:.65; filter:grayscale(.5); pointer-events:none; user-select:none; }
@media (max-width:640px) { .rfs-ops-col { flex:0 0 86vw; max-width:86vw; } .rfs-ops-map { height:320px; } .rfs-ops-kpi { flex:1 1 46%; min-width:0; } }

/* ── Alerts page + dashboard "To Sort" (rfs-alert-) ──────────────────────────
   Appended 2026-06-11 by the Alerts-page build. Traffic dots, summary chips,
   alert rows and the dashboard To Sort list. Prefix: rfs-alert- */
.rfs-alert-dot { display:inline-block; width:10px; height:10px; border-radius:50%; flex-shrink:0; position:relative; }
.rfs-alert-dot.red    { background:#f06548; }
.rfs-alert-dot.orange { background:#f7b84b; }
.rfs-alert-dot.red:not(.rfs-alert-dot-still)::after {
    content:""; position:absolute; inset:-4px; border-radius:50%;
    border:2px solid rgba(240,101,72,.55); animation:rfsAlertPulse 1.8s ease-out infinite;
}
@keyframes rfsAlertPulse {
    0%   { transform:scale(.55); opacity:.9; }
    70%  { transform:scale(1.25); opacity:0; }
    100% { transform:scale(1.25); opacity:0; }
}
.rfs-alert-chip {
    display:inline-flex; align-items:center; gap:.4rem;
    padding:.3rem .7rem; border-radius:2rem; font-size:.8125rem; font-weight:500;
}
.rfs-alert-chip-red     { background:rgba(240,101,72,.12);  color:#f06548; }
.rfs-alert-chip-orange  { background:rgba(247,184,75,.15);  color:#c08a1f; }
.rfs-alert-chip-green   { background:rgba(10,179,156,.12);  color:#0ab39c; }
.rfs-alert-chip-snoozed { background:rgba(116,120,141,.12); color:#74788d; font-size:var(--fs-xs); padding:.15rem .55rem; }
.rfs-alert-row { padding:.85rem 1rem; border-bottom:var(--hair) solid var(--vz-border-color, #e9ebec); }
.rfs-alert-row:last-child { border-bottom:0; }
.rfs-alert-row:hover { background:rgba(var(--vz-light-rgb, 243,246,249), .55); }
.rfs-alert-snoozed { opacity:.62; }
/* ── end rfs-alert- section ─────────────────────────────────────────────── */

/* ── Alert engine: traffic-light dots (lists) + show-page alert strips (rfs-light-*) ── */
.rfs-light{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px;vertical-align:middle;flex:0 0 auto}
.rfs-light-red{background:var(--vz-danger);animation:rfsLightPulse 2s ease-out infinite}
.rfs-light-orange{background:#f59e0b}
@keyframes rfsLightPulse{0%{box-shadow:0 0 0 0 rgba(var(--vz-danger-rgb),.45)}70%{box-shadow:0 0 0 6px rgba(var(--vz-danger-rgb),0)}100%{box-shadow:0 0 0 0 rgba(var(--vz-danger-rgb),0)}}
.rfs-alert-strip{display:flex;flex-direction:column;gap:var(--space-2)}
.rfs-alert-item{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;padding:var(--space-2) 12px;border-radius:var(--r-md);border:var(--hair) solid var(--vz-border-color,#e9ebec);border-left-width:4px;background:var(--vz-secondary-bg,#fff);font-size:.8125rem}
.rfs-alert-item.is-red{border-left-color:var(--vz-danger);background:rgba(var(--vz-danger-rgb),.04)}
.rfs-alert-item.is-orange{border-left-color:#f59e0b;background:rgba(245,158,11,.05)}
.rfs-alert-item .rfs-alert-ico{font-size:var(--fs-lg);line-height:1}
.rfs-alert-item.is-red .rfs-alert-ico{color:var(--vz-danger)}
.rfs-alert-item.is-orange .rfs-alert-ico{color:#f59e0b}
.rfs-alert-item .rfs-alert-title{color:var(--vz-body-color,#212529)}
.rfs-alert-item .rfs-alert-link{margin-left:auto;white-space:nowrap;font-weight:600}

/* ============================================================================
   Alerts in the notifications bell + sidebar bottom user block (rfs-side-user-*)
   The full-width attention bar (rfs-abar-*) was retired 2026-07-05 — open Hub alerts
   now render at the TOP of the bell panel (red first, then orange) and the bell
   pulses red while any RED alert is open. One top-right surface for everything.
   ========================================================================== */
#notif-btn.rfs-bell-red { animation: rfsAbarPulseRed 1.8s ease-in-out infinite; }
#notif-btn.rfs-bell-red i { color: var(--vz-danger, #ef4444); }
@keyframes rfsAbarPulseRed { 0%, 100% { box-shadow: 0 0 0 0 rgba(var(--vz-danger-rgb, 239, 68, 68), .50); } 50% { box-shadow: 0 0 0 6px rgba(var(--vz-danger-rgb, 239, 68, 68), 0); } }
.notif-alert-head { padding: 8px 14px 4px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--vz-secondary-color, #64748b); }
.notif-item.notif-alert.alert-red    { box-shadow: inset 3px 0 0 var(--vz-danger, #ef4444); }
.notif-item.notif-alert.alert-orange { box-shadow: inset 3px 0 0 var(--vz-warning, #f59e0b); }
.notif-item.notif-alert.alert-red .n-ico i    { color: var(--vz-danger, #ef4444); }
.notif-item.notif-alert.alert-orange .n-ico i { color: var(--vz-warning, #f59e0b); }
.notif-alert-all { display: block; padding: 7px 14px 9px; font-size: 12.5px; font-weight: 600; text-decoration: none; color: var(--vz-secondary-color, #64748b); border-bottom: 1px solid var(--vz-border-color, #e5e7eb); }
.notif-alert-all:hover { color: var(--vz-body-color, #212529); text-decoration: underline; text-underline-offset: 2px; }

/* Sidebar bottom user block (moved from the topbar user dropdown). The .app-menu flex-column layout
   (see "Sidebar scroll" above) places this as the last flex child, so the scrollable menu list always
   sits above it — the lower menu items (Settings, Recycle Bin) are never hidden behind it. */
.rfs-side-user { position: relative; z-index: 2; flex: 0 0 auto; margin-top: auto; display: flex; align-items: center; gap: var(--space-2); padding: 6px 12px; background: var(--vz-vertical-menu-bg, #071633); border-top: var(--hair) solid rgba(255, 255, 255, .08); }
.rfs-side-user-link { display: flex; align-items: center; gap: var(--space-2); flex: 1 1 auto; min-width: 0; text-decoration: none; }
a.rfs-side-user-link:hover .rfs-side-user-name { text-decoration: underline; text-underline-offset: 2px; }
.rfs-side-user-avatar { flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 600; font-size: 11px; }
.rfs-side-user-meta { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.rfs-side-user-name { font-size: var(--fs-xs); font-weight: 600; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rfs-side-user-sub { font-size: 10px; color: var(--vz-vertical-menu-item-color, #a3aed0); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rfs-side-user-logout { flex: 0 0 auto; width: 28px; height: 28px; border: 0; border-radius: 7px; padding: 0; background: transparent; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: var(--fs-lg); text-decoration: none; color: var(--vz-vertical-menu-item-color, #a3aed0); }
.rfs-side-user-logout:hover { background: rgba(255, 255, 255, .10); color: #fff; }
/* Collapsed (icon) sidebar: keep avatar + logout, hide the text, stack vertically.
   Velzon expands the menu on hover, which restores the full block. */
[data-sidebar-size="sm-hover"] .navbar-menu:not(:hover) .rfs-side-user { flex-direction: column; gap: var(--space-2); padding: 10px 6px; }
[data-sidebar-size="sm-hover"] .navbar-menu:not(:hover) .rfs-side-user-meta { display: none; }
[data-sidebar-size="sm"] .navbar-menu .rfs-side-user { flex-direction: column; gap: var(--space-2); padding: 10px 6px; }
[data-sidebar-size="sm"] .navbar-menu .rfs-side-user-meta { display: none; }
@media print { .rfs-side-user { display: none !important; } }

/* ───────────────────────── Alert rules settings (Settings → Alert rules) — rfs-aset- ───────────────────────── */
.rfs-aset-chip { display:inline-flex; align-items:center; gap:.3rem; padding:.18rem .5rem; border:var(--hair) solid var(--vz-border-color); border-radius:var(--r-pill); background:var(--vz-light); font-size:var(--fs-xs); line-height:1.4; color:var(--vz-body-color); }
.rfs-aset-chip-x { border:0; background:transparent; padding:0 .05rem; line-height:1; font-size:var(--fs-base); color:var(--vz-secondary-color); cursor:pointer; }
.rfs-aset-chip-x:hover { color:var(--vz-danger); }
.rfs-aset-chips .rfs-aset-add { max-width:9rem; font-size:var(--fs-xs); padding-top:.18rem; padding-bottom:.18rem; }

/* ── rfs-hub: The Hub (/ai) — Overview status tiles + tile rows (Hub v2, 2026-06-11) ── */
.rfs-hub-tile { display:flex; align-items:center; gap:14px; border-radius:var(--r-xl); padding:var(--space-4) 18px; border:var(--hair) solid var(--vz-border-color,#e9ebec); background:var(--vz-card-bg,#fff); text-decoration:none; transition:transform .12s ease, box-shadow .12s ease; height:100%; }
.rfs-hub-tile:hover { transform:translateY(-1px); box-shadow:0 8px 18px rgba(0,0,0,.08); }
.rfs-hub-tile-ic { width:44px; height:44px; border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:22px; flex:0 0 auto; background:var(--vz-light,#f3f6f9); color:var(--vz-secondary-color,#878a99); }
.rfs-hub-tile-n { font-size:24px; font-weight:700; line-height:1.1; color:var(--vz-body-color); }
.rfs-hub-tile-lb { font-size:12.5px; color:var(--vz-secondary-color,#878a99); }
.rfs-hub-tile-go { margin-left:auto; color:var(--vz-secondary-color,#aab); opacity:0; transition:opacity .12s; }
.rfs-hub-tile:hover .rfs-hub-tile-go { opacity:1; }
.rfs-hub-tile-red .rfs-hub-tile-ic { background:rgba(var(--vz-danger-rgb,240,101,101),.12); color:var(--vz-danger,#f06548); }
.rfs-hub-tile-red .rfs-hub-tile-n { color:var(--vz-danger,#f06548); }
.rfs-hub-tile-orange .rfs-hub-tile-ic { background:rgba(var(--vz-warning-rgb,247,184,75),.15); color:#d29b2a; }
.rfs-hub-tile-orange .rfs-hub-tile-n { color:#d29b2a; }
.rfs-hub-tile-green .rfs-hub-tile-ic { background:rgba(var(--vz-success-rgb,10,179,156),.12); color:var(--vz-success,#0ab39c); }
.rfs-hub-tile-green .rfs-hub-tile-n { color:var(--vz-success,#0ab39c); }
/* To-sort rows inside the Overview tile */
.rfs-hub-row { display:flex; align-items:center; gap:10px; padding:.6rem 1rem; border-bottom:var(--hair) solid var(--vz-border-color,#e9ebec); }
.rfs-hub-row:last-child { border-bottom:0; }
.rfs-hub-row:hover { background:rgba(var(--vz-light-rgb,243,246,249),.55); }
.rfs-hub-row-tt { font-size:13px; font-weight:600; color:var(--vz-body-color); }
.rfs-hub-row-sub { font-size:11.5px; color:var(--vz-secondary-color,#878a99); }
/* Briefing / weekly stat lines */
.rfs-hub-stat { display:flex; align-items:flex-start; gap:9px; font-size:13px; color:var(--vz-body-color); padding:5px 0; }
.rfs-hub-stat i { font-size:15px; flex:0 0 auto; margin-top:1px; }
.rfs-hub-stat b { font-weight:700; }
/* Captured minis */
.rfs-hub-mini { flex:1 1 0; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px; border:var(--hair) solid var(--vz-border-color,#e9ebec); border-radius:12px; padding:14px 8px; background:var(--vz-card-bg,#fff); text-decoration:none; transition:transform .12s ease, box-shadow .12s ease; }
.rfs-hub-mini:hover { transform:translateY(-1px); box-shadow:0 6px 14px rgba(0,0,0,.07); }
.rfs-hub-mini-n { font-size:22px; font-weight:700; line-height:1.1; }
.rfs-hub-mini-lb { font-size:var(--fs-xs); color:var(--vz-secondary-color,#878a99); }
/* Jump-into-chat + upgrade cards */
.rfs-hub-chatcard { border:var(--hair) solid rgba(255,94,58,.35); background:linear-gradient(135deg, rgba(255,94,58,.06), rgba(255,94,58,.01)); }
.rfs-hub-chat-ic { background:linear-gradient(135deg,#ff5e3a,#ff8a3a); color:#fff; }
.rfs-hub-upgrade { border:var(--hair) dashed var(--vz-border-color,#cfd4dc); background:var(--vz-light,#f8f9fb); }
.rfs-hub-upgrade-ic { background:rgba(var(--vz-primary-rgb),.10); color:var(--vz-primary); }

/* rfs-assist- : one-click smart suggestion chips inside the form-assist panel (deterministic,
   free on every plan). Engineer [Apply]/[Undo] + next-free-slot [Use]/[Undo] chips. */
.rfs-ai-assist-chip{display:flex;align-items:center;gap:9px;padding:var(--space-2) 11px;border-radius:var(--r-lg);
    font-size:12.5px;background:rgba(var(--vz-primary-rgb),.06);border:var(--hair) solid rgba(var(--vz-primary-rgb),.18);color:var(--vz-body-color);}
.rfs-ai-assist-chip i{font-size:var(--fs-lg);color:var(--vz-primary);flex-shrink:0;}
.rfs-ai-assist-chip span{flex:1 1 auto;min-width:0;}
.rfs-ai-assist-chip .rfs-ai-assist-btn{flex-shrink:0;}
.rfs-ai-assist-chip[data-applied]{background:rgba(10,179,156,.07);border-color:rgba(10,179,156,.25);}
.rfs-ai-assist-chip[data-applied] i{color:#0ab39c;}

/* ── Hub Alerts tab (W3) — rfs-altab-* ─────────────────────────────────────── */
#aihub-alerts .rfs-altab-row { padding:.7rem 1rem; }
#aihub-alerts .rfs-altab-reason { line-height:1.4; }
#aihub-alerts .rfs-altab-controls .dropdown-toggle::after { display:none; }
#aihub-alerts .rfs-altab-bulkbar { position:sticky; top:0; z-index:3; }
#aihub-alerts .rfs-altab-filters .btn.active { font-weight:600; }
.rfs-altab-caret { transition:transform .18s ease; }
.rfs-altab-caret-up { transform:rotate(180deg); }
#aihub-alerts .rfs-altab-countdown .rfs-altab-cd { opacity:.8; font-variant-numeric:tabular-nums; }
#aihub-alerts .btn-ghost-danger { color:#f06548; }
#aihub-alerts .btn-ghost-danger:hover { background:rgba(240,101,72,.1); color:#f06548; }
#rfs-altab-snoozed-sec, #rfs-altab-deleted-sec { margin-top:1rem; }

/* ===== rfs-qfix � Alert quick-fix buttons (W4) ============================
   Buttons rendered by partials/_alert_actions.php on the Hub Alerts tab, the Hub To Sort
   tile and the dashboard To Sort card, plus the inline date popover spawned by field2service.js.
   Soft btn-sm look (Velzon), brand var(--vz-primary). Remix icons only. ========================= */
.rfs-alert-actions { display:inline-flex; flex-wrap:wrap; gap:.35rem; align-items:center; }
.rfs-alert-actions .rfs-qfix-form { margin:0; }
.rfs-qfix-btn { white-space:nowrap; font-weight:500; }
.rfs-qfix-btn i { vertical-align:middle; }
.rfs-qfix-ai { --rfs-qfix-ai:var(--vz-primary); }
.rfs-qfix-ai:hover { box-shadow:0 0 0 .15rem rgba(var(--vz-primary-rgb),.15); }
/* Inline date/time popover (job schedule + quote validity). position:absolute set inline by JS. */
.rfs-qfix-pop { width:210px; border:var(--hair) solid rgba(0,0,0,.08); }
.rfs-qfix-pop .form-control-sm { font-size:.8125rem; }
.rfs-qfix-pop .rfs-qfix-pop-ok { background:var(--vz-primary); border-color:var(--vz-primary); }
.rfs-qfix-pop .rfs-qfix-pop-ok:hover { background:#1f3590; border-color:#1f3590; }
/* ===== end rfs-qfix ===================================================== */

/* ── Hub tab strip (rfs-aihub-tabs): optically align icon + label + badge on one line and
      tidy the pills (icons sat on the text baseline and looked high/loose). 2026-06-11 ── */
.rfs-aihub-tabs .nav-link{display:inline-flex;align-items:center;gap:7px;line-height:1.1;padding-top:.7rem;padding-bottom:.7rem}
.rfs-aihub-tabs .nav-link i{font-size:15px;line-height:1;margin:0 !important;transform:translateY(.5px)}
.rfs-aihub-tabs .nav-link .badge{margin-left:0 !important;line-height:1;padding:var(--space-1) 7px;border-radius:9px;font-weight:600}
.rfs-aihub-tabs .nav-link .ri-alarm-warning-fill{font-size:var(--fs-base);animation:rfsSysPulse 2s ease-in-out infinite}
@keyframes rfsSysPulse{0%,100%{opacity:1}50%{opacity:.45}}

/* Velzon's .nav-customs .nav-link forces display:block (beats the rule above) — enforce the
   flex layout so the 7px gap actually separates icon / label / badge. */
.rfs-aihub-tabs .nav-link{display:inline-flex !important;align-items:center !important}

/* ── Hub tabs restyle (2026-06-11): inactive tabs blended into the page background.
      Replace the theme's slanted nav-customs shape with clean raised pill tabs —
      white card pills w/ border+shadow for inactive, solid brand navy for active. ── */
.rfs-aihub-tabs{gap:var(--space-2);border-bottom:0 !important;padding:0}
.rfs-aihub-tabs .nav-item{margin:0 !important}
.rfs-aihub-tabs .nav-link{background:#fff !important;border:var(--hair) solid #dfe5f1 !important;border-radius:var(--r-lg) !important;color:#55617a !important;font-weight:600;box-shadow:0 1px 2px rgba(7,22,51,.06);padding:.6rem 1rem !important;transition:color .15s ease,border-color .15s ease,box-shadow .15s ease}
.rfs-aihub-tabs .nav-link::before,.rfs-aihub-tabs .nav-link::after{display:none !important;content:none !important}
.rfs-aihub-tabs .nav-link:hover{color:var(--vz-primary) !important;border-color:#b9c4e4 !important;box-shadow:0 3px 8px rgba(var(--vz-primary-rgb),.14)}
.rfs-aihub-tabs .nav-link:focus-visible{outline:2px solid var(--vz-primary) !important;outline-offset:2px !important;box-shadow:none !important}
.rfs-aihub-tabs .nav-link.active{background:var(--vz-primary) !important;border-color:var(--vz-primary) !important;color:#fff !important;box-shadow:0 4px 12px rgba(var(--vz-primary-rgb),.30)}
.rfs-aihub-tabs .nav-link.active .badge{background:rgba(255,255,255,.22) !important;color:#fff !important}
.rfs-aihub-tabs .nav-link.active .ri-alarm-warning-fill{color:#ffc9bb !important}

/* Pill tabs: slightly tighter so all 7 fit one row on a laptop width (Dev Ops was wrapping). */
.rfs-aihub-tabs{gap:6px}
.rfs-aihub-tabs .nav-link{padding:.55rem .8rem !important;font-size:.84rem}

/* ===== Hub header live date/time + weather strip (#rfs-hub-now, ai/index.php) 2026-06-11 ====
   Sits beside the Refresh button; the weather segment mirrors the topbar chip (no new API).
   The time span is fixed-width tabular so the 1s seconds tick never makes the strip jitter. */
.rfs-hub-now { display:inline-flex; align-items:center; gap:6px; padding:7px 12px; border-radius:var(--r-lg); background:var(--vz-light,#f3f6f9); border:var(--hair) solid var(--vz-border-color,#e9ebec); font-size:12.5px; color:var(--vz-secondary-color,#878a99); white-space:nowrap; line-height:1.2; }
.rfs-hub-now i { font-size:var(--fs-base); line-height:1; }
.rfs-hub-now-time { font-weight:700; color:var(--vz-heading-color,#495057); font-variant-numeric:tabular-nums; }
.rfs-hub-now-sep { opacity:.45; }
.rfs-hub-now-wx { display:inline-flex; align-items:center; gap:6px; }
.rfs-hub-now-wx i { font-size:15px; }
.rfs-hub-now-wxt { font-weight:700; color:var(--vz-heading-color,#495057); }
.rfs-hub-now-wxc { max-width:150px; overflow:hidden; text-overflow:ellipsis; }
@media (max-width: 575.98px){ .rfs-hub-now { display:none; } } /* phone: header space is precious */
/* ===== end #rfs-hub-now ================================================================== */


/* ═══════════ HUB COMMAND CENTER (rfs-hub-cc) — 2026-06-17 ═══════════════════════════════════
   Dark/light is Velzon-native: data-bs-theme is set on .page-content (which also carries .rfs-hub-cc),
   scoped to the Hub ONLY so nothing leaks to other pages. Everything below uses the THEMED Velzon vars
   (--vz-secondary-bg / --vz-border-color / --vz-body-color / --vz-secondary-color) so it follows the
   theme. NB: inside this dark scope, --vz-light resolves to #282b2e (Bootstrap dark-mode override) and
   --vz-card-bg = var(--vz-secondary-bg) = #212529 — correct for text but wrong for surfaces. Use
   --vz-secondary-bg explicitly here so tiles follow data-bs-theme toggle correctly. (These vars ARE
   defined globally: --vz-light:#f3f6f9 light / #282b2e dark; --vz-secondary-bg:#fff / #212529.) */

/* Hub tiles/minis/now-strip — remap to themed surface var (data-bs-theme toggles it correctly). */
.rfs-hub-cc .rfs-hub-tile,
.rfs-hub-cc .rfs-hub-mini { background: var(--vz-secondary-bg); border-color: var(--vz-border-color); }
.rfs-hub-cc .rfs-hub-now  { background: var(--vz-secondary-bg); border-color: var(--vz-border-color); }
.rfs-hub-cc .rfs-hub-tile-ic { background: rgba(var(--vz-light-rgb,243,246,249), .14); }
.rfs-hub-cc .rfs-hub-tile { border-width: 1.5px; border-radius: 15px; }

/* Tab strip → Apple-style segmented control (the mockup): ONE rounded track + a single sliding cyan pill behind
   the active tab, all tabs on one horizontally-scrollable row. The base rfs-aihub-tabs rules above paint individual
   #fff pills — these override the container + links + add the pill. Scoped to .rfs-hub-cc (the Hub), theme-aware. */
.rfs-hub-cc .rfs-aihub-tabs { position:relative; display:flex !important; flex-wrap:nowrap !important; gap:1px !important; background:var(--vz-secondary-bg) !important; border:var(--hair) solid var(--vz-border-color); border-radius:var(--r-xl); padding:var(--space-1) !important; overflow-x:auto; scrollbar-width:none; box-shadow:0 2px 10px rgba(0,0,0,.04); }
.rfs-hub-cc .rfs-aihub-tabs::-webkit-scrollbar { display:none; }
.rfs-hub-cc .rfs-aihub-tabs .nav-item { margin:0 !important; }
.rfs-hub-cc .rfs-aihub-tabs .nav-link { position:relative; z-index:1; display:flex; align-items:center; gap:5px; background:transparent !important; border:0 !important; border-radius:11px !important; padding:10px 8px !important; font-size:13px; font-weight:400; color:var(--vz-secondary-color) !important; white-space:nowrap; box-shadow:none !important; transition:color .3s ease; }
.rfs-hub-cc .rfs-aihub-tabs .nav-link .badge { padding:2px 6px !important; }
.rfs-hub-cc .rfs-aihub-tabs .nav-link i { margin:0 !important; }
.rfs-hub-cc .rfs-aihub-tabs .nav-link:hover { color:var(--vz-body-color) !important; background:transparent !important; box-shadow:none !important; }
.rfs-hub-cc .rfs-aihub-tabs .nav-link.active { color:#fff !important; background:transparent !important; box-shadow:none !important; }
.rfs-hub-cc .rfs-aihub-tabs .nav-link .badge { background:var(--vz-border-color) !important; color:var(--vz-secondary-color) !important; transition:.3s; }
.rfs-hub-cc .rfs-aihub-tabs .nav-link.active .badge { background:rgba(255,255,255,.28) !important; color:#fff !important; }
.rfs-hub-cc .rfs-aihub-tabs .nav-link.active .ri-alarm-warning-fill { color:#fff !important; }
.rfs-hub-cc .rfs-aihub-tabs .rfs-tab-pill { position:absolute; top:0; left:0; height:0; width:0; border-radius:12px; z-index:0; pointer-events:none; opacity:0;
    background:linear-gradient(145deg,var(--rfs-accent),#f2621d); box-shadow:0 6px 18px rgba(var(--rfs-accent-rgb),.4), inset 0 1px 0 rgba(255,255,255,.3);
    transition:transform .45s cubic-bezier(.34,1.45,.5,1), width .45s cubic-bezier(.34,1.45,.5,1), height .3s ease, opacity .2s ease; }
.rfs-hub-cc .rfs-aihub-tabs .rfs-tab-pill.on { opacity:1; }

/* Hub tab strip — overflow scroll arrows + tighter packing (owner 2026-07-06). Mirrors the Settings
   tab pattern (.rfs-setpage-tabnav): the bar never wraps; tabs pack LEFT (not stretched full-width) so
   spacing is tight, and when the row is wider than the viewport a prev/next arrow appears at whichever
   end still has more to reveal (JS toggles .d-none). .rfs-hubtab-wrap is the positioning context. */
.rfs-hub-cc .rfs-aihub-tabs { justify-content:flex-start !important; scroll-behavior:smooth; }
.rfs-hub-cc .rfs-aihub-tabs .nav-item { flex:0 0 auto; }
.rfs-hubtab-wrap { position:relative; }
.rfs-hubtab-nav { position:absolute; top:50%; transform:translateY(-50%); z-index:4; width:28px; height:28px;
    border-radius:50%; display:inline-flex; align-items:center; justify-content:center; font-size:18px;
    background:var(--vz-secondary-bg); border:var(--hair) solid var(--vz-border-color); color:var(--vz-secondary-color);
    cursor:pointer; box-shadow:0 2px 8px rgba(7,22,51,.12); transition:color .15s ease, border-color .15s ease, box-shadow .15s ease; }
.rfs-hubtab-nav[data-dir="prev"] { left:2px; }
.rfs-hubtab-nav[data-dir="next"] { right:2px; }
.rfs-hubtab-nav:hover { color:var(--vz-primary); border-color:var(--vz-primary); box-shadow:0 3px 10px rgba(var(--vz-primary-rgb),.2); }
.rfs-hubtab-nav i { line-height:1; }

/* Theme toggle button: subtle, sits by Refresh. */
.rfs-hub-cc #rfs-hub-theme-toggle i { font-size: 15px; vertical-align: -1px; }

/* Tighten the gap between the app topbar and the Hub content (Velzon's default page-content top padding
   over-clears the fixed topbar on this page). Scoped to the Hub. */
.page-content.rfs-hub-cc { padding-top: 93px; } /* must SELF-clear the ~77px fixed topbar — the old 44px only worked beside a .main-content 49px push that was removed (it caused the attention-bar gap); 44+49=93 was the real offset */

/* Command header (mockup): orange glyph + Hub title w/ live pulse dot + "OPERATIONS COMMAND · company"
   + an "Ask the Hub anything … ⌘K" search field. All themed via --vz-* so it follows light/dark. */
.rfs-hub-cc .rfs-hub-cmd-l { display:flex; align-items:center; gap:14px; }
.rfs-hub-cc .rfs-hub-glyph { width:46px; height:46px; border-radius:13px; display:grid; place-items:center; font-size:22px; color:#fff; flex:0 0 auto;
    background:linear-gradient(145deg,var(--rfs-accent),#e85d2a); box-shadow:0 0 0 1px rgba(255,255,255,.08),0 8px 26px rgba(var(--rfs-accent-rgb),.45),inset 0 1px 0 rgba(255,255,255,.3); }
.rfs-hub-cc .rfs-hub-cmd-h { font-size:21px; font-weight:700; letter-spacing:.2px; display:flex; align-items:center; gap:10px; color:var(--vz-body-color); }
.rfs-hub-cc .rfs-hub-pulse { width:9px; height:9px; border-radius:50%; background:#0ab39c; box-shadow:0 0 0 0 rgba(10,179,156,.7); animation:rfsHubPulse 2s infinite; flex:0 0 auto; }
@keyframes rfsHubPulse { 0%{box-shadow:0 0 0 0 rgba(10,179,156,.55)} 70%{box-shadow:0 0 0 8px rgba(10,179,156,0)} 100%{box-shadow:0 0 0 0 rgba(10,179,156,0)} }
.rfs-hub-cc .rfs-hub-cmd-sub { font-size:var(--fs-xs); color:var(--vz-secondary-color); letter-spacing:2.5px; text-transform:uppercase; margin-top:3px; }
.rfs-hub-cc .rfs-hub-cmdk { flex:1; max-width:440px; margin:0 22px; display:flex; align-items:center; gap:10px; cursor:text; text-align:left;
    background:var(--vz-secondary-bg); border:var(--hair) solid var(--vz-border-color); border-radius:12px; padding:10px 14px; color:var(--vz-secondary-color); font-size:13.5px; transition:.2s; }
.rfs-hub-cc .rfs-hub-cmdk:hover { border-color:var(--rfs-accent); color:var(--vz-body-color); }
.rfs-hub-cc .rfs-hub-cmdk i { font-size:var(--fs-lg); }
.rfs-hub-cc .rfs-hub-cmdk span { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rfs-hub-cc .rfs-hub-cmdk kbd { margin-left:auto; font-size:11px; font-family:inherit; background:var(--vz-body-bg); border:var(--hair) solid var(--vz-border-color); border-radius:var(--r-sm); padding:2px 7px; color:var(--vz-secondary-color); }
@media (max-width:991.98px){ .rfs-hub-cc .rfs-hub-cmdk { order:3; max-width:none; width:100%; margin:10px 0 0; } }

/* ── Live ticker (additive, top of Overview) — a constantly-scrolling status strip. ── */
.rfs-hub-cc .rfs-hub-ticker { display:flex; align-items:stretch; background:var(--vz-secondary-bg); border:var(--hair) solid var(--vz-border-color); border-radius:13px; overflow:hidden; margin-bottom:1.25rem; }
.rfs-hub-cc .rfs-hub-ticker-lab { flex:0 0 auto; display:flex; align-items:center; gap:7px; padding:0 16px; font-size:11.5px; font-weight:700; letter-spacing:1.5px; color:#fff; background:linear-gradient(145deg,#7e8794,#5f6772); }
.rfs-hub-cc .rfs-hub-ticker-lab .d { width:7px; height:7px; border-radius:50%; background:#fff; animation:rfsTickPulse 1.6s infinite; }
/* BRIGHT mode: make the LIVE badge much lighter with dark "LIVE" text (owner request). Dark mode keeps
   the grey gradient + white text above. */
[data-bs-theme=light] .rfs-hub-cc .rfs-hub-ticker-lab { background:#eef1f4; color:var(--vz-body-color); border-right:var(--hair) solid var(--vz-border-color); }
[data-bs-theme=light] .rfs-hub-cc .rfs-hub-ticker-lab .d { background:var(--vz-body-color); }
.rfs-hub-cc .rfs-hub-ticker-view { position:relative; overflow:hidden; flex:1; -webkit-mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent); mask-image:linear-gradient(90deg,transparent,#000 3%,#000 97%,transparent); }
.rfs-hub-cc .rfs-hub-ticker-track { display:inline-flex; align-items:center; white-space:nowrap; padding:11px 0; animation:rfsTickScroll 46s linear infinite; }
.rfs-hub-cc .rfs-hub-ticker:hover .rfs-hub-ticker-track { animation-play-state:paused; }
.rfs-hub-cc .rfs-hub-ticker-item { display:inline-flex; align-items:center; gap:9px; padding:0 24px; border-right:var(--hair) solid var(--vz-border-color); font-size:13px; color:var(--vz-body-color); }
.rfs-hub-cc .rfs-hub-ticker-item .d { width:8px; height:8px; border-radius:50%; flex:0 0 auto; }
/* LIVE strip collapse — a centred handle straddling the bottom edge hides the strip (everything below moves
   up); collapsed it stays as a slim "Live ▾" pill that reclaims the space. Choice persists per-user (ai/live). */
.rfs-hub-cc .rfs-hub-live { position:relative; margin-bottom:1.25rem; }
.rfs-hub-cc .rfs-hub-live .rfs-hub-ticker { margin-bottom:0; }
.rfs-hub-cc .rfs-hub-live-toggle { position:absolute; left:50%; bottom:-9px; transform:translateX(-50%); z-index:6; display:inline-flex; align-items:center; gap:var(--space-1); height:20px; padding:0 9px; border:var(--hair) solid var(--vz-border-color); border-radius:var(--r-lg); background:var(--vz-secondary-bg); color:var(--vz-secondary-color); font-size:var(--fs-xs); font-weight:600; line-height:1; cursor:pointer; box-shadow:0 1px 4px rgba(0,0,0,.10); transition:color .15s,border-color .15s; }
.rfs-hub-cc .rfs-hub-live-toggle i { font-size:15px; transition:transform .2s; }
.rfs-hub-cc .rfs-hub-live-toggle:hover { color:var(--vz-body-color); border-color:var(--vz-secondary-color); }
.rfs-hub-cc .rfs-hub-live-lbl { display:none; }
.rfs-hub-cc .rfs-hub-live.collapsed { margin-bottom:1rem; text-align:center; }
.rfs-hub-cc .rfs-hub-live.collapsed .rfs-hub-ticker { display:none; }
.rfs-hub-cc .rfs-hub-live.collapsed .rfs-hub-live-toggle { position:static; transform:none; left:auto; bottom:auto; }
.rfs-hub-cc .rfs-hub-live.collapsed .rfs-hub-live-toggle i { transform:rotate(180deg); }
.rfs-hub-cc .rfs-hub-live.collapsed .rfs-hub-live-lbl { display:inline; }
@keyframes rfsTickScroll { to { transform:translateX(-50%); } }
@keyframes rfsTickPulse { 0%,100%{opacity:1} 50%{opacity:.35} }
/* ── Command-center Overview surfaces (rfs-hub-cc-*) — KPI deck, briefing hero, charts, business strip,
   magic cards. All themed via --vz-* so they follow data-bs-theme. ── */
.rfs-hub-cc .cc-grid{display:grid;gap:var(--space-4)}
.rfs-hub-cc .cc-k4{grid-template-columns:repeat(4,1fr)}
.rfs-hub-cc .cc-m2{grid-template-columns:1.6fr 1fr}
.rfs-hub-cc .cc-t3{grid-template-columns:1fr 1fr 1fr}
.rfs-hub-cc .cc-b2{grid-template-columns:1.6fr 1fr}
.rfs-hub-cc .cc-snap{grid-template-columns:repeat(6,1fr)}
.rfs-hub-cc .cc-magic{grid-template-columns:repeat(4,1fr)}
@media(max-width:1200px){.rfs-hub-cc .cc-k4{grid-template-columns:repeat(2,1fr)}.rfs-hub-cc .cc-magic{grid-template-columns:repeat(2,1fr)}.rfs-hub-cc .cc-snap{grid-template-columns:repeat(3,1fr)}}
@media(max-width:992px){.rfs-hub-cc .cc-m2,.rfs-hub-cc .cc-t3,.rfs-hub-cc .cc-b2{grid-template-columns:1fr}}
/* Phones: KPI stat tiles (.cc-k4 = the hero + "Business at a glance" rows) stay a clean 2×2
   grid (owner's explicit ask — never 1-up-stacked). Action/snapshot grids keep 1-up. */
@media(max-width:600px){.rfs-hub-cc .cc-magic,.rfs-hub-cc .cc-snap{grid-template-columns:1fr}.rfs-hub-cc .cc-k4{grid-template-columns:1fr 1fr}}

/* KPI tiles */
.rfs-hub-cc .cc-kpi{position:relative;display:flex;flex-direction:column;min-height:150px;padding:var(--space-4) 18px 0;border:var(--hair) solid var(--vz-border-color);border-radius:15px;background:var(--vz-secondary-bg);overflow:hidden;text-decoration:none}
.rfs-hub-cc .cc-kpi .cc-top{display:flex;align-items:flex-start;justify-content:space-between}
.rfs-hub-cc .cc-kpi .cc-ic{width:40px;height:40px;border-radius:12px;display:grid;place-items:center;font-size:20px}
.rfs-hub-cc .cc-kpi .cc-nrow{display:flex;align-items:baseline;gap:10px;margin-top:13px;line-height:1}
.rfs-hub-cc .cc-kpi .cc-n{font-size:38px;font-weight:800;letter-spacing:-1px;line-height:1}
.rfs-hub-cc .cc-kpi .cc-nlb{font-size:38px;font-weight:500;letter-spacing:-1px;color:var(--vz-secondary-color)}
.rfs-hub-cc .cc-kpi .cc-sub{font-size:var(--fs-xs);color:var(--vz-secondary-color);margin-top:6px}
.rfs-hub-cc .cc-kpi .cc-spark{margin:14px -18px 0;height:48px;margin-top:auto}
.rfs-hub-cc .cc-kpi .cc-delta{font-size:15px;font-weight:600;display:flex;align-items:center;gap:3px}
.rfs-hub-cc .cc-kpi .cc-delta.up{color:var(--vz-success,#0ab39c)} .rfs-hub-cc .cc-kpi .cc-delta.dn{color:var(--vz-danger,#f06548)}
.rfs-hub-cc .cc-red   .cc-ic{background:rgba(var(--vz-danger-rgb,240,101,72),.14);color:var(--vz-danger,#f06548)}  .rfs-hub-cc .cc-red .cc-n{color:var(--vz-danger,#f06548)}
.rfs-hub-cc .cc-amber .cc-ic{background:rgba(247,184,75,.16);color:#d29b2a} .rfs-hub-cc .cc-amber .cc-n{color:#d29b2a}
.rfs-hub-cc .cc-cyan  .cc-ic{background:rgba(var(--vz-info-rgb),.14);color:#1f9fd0} .rfs-hub-cc .cc-cyan .cc-n{color:#1f9fd0}
.rfs-hub-cc .cc-green .cc-ic{background:rgba(var(--vz-success-rgb,10,179,156),.14);color:var(--vz-success,#0ab39c)} .rfs-hub-cc .cc-green .cc-n{color:var(--vz-success,#0ab39c)}

/* Briefing hero + Next best action */
.rfs-hub-cc .cc-orb{width:50px;height:50px;border-radius:15px;display:grid;place-items:center;font-size:24px;color:#fff;flex:0 0 auto;background:linear-gradient(145deg,var(--rfs-accent),#e85d2a);box-shadow:0 8px 24px rgba(var(--rfs-accent-rgb),.4)}
.rfs-hub-cc .cc-briefing{background:radial-gradient(420px 200px at 92% 0%,rgba(var(--rfs-accent-rgb),.14),transparent 60%),var(--vz-secondary-bg)}
.rfs-hub-cc .cc-brief-text{font-size:14.5px;line-height:1.75;color:var(--vz-body-color)}
.rfs-hub-cc .cc-on{font-size:11px;color:var(--vz-success,#0ab39c);font-weight:600;display:inline-flex;align-items:center;gap:5px}
.rfs-hub-cc .cc-on::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--vz-success,#0ab39c)}
.rfs-hub-cc .cc-nba-lab{font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:#e85d2a;font-weight:700;display:flex;align-items:center;gap:7px}
.rfs-hub-cc .cc-chip-btn{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;color:var(--vz-body-color);background:var(--vz-light,rgba(var(--vz-light-rgb,243,246,249),.5));border:var(--hair) solid var(--vz-border-color);border-radius:var(--r-lg);padding:var(--space-2) 13px;cursor:pointer;text-decoration:none;transition:.15s}
.rfs-hub-cc .cc-chip-btn:hover{border-color:var(--rfs-accent);color:#e85d2a}
.rfs-hub-cc .cc-chip-btn i{color:#e85d2a;font-size:var(--fs-base)}

/* section eyebrow */
.rfs-hub-cc .cc-sec{display:flex;align-items:center;gap:9px;margin:6px 2px 12px;font-size:11.5px;letter-spacing:1.5px;text-transform:uppercase;color:var(--vz-secondary-color);font-weight:600}
.rfs-hub-cc .cc-sec::after{content:"";flex:1;height:1px;background:var(--vz-border-color)}

/* business snapshot tiles */
.rfs-hub-cc .cc-snap-tile{position:relative;padding:15px 16px 24px;min-height:112px;border:var(--hair) solid var(--vz-border-color);border-radius:var(--r-xl);background:var(--vz-secondary-bg);overflow:hidden}
.rfs-hub-cc .cc-snap-tile .cc-sl{font-size:11.5px;color:var(--vz-secondary-color);font-weight:500;display:flex;align-items:center;gap:6px}
.rfs-hub-cc .cc-snap-tile .cc-sn{font-size:22px;font-weight:800;letter-spacing:-.5px;margin-top:9px;line-height:1;color:var(--vz-body-color)}
.rfs-hub-cc .cc-snap-tile .cc-sd{font-size:11.5px;margin-top:5px;color:var(--vz-secondary-color)}
.rfs-hub-cc .cc-snap-tile .cc-msp{position:absolute;right:0;bottom:0;left:0;height:34px;opacity:.16;pointer-events:none}

/* magic cards rows */
.rfs-hub-cc .cc-mrow{display:flex;align-items:flex-start;gap:10px;padding:9px 2px;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-hub-cc .cc-mrow:last-child{border-bottom:0}
.rfs-hub-cc .cc-mi{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;font-size:15px;flex:0 0 auto;background:var(--vz-light,rgba(var(--vz-light-rgb,243,246,249),.5))}
.rfs-hub-cc .cc-mt{font-size:13px;font-weight:500;color:var(--vz-body-color)}
.rfs-hub-cc .cc-ms{font-size:11.5px;color:var(--vz-secondary-color);margin-top:2px}
.rfs-hub-cc .cc-rchip{margin-left:auto;font-size:10.5px;font-weight:600;padding:3px 9px;border-radius:var(--r-md);align-self:center;white-space:nowrap}
.rfs-hub-cc .cc-hbadge{margin-left:auto;font-size:10.5px;font-weight:700;padding:2px 9px;border-radius:var(--r-md);background:rgba(var(--rfs-accent-rgb),.14);color:#e85d2a}

/* Dark topbar contrast: these CUSTOM topbar widgets are coloured for the default LIGHT topbar. The topbar
   renders DARK whenever the theme is dark (data-bs-theme=dark → dark-grey bar) OR the topbar is explicitly
   dark (data-topbar=dark). Lift the widgets to light text in BOTH cases — applies site-wide so the Hub and a
   dark main site stay readable AND identical. */
[data-bs-theme="dark"] .rfs-ai-usage-txt, [data-topbar="dark"] .rfs-ai-usage-txt,
[data-bs-theme="dark"] .rfs-ai-usage-meta, [data-topbar="dark"] .rfs-ai-usage-meta,
[data-bs-theme="dark"] .rfs-ai-usage-meta small, [data-topbar="dark"] .rfs-ai-usage-meta small,
[data-bs-theme="dark"] #rfs-ai-usage, [data-topbar="dark"] #rfs-ai-usage { color: rgba(255,255,255,.82) !important; }
[data-bs-theme="dark"] #rfs-ai-usage .progress, [data-topbar="dark"] #rfs-ai-usage .progress { background-color: rgba(255,255,255,.18) !important; }
[data-bs-theme="dark"] #rfs-clock-mini-btn.btn-soft-primary, [data-topbar="dark"] #rfs-clock-mini-btn.btn-soft-primary { color:#fff; background-color:rgba(255,255,255,.14); border-color:transparent; }
[data-bs-theme="dark"] #rfs-clock-mini-btn.btn-soft-primary:hover, [data-topbar="dark"] #rfs-clock-mini-btn.btn-soft-primary:hover { color:#fff; background-color:rgba(255,255,255,.24); }

/* ═══════════ end HUB COMMAND CENTER ═══════════════════════════════════════════════════════ */


/* ═════════ Settings overhaul (rfs-set-*) — one-page settings: sticky pill bar, section heads, card groups, search (2026-06-12) ═════════ */
.rfs-set-bar{position:sticky;top:70px;z-index:1015;background:var(--vz-body-bg);padding:.55rem 0 .5rem;margin:-.25rem 0 1rem;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-set-tabs{display:flex;gap:5px;border-bottom:0;padding:0;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none}
.rfs-set-tabs::-webkit-scrollbar{display:none}
.rfs-set-tabs .nav-item{margin:0}
.rfs-set-tabs .nav-link{display:inline-flex;align-items:center;gap:6px;line-height:1.1;background:#fff;border:var(--hair) solid #dfe5f1;border-radius:var(--r-lg);color:#55617a;font-weight:600;box-shadow:0 1px 2px rgba(7,22,51,.06);padding:.45rem .65rem;font-size:var(--fs-sm);white-space:nowrap;transition:color .15s ease,border-color .15s ease,box-shadow .15s ease}
.rfs-set-tabs .nav-link i{font-size:var(--fs-base);line-height:1;margin:0}
.rfs-set-tabs .nav-link:hover{color:var(--vz-primary);border-color:#b9c4e4;box-shadow:0 3px 8px rgba(var(--vz-primary-rgb),.14)}
.rfs-set-tabs .nav-link:focus-visible{outline:2px solid var(--vz-primary);outline-offset:2px;box-shadow:none}
.rfs-set-tabs .nav-link.active{background:var(--vz-primary);border-color:var(--vz-primary);color:#fff;box-shadow:0 4px 12px rgba(var(--vz-primary-rgb),.30)}
[data-bs-theme=dark] .rfs-set-tabs .nav-link{background:var(--vz-secondary-bg);border-color:var(--vz-border-color);color:var(--vz-body-color)}
[data-bs-theme=dark] .rfs-set-tabs .nav-link:hover{color:#aab8ff;border-color:#4a5578}
[data-bs-theme=dark] .rfs-set-tabs .nav-link.active{background:var(--vz-primary);border-color:var(--vz-primary);color:#fff}
.rfs-set-search{width:15rem}
@media (max-width:1500px){.rfs-set-search{width:11rem}.rfs-set-tabs .nav-link{padding:.42rem .55rem;font-size:.76rem;gap:5px}}
@media (max-width:1280px){.rfs-set-tabs .nav-link i{display:none}}
.rfs-set-wrap{max-width:1160px}
.rfs-set-section{margin-bottom:2.4rem}
.rfs-set-sechead{padding:.3rem 0 .6rem;scroll-margin-top:135px}
.rfs-set-sechead .rfs-set-secico{font-size:1.2rem;color:var(--vz-primary);line-height:1}
.rfs-set-sechead h5{font-weight:700;letter-spacing:.01em}
.rfs-set-secline{border-bottom:var(--hair) solid var(--vz-border-color);margin-left:.25rem}
.rfs-set-resetbtn{font-size:.72rem;white-space:nowrap}
.rfs-set-group{margin-bottom:1.5rem;scroll-margin-top:135px}
.rfs-set-group > .card:last-child{margin-bottom:0}
.rfs-set-cardhead{margin:0 0 .55rem;padding-left:.1rem}
.rfs-set-cardhead h6{font-weight:700}
.rfs-set-ico{width:32px;height:32px;border-radius:var(--r-md);background:var(--vz-light);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}
.rfs-set-ico i{font-size:var(--fs-lg);color:var(--vz-primary);line-height:1}
.rfs-set-sub{font-size:var(--fs-xs);line-height:1.3}
.rfs-set-group .card[id^="pay-"],.rfs-set-group .accordion-item[id^="tpl-"],.rfs-set-group .accordion-item[id^="sms-"]{scroll-margin-top:135px}
.rfs-set-hit{animation:rfsSetHit 1.4s ease}
@keyframes rfsSetHit{0%{outline:2px solid rgba(var(--vz-primary-rgb),0);outline-offset:5px;border-radius:var(--r-md)}20%{outline:3px solid rgba(var(--vz-primary-rgb),.6)}100%{outline:2px solid rgba(var(--vz-primary-rgb),0)}}

/* ═════════ Settings POPUP (rfs-setpop-*) — wide modal: left nav + AJAX panes + ONE global Save (2026-06-13) ═════════ */
.rfs-setpop-dialog{max-width:min(1180px,96vw)}
.rfs-setpop .modal-content{height:min(90vh,880px);max-height:90vh;display:flex;flex-direction:column;overflow:hidden;border-radius:16px}
/* Header (extends .rfs-modal header) */
.rfs-setpop-header{flex:0 0 auto}
.rfs-setpop-headactions{display:flex;align-items:center;gap:.55rem;margin-left:auto}
.rfs-setpop-dirty{font-size:.78rem;font-weight:600;color:var(--vz-warning);background:rgba(var(--vz-warning-rgb),.13);padding:.32rem .6rem;border-radius:var(--r-md);white-space:nowrap}
.rfs-setpop-dirty i{margin-right:.15rem}
.rfs-setpop-save{min-width:86px}
.rfs-setpop-save.rfs-busy{pointer-events:none;opacity:.65}
.rfs-setpop-save:disabled{opacity:.5}
/* Post-save confirmation flash (set by the page's onSaved hook): green tick, stays solid even though the
   button goes disabled the instant the dirty count hits 0. */
.rfs-setpop-save.rfs-saved,.rfs-setpop-save.rfs-saved:disabled{background:#0ab39c!important;border-color:#0ab39c!important;color:#fff!important;opacity:1!important}
/* My account avatar button (sits by Save; personal pane, not in the company nav) */
.rfs-setpop-acct{border:0;background:none;padding:0;margin:0;cursor:pointer;border-radius:50%;flex-shrink:0;display:inline-flex;line-height:0}
.rfs-setpop-acct-av{width:34px;height:34px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-size:.78rem;font-weight:600;transition:filter .12s,box-shadow .12s}
.rfs-setpop-acct-av i{font-size:17px}
.rfs-setpop-acct:hover .rfs-setpop-acct-av{filter:brightness(.93)}
.rfs-setpop-acct.active .rfs-setpop-acct-av,.rfs-setpop-acct:focus-visible .rfs-setpop-acct-av{box-shadow:0 0 0 2px var(--vz-secondary-bg),0 0 0 4px var(--vz-primary);outline:none}
.rfs-setpop-headsep{width:1px;height:24px;background:var(--vz-border-color);margin:0 .15rem;flex-shrink:0}
/* Body: a top search bar over a nav + content split (each scrolls independently; page never moves) */
.rfs-setpop-body{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.rfs-setpop-split{flex:1 1 auto;min-height:0;display:flex}
/* Header search icon (toggles the search bar open) */
.rfs-setpop-iconbtn{border:0;background:none;color:var(--vz-secondary-color);width:34px;height:34px;border-radius:var(--r-md);display:inline-flex;align-items:center;justify-content:center;font-size:var(--fs-xl);cursor:pointer;flex-shrink:0;transition:background .12s,color .12s}
.rfs-setpop-iconbtn:hover{background:var(--vz-light);color:var(--vz-primary)}
.rfs-setpop-iconbtn.active{background:rgba(var(--vz-primary-rgb),.12);color:var(--vz-primary)}
/* Live search bar — hidden until the header search icon opens it */
.rfs-setpop-searchbar{flex:0 0 auto;display:none;align-items:center;gap:.55rem;padding:.6rem 1rem;border-bottom:var(--hair) solid var(--vz-border-color);background:var(--vz-secondary-bg)}
.rfs-setpop-searchbar.open{display:flex}
.rfs-setpop-searchbar > i{font-size:17px;color:var(--vz-secondary-color)}
.rfs-setpop-searchbar input{flex:1 1 auto;border:0;background:transparent;outline:none;font-size:.9rem;color:var(--vz-body-color)}
.rfs-setpop-searchbar input::placeholder{color:var(--vz-secondary-color)}
.rfs-setpop-searchclear{cursor:pointer;color:var(--vz-secondary-color);font-size:var(--fs-xl);line-height:1;padding:0 .25rem;display:none}
.rfs-setpop-searchbar.has-q .rfs-setpop-searchclear{display:inline}
/* Results panel (replaces the pane content while searching) */
.rfs-setpop-content.rfs-setpop-searching > .rfs-setpop-pane,.rfs-setpop-content.rfs-setpop-searching > .rfs-setpop-loading{display:none!important}
.rfs-setpop-results{max-width:720px;margin:0 auto}
.rfs-setpop-resgrp{font-size:.72rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--vz-secondary-color);margin:1rem 0 .35rem;padding-left:.2rem}
.rfs-setpop-resgrp:first-child{margin-top:.2rem}
.rfs-setpop-resitem{display:flex;flex-direction:column;align-items:flex-start;gap:1px;width:100%;text-align:left;border:var(--hair) solid var(--vz-border-color);background:var(--vz-secondary-bg);border-radius:9px;padding:.55rem .8rem;margin-bottom:6px;cursor:pointer;transition:border-color .12s,background .12s}
.rfs-setpop-resitem:hover{border-color:var(--vz-primary);background:rgba(var(--vz-primary-rgb),.05)}
.rfs-setpop-resmain{font-size:var(--fs-base);font-weight:500;color:var(--vz-heading-color)}
.rfs-setpop-ressub{font-size:.76rem;color:var(--vz-secondary-color)}
.rfs-setpop-noresults,.rfs-setpop-searchwait{text-align:center;color:var(--vz-secondary-color);font-size:.85rem;padding:2.5rem 1rem}
.rfs-setpop-flash{animation:rfsSetpopFlash 1.4s ease}
@keyframes rfsSetpopFlash{0%{box-shadow:0 0 0 0 rgba(var(--vz-primary-rgb),.5)}30%{box-shadow:0 0 0 3px rgba(var(--vz-primary-rgb),.5);border-radius:12px}100%{box-shadow:0 0 0 0 rgba(var(--vz-primary-rgb),0)}}
.rfs-setpop-nav{width:252px;flex:0 0 252px;overflow-y:auto;border-right:var(--hair) solid var(--vz-border-color);padding:1.15rem .55rem .8rem;flex-direction:column;gap:2px;background:var(--vz-light)}
[data-bs-theme=dark] .rfs-setpop-nav{background:var(--vz-secondary-bg)}
.rfs-setpop-navhead{font-size:.66rem;font-weight:700;text-transform:uppercase;letter-spacing:.045em;color:var(--vz-secondary-color);padding:.45rem .65rem .25rem}
.rfs-setpop-navhead-div{margin-top:.45rem;border-top:var(--hair) solid var(--vz-border-color);padding-top:.6rem}
.rfs-setpop-navitem{display:flex;align-items:center;gap:.6rem;width:100%;text-align:left;border:0;background:transparent;color:var(--vz-body-color);font-weight:500;font-size:.85rem;padding:.52rem .65rem;border-radius:var(--r-md);cursor:pointer;transition:background .12s,color .12s,box-shadow .12s}
.rfs-setpop-navitem > i:first-child{font-size:var(--fs-lg);width:18px;text-align:center;color:var(--vz-secondary-color);transition:color .12s}
.rfs-setpop-navitem > span{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rfs-setpop-navitem:hover{background:rgba(var(--vz-primary-rgb),.09);color:var(--vz-primary)}
.rfs-setpop-navitem:hover > i:first-child{color:var(--vz-primary)}
.rfs-setpop-navitem.active{background:var(--vz-primary);color:#fff;box-shadow:0 3px 9px rgba(var(--vz-primary-rgb),.3)}
.rfs-setpop-navitem.active > i:first-child{color:#fff}
.rfs-setpop-navitem:focus-visible{outline:2px solid var(--vz-primary);outline-offset:1px}
.rfs-setpop-dot{font-size:7px;margin-left:auto;color:var(--vz-warning);opacity:0;transition:opacity .12s;flex-shrink:0}
.rfs-setpop-navitem.has-dirty .rfs-setpop-dot{opacity:1}
.rfs-setpop-navitem.active.has-dirty .rfs-setpop-dot{color:#fff}
/* Content + panes */
.rfs-setpop-content{flex:1 1 auto;min-width:0;overflow-y:auto;padding:1.4rem 1.6rem;position:relative}
.rfs-setpop-loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:var(--vz-secondary-bg);z-index:5}
.rfs-setpop-pane.d-none{display:none!important}
.rfs-setpop-pane-inner{max-width:920px}
.rfs-setpop-panehead{margin-bottom:1.25rem;padding-bottom:.85rem;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-setpop-panehead h4{font-size:1.15rem;font-weight:600;margin:0 0 .2rem}
.rfs-setpop-panehead p{font-size:.82rem}
.rfs-setpop-content .rfs-set-group{scroll-margin-top:0}
.rfs-setpop-content .rfs-set-group:last-child{margin-bottom:0}
/* The per-card kv Save buttons are kept in markup (byte-for-byte) but hidden — the header's global Save commits.
   [formaction] submits (e.g. Appearance "Reset to Defaults") stay visible as discrete actions. */
.rfs-setpop-content form[data-settings-form] button[type="submit"]:not([formaction]),
.rfs-setpop-content form[data-settings-form] input[type="submit"]:not([formaction]){display:none!important}
.rfs-setpop-content form[data-settings-form] .col-12:has(> button[type="submit"]:only-child){display:none}
.rfs-setpop-errform{box-shadow:0 0 0 2px var(--vz-danger)!important;border-radius:var(--r-lg)}
/* Empty / migrating / locked states */
.rfs-setpop-empty{max-width:440px;margin:3rem auto;text-align:center}
.rfs-setpop-emptyico{font-size:36px;color:var(--vz-primary);width:78px;height:78px;border-radius:20px;background:rgba(var(--vz-primary-rgb),.1);display:flex;align-items:center;justify-content:center;margin:0 auto 1.1rem}
.rfs-setpop-emptysub{font-size:.85rem;margin-bottom:1.25rem}
/* Mobile: nav collapses to a top select; modal goes near-full-screen */
.rfs-setpop-mobbar{padding:.6rem .9rem;border-bottom:var(--hair) solid var(--vz-border-color);background:var(--vz-light)}
@media (max-width:767.98px){
  .rfs-setpop-dialog{max-width:100%;margin:0;min-height:100%}
  .rfs-setpop .modal-content{height:100vh;max-height:100vh;border-radius:0}
  .rfs-setpop-split{flex-direction:column}
  .rfs-setpop-content{padding:1rem}
  .rfs-setpop-pane-inner{max-width:none}
  .rfs-setpop-save-lbl{display:none}
  .rfs-setpop-save{min-width:0}
}

/* ── Settings rows design (Option A, approved 2026-06-13) — carded groups, label+helper left / control right ── */
.rfs-setpop .modal-header{padding:1.25rem 1.5rem 15px}                    /* 15px breathing room BELOW the popup title/subtitle */
/* Velzon forces non-scrollable modal headers to padding-bottom:0 (specificity 0,3,0) — beat it (0,4,0). */
.rfs-setpop .modal-dialog:not(.modal-dialog-scrollable) .modal-header{padding-bottom:15px}
.rfs-setpop-header .rfs-modal-sub{margin-top:4px}
.rfs-setpop-content{background:var(--vz-body-bg);padding:1.9rem 1.7rem}   /* soft canvas so the white group cards read as cards */
.rfs-setpop-pane-inner{max-width:720px;margin:0 auto}
.rfs-setpop-panehead{margin:0 0 1.1rem}
.rfs-setpop-panehead h4{font-size:1.1rem;font-weight:600;margin:0 0 .15rem}
.rfs-setpop-panehead p{font-size:.82rem}
/* Group = a clean card: icon + title header, padded body of rows */
.rfs-setpop-group{background:var(--vz-secondary-bg);border:var(--hair) solid var(--vz-border-color);border-radius:var(--r-xl);margin-bottom:1.15rem;overflow:hidden;box-shadow:0 1px 2px rgba(15,23,42,.04)}
.rfs-setpop-group:last-child{margin-bottom:.25rem}
.rfs-setpop-grouphead{display:flex;align-items:center;gap:.75rem;padding:.95rem 1.35rem;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-setpop-groupicon{width:34px;height:34px;border-radius:9px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:var(--fs-xl);background:rgba(var(--vz-primary-rgb),.1);color:var(--vz-primary)}
.rfs-setpop-grouptitle{font-size:.95rem;font-weight:600;color:var(--vz-heading-color);line-height:1.2}
.rfs-setpop-groupsub{display:block;font-size:.795rem;font-weight:400;color:var(--vz-secondary-color);line-height:1.35;margin-top:1px}
.rfs-setpop-groupbody{padding:.3rem 1.35rem 1rem}
/* Pane sub-tabs — show one section (card) at a time, mirroring the old /global one-list-at-a-time nav */
.rfs-setpop-subtabs{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 1.3rem;padding-bottom:1rem;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-setpop-subtab{display:inline-flex;align-items:center;gap:6px;border:var(--hair) solid var(--vz-border-color);background:var(--vz-secondary-bg);color:var(--vz-secondary-color);border-radius:9px;padding:.42rem .75rem;font-size:.82rem;font-weight:500;cursor:pointer;line-height:1.2;transition:color .12s,border-color .12s,background .12s}
.rfs-setpop-subtab i{font-size:15px}
.rfs-setpop-subtab:hover{border-color:var(--vz-primary);color:var(--vz-primary)}
.rfs-setpop-subtab.active{background:var(--vz-primary);border-color:var(--vz-primary);color:#fff}
.rfs-setpop-subtab.active i{color:#fff}
.rfs-setpop-group.rfs-tab-hidden{display:none}
.rfs-setpop-subtabs ~ .rfs-setpop-group{margin-bottom:.3rem}
/* Rows */
.rfs-setpop-row{display:flex;align-items:center;justify-content:space-between;gap:1.5rem;padding:.9rem 0;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-setpop-groupbody > .rfs-setpop-row:last-child,.rfs-setpop-groupbody > form > .rfs-setpop-row:last-child{border-bottom:0}
.rfs-setpop-rowlabel{flex:1 1 auto;min-width:0;padding-right:.5rem}
.rfs-setpop-rowtitle{display:block;font-size:var(--fs-base);font-weight:500;color:var(--vz-heading-color);margin:0;line-height:1.3}
.rfs-setpop-rowhelp{font-size:.795rem;color:var(--vz-secondary-color);margin-top:2px;line-height:1.4}
.rfs-setpop-rowhelp code{font-size:.74rem}
.rfs-setpop-rowctrl{flex:0 0 280px;max-width:280px;display:flex;align-items:center;justify-content:flex-end;gap:.5rem}
.rfs-setpop-rowctrl > .form-control,.rfs-setpop-rowctrl > .form-select{width:100%}
.rfs-setpop-row-stack{flex-direction:column;align-items:stretch;gap:.55rem}
.rfs-setpop-row-stack .rfs-setpop-rowctrl{flex:1 1 auto;max-width:none;width:100%;justify-content:flex-start}
.rfs-setpop-row-stack .rfs-setpop-rowctrl > .form-control,.rfs-setpop-row-stack .rfs-setpop-rowctrl > textarea{width:100%}
/* Topbar — a touch more height + de-crowd the right-side icons (≤23px slack confirmed, no overlap) */
@media (min-width:768px){
  #page-topbar .navbar-header{height:76px;align-items:center}
  /* (removed .main-content padding-top:49px — it compensated for the old abar living in the fixed
     topbar; the abar now sits inline in .page-content, which already clears the topbar.) */
  #page-topbar .navbar-header > div:last-child{gap:2px}
}
/* Toggle switch */
.rfs-setpop-switch{position:relative;display:inline-flex;width:40px;height:23px;flex-shrink:0;margin:0;cursor:pointer}
.rfs-setpop-switch input{position:absolute;width:0;height:0;opacity:0}
.rfs-setpop-switch span{width:40px;height:23px;border-radius:12px;background:var(--vz-border-color);transition:background .15s}
.rfs-setpop-switch span::after{content:"";position:absolute;top:2px;left:2px;width:19px;height:19px;border-radius:50%;background:#fff;transition:transform .15s;box-shadow:0 1px 2px rgba(0,0,0,.2)}
.rfs-setpop-switch input:checked + span{background:var(--vz-primary)}
.rfs-setpop-switch input:checked + span::after{transform:translateX(17px)}
.rfs-setpop-switch input:disabled + span{opacity:.5;cursor:default}
.rfs-setpop-switch input:focus-visible + span{outline:2px solid var(--vz-primary);outline-offset:2px}
/* Progressive disclosure */
.rfs-setpop-reveal{overflow:hidden;transition:max-height .24s ease,opacity .2s ease;max-height:1500px;opacity:1}
.rfs-setpop-reveal.rfs-collapsed{max-height:0;opacity:0}
.rfs-setpop-reveal > .rfs-setpop-revinner{border-left:2px solid rgba(var(--vz-primary-rgb),.18);padding:.3rem 0 .3rem 1rem;margin:.1rem 0 .3rem}
.rfs-setpop-reveal .rfs-setpop-row:first-child{padding-top:.4rem}
/* Day pills (re-skin the hours day checkboxes) */
.rfs-setpop-days{display:flex;flex-wrap:wrap;gap:6px}
.rfs-setpop-days .form-check{margin:0;padding:0;min-height:0;display:inline-block}
.rfs-setpop-days input{position:absolute;opacity:0;pointer-events:none}
.rfs-setpop-days label{display:inline-block;padding:5px 13px;border:var(--hair) solid var(--vz-border-color);border-radius:var(--r-md);font-size:var(--fs-sm);color:var(--vz-secondary-color);cursor:pointer;user-select:none;transition:background .12s,border-color .12s,color .12s}
.rfs-setpop-days input:checked + label{background:var(--vz-primary);border-color:var(--vz-primary);color:#fff}
.rfs-setpop-days input:focus-visible + label{outline:2px solid var(--vz-primary);outline-offset:2px}
.rfs-setpop-days input:disabled + label{opacity:.55;cursor:default}
/* Logo row + inline note + colour field */
.rfs-setpop-logo{width:84px;height:84px;border:var(--hair) solid var(--vz-border-color);border-radius:var(--r-lg);display:flex;align-items:center;justify-content:center;background:var(--vz-light);overflow:hidden;flex-shrink:0}
.rfs-setpop-logo img{max-width:100%;max-height:100%}
.rfs-setpop-colorwrap{display:flex;align-items:center;gap:.5rem;width:100%}
.rfs-setpop-colorwrap .form-control-color{flex:0 0 38px;padding:3px}
.rfs-setpop-note{font-size:.78rem;color:var(--vz-secondary-color);background:var(--vz-light);border:var(--hair) solid var(--vz-border-color);border-radius:var(--r-md);padding:.55rem .75rem;display:flex;gap:.45rem;align-items:flex-start}
.rfs-setpop-note i{margin-top:1px}
/* Appearance section sits in the rows flow but its controls are visual blocks */
.rfs-setpop-appitem{padding:.85rem 0;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-setpop-appitem:last-child{border-bottom:0}
.rfs-setpop-appitem > .rfs-setpop-rowtitle{margin-bottom:.5rem}
/* Inline field clusters (numbering, address) */
.rfs-setpop-inline{display:flex;gap:.65rem;flex-wrap:wrap;width:100%}
.rfs-setpop-inline > div{flex:1 1 90px;min-width:0}
.rfs-setpop-sublabel{font-size:.72rem;color:var(--vz-secondary-color);display:block;margin-bottom:3px}

/* ===== SETTINGS PAGE (full-width primary surface) =====
   The page-only `.rfs-setpage-*` design + the page's `.rfs-setpop-*` overrides were MIGRATED to the
   dedicated, page-scoped stylesheet public/assets/css/rfs-settings.css (loaded by Views/settings/page.php).
   The shared `.rfs-setpop-*` BASE rules above remain here for the dormant settings popup. */


/* ===== HUB COMMAND CENTER — pane component CSS (workflow port 2026-06-17) ===== */
.rfs-hub-cc { --rfs-hub-dark: #03303a; } /* A-240: scoped Hub-dark alias (§6 bespoke) — value unchanged, hex now lives in ONE place */
/* ============================================================
   Hub Command Center — pane component CSS (ported from _hub-mockup.html)
   All selectors scoped to .rfs-hub-cc; colors via themed Velzon vars
   so both dark + light (data-bs-theme) work. Accents stay vivid hex.
   ============================================================ */

/* card helpers (flat surface; no hardcoded dark hex) */
.rfs-hub-cc .card{position:relative;background:var(--vz-secondary-bg);
  border:var(--hair) solid var(--vz-border-color);border-radius:var(--r-xl);padding:18px 18px 16px;overflow:hidden;
  transition:background .35s,border-color .25s,box-shadow .25s}
.rfs-hub-cc .card h3{font-size:13px;font-weight:600;color:var(--vz-secondary-color);letter-spacing:.4px;display:flex;align-items:center;gap:var(--space-2);margin-bottom:4px}
.rfs-hub-cc .card h3 i{font-size:var(--fs-lg)}
.rfs-hub-cc .card .foot{margin-top:12px;border-top:var(--hair) solid var(--vz-border-color);padding-top:10px;font-size:12.5px;color:var(--vz-secondary-color)}
.rfs-hub-cc .card .foot a{color:var(--rfs-accent);text-decoration:none}

/* panes (tab switching) */
.rfs-hub-cc .pane{display:none}
.rfs-hub-cc .pane.show{display:block;animation:rfsccFadein .3s ease}
@keyframes rfsccFadein{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}
.rfs-hub-cc .pane-empty{text-align:center;padding:64px 20px}
.rfs-hub-cc .pane-empty i{font-size:40px;display:block;margin-bottom:12px}
.rfs-hub-cc .pane-empty .pe-t{font-size:var(--fs-lg);font-weight:600}
.rfs-hub-cc .pane-empty .pe-s{font-size:13px;color:var(--vz-secondary-color);margin-top:6px}

/* segmented control + frost select + ghost button — the ONE definition of each (A-347).
   Hub-wide, not alerts-only: the Tasks pane (.rfs-cc-tk-*) leans on these bases too. Modifiers
   (:hover / ::after / -sm) live here beside their base — a second copy elsewhere goes dead. */
.rfs-hub-cc .seg{display:inline-flex;gap:2px;background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);border-radius:11px;padding:var(--space-1)}
.rfs-hub-cc .seg-item{padding:7px 15px;border-radius:var(--r-md);font-size:12.5px;font-weight:500;color:var(--vz-secondary-color);cursor:pointer;transition:.18s;border:0;background:transparent;line-height:1.2}
.rfs-hub-cc .seg-item:hover{color:var(--vz-body-color)}
.rfs-hub-cc .seg-item.active{background:rgba(var(--vz-info-rgb),.16);color:var(--vz-info);font-weight:600}
.rfs-hub-cc .frost-sel{background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);border-radius:11px;padding:var(--space-2) 12px;font-size:12.5px;color:var(--vz-body-color);font-family:inherit;cursor:pointer;line-height:1.2}
.rfs-hub-cc .frost-sel:hover{border-color:var(--rfs-accent)}
.rfs-hub-cc .frost-sel.dropdown-toggle::after{margin-left:6px;vertical-align:1px}
.rfs-hub-cc .ghost-btn{display:inline-flex;align-items:center;gap:7px;background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);border-radius:11px;padding:var(--space-2) 13px;font-size:12.5px;font-weight:500;color:var(--vz-body-color);cursor:pointer;transition:.15s;line-height:1.2;text-decoration:none}
.rfs-hub-cc .ghost-btn:hover{border-color:var(--rfs-accent);color:var(--rfs-accent)}
.rfs-hub-cc .ghost-btn.dropdown-toggle::after{margin-left:2px}
.rfs-hub-cc .ghost-btn-sm{padding:6px 11px;font-size:var(--fs-xs)}

/* ── To Sort / alerts pane ───────────────────────────── */
.rfs-hub-cc .al-count{display:flex;align-items:center;gap:var(--space-2);font-size:13.5px;color:var(--vz-secondary-color)}
.rfs-hub-cc .al-count b{color:var(--vz-body-color);font-size:var(--fs-lg);font-weight:700}
.rfs-hub-cc .al-dot{width:9px;height:9px;border-radius:50%;display:inline-block}
.rfs-hub-cc .al-dot.red{background:var(--vz-danger,#f06548)}
.rfs-hub-cc .al-dot.amber{background:#f7b84b}
.rfs-hub-cc .al-bar{display:flex;width:170px;height:8px;border-radius:5px;overflow:hidden;background:rgba(130,140,160,.10)}
.rfs-hub-cc .al-bar span{display:block;height:100%}
.rfs-hub-cc .al-row{display:flex;align-items:center;gap:13px;padding:14px 18px;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-hub-cc .al-row:last-child{border-bottom:0}
.rfs-hub-cc .al-row:hover{background:rgba(130,140,160,.06)}
.rfs-hub-cc .al-sev{width:11px;height:11px;border-radius:50%;flex:0 0 auto}
.rfs-hub-cc .al-sev.red{background:var(--vz-danger,#f06548);box-shadow:0 0 11px rgba(240,101,72,.55)}
.rfs-hub-cc .al-sev.amber{background:#f7b84b;box-shadow:0 0 9px rgba(247,184,75,.45)}
.rfs-hub-cc .al-body{flex:1;min-width:0}
.rfs-hub-cc .al-title{font-size:var(--fs-base);font-weight:600;display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.rfs-hub-cc .al-cat{font-size:10.5px;font-weight:600;text-transform:capitalize;padding:2px 8px;border-radius:7px;background:rgba(130,140,160,.10);color:var(--vz-secondary-color)}
.rfs-hub-cc .al-reason{font-size:12.5px;color:var(--vz-secondary-color);margin-top:3px}
.rfs-hub-cc .al-actions{display:flex;align-items:center;gap:6px;flex-shrink:0}
.rfs-hub-cc .al-act{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-xs);font-weight:500;color:var(--vz-body-color);background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);border-radius:9px;padding:6px 11px;cursor:pointer;white-space:nowrap;transition:.15s;line-height:1.2;text-decoration:none}
.rfs-hub-cc .al-act:hover{border-color:var(--vz-secondary-color);filter:brightness(1.08)}
.rfs-hub-cc .al-act.ico{padding:6px 9px;color:var(--vz-secondary-color)}
.rfs-hub-cc .al-act.ai{color:var(--rfs-accent);background:rgba(var(--rfs-accent-rgb),.12);border-color:rgba(var(--rfs-accent-rgb),.32)}
.rfs-hub-cc .al-act.ai:hover{background:rgba(var(--rfs-accent-rgb),.2)}
@media(max-width:1100px){.rfs-hub-cc .al-row{flex-wrap:wrap}.rfs-hub-cc .al-actions{width:100%;padding-left:24px}}

/* ── Notifications pane — the ONE definition of each (A-403; see A-347 for the same root). ──── */
.rfs-hub-cc .nlist-group{font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--vz-secondary-color);font-weight:600;margin:var(--space-4) 18px 4px}
.rfs-hub-cc .nrow2{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-3) 18px;border-bottom:var(--hair) solid var(--vz-border-color);cursor:pointer;transition:.15s}
.rfs-hub-cc .nrow2:hover{background:rgba(130,140,160,.06)}
.rfs-hub-cc .nrow2:last-child{border-bottom:0}
.rfs-hub-cc .nrow2 .ni{width:36px;height:36px;border-radius:var(--r-lg);display:grid;place-items:center;font-size:17px;flex:0 0 auto;background:rgba(130,140,160,.10);color:var(--vz-info,var(--vz-info))}
.rfs-hub-cc .nrow2 .nt{font-size:13.5px;font-weight:500;color:var(--vz-body-color)}
.rfs-hub-cc .nrow2 .ns{font-size:11.5px;color:var(--vz-secondary-color);margin-top:2px}
.rfs-hub-cc .nrow2.read .nt{color:var(--vz-secondary-color);font-weight:400}
.rfs-hub-cc .nrow2 .nu{margin-left:auto;width:9px;height:9px;border-radius:50%;background:var(--rfs-accent);box-shadow:0 0 8px rgba(var(--rfs-accent-rgb),.85);flex:0 0 auto}

/* ── Tasks pane ──────────────────────────────────────── */
.rfs-hub-cc .tk-row{display:flex;align-items:center;gap:14px;padding:14px 18px;border-bottom:var(--hair) solid var(--vz-border-color);transition:.15s}
.rfs-hub-cc .tk-row:hover{background:rgba(130,140,160,.06)}
.rfs-hub-cc .tk-row:last-child{border-bottom:0}
.rfs-hub-cc .tk-check{width:22px;height:22px;border-radius:50%;border:2px solid var(--vz-border-color);flex:0 0 auto;cursor:pointer}
.rfs-hub-cc .tk-title{font-size:var(--fs-base);font-weight:600}
.rfs-hub-cc .tk-sub{font-size:var(--fs-xs);color:var(--vz-secondary-color);margin-top:2px;max-width:520px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rfs-hub-cc .tk-meta{margin-left:auto;display:flex;align-items:center;gap:var(--space-4);flex-shrink:0}
.rfs-hub-cc .tk-av{width:28px;height:28px;border-radius:50%;display:grid;place-items:center;font-size:10.5px;font-weight:700;background:rgba(139,124,246,.18);color:#8b7cf6;flex:0 0 auto}
.rfs-hub-cc .pill{font-size:11px;font-weight:600;padding:3px 11px;border-radius:var(--r-md);white-space:nowrap}
.rfs-hub-cc .pill.todo{background:rgba(130,140,160,.10);color:var(--vz-secondary-color)}
.rfs-hub-cc .pill.prog{background:rgba(var(--vz-info-rgb),.15);color:var(--vz-info)}
.rfs-hub-cc .pill.done{background:rgba(10,179,156,.16);color:var(--vz-success,#0ab39c)}
.rfs-hub-cc .pill.norm{background:rgba(130,140,160,.10);color:var(--vz-secondary-color)}
.rfs-hub-cc .pill.high{background:rgba(240,101,72,.15);color:var(--vz-danger,#f06548)}
.rfs-hub-cc .tk-due{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;color:var(--vz-secondary-color);min-width:78px}
.rfs-hub-cc .tk-due.over{color:var(--vz-danger,#f06548);font-weight:600}
@media(max-width:900px){.rfs-hub-cc .tk-meta{gap:10px}.rfs-hub-cc .tk-sub{max-width:160px}}

/* ── AI Assistant console pane ───────────────────────── */
.rfs-hub-cc .chat-wrap{display:grid;grid-template-columns:1.6fr 1fr;gap:var(--space-4)}
@media(max-width:900px){.rfs-hub-cc .chat-wrap{grid-template-columns:1fr}}
.rfs-hub-cc .chat-head{display:flex;align-items:center;gap:13px;padding:15px 18px;border-bottom:var(--hair) solid var(--vz-border-color);
  background:radial-gradient(440px 130px at 100% 0%,rgba(var(--rfs-accent-rgb),.16),transparent 60%)}
.rfs-hub-cc .chat-head .orb{width:42px;height:42px;border-radius:12px;display:grid;place-items:center;font-size:21px;background:linear-gradient(145deg,var(--rfs-accent),#e85d2a);box-shadow:0 8px 22px rgba(var(--rfs-accent-rgb),.42);flex:0 0 auto}
.rfs-hub-cc .chat-head .orb i{color:#fff}
.rfs-hub-cc .chat-head h4{font-size:15px;font-weight:700;display:flex;align-items:center;gap:9px}
.rfs-hub-cc .chat-head p{font-size:var(--fs-xs);color:var(--vz-secondary-color);margin-top:2px}
.rfs-hub-cc .chat-body{padding:18px;display:flex;flex-direction:column;gap:var(--space-3);min-height:300px}
.rfs-hub-cc .bubble{max-width:82%;padding:11px 15px;border-radius:15px;font-size:13.5px;line-height:1.55}
.rfs-hub-cc .bubble.ai{align-self:flex-start;background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);border-top-left-radius:5px}
.rfs-hub-cc .bubble.me{align-self:flex-end;background:linear-gradient(145deg,var(--rfs-accent),#e85d2a);color:#fff;border-top-right-radius:5px}
.rfs-hub-cc .qr-row{display:flex;flex-wrap:wrap;gap:var(--space-2);align-self:flex-start}
.rfs-hub-cc .qb{font-size:12.5px;color:var(--vz-body-color);background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);
  padding:var(--space-2) 13px;border-radius:var(--r-lg);cursor:pointer;display:flex;align-items:center;gap:7px;transition:.15s}
.rfs-hub-cc .qb:hover{background:rgba(var(--rfs-accent-rgb),.14);border-color:rgba(var(--rfs-accent-rgb),.4)}
.rfs-hub-cc .qb i{color:var(--rfs-accent);font-size:var(--fs-base)}
.rfs-hub-cc .chat-foot{padding:14px 18px;border-top:var(--hair) solid var(--vz-border-color)}
.rfs-hub-cc .ai-input{display:flex;align-items:center;gap:10px;background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);
  border-radius:var(--r-xl);padding:7px 7px 7px 15px}
.rfs-hub-cc .ai-input input{flex:1;background:transparent;border:0;outline:0;color:var(--vz-body-color);font-size:13.5px;font-family:inherit}
.rfs-hub-cc .ai-input input::placeholder{color:var(--vz-secondary-color)}
.rfs-hub-cc .ai-send{width:38px;height:38px;border-radius:11px;border:0;cursor:pointer;display:grid;place-items:center;color:#fff;font-size:17px;
  background:linear-gradient(145deg,var(--rfs-accent),#e85d2a);box-shadow:0 6px 18px rgba(var(--rfs-accent-rgb),.4)}
.rfs-hub-cc .cap-rail{display:flex;flex-direction:column;gap:var(--space-2)}
.rfs-hub-cc .cap-card{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-3) 14px;border-radius:12px;background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);cursor:pointer;transition:.15s}
.rfs-hub-cc .cap-card:hover{border-color:rgba(var(--rfs-accent-rgb),.4);background:rgba(var(--rfs-accent-rgb),.07)}
.rfs-hub-cc .cap-card .ci{width:34px;height:34px;border-radius:var(--r-lg);display:grid;place-items:center;font-size:17px;flex:0 0 auto}
.rfs-hub-cc .cap-card .ct{font-size:13px;font-weight:600}
.rfs-hub-cc .cap-card .cs{font-size:11.5px;color:var(--vz-secondary-color);margin-top:1px}

/* ── Messages (staff) pane ───────────────────────────── */
.rfs-hub-cc .msg-wrap{display:grid;grid-template-columns:300px 1fr}
@media(max-width:760px){.rfs-hub-cc .msg-wrap{grid-template-columns:1fr}}
.rfs-hub-cc .conv{display:flex;align-items:center;gap:11px;padding:13px 16px;border-bottom:var(--hair) solid var(--vz-border-color);cursor:pointer;transition:.15s}
.rfs-hub-cc .conv:hover{background:rgba(130,140,160,.06)}
.rfs-hub-cc .conv.active{background:rgba(var(--vz-info-rgb),.08);box-shadow:inset 3px 0 0 var(--vz-info)}
.rfs-hub-cc .conv .av{width:38px;height:38px;border-radius:50%;display:grid;place-items:center;font-size:13px;font-weight:700;flex:0 0 auto}
.rfs-hub-cc .conv .cn{font-size:13.5px;font-weight:600;display:flex;align-items:center;gap:7px}
.rfs-hub-cc .conv .cp{font-size:11.5px;color:var(--vz-secondary-color);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:165px}
.rfs-hub-cc .role-chip{font-size:9.5px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;padding:1px 7px;border-radius:var(--r-sm);background:rgba(130,140,160,.10);color:var(--vz-secondary-color)}
.rfs-hub-cc .conv .cu{margin-left:auto;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--vz-info);color:var(--rfs-hub-dark);font-size:10px;font-weight:700;display:grid;place-items:center;flex:0 0 auto}
.rfs-hub-cc .thread-head{display:flex;align-items:center;gap:11px;padding:13px 18px;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-hub-cc .thread-body{padding:18px;display:flex;flex-direction:column;gap:10px;min-height:240px}
.rfs-hub-cc .mbub{max-width:70%;padding:9px 13px;border-radius:13px;font-size:13px;line-height:1.45}
.rfs-hub-cc .mbub.them{align-self:flex-start;background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);border-top-left-radius:4px}
.rfs-hub-cc .mbub.me{align-self:flex-end;background:var(--vz-info);color:var(--rfs-hub-dark);border-top-right-radius:4px}
.rfs-hub-cc .mbub .mt2{font-size:10px;margin-top:3px;opacity:.65}

/* ── Requests pane ───────────────────────────────────── */
.rfs-hub-cc .req-card{display:flex;align-items:center;gap:15px;padding:var(--space-4) 18px;border-bottom:var(--hair) solid var(--vz-border-color);flex-wrap:wrap}
.rfs-hub-cc .req-card:last-child{border-bottom:0}
.rfs-hub-cc .req-ic{width:44px;height:44px;border-radius:12px;display:grid;place-items:center;font-size:20px;background:rgba(var(--vz-info-rgb),.14);color:var(--vz-info);flex:0 0 auto}
.rfs-hub-cc .req-name{font-size:var(--fs-base);font-weight:600;display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.rfs-hub-cc .req-sub{font-size:12.5px;color:var(--vz-secondary-color);margin-top:2px}
.rfs-hub-cc .req-when{margin-left:auto;text-align:right;flex-shrink:0}
.rfs-hub-cc .req-acts{display:flex;gap:var(--space-2);flex-shrink:0}
.rfs-hub-cc .btn-approve{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:600;color:var(--rfs-hub-dark);background:var(--vz-success,#0ab39c);border:0;border-radius:9px;padding:var(--space-2) 13px;cursor:pointer;transition:filter .12s,opacity .12s}
.rfs-hub-cc .btn-approve:hover{filter:brightness(.92)}
.rfs-hub-cc .btn-approve:active{filter:brightness(.85);transform:translateY(1px)}
.rfs-hub-cc .btn-approve:focus-visible{outline:2px solid var(--vz-success,#0ab39c);outline-offset:2px}
.rfs-hub-cc .btn-approve:disabled,.rfs-hub-cc .btn-approve[disabled]{opacity:.5;cursor:not-allowed;pointer-events:none}
.rfs-hub-cc .btn-decline{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:500;color:var(--vz-secondary-color);background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);border-radius:9px;padding:var(--space-2) 13px;cursor:pointer;transition:background .12s,border-color .12s}
.rfs-hub-cc .btn-decline:hover{background:rgba(130,140,160,.18);border-color:var(--vz-secondary-color)}
.rfs-hub-cc .btn-decline:active{background:rgba(130,140,160,.26);transform:translateY(1px)}
.rfs-hub-cc .btn-decline:focus-visible{outline:2px solid var(--vz-secondary-color);outline-offset:2px}
.rfs-hub-cc .btn-decline:disabled,.rfs-hub-cc .btn-decline[disabled]{opacity:.5;cursor:not-allowed;pointer-events:none}

/* ── System pane ─────────────────────────────────────── */
.rfs-hub-cc .health{display:grid;grid-template-columns:repeat(5,1fr);gap:var(--space-3);margin-bottom:16px}
@media(max-width:900px){.rfs-hub-cc .health{grid-template-columns:repeat(2,1fr)}}
.rfs-hub-cc .hcell{display:flex;align-items:center;gap:11px;padding:14px 15px}
.rfs-hub-cc .hcell .hi{width:38px;height:38px;border-radius:11px;display:grid;place-items:center;font-size:var(--fs-xl);flex:0 0 auto}
.rfs-hub-cc .hcell .hn{font-size:13px;font-weight:600}
.rfs-hub-cc .hcell .hs{font-size:11.5px;margin-top:1px}
.rfs-hub-cc .hs.ok{color:var(--vz-success,#0ab39c)}
.rfs-hub-cc .hs.warn{color:#f7b84b}
.rfs-hub-cc .sys-row{display:flex;align-items:center;gap:13px;padding:15px 18px;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-hub-cc .sys-row:last-child{border-bottom:0}
.rfs-hub-cc .sys-ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;font-size:19px;flex:0 0 auto}

/* ── Dev Ops / AI command panel ──────────────────────── */
.rfs-hub-cc .ai-panel{display:grid;grid-template-columns:1.45fr 1fr;gap:22px}
@media(max-width:900px){.rfs-hub-cc .ai-panel{grid-template-columns:1fr}}
.rfs-hub-cc .ai-head{display:flex;align-items:center;gap:13px;margin-bottom:15px}
.rfs-hub-cc .ai-head .orb{width:48px;height:48px;border-radius:var(--r-xl);display:grid;place-items:center;font-size:24px;
  background:linear-gradient(145deg,var(--rfs-accent),#e85d2a);box-shadow:0 8px 24px rgba(var(--rfs-accent-rgb),.45),inset 0 1px 0 rgba(255,255,255,.3);flex:0 0 auto}
.rfs-hub-cc .ai-head .orb i{color:#fff}
.rfs-hub-cc .ai-head h2{font-size:17px;font-weight:700;display:flex;align-items:center;gap:9px}
.rfs-hub-cc .ai-head .on{font-size:11px;color:var(--vz-success,#0ab39c);display:inline-flex;align-items:center;gap:5px;font-weight:600}
.rfs-hub-cc .ai-head .on::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--vz-success,#0ab39c);box-shadow:0 0 8px var(--vz-success,#0ab39c)}
.rfs-hub-cc .ai-head p{font-size:12.5px;color:var(--vz-secondary-color);margin-top:2px}
.rfs-hub-cc .try-lb{font-size:11.5px;color:var(--vz-secondary-color);margin:15px 0 9px;letter-spacing:.5px}
.rfs-hub-cc .feed-title{font-size:var(--fs-xs);letter-spacing:1px;text-transform:uppercase;color:var(--vz-secondary-color);font-weight:600;margin-bottom:10px;display:flex;align-items:center;gap:7px}
.rfs-hub-cc .afeed-row{display:flex;align-items:flex-start;gap:11px;padding:9px 2px;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-hub-cc .afeed-row:last-child{border-bottom:0}
.rfs-hub-cc .afeed-row .ck{width:26px;height:26px;border-radius:var(--r-md);display:grid;place-items:center;font-size:var(--fs-base);flex:0 0 auto;
  background:rgba(10,179,156,.14);color:var(--vz-success,#0ab39c)}
.rfs-hub-cc .afeed-row .at{font-size:13px;font-weight:500}
.rfs-hub-cc .afeed-row .au{font-size:11px;color:var(--vz-secondary-color);margin-top:2px}
.rfs-hub-cc .credits-mini{margin-top:14px}
.rfs-hub-cc .credits-mini .cm-top{display:flex;justify-content:space-between;font-size:11.5px;color:var(--vz-secondary-color);margin-bottom:6px}
.rfs-hub-cc .credits-mini .cm-bar{height:7px;border-radius:var(--r-sm);background:rgba(130,140,160,.10);overflow:hidden}
.rfs-hub-cc .credits-mini .cm-fill{height:100%;width:74%;border-radius:var(--r-sm);background:linear-gradient(90deg,var(--rfs-accent),#f7b84b)}

/* ── magic-card rows + badges (stay-ahead) ───────────── */
.rfs-hub-cc .hbadge{margin-left:auto;font-size:10.5px;font-weight:700;padding:2px 9px;border-radius:var(--r-md);background:rgba(var(--rfs-accent-rgb),.14);color:var(--rfs-accent)}
.rfs-hub-cc .hbadge.mut{background:rgba(130,140,160,.10);color:var(--vz-secondary-color)}
.rfs-hub-cc .mrow{display:flex;align-items:flex-start;gap:10px;padding:9px 2px;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-hub-cc .mrow:last-child{border-bottom:0}
.rfs-hub-cc .mrow .mi{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;font-size:15px;flex:0 0 auto;background:rgba(130,140,160,.10)}
.rfs-hub-cc .mrow .mt{font-size:13px;font-weight:500;line-height:1.3}
.rfs-hub-cc .mrow .ms{font-size:11.5px;color:var(--vz-secondary-color);margin-top:2px}
.rfs-hub-cc .mrow .send{margin-left:auto;font-size:11.5px;font-weight:600;color:var(--rfs-accent);background:rgba(var(--rfs-accent-rgb),.12);border:var(--hair) solid rgba(var(--rfs-accent-rgb),.32);border-radius:var(--r-md);padding:5px 11px;cursor:pointer;align-self:center;white-space:nowrap;transition:.15s}
.rfs-hub-cc .mrow .send:hover{background:rgba(var(--rfs-accent-rgb),.22)}
.rfs-hub-cc .mrow .rchip{margin-left:auto;font-size:10.5px;font-weight:600;padding:3px 9px;border-radius:var(--r-md);align-self:center;white-space:nowrap}

/* pane:alerts */
/* ── Hub command-center · To Sort (Alerts) pane — mockup component port, themed + scoped ──
   Mockup vars mapped: --txt→body-color · --mut→secondary-color · --line/--line2→border-color
   --chip-bg→rgba(130,140,160,.10) · --hover→rgba(130,140,160,.06) · accents are fixed vivid hex. */

/* Card surface flat (matches the rest of the command center) */
.rfs-hub-cc .rfs-altab-card { background: var(--vz-secondary-bg); border-color: var(--vz-border-color); }
.rfs-hub-cc .rfs-altab-head { background: transparent; border-bottom-color: var(--vz-border-color); }

/* Header counts + split bar — .al-count/.al-dot/.al-bar are defined once in the component block above. */
.rfs-hub-cc .rfs-altab-counts { gap: 22px; }
/* split-bar colour aliases used by the inline width spans */
.rfs-hub-cc .rfs-altab-head { --red: var(--vz-danger,#f06548); --amber:#f7b84b; }

/* Bulk-action ghost button, destructive variant (.ghost-btn itself lives in the component block above) */
.rfs-hub-cc .rfs-altab-bulk-danger:hover { border-color: var(--vz-danger,#f06548); color: var(--vz-danger,#f06548); }

/* Staff | Customers segment for the shared messaging panel (partials/_messaging_panel) — the Hub's .seg styles
   are scoped to .rfs-hub-cc, so this makes the SAME control look right on the standalone /messages page too.
   Values mirror the Hub exactly, so inside the Hub the result is identical (no regression). */
.rfs-msgsub-seg { display:inline-flex; gap:2px; background:rgba(130,140,160,.10); border:var(--hair) solid var(--vz-border-color); border-radius:11px; padding:var(--space-1); }
.rfs-msgsub-seg .seg-item { display:inline-flex; align-items:center; gap:5px; padding:7px 15px; border-radius:var(--r-md); font-size:12.5px; font-weight:500; color:var(--vz-secondary-color); cursor:pointer; transition:.18s; border:0; background:transparent; line-height:1.2; }
.rfs-msgsub-seg .seg-item:hover { color:var(--vz-body-color); }
.rfs-msgsub-seg .seg-item.active { background:rgba(var(--vz-info-rgb),.16); color:var(--vz-info); font-weight:600; }

/* Bulk bar surface (was bg-light → flat themed) */
.rfs-hub-cc .rfs-altab-bulkbar { background: rgba(130,140,160,.06); border-bottom-color: var(--vz-border-color); }
.rfs-hub-cc .rfs-altab-selallbar { background: transparent; }

/* Alert rows (mockup .al-row/.al-sev/.al-body/.al-title/.al-reason/.al-actions/.al-act).
   Applies to the shared _alert_row partial (active + snoozed) AND the inline deleted-bin rows.
   The partial keeps its rfs-* classes; we add mockup look via the row wrapper + children. */
.rfs-hub-cc .rfs-altab-rows .rfs-altab-row,
.rfs-hub-cc .rfs-altab-row.al-row { padding:14px 18px; border-bottom:var(--hair) solid var(--vz-border-color); transition:.15s; }
.rfs-hub-cc .rfs-altab-rows .rfs-altab-row:last-child,
.rfs-hub-cc .rfs-altab-row.al-row:last-child { border-bottom:0; }
.rfs-hub-cc .rfs-altab-rows .rfs-altab-row:hover,
.rfs-hub-cc .rfs-altab-row.al-row:hover { background: rgba(130,140,160,.06); }

/* Category chip + reason line + title (mockup .al-cat/.al-reason/.al-title) — applied to the
   shared partial's badge/reason via the row scope so the To Sort list matches the mockup. */
.rfs-hub-cc .rfs-altab-rows .badge[class*="-subtle"],
.rfs-hub-cc .rfs-altab-row.al-row .badge[class*="-subtle"] { font-size:10.5px; font-weight:600; text-transform:capitalize; padding:2px 8px; border-radius:7px; }
.rfs-hub-cc .rfs-altab-reason { font-size:12.5px; color: var(--vz-secondary-color); }

@media (max-width:1100px){
  .rfs-hub-cc .rfs-altab-row.al-row { flex-wrap:wrap; }
}

/* pane:notifications */
/* ── Hub command-center — Notifications pane (ported from _hub-mockup.html #pane-notifications) ──
   Scoped to .rfs-hub-cc; mockup vars mapped to themed Velzon vars so dark + light both work. */
.rfs-hub-cc .rfs-ntab-card{padding:0;overflow:hidden}
.rfs-hub-cc .rfs-ntab-head{padding:var(--space-4) 18px 6px}
.rfs-hub-cc .rfs-ntab-head h6{font-size:15px;font-weight:600;color:var(--vz-body-color)}
.rfs-hub-cc .rfs-ntab-headsub{font-weight:400;color:var(--vz-secondary-color);font-size:var(--fs-xs);letter-spacing:0;text-transform:none;margin-left:2px}
.rfs-hub-cc .rfs-ntab-body{padding-bottom:6px}

/* Group label + row (.nlist-group/.nrow2 and children) are defined once in the Notifications-pane
   component block above — A-403. Only this pane's own additions live here. */
.rfs-hub-cc #rfs-ntab-list .nrow2:last-child{border-bottom:0}
/* read variant — live pane swaps .rfs-ntab-unread for .read */
.rfs-hub-cc .nrow2.read .ni{color:var(--vz-secondary-color)}

/* Notification rows read less bare with a category-tinted icon chip + a category pill (instead of rows of
   identical grey bells). Tints are subtle rgba so light + dark both stay legible. */
.rfs-hub-cc .nrow2 .ni.ni-message{background:rgba(var(--vz-info-rgb),.15);color:#1aa6ba}
.rfs-hub-cc .nrow2 .ni.ni-invoice,.rfs-hub-cc .nrow2 .ni.ni-payment{background:rgba(10,179,156,.15);color:#0ab39c}
.rfs-hub-cc .nrow2 .ni.ni-quote,.rfs-hub-cc .nrow2 .ni.ni-customer,.rfs-hub-cc .nrow2 .ni.ni-job{background:rgba(108,92,255,.15);color:#6c5cff}
.rfs-hub-cc .nrow2 .ni.ni-booking{background:rgba(41,156,219,.15);color:#299cdb}
.rfs-hub-cc .nrow2 .ni.ni-task{background:rgba(247,184,75,.18);color:#e0961a}
.rfs-hub-cc .nrow2 .ni.ni-automation{background:rgba(var(--rfs-accent-rgb),.16);color:var(--rfs-accent)}
.rfs-hub-cc .nrow2 .ni.ni-general{background:rgba(130,140,160,.14);color:var(--vz-secondary-color)}
.rfs-hub-cc .nrow2.read .ni{opacity:.6}
/* subtitle row: pill · time · who */
.rfs-hub-cc .nrow2 .ns{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.rfs-hub-cc .rfs-ntab-cat{font-size:9.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;padding:1px 7px;border-radius:5px;line-height:1.55;white-space:nowrap}
.rfs-hub-cc .rfs-ntab-cat.cat-message{background:rgba(var(--vz-info-rgb),.15);color:#1aa6ba}
.rfs-hub-cc .rfs-ntab-cat.cat-invoice,.rfs-hub-cc .rfs-ntab-cat.cat-payment{background:rgba(10,179,156,.15);color:#0ab39c}
.rfs-hub-cc .rfs-ntab-cat.cat-quote,.rfs-hub-cc .rfs-ntab-cat.cat-customer,.rfs-hub-cc .rfs-ntab-cat.cat-job{background:rgba(108,92,255,.15);color:#6c5cff}
.rfs-hub-cc .rfs-ntab-cat.cat-booking{background:rgba(41,156,219,.15);color:#299cdb}
.rfs-hub-cc .rfs-ntab-cat.cat-task{background:rgba(247,184,75,.18);color:#e0961a}
.rfs-hub-cc .rfs-ntab-cat.cat-automation{background:rgba(var(--rfs-accent-rgb),.16);color:var(--rfs-accent)}
.rfs-hub-cc .rfs-ntab-cat.cat-general{background:rgba(130,140,160,.14);color:var(--vz-secondary-color)}
.rfs-hub-cc .nrow2 .rfs-ntab-by{color:var(--vz-secondary-color)}

/* pager — flat, themed top divider */
.rfs-hub-cc .rfs-ntab-pager{border-top:var(--hair) solid var(--vz-border-color)}

/* pane:tasks */
/* ── Hub command-center · Tasks pane skin (scoped to .rfs-hub-cc; dark+light via Velzon vars) ──
   The live pane is a real <table> (Columns picker + inline cell-edit + live-poll all key off
   data-col cells / .rfs-cell-edit), so we KEEP the table and skin it to the mockup's .tk-row look.
   Mockup component classes (.tk-row/.tk-title/.tk-sub/.tk-due/.pill/.tk-av/.al-act.ico/.ghost-btn)
   are ported here scoped — they aren't in the shared command-center port yet. */
.rfs-hub-cc .rfs-cc-tasks{ background:var(--vz-secondary-bg); border:var(--hair) solid var(--vz-border-color); }
.rfs-hub-cc .rfs-cc-tasks .rfs-cc-tk-head{ background:transparent; border-bottom:var(--hair) solid var(--vz-border-color); padding:var(--space-4) 18px 12px; }
.rfs-hub-cc .rfs-cc-tk-h{ color:var(--vz-body-color); font-size:15px; }
.rfs-hub-cc .rfs-cc-tk-h i{ color:var(--purple); }
.rfs-hub-cc .rfs-cc-tk-sub{ color:var(--vz-secondary-color); letter-spacing:0; text-transform:none; }

/* Header ghost buttons (mockup .ghost-btn) — keep BS classes for behaviour, override the look */
.rfs-hub-cc .rfs-cc-tk-btns .ghost-btn,
.rfs-hub-cc .rfs-cc-tk-btns .rfs-cols > .btn{
    display:inline-flex; align-items:center; gap:7px;
    background:rgba(130,140,160,.10); border:var(--hair) solid var(--vz-border-color);
    border-radius:11px; padding:7px 13px; font-size:12.5px; font-weight:500;
    color:var(--vz-body-color); }
.rfs-hub-cc .rfs-cc-tk-btns .ghost-btn:hover,
.rfs-hub-cc .rfs-cc-tk-btns .rfs-cols > .btn:hover{ border-color:var(--orange); color:var(--orange2); }

/* Flatten the table into mockup rows */
.rfs-hub-cc .rfs-cc-tk-table{ color:var(--vz-body-color); }
.rfs-hub-cc .rfs-cc-tk-table > thead{ display:none; }   /* mockup rows have no column header chrome */
.rfs-hub-cc .rfs-cc-tk-table.rfs-no-tcards{ white-space:normal; }
.rfs-hub-cc .rfs-cc-tk-table > tbody > tr.tk-row{ transition:.15s; }
.rfs-hub-cc .rfs-cc-tk-table > tbody > tr.tk-row:hover{ background:rgba(130,140,160,.06); }
.rfs-hub-cc .rfs-cc-tk-table > tbody > tr.tk-row > td{
    border-top:0; border-bottom:var(--hair) solid var(--vz-border-color);
    background:transparent; vertical-align:middle; }
.rfs-hub-cc .rfs-cc-tk-table > tbody > tr.tk-row:last-child > td{ border-bottom:0; }

/* Title + sub */
.rfs-hub-cc .rfs-cc-tk-table .tk-title{ font-size:var(--fs-base); font-weight:600; color:var(--vz-body-color); }
.rfs-hub-cc .rfs-cc-tk-table .tk-sub{ font-size:var(--fs-xs); color:var(--vz-secondary-color); }

/* Round check */
.rfs-hub-cc .rfs-cc-tk-table .tk-check{ border-radius:50%; }

/* Avatar chip */
.rfs-hub-cc .rfs-cc-tk-table .tk-av{ font-weight:700; }
.rfs-hub-cc .rfs-cc-tk-table .tk-av-none{ background:rgba(130,140,160,.10)!important; color:var(--vz-secondary-color); }

/* Pills (priority + status) — recolour the Velzon badge to the mockup palette */
.rfs-hub-cc .rfs-cc-tk-table .pill{ font-size:11px; font-weight:600; padding:3px 11px; border-radius:var(--r-md); white-space:nowrap; }
.rfs-hub-cc .rfs-cc-tk-table .pill.todo{ background:rgba(130,140,160,.10); color:var(--vz-secondary-color); }
.rfs-hub-cc .rfs-cc-tk-table .pill.prog{ background:rgba(var(--vz-info-rgb),.15); color:var(--cyan); }
.rfs-hub-cc .rfs-cc-tk-table .pill.done{ background:rgba(45,212,167,.16); color:var(--green); }
.rfs-hub-cc .rfs-cc-tk-table .pill.norm{ background:rgba(130,140,160,.10); color:var(--vz-secondary-color); }
.rfs-hub-cc .rfs-cc-tk-table .pill.high{ background:rgba(240,101,72,.15); color:var(--red); }

/* Due cell */
.rfs-hub-cc .rfs-cc-tk-table .tk-due{ display:inline-flex; align-items:center; gap:5px; font-size:12.5px; color:var(--vz-secondary-color); }
.rfs-hub-cc .rfs-cc-tk-table .tk-due.over{ color:var(--red); font-weight:600; }

/* Eye action (mockup .al-act.ico) */
.rfs-hub-cc .rfs-cc-tk-table .al-act.ico{
    display:inline-flex; align-items:center; justify-content:center;
    background:rgba(130,140,160,.10); border:var(--hair) solid var(--vz-border-color);
    border-radius:9px; color:var(--vz-secondary-color); }
.rfs-hub-cc .rfs-cc-tk-table .al-act.ico:hover{ border-color:var(--orange); color:var(--orange2); }

/* Local theme tokens so any stray mockup var() resolves correctly inside this pane */
.rfs-hub-cc .rfs-cc-tasks{
    --purple:#8b7cf6; --cyan:var(--vz-info); --orange:var(--rfs-accent); --orange2:var(--rfs-accent);
    --green:var(--vz-success,#0ab39c); --red:var(--vz-danger,#f06548); }

/* pane:messages */
/* ── Hub command-center · AI Assistant pane (#aihub-messages) ──────────────────
   All selectors scoped to .rfs-hub-cc so nothing leaks outside the Hub. Surfaces stay
   flat (var(--vz-secondary-bg)); the mockup's hardcoded vars are mapped to themed ones
   so both data-bs-theme=dark and =light read correctly. The real chat lives inside
   #rfs-ai-mount (JS-mounted) — we only frame it with the orb header here. */

/* Chat card: command-center frame around the live #rfs-ai-mount widget */
.rfs-hub-cc .rfs-cc-chatcard{overflow:hidden;display:flex;flex-direction:column}
.rfs-hub-cc .rfs-cc-chathead{
  display:flex;align-items:center;gap:13px;padding:15px 18px;
  border-bottom:var(--hair) solid var(--vz-border-color);
  background:radial-gradient(440px 130px at 100% 0%,rgba(var(--rfs-accent-rgb),.16),transparent 60%);
}
.rfs-hub-cc .rfs-cc-orb{
  width:42px;height:42px;border-radius:12px;display:grid;place-items:center;font-size:21px;flex:0 0 auto;
  background:linear-gradient(145deg,var(--rfs-accent),#e85d2a);
  box-shadow:0 8px 22px rgba(var(--rfs-accent-rgb),.42);
}
.rfs-hub-cc .rfs-cc-orb i{color:#fff}
.rfs-hub-cc .rfs-cc-chath{
  font-size:15px;font-weight:700;display:flex;align-items:center;gap:9px;margin:0;
  color:var(--vz-body-color);
}
.rfs-hub-cc .rfs-cc-on{
  font-size:11px;color:var(--vz-success,#0ab39c);display:inline-flex;align-items:center;gap:5px;font-weight:600;
}
.rfs-hub-cc .rfs-cc-on::before{
  content:"";width:7px;height:7px;border-radius:50%;
  background:var(--vz-success,#0ab39c);box-shadow:0 0 8px var(--vz-success,#0ab39c);
}
.rfs-hub-cc .rfs-cc-chatsub{font-size:var(--fs-xs);color:var(--vz-secondary-color);margin-top:2px}
/* the mounted chat fills the remaining height of the framed card */
.rfs-hub-cc .rfs-cc-mount{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}

/* Try-asking rail → mockup .cap-card look */
.rfs-hub-cc .rfs-cc-railgrp{
  font-size:11.5px;color:var(--vz-secondary-color);margin:15px 0 9px;letter-spacing:.5px;
  text-transform:none;font-weight:600;
}
.rfs-hub-cc .rfs-cc-rail .rfs-cc-railgrp:first-child{margin-top:2px}
.rfs-hub-cc .rfs-cc-cap{
  display:flex;align-items:center;gap:var(--space-3);padding:var(--space-3) 14px;border-radius:12px;
  background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);
  cursor:pointer;transition:.15s;width:100%;text-align:left;margin-bottom:8px;
}
.rfs-hub-cc .rfs-cc-cap:hover{border-color:rgba(var(--rfs-accent-rgb),.4);background:rgba(var(--rfs-accent-rgb),.07)}
.rfs-hub-cc .rfs-cc-cap-ic{
  width:34px;height:34px;border-radius:var(--r-lg);display:grid;place-items:center;font-size:17px;flex:0 0 auto;
}
.rfs-hub-cc .rfs-cc-cap-t{font-size:13px;font-weight:600;color:var(--vz-body-color)}
.rfs-hub-cc .rfs-cc-cap-s{font-size:11.5px;color:var(--vz-secondary-color);margin-top:1px}

/* pane:chat */
/* ── Hub "Messages" pane → command-center messenger skin ───────────────────
   Re-skins the SHARED partials/_messenger (.rfs-msgr) to the mockup's
   .msg-wrap / .conv / .thread-head / .thread-body / .mbub look — WITHOUT
   touching the partial's markup or its own scoped <style>/JS. Scoped to
   `.rfs-hub-cc .rfs-hub-msg` so the standalone /messages page is unaffected.
   Mockup vars mapped to themed --vz-* so dark + light both work.
   Accents fixed-hex per brief: --cyan var(--vz-info) (mbub.me / active rail). */
.rfs-hub-cc .rfs-hub-msg .rfs-msgr{
  border:var(--hair) solid var(--vz-border-color);
  border-radius:18px;
  background:var(--vz-secondary-bg);
  box-shadow:none;
}
/* conversation list column (.msg-wrap left = 300px in mockup) */
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-list{
  width:300px;min-width:260px;
  border-right:var(--hair) solid var(--vz-border-color);
  background:var(--vz-secondary-bg);
}
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-list-head{
  border-bottom:var(--hair) solid var(--vz-border-color);
  color:var(--vz-body-color);
}
/* .conv rows */
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-person{
  gap:11px;padding:13px 16px;
  border-bottom:var(--hair) solid var(--vz-border-color);
  transition:background .15s;
}
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-person:hover{
  background:rgba(130,140,160,.06);
}
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-person.active{
  background:rgba(var(--vz-info-rgb),.08);
  box-shadow:inset 3px 0 0 var(--vz-info);
}
/* .av avatar */
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-ava{
  width:38px;height:38px;font-size:13px;
}
/* .cn name + .cp preview + role-chip (.rfs-msgr-p-wt) */
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-p-name{
  font-size:13.5px;color:var(--vz-body-color);
}
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-p-prev{
  font-size:11.5px;color:var(--vz-secondary-color);
}
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-p-wt{
  font-size:9.5px;font-weight:600;text-transform:uppercase;letter-spacing:.5px;
  padding:1px 7px;border-radius:var(--r-sm);
  background:rgba(130,140,160,.10);color:var(--vz-secondary-color);
}
/* .cu unread pill → cyan */
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-p-unread.badge{
  background:var(--vz-info) !important;color:var(--rfs-hub-dark);
}
/* thread column → .thread-head / .thread-body */
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-pane-head{
  gap:11px;padding:13px 18px;
  border-bottom:var(--hair) solid var(--vz-border-color);
}
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-body{
  padding:18px;background:var(--vz-secondary-bg);
}
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-day span{
  background:rgba(130,140,160,.10);color:var(--vz-secondary-color);
}
/* .mbub bubbles — them = chip surface, me = cyan */
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-bubble{
  max-width:70%;padding:9px 13px;border-radius:13px;font-size:13px;line-height:1.45;
  background:rgba(130,140,160,.10);
  border:var(--hair) solid var(--vz-border-color);
  color:var(--vz-body-color);
  border-bottom-left-radius:4px;border-bottom-right-radius:13px;
}
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-msg.mine .rfs-msgr-bubble{
  background:var(--vz-info);color:var(--rfs-hub-dark);border:0;
  border-top-right-radius:4px;border-bottom-right-radius:13px;border-bottom-left-radius:13px;
}
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-msg.mine .rfs-msgr-ticks.read{color:var(--rfs-hub-dark);}
/* composer / deleted-folder surfaces stay flat + themed */
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-foot,
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-delsec,
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-delrow{
  border-color:var(--vz-border-color);
}
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-photochip{
  background:rgba(130,140,160,.10);color:var(--vz-secondary-color);
}
/* keep mobile collapse rules working (≤767.98px) — width override only on desktop */
@media (max-width:767.98px){
  .rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-list{width:100%;border-right:0;}
}
/* Composer: keep attach + textarea + send on ONE row. The textarea was flex:1 1 auto with form-control
   width:100% → it claimed a full flex-basis and (with flex-wrap) pushed the buttons onto separate lines.
   flex:1 1 0 makes it grow from zero instead, so the row stays inline. Staff + customer messenger both. */
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-foot{ align-items:center; }
.rfs-hub-cc .rfs-hub-msg .rfs-msgr .rfs-msgr-input{ flex:1 1 0; min-width:0; }

/* pane:system */
/* ── Hub command-center: System pane (scoped to .rfs-hub-cc) ──────────── */
.rfs-hub-cc .rfs-hubcc-syscard{padding:0;overflow:hidden}
.rfs-hub-cc .rfs-hubcc-syshead{padding:var(--space-4) 18px 4px}
.rfs-hub-cc .rfs-hubcc-systitle{margin:0;font-size:15px;font-weight:600;display:flex;align-items:center;gap:var(--space-2);color:var(--vz-body-color)}
.rfs-hub-cc .rfs-hubcc-systitle i{color:#f7b84b}
.rfs-hub-cc .rfs-hubcc-sys-row{display:flex;align-items:center;gap:13px;padding:15px 18px;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-hub-cc .rfs-hubcc-sys-row:last-child{border-bottom:0}
.rfs-hub-cc .rfs-hubcc-sys-resolved{opacity:.6}
.rfs-hub-cc .rfs-hubcc-sys-t{font-size:var(--fs-base);font-weight:600;color:var(--vz-body-color)}
.rfs-hub-cc .rfs-hubcc-sys-d{font-size:12.5px;color:var(--vz-secondary-color);margin-top:1px}
.rfs-hub-cc .rfs-hubcc-sys-ic,
.rfs-hub-cc .rfs-hubcc-sysnote .rfs-hubcc-sys-ic{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;font-size:19px;flex:0 0 auto}
.rfs-hub-cc .rfs-hubcc-ic-amber{background:rgba(247,184,75,.14);color:#f7b84b}
.rfs-hub-cc .rfs-hubcc-ic-cyan{background:rgba(var(--vz-info-rgb),.14);color:var(--vz-info)}
.rfs-hub-cc .rfs-hubcc-ic-mut{background:rgba(130,140,160,.10);color:var(--vz-secondary-color)}
.rfs-hub-cc .rfs-hubcc-ghost-btn{display:inline-flex;align-items:center;gap:5px;background:rgba(130,140,160,.10);border:var(--hair) solid var(--vz-border-color);border-radius:11px;padding:7px 12px;font-size:12.5px;font-weight:500;color:var(--vz-body-color);cursor:pointer;transition:.15s;white-space:nowrap}
.rfs-hub-cc .rfs-hubcc-ghost-btn:hover{border-color:var(--rfs-accent);color:var(--rfs-accent)}

/* pane:devops */
/* ── Hub Command Center — Dev Ops pane (cc-devops) — mockup parity, theme-aware ──
   Scoped to .rfs-hub-cc so dark/light follow data-bs-theme. Flat surfaces (var(--vz-secondary-bg)),
   no hardcoded dark hex. */
.rfs-hub-cc .cc-magic-card{background:var(--vz-secondary-bg);border:var(--hair) solid var(--vz-border-color);border-radius:var(--r-xl)}
.rfs-hub-cc .cc-magic-card .card-header,
.rfs-hub-cc .cc-magic-card .card-footer{background:transparent;border-color:var(--vz-border-color)}
.rfs-hub-cc .cc-devops-foot{font-size:var(--fs-xs);color:var(--vz-secondary-color)}

/* muted hbadge variant (mockup .hbadge.mut) — the count pill on the two capture cards */
.rfs-hub-cc .cc-hbadge-mut{position:static;margin:0;background:rgba(130,140,160,.10);color:var(--vz-secondary-color)}

/* Capture rows: re-skin the EXISTING .rfs-aihub-issue markup (shared by PHP + the live-poll JS,
   so it can't change shape) into the mockup's flat .mrow look — flat row, divider, no boxed card. */
.rfs-hub-cc .cc-capture .rfs-aihub-issue{border:0;border-bottom:var(--hair) solid var(--vz-border-color);border-radius:0;padding:10px 2px;margin:0;background:transparent}
.rfs-hub-cc .cc-capture .rfs-aihub-issue:last-child{border-bottom:0}
.rfs-hub-cc .cc-capture .rfs-aihub-issue-tx{order:-1;font-size:13px;font-weight:500;color:var(--vz-body-color);margin-bottom:3px}
.rfs-hub-cc .cc-capture .rfs-aihub-issue-top{margin:0}
.rfs-hub-cc .cc-capture .rfs-aihub-issue-ts{color:var(--vz-secondary-color)}

/* Credits-mini bar (mockup .credits-mini / .cm-top / .cm-bar / .cm-fill) */
.rfs-hub-cc .cc-credits-mini .cc-cm-top{display:flex;justify-content:space-between;font-size:11.5px;color:var(--vz-secondary-color);margin-bottom:6px}
.rfs-hub-cc .cc-credits-mini .cc-cm-top b{color:var(--vz-body-color)}
.rfs-hub-cc .cc-credits-mini .cc-cm-bar{height:7px;border-radius:var(--r-sm);background:rgba(130,140,160,.18);overflow:hidden}
.rfs-hub-cc .cc-credits-mini .cc-cm-fill{height:100%;border-radius:var(--r-sm);background:linear-gradient(90deg,var(--rfs-accent),#f7b84b)}
.rfs-hub-cc .cc-credits-mini .cc-cm-warning{background:linear-gradient(90deg,#f7b84b,var(--rfs-accent))}
.rfs-hub-cc .cc-credits-mini .cc-cm-danger{background:linear-gradient(90deg,var(--vz-danger,#f06548),var(--rfs-accent))}

/* Recent-actions feed (mockup .afeed-row / .ck / .at / .au) */
.rfs-hub-cc .cc-feed-title{font-size:var(--fs-xs);letter-spacing:1px;text-transform:uppercase;color:var(--vz-secondary-color);font-weight:600;margin-bottom:8px}
.rfs-hub-cc .cc-afeed-row{display:flex;align-items:flex-start;gap:11px;padding:9px 2px;border-bottom:var(--hair) solid var(--vz-border-color)}
.rfs-hub-cc .cc-afeed-row:last-child{border-bottom:0}
.rfs-hub-cc .cc-afeed-row .cc-ck{width:26px;height:26px;border-radius:var(--r-md);display:grid;place-items:center;font-size:var(--fs-base);flex:0 0 auto;background:rgba(var(--vz-success-rgb,10,179,156),.14);color:var(--vz-success,#0ab39c)}
.rfs-hub-cc .cc-afeed-row .cc-at{font-size:13px;font-weight:500;color:var(--vz-body-color)}
.rfs-hub-cc .cc-afeed-row .cc-au{font-size:11px;color:var(--vz-secondary-color);margin-top:2px}

/* A-072/A-083 — Velzon global `.badge { color: #fff }` forces white text on contextual badges whose
   backgrounds are too light for legible white ink (warning amber, teal info, success green, coral danger).
   A-072: bg-success/info/warning. A-083: bg-danger (Velzon coral rgb(240,101,72) = 2.94:1 with white → WCAG fail;
   dark text ≈5.4:1 ✓). These overrides ensure WCAG AA contrast on every class-background badge. */
.badge.bg-success, .badge.bg-info, .badge.bg-warning, .badge.bg-danger { color: var(--vz-dark) !important; }

/* A-316 — snap-tile icon accent colours (Hub AI page); centralised so inline style= can be removed. */
.rfs-c-teal   { color: #1f9fd0; }
.rfs-c-violet { color: #8b7cf6; }

/* A-233/A-289/A-305 — font-size + layout utility shims; used instead of inline style= in views. */
.fs-13 { font-size: 13px !important; }
.fs-14 { font-size: 14px !important; }
.rfs-fs-xs   { font-size: var(--fs-xs)   !important; }  /* replaces style="font-size:12px" */
.rfs-fs-sm   { font-size: var(--fs-sm)   !important; }  /* replaces style="font-size:12.8px" */
.rfs-fs-base { font-size: var(--fs-base) !important; }  /* replaces style="font-size:14px" */
.rfs-thumb-sm { border-radius: var(--r-sm); }           /* replaces style="border-radius:6px" on img thumbnails */

/* A-208 — auth page common styles; shared by auth/ and portal/auth/ views (avoids duplication). */
.rfs-brand-badge{width:52px;height:52px;border-radius:14px;background:rgba(255,255,255,.18);backdrop-filter:blur(4px);color:#fff;font-weight:800;font-size:17px;letter-spacing:.5px;display:inline-flex;align-items:center;justify-content:center}
.auth-one-bg{background:radial-gradient(1100px 560px at 8% 18%,rgba(11,179,156,.40),transparent 60%),radial-gradient(900px 520px at 92% 8%,rgba(124,58,237,.45),transparent 55%),radial-gradient(800px 600px at 75% 95%,rgba(41,156,219,.35),transparent 55%),linear-gradient(135deg,#283163 0%,#3b3f86 45%,#2e2a6b 100%) !important}
.auth-one-bg .bg-overlay{display:none}
.auth-one-bg .shape svg{fill:var(--vz-secondary-bg,#f3f3f9)}
.auth-page-wrapper .card{box-shadow:0 20px 60px rgba(16,24,40,.25)}
/* A-208 — pay/deposit common styles. */
.pay-amount{font-size:2.2rem;font-weight:800;letter-spacing:-.5px}

/* ═══════════ OFFICE DASHBOARD REDESIGN (rfs-dash) — 2026-07-06 ═══════════════════════════════
   Page-scoped skin for dashboard/_office_body — the ONE body shared by the standalone /dashboard
   page AND the Hub's "Dashboard" tab. Mirrors the Hub cc- command-center card language but is self-
   contained (its own rfs-dash- classes, NOT a fork of .rfs-hub-cc) so it renders identically in the
   plain app shell and injected inside .rfs-hub-cc. All surfaces use --vz-secondary-bg / --vz-border-
   color / --vz-body-color / --vz-secondary-color so BOTH the light app theme AND the Hub's dark/light
   (data-bs-theme) render correctly (⚠ --vz-card-bg is undefined in the Hub — never used here). */
.rfs-dash .rfs-dash-sec{display:flex;align-items:center;gap:10px;margin:6px 2px 14px;font-size:11px;letter-spacing:1.6px;text-transform:uppercase;color:var(--vz-secondary-color);font-weight:700}
.rfs-dash .rfs-dash-sec::after{content:"";flex:1;height:1px;background:linear-gradient(90deg,var(--vz-border-color),transparent)}
.rfs-dash .rfs-dash-sec i{font-size:15px;color:var(--vz-primary)}

/* Hero band — headline money/priority numbers (auto-fit so 2 or 3 tiles both fill the row).
   Each tone drives a var trio: --h-grad (gradient icon chip), --h-glow (soft corner wash), --h-bar (accent). */
.rfs-dash .rfs-dash-hero{display:grid;grid-template-columns:repeat(auto-fit,minmax(246px,1fr));gap:1.1rem;margin-bottom:1.6rem}
.rfs-dash .rfs-dash-h{position:relative;display:flex;flex-direction:column;min-height:150px;padding:20px 22px;border:1px solid var(--vz-border-color);border-radius:18px;background:var(--vz-secondary-bg);overflow:hidden;box-shadow:0 1px 2px rgba(16,24,40,.05);transition:box-shadow .22s ease,transform .22s ease}
.rfs-dash .rfs-dash-h:hover{transform:translateY(-3px);box-shadow:0 14px 34px rgba(16,24,40,.12)}
.rfs-dash .rfs-dash-h .h-accent{position:absolute;left:0;top:16px;bottom:16px;width:4px;border-radius:0 4px 4px 0;background:var(--h-bar)}
.rfs-dash .rfs-dash-h .h-top{position:relative;display:flex;align-items:center;justify-content:space-between;gap:10px}
.rfs-dash .rfs-dash-h .h-label{font-size:11.5px;font-weight:700;text-transform:uppercase;letter-spacing:.7px;color:var(--vz-secondary-color)}
.rfs-dash .rfs-dash-h .h-ic{width:46px;height:46px;border-radius:14px;display:grid;place-items:center;font-size:22px;color:#fff;flex:0 0 auto;background:var(--h-grad)}
.rfs-dash .rfs-dash-h .h-num{position:relative;font-size:34px;font-weight:800;letter-spacing:-1.3px;line-height:1.1;margin-top:16px;color:var(--vz-body-color)}
.rfs-dash .rfs-dash-h .h-sub{position:relative;font-size:12.5px;color:var(--vz-secondary-color);margin-top:9px;display:flex;align-items:center;gap:5px;flex-wrap:wrap}
.rfs-dash .rfs-dash-h .h-sub i{font-size:14px}
.rfs-dash .h-money{--h-grad:linear-gradient(145deg,#0eb7a0,#0a8a78);--h-bar:var(--vz-success,#0ab39c)}
.rfs-dash .h-danger{--h-grad:linear-gradient(145deg,#f26a4d,#d0432a);--h-bar:var(--vz-danger,#f06548)}
.rfs-dash .h-primary{--h-grad:linear-gradient(145deg,#4d5ba6,#374378);--h-bar:var(--vz-primary,#405189)}

/* Secondary strip — dense lesser counters (label up top, number + soft-tinted icon chip pinned to the base) */
.rfs-dash .rfs-dash-strip{display:grid;grid-template-columns:repeat(5,1fr);gap:.85rem;margin-bottom:1.6rem}
.rfs-dash .rfs-dash-mini{position:relative;display:flex;flex-direction:column;padding:15px 16px;border:1px solid var(--vz-border-color);border-radius:15px;background:var(--vz-secondary-bg);min-height:98px;box-shadow:0 1px 2px rgba(16,24,40,.04);transition:box-shadow .22s ease,transform .22s ease}
.rfs-dash .rfs-dash-mini:hover{transform:translateY(-2px);box-shadow:0 8px 20px rgba(16,24,40,.09)}
.rfs-dash .rfs-dash-mini .m-lab{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;color:var(--vz-secondary-color);line-height:1.35}
.rfs-dash .rfs-dash-mini .m-btm{display:flex;align-items:flex-end;justify-content:space-between;gap:8px;margin-top:auto;padding-top:12px}
.rfs-dash .rfs-dash-mini .m-num{font-size:24px;font-weight:800;letter-spacing:-.5px;line-height:1;color:var(--vz-body-color)}
.rfs-dash .rfs-dash-mini .m-ic{width:32px;height:32px;border-radius:9px;display:grid;place-items:center;font-size:16px;flex:0 0 auto}
@media(max-width:1200px){.rfs-dash .rfs-dash-strip{grid-template-columns:repeat(3,1fr)}}
@media(max-width:576px){.rfs-dash .rfs-dash-strip{grid-template-columns:repeat(2,1fr)}}

/* Quick actions — a light action bar (buttons stretch to fill on wide, wrap on narrow) */
.rfs-dash .rfs-dash-qa{display:flex;flex-wrap:wrap;gap:.7rem;margin-bottom:1.6rem}
.rfs-dash .rfs-dash-qa .btn{flex:1 1 auto;min-width:150px;border-radius:12px;padding:.62rem 1rem;font-weight:600;box-shadow:0 1px 2px rgba(16,24,40,.05)}
@media(max-width:576px){.rfs-dash .rfs-dash-qa .btn{flex:1 1 46%}}

/* Charts + list cards — consistent rounded, soft-shadow card language */
.rfs-dash .card{border-radius:18px;box-shadow:0 1px 2px rgba(16,24,40,.04)}
.rfs-dash .rfs-dash-chart .card-header{border:0;padding-bottom:2px}
.rfs-dash .rfs-dash-chart .card-title{font-size:14px;font-weight:600}

/* Recent Activity — tamed: a header bar + collapsible body (lazy-loaded on first expand) */
.rfs-dash .rfs-dash-act{margin-top:1.3rem}
.rfs-dash .rfs-dash-act-head{display:flex;align-items:center;gap:11px;padding:15px 20px;border:1px solid var(--vz-border-color);border-radius:16px;background:var(--vz-secondary-bg);box-shadow:0 1px 2px rgba(16,24,40,.04)}
.rfs-dash .rfs-dash-act-head > i{font-size:18px;color:var(--vz-primary)}
.rfs-dash .rfs-dash-act-head h4{font-size:14px;font-weight:600;margin:0;flex:1;color:var(--vz-body-color)}
.rfs-dash .rfs-dash-act-body{display:none;margin-top:1rem}
.rfs-dash .rfs-dash-act-body.is-open{display:block}
.rfs-dash .rfs-dash-act-open .chev{transition:transform .2s}
.rfs-dash .rfs-dash-act-open[aria-expanded="true"] .chev{transform:rotate(180deg)}

/* ─────────────────────────────────────────────────────────────────────────────
   TICKET VIEW (tickets/show.php) — helpdesk skin (+324 UX pass). Page-scoped
   `rfs-tkt-` classes only; vz tokens throughout (⚠ never --vz-card-bg — undefined
   in the Hub skin). Conversation = a connected timeline: icon dots on a rail,
   tinted bubbles per kind (note=warning, comms=info), plain lines for events.
   ───────────────────────────────────────────────────────────────────────────── */
.rfs-tkt-hero { border-left: 3px solid rgba(var(--vz-primary-rgb), .55); }
.rfs-tkt-hero .rfs-tkt-ref { font-weight: 500; color: var(--vz-secondary-color); letter-spacing: .3px; }
.rfs-tkt-hero h4 { letter-spacing: -.3px; }
.rfs-tkt-meta { display: flex; align-items: center; flex-wrap: wrap; gap: .35rem 1.15rem; color: var(--vz-secondary-color); font-size: 12.5px; }
.rfs-tkt-meta i { opacity: .75; margin-right: 4px; }
.rfs-tkt-status .btn { font-weight: 500; }

.rfs-tkt-stream { position: relative; }
.rfs-tkt-item { display: flex; gap: 11px; position: relative; padding-bottom: 14px; }
.rfs-tkt-item:last-child { padding-bottom: 2px; }
/* the connector rail between dots */
.rfs-tkt-item:not(:last-child)::before { content: ""; position: absolute; left: 13px; top: 30px; bottom: 2px; width: 2px; background: var(--vz-border-color); border-radius: 2px; }
.rfs-tkt-dot { width: 27px; height: 27px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 13px; flex-shrink: 0; border: 1px solid var(--vz-border-color); background: var(--vz-secondary-bg); z-index: 1; }
.rfs-tkt-item[data-kind="note"]  .rfs-tkt-dot { background: rgba(var(--vz-warning-rgb), .12); border-color: rgba(var(--vz-warning-rgb), .4); }
.rfs-tkt-item[data-kind="comms"] .rfs-tkt-dot { background: rgba(var(--vz-info-rgb), .12);    border-color: rgba(var(--vz-info-rgb), .4); }
.rfs-tkt-bubble { border: 1px solid var(--vz-border-color); border-radius: 8px; padding: 8px 11px; background: var(--vz-secondary-bg); }
.rfs-tkt-item[data-kind="note"]  .rfs-tkt-bubble { background: rgba(var(--vz-warning-rgb), .06); border-color: rgba(var(--vz-warning-rgb), .3); }
.rfs-tkt-item[data-kind="comms"] .rfs-tkt-bubble { background: rgba(var(--vz-info-rgb), .06);    border-color: rgba(var(--vz-info-rgb), .3); }
.rfs-tkt-desc { border: 1px dashed var(--vz-border-color); border-radius: 8px; padding: 10px 12px; background: rgba(var(--vz-light-rgb), .5); }
.rfs-tkt-when { font-size: 11px; color: var(--vz-secondary-color); margin-top: 3px; }

/* ============================================================================
   Accessibility utilities — staff app shell (skip-link, focus, touch, contrast)
   Scoped helpers only; do not restyle the Velzon theme globally.
   ========================================================================== */

/* Skip link: visually hidden until keyboard focus, then a solid banner above the fixed topbar. */
.rfs-skip-link {
    position: fixed;
    left: 12px;
    top: -120px;
    z-index: 11000;
    padding: .55rem 1rem;
    background: var(--vz-primary, #405189);
    color: #fff !important;
    font-weight: 600;
    font-size: .875rem;
    line-height: 1.2;
    border-radius: var(--r-md, 8px);
    text-decoration: none;
    box-shadow: 0 4px 16px rgba(16, 24, 40, .28);
}
.rfs-skip-link:focus,
.rfs-skip-link:focus-visible {
    top: 12px;
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* Visible :focus-visible on interactive controls (2px primary). */
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
.btn:focus-visible,
.nav-link:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible,
.dropdown-item:focus-visible,
.rfs-ai-hbtn:focus-visible,
.rfs-side-user-logout:focus-visible,
.rfs-palette-btn:focus-visible,
.topnav-hamburger:focus-visible,
#rfs-ai-launch:focus-visible,
#rfs-ai-attach:focus-visible,
#rfs-ai-attach-x:focus-visible {
    outline: 2px solid var(--vz-primary, #405189);
    outline-offset: 2px;
}

.rfs-auth-eye { min-width:44px; min-height:44px; }
.rfs-auth-forgot { display:inline-flex; align-items:center; min-height:44px; }
.app-menu a:focus-visible,
.app-menu button:focus-visible,
.rfs-side-user-logout:focus-visible {
    outline-color: #fff;
}

/* 44×44 CSS-pixel touch targets at narrow viewports only — desktop density unchanged.
   Icon/control buttons and nav/pagination links. Never enlarge checkboxes/radios. */
@media (max-width: 480px) {
    #page-topbar .btn-icon,
    #page-topbar .topnav-hamburger,
    #page-topbar .rfs-palette-btn,
    #page-topbar .rfs-sidebar-collapse-btn,
    #page-topbar .header-item.btn,
    #page-topbar .btn-topbar,
    #page-topbar a.header-item,
    .rfs-side-user-logout,
    #rfs-ai-launch,
    #rfs-ai-attach,
    #rfs-ai-attach-x,
    .rfs-ai-hbtn,
    .btn-icon,
    a.btn-icon,
    button.btn-icon,
    .btn-close,
    .page-link,
    .pagination .page-link,
    .app-menu .nav-link,
    .navbar-menu .nav-link,
    .navbar-nav .nav-link,
    .rfs-hubtab-wrap .nav-link,
    .rfs-hubtab-nav,
    .rfs-hub-live-toggle,
    .rfs-hub-cmdk,
    #rfs-hub-theme-toggle,
    #rfs-clock-mini-btn,
    .nav-tabs .nav-link,
    .rfs-page-header .btn-icon {
        min-width: 44px;
        min-height: 44px;
    }
    input[type="checkbox"],
    input[type="radio"],
    .form-check-input,
    .form-check-input[type="checkbox"],
    .form-check-input[type="radio"] {
        min-width: unset;
        min-height: unset;
    }
}

/* Contrast helpers — topbar muted greys (~#878a99 on white ≈ 3.5:1) and dark-topbar muted whites. */
#page-topbar .rfs-greet-dt,
#page-topbar .rfs-ai-usage-txt {
    color: #4b5162;
}
#page-topbar .btn-ghost-secondary,
#page-topbar .rfs-sidebar-collapse-btn,
#page-topbar .rfs-palette-btn,
#page-topbar .topnav-hamburger {
    color: #4b5162;
}
[data-topbar="dark"] #page-topbar .rfs-greet-dt,
[data-topbar="dark"] #page-topbar .rfs-ai-usage-txt {
    color: rgba(255, 255, 255, .92);
}
[data-topbar="dark"] #page-topbar .btn-ghost-secondary,
[data-topbar="dark"] #page-topbar .rfs-sidebar-collapse-btn,
[data-topbar="dark"] #page-topbar .rfs-palette-btn,
[data-topbar="dark"] #page-topbar .topnav-hamburger {
    color: #fff;
}
.rfs-side-user-sub,
.rfs-side-user-logout {
    color: #c9d0ea;
}
