/* ============================================================
   styles.css — layout & components for Quantum Connect OmniCare AI
   Colors come from theme.css (:root vars). Do not hardcode brand hex here.
   ============================================================ */
*{box-sizing:border-box} html{-webkit-text-size-adjust:100%;text-size-adjust:100%} body{margin:0;font-family:Inter,Segoe UI,Roboto,Arial,sans-serif;color:var(--text);background:var(--bg)}

/* ---- Minimal custom scrollbars (themed to the sidebar: navy + indigo accent) ---- */
/* Firefox */
*{scrollbar-width:thin;scrollbar-color:rgba(109,93,252,.4) transparent}
/* WebKit/Chromium — thin transparent track, rounded indigo thumb inset via a
   transparent border so it reads as a slim pill, brightening on hover. */
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:rgba(109,93,252,.4);border:3px solid transparent;border-radius:999px;background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background:rgba(109,93,252,.7);background-clip:padding-box}
::-webkit-scrollbar-corner{background:transparent}
/* Only the nav list scrolls (see #nav below) — style ITS scrollbar. A
   translucent-light pill that turns brand-purple on hover stays visible against
   the navy gradient. */
.sidebar #nav{scrollbar-color:rgba(255,255,255,.22) transparent}
.sidebar #nav::-webkit-scrollbar{width:8px}
.sidebar #nav::-webkit-scrollbar-thumb{background:rgba(255,255,255,.18);border:2px solid transparent;border-radius:999px;background-clip:padding-box}
.sidebar #nav::-webkit-scrollbar-thumb:hover{background:rgba(124,87,255,.65);background-clip:padding-box}
.app-shell{display:grid;grid-template-columns:282px 1fr;height:100vh;overflow:hidden}
/* The sidebar itself no longer scrolls: brand + location stay pinned at the top
   and the plan card stays pinned at the bottom, while ONLY the nav list scrolls
   when it has more items than fit. */
.sidebar{background:linear-gradient(180deg,var(--navy),var(--navy2));color:#fff;padding:18px 16px;display:flex;flex-direction:column;gap:14px;position:sticky;top:0;height:100vh;overflow:hidden}
.sidebar #nav{flex:1 1 auto;min-height:0;overflow-y:auto}
/* Scroll affordance: when the nav has more items than fit, the last visible row
   would otherwise sit flush against a hard edge and read as the end of the list.
   Fade the content out at whichever edge still has items off-screen (classes
   toggled by app.js updateNavScrollHints) so it's obvious the list continues. On
   mobile the nav doesn't scroll, so these never engage. */
.sidebar #nav.nav-more-below:not(.nav-more-above){
  -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 34px),transparent);
          mask-image:linear-gradient(to bottom,#000 calc(100% - 34px),transparent);
}
.sidebar #nav.nav-more-above:not(.nav-more-below){
  -webkit-mask-image:linear-gradient(to bottom,transparent,#000 34px);
          mask-image:linear-gradient(to bottom,transparent,#000 34px);
}
.sidebar #nav.nav-more-above.nav-more-below{
  -webkit-mask-image:linear-gradient(to bottom,transparent,#000 34px,#000 calc(100% - 34px),transparent);
          mask-image:linear-gradient(to bottom,transparent,#000 34px,#000 calc(100% - 34px),transparent);
}
.brand{display:flex;align-items:center;gap:14px;padding-bottom:12px;border-bottom:1px solid rgba(255,255,255,.1)}
.brand-mark{width:46px;height:46px;border-radius:14px;background:linear-gradient(135deg,#7857ff,#12b8a6);display:grid;place-items:center;font-size:28px}
.brand-mark.has-img{background:none}
.brand-mark img{width:100%;height:100%;display:block}
/* Sized to the rail, not to taste: the sidebar is 282px with 16px padding and a 46px
   mark + 14px gap, leaving 190px. "Quantum Connect" runs ~8.7em, so anything past ~21px
   wraps — and at a sub-1 line-height a wrapped line collides with the one under it.
   line-height is .95 rather than the old .82 because "Q" has a descending tail and the
   previous three-letter wordmark did not. Both numbers are load-bearing; re-check them
   if the wordmark text changes. */
.brand-title{font-weight:800;font-size:20px;line-height:.95}
.brand-title span{color:#e4e7ff}
.brand-subtitle{font-size:12px;color:#c7d2fe;margin-top:6px}
.nav-item{display:flex;align-items:center;gap:12px;padding:11px 14px;border-radius:11px;color:#e8edf8;text-decoration:none;margin:2px 0;font-weight:600}
.nav-item:hover,.nav-item.active{background:linear-gradient(90deg,#4f46e5,#6d5dfc);box-shadow:0 10px 18px rgba(79,70,229,.28)}
.nav-icon{width:22px;text-align:center}
/* Live count pill on a nav item (Escalations). Sizes to its digits: a circle for
   one digit, a rounded pill for two or three ("99+"). border-box keeps min-width
   and padding from fighting. */
.nav-badge{margin-left:auto;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;height:20px;min-width:20px;padding:0 7px;border-radius:999px;background:var(--red);color:#fff;font-size:11px;font-weight:700;line-height:1}
.nav-badge[hidden]{display:none}
/* Section Access: a section Quantum Connect hasn't enabled for this workspace stays VISIBLE in the
   nav but greyed + locked (an upsell hint) instead of hidden. The full-item greyscale
   dims its colored icon; hover lifts it slightly to signal it's clickable (opens a
   "contact your System Administrator" notice). The server still enforces access via requireSection. */
.nav-item.nav-locked{opacity:.45;filter:grayscale(1)}
.nav-item.nav-locked:hover,.nav-item.nav-locked.active{opacity:.7;background:rgba(255,255,255,.06);box-shadow:none}
.nav-lock{margin-left:auto;font-size:12px;line-height:1;opacity:.9}
/* Location scope selector, moved into the sidebar so it reads as the global
   context for every page in the nav below it. The top-bar select styling no
   longer applies here, so the dark-rail look is defined explicitly. The whole
   block (label included) collapses when the tenant has no selectable locations
   and the switcher renders empty. */
.sidebar-location{display:flex;flex-direction:column;gap:7px}
.sidebar-location:has(#location-switcher:empty){display:none}
.sidebar-location .loc-label{font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:#93a4c9;padding-left:2px}
.sidebar-location .location-switcher{display:block}
.sidebar-location select{width:100%;height:42px;padding:0 34px 0 12px;border-radius:10px;border:1px solid rgba(255,255,255,.14);background-color:rgba(255,255,255,.06);color:#f1f4fb;font-weight:600;font-size:14px;cursor:pointer;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2393a4c9' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 12px center}
.sidebar-location select:hover{background-color:rgba(255,255,255,.1)}
.sidebar-location select option{color:#0b1220}
.sidebar-location .location-static{display:flex;align-items:center;gap:6px;height:42px;box-sizing:border-box;padding:0 12px;border-radius:10px;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.06);color:#f1f4fb;font-weight:600;white-space:nowrap}
.plan-card{flex:0 0 auto;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.06);border-radius:14px;padding:14px}
.muted{color:#8aa0c5;font-size:13px}
.plan-name{color:#35e084;font-weight:800;font-size:18px;margin:5px 0 12px}
.usage-row{display:flex;justify-content:space-between;font-size:12px;margin-top:12px}
.meter{height:8px;background:rgba(255,255,255,.14);border-radius:999px;margin-top:8px;overflow:hidden}
.meter span{display:block;height:100%;background:var(--green);border-radius:999px}
.meter.purple span{background:#6d5dfc}
.meter.over span{background:#ff6b6b}
.plan-note{color:#8aa0c5;font-size:12px;line-height:1.5;margin-top:2px}
/* Settings › Plan & Usage (light panel meters, distinct from the dark sidebar card) */
.plan-current{margin:0 0 16px}
.plan-current-name{font-size:20px;font-weight:800;color:var(--text);margin-top:2px}
.plan-usage{display:flex;flex-direction:column;gap:16px;margin:0 0 10px}
.plan-usage-row{display:flex;justify-content:space-between;font-size:13.5px;color:var(--text);margin-bottom:7px}
.plan-usage-row strong{font-variant-numeric:tabular-nums}
.plan-meter{height:10px;background:var(--line);border-radius:999px;overflow:hidden}
.plan-meter span{display:block;height:100%;background:var(--green);border-radius:999px}
.plan-meter.purple span{background:#6d5dfc}
.plan-meter.over span{background:#ff6b6b}
.plan-usage-note{color:var(--muted);font-size:12px;line-height:1.5;margin:0 0 4px}
.plan-divider{border:none;border-top:1px solid var(--line);margin:20px 0 18px}
.help{display:flex;gap:12px;align-items:center;color:#fff;padding:8px 6px}
.help small{color:#b8c7e6}
.main{min-width:0;display:flex;flex-direction:column;height:100vh}
.topbar{height:118px;flex:0 0 auto;background:#fff;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;padding:0 34px}
.topbar h1{font-size:28px;margin:0 0 6px}
.topbar p{margin:0;color:#475467}
/* The workspace/location name inside a page subtitle. Only pageMeta()'s accent
   argument writes this span, and it escapes the text it wraps. */
.page-accent{color:var(--purple);font-weight:700}
.top-actions{display:flex;align-items:center;gap:14px}
/* Mobile sidebar drawer trigger — hidden on desktop, shown ≤800px inside
   .has-drawer (the tenant app shell). Kept OUTSIDE .top-actions so it never
   collides with the #notif-bell selector. */
.nav-toggle{display:none;align-items:center;justify-content:center;width:42px;height:42px;flex:0 0 auto;border:1px solid var(--line);background:#fff;border-radius:10px;font-size:20px;line-height:1;color:var(--text);cursor:pointer}
.nav-toggle:hover{background:var(--bg)}
/* Dimmer behind the open drawer; toggled to display:block ≤800px when open. */
.sidebar-backdrop{display:none}
.top-actions select,.filterbar select,.filterbar input,.ws-inner-search,.wt-title-search input{height:43px;border:1px solid var(--line);border-radius:9px;background:#fff;padding:0 14px;color:#344054}
.ghost{height:43px;min-width:43px;border:1px solid var(--line);background:#fff;border-radius:10px;position:relative;cursor:pointer}
.badge{position:absolute;background:var(--red);color:#fff;border-radius:999px;font-size:11px;line-height:17px;height:17px;min-width:17px;top:-6px;right:-6px}
.user-chip{display:flex;gap:10px;align-items:center}
.user-chip>span{width:42px;height:42px;border-radius:50%;background:#667085;color:white;display:grid;place-items:center;font-weight:800}
.user-chip small{color:#667085}
/* Location switcher base (it now lives in the sidebar — see .sidebar-location
   above for the dark-rail look): a real <select> when multiple sites exist, a
   static label when there's exactly one, and nothing at all (:empty collapses)
   when none are configured. */
.location-switcher{display:flex;align-items:center}
.location-switcher:empty{display:none}
.location-static{display:inline-flex;align-items:center;height:43px;padding:0 14px;border:1px solid var(--line);border-radius:9px;background:#fff;color:#344054;font-weight:600;white-space:nowrap}
/* Per-page "Working location" picker: a slim tinted bar above the tabs on
   single-location pages. Lets a grouped practice scope THIS page to one member
   while the top bar stays on "All". Renders no markup for a solo tenant. Tint +
   accent match .icon / .tab.active so it reads as part of the page chrome. */
.loc-scope-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:-4px 0 18px;padding:10px 14px;background:#eef2ff;border:1px solid var(--line);border-radius:11px}
.loc-scope-icon{font-size:15px;line-height:1}
.loc-scope-label{font-weight:700;font-size:13px;color:#3730a3}
.loc-scope-bar select{height:36px;padding:0 12px;border:1px solid var(--line);border-radius:9px;background:#fff;color:var(--text);font-weight:600;font-size:13px;cursor:pointer}
.loc-scope-hint{color:var(--muted);font-size:12px}
/* Tag on a shared group document shown within a single location's file list. */
.loc-all-badge{display:inline-block;padding:1px 8px;border-radius:999px;font-size:11px;font-weight:600;background:#eef2ff;color:#3730a3;border:1px solid #c7d2fe;vertical-align:middle}
.content{padding:28px 34px 36px;flex:1 1 auto;overflow-y:auto;min-height:0}
.tabs{display:flex;gap:28px;margin:-8px 0 22px;border-bottom:1px solid var(--line)}
.tab{padding:14px 2px;color:#344054;font-weight:600;cursor:pointer}
.tab.active{color:#4f46e5;border-bottom:2px solid #4f46e5}
.cards{display:grid;grid-template-columns:repeat(5,minmax(150px,1fr));gap:16px;margin-bottom:20px}
/* KPI row that carries fewer than the base 5 cards (a metric was removed because
   nothing backs it). auto-fit lets 3-4 cards fill the row instead of leaving dead
   columns. It MUST be restated in the max-width:800px block below: .cards.fit
   outranks the plain .cards reflow on specificity, so without the restatement a
   "fit" row would keep 3 columns on a phone while every other KPI row goes to 1. */
.cards.fit{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}
.card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:18px;box-shadow:var(--shadow);min-width:0}
.metric{display:flex;gap:14px;align-items:center;min-width:0}
/* A flex item will not shrink below its content by default, which is how a long
   currency total ended up drawn past the card's own border. min-width:0 lets the
   text box shrink; the size steps below (set by helpers.js metric()) keep the
   number legible as it does. */
.metric-body{min-width:0;flex:1 1 auto}
.icon{width:46px;height:46px;border-radius:50%;display:grid;place-items:center;font-size:21px;background:#eef2ff;color:#4f46e5}
.icon.green{background:#e9f9f1;color:var(--green)}
.icon.orange{background:#fff5df;color:var(--orange)}
.icon.red{background:#ffecef;color:var(--red)}
.icon.teal{background:#e8faf7;color:var(--teal)}
.metric h3{font-size:26px;margin:2px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  font-variant-numeric:tabular-nums;letter-spacing:-.01em}
/* Length-driven steps, applied by helpers.js metric(). Chosen so the widest realistic
   value of each length still fits a card at the row's narrowest reflow: 10-12 chars
   (1,234,567), 13-15 ($13,682,838.00), 16+ (anything longer). The ellipsis above is
   the backstop past that, and the full value stays on the title attribute. */
.metric h3.m-lg{font-size:22px}
.metric h3.m-xl{font-size:19px}
.metric h3.m-xxl{font-size:17px}
.metric p{margin:0;color:#344054;font-size:13px;min-width:0;overflow-wrap:break-word}
.trend{font-size:12px;color:var(--green);margin-top:8px}
.trend.down{color:var(--red)}
.trend.muted{color:#98a2b3}
/* "vs prior period" tag appended to a flow KPI's delta (reports.js repTrend). It
   sets its OWN muted color so it stays grey inside a red (down) or green (up) trend
   line — the colored arrow/% reads as the signal, this reads as its quiet caption. */
.trend .trend-vs{color:#98a2b3;font-weight:400;font-size:11px;white-space:nowrap}
/* A KPI card that links somewhere — the dashboard totals, which drill into the
   sections listed in pages/dashboard.js DASH_PAGE_LABELS. Named by that symbol and
   not enumerated here on purpose: this comment used to spell the destinations out
   and still said "Text & Email" long after the menu, the page title and the section
   catalog had all become "Texts". A CSS comment is the last place anyone looks for
   a stale menu name. It stays visually a card: no underline, no link colour, just a
   chevron affordance and a lift on hover, so the row reads as data first and
   navigation second. Cards whose destination is locked for this user stay plain
   .card divs (see pages/dashboard.js dashLink), so "looks clickable" always means
   "is clickable". */
.card-link{display:block;position:relative;color:inherit;text-decoration:none;
  transition:transform .14s ease,box-shadow .14s ease,border-color .14s ease}
.card-link:hover{transform:translateY(-2px);border-color:color-mix(in srgb,var(--purple) 35%,var(--line));
  box-shadow:0 12px 28px rgba(16,24,40,.12)}
.card-link:focus-visible{outline:2px solid var(--purple);outline-offset:2px}
.card-go{position:absolute;top:14px;right:16px;font-size:18px;line-height:1;font-weight:700;
  color:#c3c9d4;transition:transform .14s ease,color .14s ease}
.card-link:hover .card-go{color:var(--purple);transform:translateX(2px)}
@media (prefers-reduced-motion: reduce){
  .card-link,.card-go{transition:none}
  .card-link:hover{transform:none}
  .card-link:hover .card-go{transform:none}
}

/* Header above the KPI row: what the totals are, and the period selector that
   drives them. */
.kpi-bar{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap;margin:0 0 14px}
.kpi-head{min-width:0}
.kpi-title{font-size:17px;font-weight:800;margin:0;color:var(--text)}
.kpi-caption{margin:3px 0 0;color:var(--muted);font-size:12.5px;font-weight:600}
/* Second and later zone headings on the dashboard. The first sits under the page title
   and needs nothing; the rest follow a panel and would otherwise read as a caption ON
   that panel instead of the start of the next band. */
.kpi-bar.zone{margin-top:12px}
/* Segmented control (Today / Week / Month / Year). One tinted track, the active
   choice lifted out of it on a white pill — the same shape the rest of the app uses
   for a small set of mutually exclusive options. */
.range-seg{display:inline-flex;gap:2px;padding:3px;border:1px solid var(--line);border-radius:999px;background:var(--bg)}
.seg-btn{border:0;background:transparent;border-radius:999px;padding:7px 15px;cursor:pointer;
  font-size:12.5px;font-weight:700;color:var(--muted);white-space:nowrap;
  transition:background .14s ease,color .14s ease,box-shadow .14s ease}
.seg-btn:hover{color:var(--text)}
.seg-btn.active{background:var(--card);color:var(--purple);box-shadow:0 1px 3px rgba(16,24,40,.14)}
.seg-btn:focus-visible{outline:2px solid var(--purple);outline-offset:1px}
@media (prefers-reduced-motion: reduce){.seg-btn{transition:none}}
/* Dashboard "while you were away" recap strip (overnight / weekend / today).
   Sits above the KPI cards; each card = title + window sublabel + big count +
   outcome chips. `.prominent` marks the lead recap (weekend on Monday, overnight
   on Tuesday) with the indigo tint so the freshest catch-up reads first. */
/* Overnight / Today / Weekend — always three, always the same row, wrapping to two
   then one as the viewport narrows. */
.recap-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:16px;margin-bottom:20px}
/* Each window carries its own quiet tint, so the three cards read as one set
   instead of one themed card beside two blank ones: indigo for the overnight
   hours, warm amber for the working day, teal for the weekend. The recipe is
   identical for all three and only --recap-accent changes, so a rebrand moves
   them together and nothing here hardcodes a colour. .prominent then deepens
   whichever card is the lead catch-up, in that card's own accent rather than
   always in indigo. */
.recap-card{--recap-accent:var(--purple);
  background:linear-gradient(180deg,color-mix(in srgb,var(--recap-accent) 5%,#fff),var(--card));
  border:1px solid color-mix(in srgb,var(--recap-accent) 20%,var(--line));
  border-radius:14px;padding:16px 18px;box-shadow:var(--shadow)}
.recap-card.kind-overnight{--recap-accent:var(--purple)}
.recap-card.kind-today{--recap-accent:var(--orange)}
.recap-card.kind-weekend{--recap-accent:var(--teal)}
.recap-card.prominent{border-color:color-mix(in srgb,var(--recap-accent) 38%,#fff);
  background:linear-gradient(180deg,color-mix(in srgb,var(--recap-accent) 11%,#fff),var(--card))}
.recap-head{display:flex;gap:12px;align-items:center}
.recap-icon{width:38px;height:38px;border-radius:50%;display:grid;place-items:center;font-size:18px;
  background:color-mix(in srgb,var(--recap-accent) 14%,#fff)}
.recap-card.prominent .recap-icon{background:color-mix(in srgb,var(--recap-accent) 22%,#fff)}
.recap-title{font-weight:800;font-size:14px;color:var(--text)}
.recap-sub{font-size:12px;color:var(--muted);margin-top:1px}
.recap-total{display:flex;align-items:baseline;gap:7px;margin:10px 0 8px}
.recap-total b{font-size:26px}
.recap-total small{color:var(--muted);font-size:12px;font-weight:600}
.recap-parts{display:flex;flex-wrap:wrap;gap:6px;min-height:22px}
.recap-chip{display:inline-flex;padding:3px 9px;border-radius:999px;font-size:11.5px;font-weight:700;background:#f2f4f7;color:#344054;border:1px solid var(--line)}
/* Outcome tones. Each is one theme colour mixed three ways — a pale fill, a darkened
   text shade, a mid-strength border — so a rebrand moves the chips with everything
   else and the family stays visually consistent (the tinted-badge house style).
   good = handled without a human, info = handed to staff, cool = message waiting,
   warn = someone owes a call back, bad = nobody picked up. */
.recap-chip.good{background:color-mix(in srgb,var(--green) 12%,#fff);color:color-mix(in srgb,var(--green) 60%,var(--text));border-color:color-mix(in srgb,var(--green) 32%,#fff)}
.recap-chip.info{background:color-mix(in srgb,var(--blue) 12%,#fff);color:color-mix(in srgb,var(--blue) 60%,var(--text));border-color:color-mix(in srgb,var(--blue) 32%,#fff)}
.recap-chip.cool{background:color-mix(in srgb,var(--teal) 12%,#fff);color:color-mix(in srgb,var(--teal) 60%,var(--text));border-color:color-mix(in srgb,var(--teal) 32%,#fff)}
.recap-chip.warn{background:color-mix(in srgb,var(--orange) 14%,#fff);color:color-mix(in srgb,var(--orange) 58%,var(--text));border-color:color-mix(in srgb,var(--orange) 36%,#fff)}
.recap-chip.bad{background:color-mix(in srgb,var(--red) 12%,#fff);color:color-mix(in srgb,var(--red) 62%,var(--text));border-color:color-mix(in srgb,var(--red) 32%,#fff)}
.recap-quiet{font-size:12.5px;color:#98a2b3;font-weight:600}
.empty-state{display:grid;place-items:center;min-height:120px;color:#98a2b3;font-size:14px;font-weight:600;text-align:center}
/* spinner() — shared "still loading" indicator (helpers.js). Fills a panel body
   like .empty-state so swapping the two keeps the card's shape. Ring = light
   accent track with one solid accent arc, rotating; label sits beneath it. */
.oc-spin{display:grid;place-items:center;gap:10px;min-height:120px;width:100%;text-align:center}
.oc-spin-ring{width:26px;height:26px;border-radius:50%;border:3px solid color-mix(in srgb,var(--blue,#2563eb) 20%,transparent);border-top-color:var(--blue,#2563eb);animation:ocSpin .7s linear infinite}
.oc-spin-lbl{font-size:13px;font-weight:600;color:var(--muted,#667085)}
/* Inline variant: small ring + label on one line, for a tight spot (hint line, cell). */
.oc-spin-inline{display:inline-flex;align-items:center;gap:8px;min-height:0;width:auto;grid-template-columns:none}
.oc-spin-inline .oc-spin-ring{width:14px;height:14px;border-width:2px}
.oc-spin-inline .oc-spin-lbl{font-size:13px}
@keyframes ocSpin{to{transform:rotate(360deg)}}
/* Reduced-motion: keep it turning (that's the whole point) but slow and gentle. */
@media (prefers-reduced-motion:reduce){.oc-spin-ring{animation-duration:1.5s}}
.grid{display:grid;grid-template-columns:2fr 1fr;gap:18px}
.grid.three{grid-template-columns:1.25fr 1fr .9fr}
/* Dashboard "Right now" band: one metric card and two status panels, as peers. The card
   is the short one, so it is stretched to the row and centres its own content rather
   than sitting at the top of a tall empty box — and it takes the panels' 18px bottom
   margin so all three bottom edges land on the same line. Collapses at 1200px with the
   other multi-column grids (see the media query below — add any new grid to BOTH). */
.now-row{display:grid;grid-template-columns:.85fr 1fr 1fr;gap:18px}
.now-row>.card,.now-row>.card-link{display:flex;flex-direction:column;justify-content:center;margin-bottom:18px}
.panel{background:#fff;border:1px solid var(--line);border-radius:14px;padding:20px;box-shadow:var(--shadow);margin-bottom:18px}
/* A panel whose body should take the height its ROW turns out to be, rather than its own
   natural height. Grid rows stretch every panel in them to the tallest, so a panel with
   fixed-height content beside a panel with list content ends up with a pool of dead space
   under it — and that pool grows as the neighbour's list does. Opt in with
   widget({className:'panel-fill'}); the content still needs a min-height of its own so
   the panel doesn't collapse when IT is the taller one (see .panel-fill .actchart).
   Only the last child grows: the head stays put. */
.panel-fill{display:flex;flex-direction:column}
.panel-fill>:last-child{flex:1 1 auto;display:flex;flex-direction:column;min-height:0}
.panel h2{font-size:18px;margin:0 0 16px}
.panel-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:14px}
.widget-action{display:flex;gap:8px;align-items:center}
.btn{height:42px;border:0;border-radius:9px;background:linear-gradient(90deg,#4f46e5,#6d5dfc);color:#fff;font-weight:800;padding:0 16px;cursor:pointer}
.btn.secondary{background:#fff;color:#344054;border:1px solid var(--line)}
/* Secondary button in an "open"/active state (e.g. a toggle whose panel is shown
   below): purple-tinted so it's clear which one is expanded. */
.btn.secondary.open{background:#eef2ff;color:#4f46e5;border-color:#c7d2fe}
/* "View as" / "View as group": the primary action on each Workspaces/Mappings row,
   so lift them out of the plain-grey secondary crowd (Unlink, Reset) with a light-blue
   tint (theme --blue). Placed after .btn.secondary to win at equal specificity, but
   before .btn:disabled so the ghosting-in disabled state still greys out. */
.btn.view-as,.btn.view-as-group{
  background:color-mix(in srgb, var(--blue) 10%, #fff);
  color:var(--blue);
  border:1px solid color-mix(in srgb, var(--blue) 35%, #fff)}
.btn.view-as:hover,.btn.view-as-group:hover{
  background:color-mix(in srgb, var(--blue) 18%, #fff);
  border-color:color-mix(in srgb, var(--blue) 55%, #fff)}
.btn.danger{background:var(--red)}
/* Disabled buttons (e.g. self-row actions you can't perform on your own account):
   greyed out + not-allowed, overriding the primary gradient / secondary / danger
   fills. Placed after the variants so it wins at equal specificity. */
.btn:disabled,.btn[disabled]{background:#f1f2f4;color:#98a2b3;border:1px solid var(--line);cursor:not-allowed;opacity:.65;box-shadow:none}
.filterbar{display:flex;gap:12px;margin-bottom:16px;align-items:center}
.filterbar input{min-width:300px}
.table{width:100%;border-collapse:collapse;background:#fff}
/* Emitted by table() in helpers.js for every table given fixed {cols} widths, at ALL
   viewports. Those widths are a floor the table cannot shrink under, so the overflow
   has to go somewhere: either this box scrolls, or the page body does. */
.table-wrap{overflow-x:auto}
/* ocTablePager (helpers.js) — the bar ABOVE a long table: search, count, page
   buttons, rows-per-page. Above and not below, because the reason it exists is
   not having to scroll to the bottom of a 200-row table to change what the top
   shows. Reuses the app-wide focus ring and the .filterbar control metrics. */
.oc-page{display:flex;flex-direction:column;gap:10px}
.oc-page-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.oc-page-q{flex:1;min-width:200px;box-sizing:border-box;height:36px;padding:0 12px;
  border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--text);
  font-family:inherit;font-size:13px}
.oc-page-q:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.oc-page-spacer{flex:1;min-width:0}
.oc-page-at{flex:none;color:var(--muted);font-size:12px;font-variant-numeric:tabular-nums}
.oc-page-nav{display:flex;gap:6px;flex:none}
.oc-page-btn{width:32px;height:32px;padding:0;border:1px solid var(--line);border-radius:8px;
  background:#fff;color:var(--text);font-family:inherit;font-size:15px;line-height:1;cursor:pointer}
.oc-page-btn:hover:not(:disabled){border-color:var(--blue);color:var(--blue)}
.oc-page-btn:disabled{opacity:.4;cursor:default}
/* Nothing to page through: the buttons stay in place but stop asking to be clicked,
   rather than appearing and disappearing as a search narrows the set. */
.oc-page-bar.one-page .oc-page-nav{opacity:.45}
.oc-page-size{display:flex;align-items:center;gap:6px;flex:none;color:var(--muted);font-size:12px}
.oc-page-size select{height:32px;padding:0 8px;border:1px solid var(--line);border-radius:8px;
  background:#fff;color:var(--text);font-family:inherit;font-size:12px}
.oc-page-size select:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.oc-page-hide{display:none !important}
.oc-page-last td{border-bottom:none}
@media (max-width:700px){
  .oc-page-q{min-width:100%;order:-1}
}
.table th,.table td{padding:14px 12px;border-bottom:1px solid var(--line);text-align:left;font-size:13px;vertical-align:middle}
.table th{color:#344054;background:#fafbff;font-weight:800}
/* Access Log (platform console): expandable detail rows + pager. The console loads
   this shared stylesheet, so these classes live here alongside .table/.filterbar. */
.al-details summary{cursor:pointer;color:#475467;font-size:12px;list-style:none;user-select:none}
.al-details summary::-webkit-details-marker{display:none}
.al-details summary::marker{content:''}
.al-details[open] summary{color:#1d2939;font-weight:700}
.al-json{margin:8px 0 2px;padding:10px 12px;background:#f6f7fb;color:#344054;border:1px solid var(--line);border-radius:8px;font-size:11.5px;line-height:1.5;white-space:pre-wrap;word-break:break-word;max-height:260px;overflow:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.al-pager{display:flex;gap:12px;align-items:center;justify-content:flex-end;margin-top:16px}
.al-pager:empty{display:none}
.status{display:inline-flex;border-radius:999px;padding:5px 9px;font-size:12px;font-weight:700}
.status.good{background:#e9f9f1;color:#087443}
.status.warn{background:#fff3e0;color:#b54708}
.status.bad{background:#ffecef;color:#b42318}
.status.info{background:#edf4ff;color:#175cd3}
.status.muted{background:#f2f4f7;color:#475467}
.status.purple{background:#f0ecff;color:#5e3eca}
/* Test/demo workspace — black-and-yellow construction tape, matching the shared
   mode badge (js/components/workspacetable.js HAZARD_SKIN). Stripes ride in the
   border ring (border-box clip) and the face stays solid yellow (padding-box
   clip), since text over full-width stripes is unreadable. The 3px ring is paid
   for out of .status's 5px/9px padding so the chip's outer size never changes. */
.status.test-tag{color:#241a00;border:3px solid transparent;padding:2px 6px;
  background:linear-gradient(#ffd95e,#ffc400) padding-box,
    repeating-linear-gradient(-45deg,#181818 0 4px,#ffd21f 4px 8px) border-box;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.38)}
.mini-list{display:flex;flex-direction:column;gap:12px}
.mini-item{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--line);padding-bottom:12px}
.mini-item:last-child{border-bottom:0}
/* A category row that stacks its name over a "no files yet" note (Knowledge Base). */
.kb-cat-cell{display:flex;flex-direction:column;gap:3px;min-width:0}
.kb-cat-empty{font-size:12.5px;color:var(--muted,#667085)}
.right-note{font-size:13px;color:#667085}
.chart{height:240px;background:linear-gradient(180deg,#fbfcff,#fff);border:1px dashed #d7dce8;border-radius:12px;padding:20px;position:relative}
.line{position:absolute;left:35px;right:30px;height:2px;background:#4f46e5;top:55%;transform:rotate(-5deg);box-shadow:60px -30px 0 #20b26b,120px 18px 0 #f59e0b,210px -42px 0 #6d5dfc}
.donut{width:174px;height:174px;border-radius:50%;background:conic-gradient(#20b26b 0 58%,#2563eb 58% 76%,#f59e0b 76% 88%,#ef4444 88% 100%);position:relative;margin:auto}
.donut:after{content:"";position:absolute;inset:38px;background:#fff;border-radius:50%}
/* Flex column (not grid): a grid put the old <br> in its own empty row, spreading
   the number and "Total" apart. Now they sit as one tight, centered stack. */
.donut-label{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;font-weight:800;z-index:2;text-align:center;line-height:1.15}
.donut-total{font-size:24px;font-variant-numeric:tabular-nums;white-space:nowrap}
/* Length steps set by dashDonut (pages/dashboard.js). The ring's hole is ~100px
   across, so the base size holds about six characters — past that the total has to
   shrink or it is drawn out over the arcs. */
.donut-total.d-lg{font-size:20px}
.donut-total.d-xl{font-size:17px}
.donut-total.d-xxl{font-size:14px}
.donut-label small{font-size:12px;font-weight:700;color:#667085;text-transform:uppercase;letter-spacing:.04em}
/* Activity Overview bar chart — dependency-free, one STACKED column per bucket
   (calls + texts + emails). The stack grows from the bottom of .actbar-bar; the
   total rides just above it; the x-label sits beneath. The stack height is a % of
   the fixed chart height; each segment is a % of its bar's total (both set inline). */
.actchart{display:flex;align-items:flex-end;gap:10px;height:210px;padding-top:6px}
.actbar{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;height:100%}
.actbar-bar{flex:1;min-height:0;width:100%;display:flex;flex-direction:column;justify-content:flex-end;align-items:center}
.actbar-val{font-size:11px;font-weight:700;color:#344054;font-variant-numeric:tabular-nums;line-height:1;margin-bottom:4px;min-height:11px}
/* A day with no activity still states its zero, in the same grey as the date beneath it:
   it is a fact about that day, not a value competing with the bars for attention. */
.actbar-val.is-zero{font-weight:600;color:var(--muted)}
.actbar-stack{width:70%;max-width:34px;display:flex;flex-direction:column;justify-content:flex-end;border-radius:6px 6px 0 0;overflow:hidden;transition:height .3s ease}
.actseg{width:100%;flex-basis:0;min-height:0}
.actbar:hover .actbar-stack{filter:brightness(1.06) saturate(1.04)}
.actbar-label{font-size:11px;color:#667085;margin-top:8px;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Legend shared by the activity chart (below the bars) and the donut list rows. */
.chart-legend{display:flex;gap:12px;justify-content:center;margin-top:14px;flex-wrap:wrap}
.leg-item{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:600;color:#667085}
.leg-lbl{display:inline-flex;align-items:center;gap:8px}
.leg-dot{box-sizing:border-box;width:10px;height:10px;border-radius:3px;display:inline-block;flex:0 0 auto}
/* Interactive legend buttons: click a channel to show/hide it in the Activity chart. */
.leg-toggle{padding:3px 8px;border:0;border-radius:7px;background:none;font-family:inherit;cursor:pointer;transition:opacity .15s ease,background .15s ease;-webkit-appearance:none;appearance:none}
.leg-toggle:hover{background:rgba(16,24,40,.05)}
.leg-toggle:focus-visible{outline:2px solid var(--primary);outline-offset:2px}
.leg-toggle.is-off{opacity:.45}
.leg-toggle.is-off:hover{opacity:.7}
/* Shown when the window has activity but every data-bearing channel is toggled off. */
.actchart-note{height:210px;display:flex;align-items:center;justify-content:center;color:#667085;font-size:13px;text-align:center}
/* Activity Overview inside a .panel-fill panel: the chart takes the leftover height
   instead of a fixed 210px, which becomes its floor. align-items:stretch does the job
   the bars' own height:100% did, so the bar heights no longer depend on a percentage
   resolving against a flex-sized ancestor — they bottom-align regardless, because
   .actbar-bar already uses justify-content:flex-end. The legend is not in this list on
   purpose: it keeps its natural height and stays pinned under the bars.
   Both stand-in bodies grow the same way so a chart, a hidden-channel note and an empty
   state all leave the panel exactly the same size. */
.panel-fill .actchart{height:auto;flex:1 1 auto;min-height:210px;align-items:stretch}
.panel-fill .actchart-note{height:auto;flex:1 1 auto;min-height:210px}
.panel-fill .empty-state{flex:1 1 auto}
/* SVG donut (dashboard Channel Breakdown) — crisp vector ring, replaces the
   conic-gradient .donut for this widget so slice edges don't alias. Each .dseg is a
   hoverable stroked arc; the center label must let pointer events reach the ring. */
.svg-donut{position:relative;width:174px;height:174px;margin:auto}
.svg-donut .donut-svg-el{width:100%;height:100%;display:block}
.svg-donut .donut-label{pointer-events:none}
.svg-donut .track{stroke:var(--line)}
.svg-donut .dseg{transition:stroke-width .15s ease,opacity .15s ease;cursor:default}
/* Side-by-side ring + legend (dashDonut's `row` option). The dashboard's Channel
   Breakdown spans the full width of the Totals band, where the default stacked layout
   would centre a 174px ring over a very wide panel and stretch the legend beneath it.
   Wraps back to stacked when the panel gets narrow, which is the same layout the Calls
   page uses by default — so nothing here changes that page. */
.donut-row{display:flex;align-items:center;gap:38px;flex-wrap:wrap}
.donut-row .svg-donut{margin:0;flex:0 0 auto}
.donut-row .mini-list{flex:1 1 240px;min-width:0}
.donut-svg-el:hover .dseg{opacity:.45}
.donut-svg-el .dseg:hover{opacity:1;stroke-width:7.4}
/* Floating chart tooltip (activity bars + donut slices). Positioned by the cursor. */
.chart-tip{position:fixed;z-index:1000;pointer-events:none;background:#1f2937;color:#fff;border-radius:10px;padding:9px 11px;font-size:12px;line-height:1.5;box-shadow:0 10px 28px rgba(16,24,40,.28);min-width:124px;max-width:220px}
.chart-tip .tip-title{font-weight:800;margin-bottom:5px}
.chart-tip .tip-row,.chart-tip .tip-total{display:flex;align-items:center;gap:8px}
.chart-tip .tip-total{margin-top:5px;padding-top:5px;border-top:1px solid rgba(255,255,255,.16)}
.chart-tip .tip-name{flex:1 1 auto;color:#e5e7eb}
.chart-tip .tip-dot{width:9px;height:9px;border-radius:3px;flex:0 0 auto}
.chart-tip b{font-variant-numeric:tabular-nums;font-weight:800}
/* Consent-pill description popover (patient header). Hover or click a pill to read
   what that consent type means. Same dark tooltip look as .chart-tip, but pinnable. */
.pt-consent-chip{cursor:help}
.pt-tip{position:fixed;z-index:1200;max-width:290px;background:#1f2937;color:#fff;border-radius:10px;padding:10px 12px;font-size:12.5px;line-height:1.5;box-shadow:0 10px 28px rgba(16,24,40,.28)}
.pt-tip-h{font-weight:800;margin-bottom:4px}
.pt-tip-state{font-weight:700;opacity:.78;font-size:11.5px}
.pt-tip-b{color:#e5e7eb}
.pt-tip-muted{opacity:.7;font-style:italic}
.split{display:grid;grid-template-columns:1fr 320px;gap:18px}
.side-panel{background:#fff;border-left:1px solid var(--line);padding:22px}
.avatar{width:70px;height:70px;border-radius:50%;background:linear-gradient(135deg,#8b5cf6,#b794f4);color:white;display:grid;place-items:center;font-size:26px;font-weight:800}
/* min-height, never height: this box holds a variable number of controls (the
   Knowledge Base category adds three more rows) and a fixed height made them spill
   out over whatever panel came next. It still opens at the same size. */
.upload-zone{min-height:260px;padding:20px;box-sizing:border-box;border:2px dashed #9aa7ff;border-radius:16px;background:#fbfcff;display:grid;place-items:center;text-align:center}
.upload-icon{font-size:58px;color:#4f46e5}
.settings-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.setting-card{min-height:145px}
.conversation{height:430px;border:1px solid var(--line);border-radius:14px;background:#fbfcfe;display:flex;flex-direction:column}
.messages{padding:20px;display:flex;flex-direction:column;gap:10px;overflow:auto}
/* Inbound = neutral grey hugging the left; outbound = blue hugging the right, each
   with a matching squared corner so the two sides read clearly apart. */
.bubble{align-self:flex-start;max-width:74%;padding:10px 14px;border-radius:14px 14px 14px 4px;background:#f2f4f7;color:#1d2939;font-size:14px;line-height:1.45}
.bubble.me{align-self:flex-end;background:#e0e9ff;border-radius:14px 14px 4px 14px}
.bubble-time{display:block;margin-top:5px;font-size:11px;color:#667085}
/* Centered day divider so the date isn't repeated on every bubble. */
.tx-day{align-self:center;margin:4px 0}
.tx-day span{font-size:12px;color:#667085;background:#eef1f6;padding:3px 12px;border-radius:999px}
.composer{margin-top:auto;border-top:1px solid var(--line);padding:14px;display:flex;gap:10px}
.composer input{flex:1;border:1px solid var(--line);border-radius:9px;padding:0 12px}
/* Read-only footer (combined "All locations" view): a quiet note + a centered,
   content-width action instead of a full-bleed bar. */
.composer.tx-readonly{flex-direction:column;align-items:center;gap:10px;text-align:center}
/* pages/textemail.js (page id 'textemail'; the .tx- prefix below is that page's) —
   conversation thread cards, the left list. Named by page id, not by menu label: the
   label has been renamed once already and this comment kept the old one. Own layout
   (not the shared .mini-item) so a long SMS preview truncates to one clean line and the
   time stays pinned top-right beside the name instead of splitting across the wrapped
   preview. */
.tx-threads{display:flex;flex-direction:column;gap:2px}
.tx-thread{display:flex;flex-direction:column;gap:3px;cursor:pointer;padding:10px 12px;border:1px solid transparent;border-radius:10px;transition:background .12s,border-color .12s}
.tx-thread:hover{background:#f7f8fc}
.tx-thread.sel{background:#eef2ff;border-color:#dfe3fb}
.tx-thread-top{display:flex;align-items:baseline;gap:8px}
.tx-thread-idline{display:flex;align-items:baseline;gap:6px;min-width:0;flex:1}
.tx-thread-name{font-weight:600;color:#101828;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tx-thread-top .status{flex:0 0 auto;padding:2px 7px;font-size:11px}
.tx-thread-time{flex:0 0 auto;font-size:12px;color:#98a2b3;white-space:nowrap;font-variant-numeric:tabular-nums}
.tx-thread-preview{font-size:13px;color:#475467;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tx-thread-preview.empty{color:#98a2b3}
.tx-thread-meta{font-size:12px;color:#98a2b3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.footer{color:#667085;font-size:12px;margin-top:22px}
.callout{border:1px solid #b3cdfd;background:#eff6ff;border-radius:14px;padding:16px;margin-top:16px;color:#1849a9}
/* A plain callout STATES something. These two CONFIRM or REFUSE something that just
   happened — a different job, and in one blue they were indistinguishable at a glance,
   which is the one thing a confirmation has to be. Colour carries the meaning and the
   mark repeats it, so it still reads without colour vision.
   Absolutely positioned rather than a flex row on purpose: these callouts hold arbitrary
   inner markup (<b>, <br>, sentences), and flex would make every text node its own
   column. */
.callout.ok,.callout.err,.callout.warn{position:relative;padding-left:50px}
.callout.ok::before,.callout.err::before,.callout.warn::before{position:absolute;left:16px;top:14px;
  width:22px;height:22px;border-radius:999px;color:#fff;font-size:13px;font-weight:800;
  line-height:22px;text-align:center}
.callout.ok{border-color:color-mix(in srgb,var(--green) 34%,#fff);
  background:color-mix(in srgb,var(--green) 9%,#fff);
  color:color-mix(in srgb,var(--green) 72%,var(--text))}
.callout.ok::before{content:'✓';background:var(--green)}
.callout.err{border-color:color-mix(in srgb,var(--red) 34%,#fff);
  background:color-mix(in srgb,var(--red) 8%,#fff);
  color:color-mix(in srgb,var(--red) 68%,var(--text))}
.callout.err::before{content:'!';background:var(--red)}
/* WARN — something imported but needs the user's attention (e.g. accounts arrived with
   missing/incomplete data). Amber, distinct from the green "all good" confirmation. */
.callout.warn{border-color:color-mix(in srgb,var(--orange) 40%,#fff);
  background:color-mix(in srgb,var(--orange) 10%,#fff);
  color:color-mix(in srgb,var(--orange) 60%,var(--text))}
.callout.warn::before{content:'!';background:var(--orange)}
/* A confirmation sitting above the box it is about needs to read as separate from it,
   not as the box's own first row. */
.callout.standalone{margin:0 0 16px}
/* A callout that ends in an action. The sentence takes the room it needs and the
   button stays whole beside it, dropping underneath only when there isn't room
   for both - a wrapped button label is worse than a stacked callout. */
.callout.with-action{display:flex;flex-wrap:wrap;align-items:center;gap:14px}
.callout.with-action>div{flex:1 1 320px;min-width:0}
.callout.with-action>.btn{flex:0 0 auto}
/* Temp-password row + small clipboard copy button (neutral at rest, blue on
   hover, green once copied). */
.temp-pw{display:inline-flex;align-items:center;gap:8px;margin-top:6px}
.temp-pw-code{font-size:15px}
.copy-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:1px solid var(--line);border-radius:7px;background:var(--card);color:var(--muted);cursor:pointer}
.copy-btn:hover{border-color:var(--blue);color:var(--blue)}
.copy-btn.copied{border-color:var(--green);color:var(--green)}
.copy-btn svg{width:15px;height:15px}
.copy-ok{font-size:13px;font-weight:700;color:var(--green)}
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.stack{display:flex;flex-direction:column;gap:12px}

/* ---- AI Receptionist status panel (Inbound › Overview) ----
   A modern property list (icon chip + label + value) paired with a presence
   card. Icon chips reuse the shared .icon tints; all color via tokens. */
/* Inbound > Overview row. The shared .grid is 2fr/1fr, which put two thirds of
   the width behind three short facts and squeezed four KPI cards plus two rings
   into the remaining third. Reversed, and weighted further: the performance
   panel is the one with something to show. */
.grid.rx-overview{grid-template-columns:minmax(290px,1fr) minmax(0,2.6fr)}
/* Two columns only while both can still be read; auto-fit stacks the presence
   card under the facts rather than crushing a phone number and its badge. */
.rx-status{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:20px;align-items:stretch}
.rx-stats{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:12px;overflow:hidden;background:var(--card)}
/* flex:1 shares the stretched column's extra height across the rows (the
   .rx-status grid stretches this list to the presence card's height) instead
   of leaving a dead gap under the last row. */
.rx-stat{display:flex;align-items:center;gap:12px;padding:12px 14px;flex:1 1 auto}
.rx-stat + .rx-stat{border-top:1px solid var(--line)}
.rx-stat .icon{flex:0 0 auto}
.rx-stat-body{display:flex;flex-direction:column;gap:3px;min-width:0}
.rx-stat-label{font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}
.rx-stat-value{font-size:15px;font-weight:700;color:var(--text);display:flex;align-items:center;gap:8px;flex-wrap:wrap;word-break:break-word}
.rx-presence{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:12px;padding:18px 16px;border:1px solid var(--line);border-radius:12px;background:var(--bg)}
.rx-presence .icon{flex:0 0 auto}
.rx-presence-state{display:inline-flex;align-items:center;gap:8px;font-weight:800;font-size:15px;color:var(--text)}
.rx-dot{width:9px;height:9px;border-radius:50%;position:relative;flex:0 0 auto}
.rx-dot.live{background:var(--green)}
.rx-dot.setup{background:var(--orange)}
.rx-dot.live::after{content:"";position:absolute;inset:0;border-radius:50%;background:var(--green);animation:rxPulse 1.8s ease-out infinite}
.rx-presence p{margin:0;color:var(--muted);font-size:13px;line-height:1.5;max-width:280px}
/* Call-forwarding caution that replaced the Quantum Connect-only Test / Turn On-Off buttons on this
   card (2026-08-28): those controls moved to the platform console's Voice Agents page.
   Fixed amber caution palette, same as .auth-warn / .warning-strip elsewhere. */
.rx-fwd-ack-row{margin-top:9px}
.rx-fwd-ack-row .btn{background:#fff;color:#b54708;border:1px solid #fed7aa}
.rx-fwd-ack-row .btn:hover{background:#fff7ed}
.rx-forward-note{background:#fff4e6;border:1px solid #fed7aa;color:#b54708;border-radius:10px;padding:10px 12px;font-size:13px;line-height:1.45;text-align:left;max-width:300px}
.rx-forward-note strong{color:#b54708}
/* What decides whether four KPI cards fit is how wide THIS PANEL is, not how wide
   the window is - the panel is a fraction of the row and the row stacks at 1200px,
   so viewport breakpoints only ever approximated it. Ask the panel directly. Two
   across is the floor: four cards at a narrow width is what folded the labels. */
.rx-perf{container-type:inline-size}
.rx-perf-cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin-bottom:20px}
@container (min-width:820px){.rx-perf-cards{grid-template-columns:repeat(4,minmax(0,1fr))}}
/* Compact inside this panel: four cards in a shared row have less to spend on
   chrome than a full-width KPI strip does, and the label is what needs the room. */
.rx-perf-cards .card{padding:15px}
.rx-perf-cards .metric{gap:11px}
.rx-perf-cards .icon{width:38px;height:38px;font-size:18px}

/* Overview charts: two SVG donuts side by side under the AI Performance cards,
   stacking on a narrow panel. The rings themselves are .svg-donut (see above). */
.rx-charts{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:22px;margin-top:22px}
.rx-chart{min-width:0;display:flex;flex-direction:column}
.rx-chart h3{margin:0 0 14px;font-size:14px;font-weight:800;color:var(--text);display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.rx-chart h3 .right-note{margin-left:auto;font-size:12px;font-weight:700;color:var(--muted)}
/* Every ring gets the SAME box whether the location has a year of calls, three, or
   none at all — a workspace with no data must not render a panel half the height of
   the one beside it, and switching locations must not move the page underneath the
   reader. 174px ring + its 18px gap + a legend that scrolls past six entries rather
   than growing the panel, so an unusually varied location cannot stretch it either. */
.rx-chart-body{flex:1 1 auto;display:flex;flex-direction:column;min-height:452px}
.rx-chart-body>.svg-donut{flex:0 0 auto}
.rx-chart-body>.mini-list{flex:0 1 auto;min-height:0;max-height:260px;overflow-y:auto;overscroll-behavior:contain}
.rx-chart-body>.empty-state{flex:1 1 auto;min-height:0}
/* .panel-fill drives its last child to flex-column so it can take the row's height.
   These two ARE that last child and must stay grids while they grow. */
.panel-fill>.rx-status,.panel-fill>.rx-charts{display:grid}
@media (max-width:900px){.rx-charts{grid-template-columns:1fr}}
@keyframes rxPulse{0%{transform:scale(1);opacity:.55}100%{transform:scale(2.6);opacity:0}}
@media (prefers-reduced-motion: reduce){.rx-dot.live::after{animation:none}}
@media(max-width:560px){.rx-status{grid-template-columns:1fr}}
.mock-phone{border:1px solid var(--line);border-radius:22px;padding:18px;background:#fff;max-width:360px;margin:auto;box-shadow:var(--shadow)}
.phone-screen{background:#f3f6fb;border-radius:18px;padding:16px;min-height:360px}
.script-box{background:#fbfcff;border:1px solid var(--line);padding:14px;border-radius:10px;color:#344054;line-height:1.5}
.kicker{text-transform:uppercase;font-size:12px;letter-spacing:.06em;color:#667085;font-weight:800}
.pill-row{display:flex;gap:8px;flex-wrap:wrap}
.pill{background:#eef2ff;color:#4f46e5;border-radius:999px;padding:7px 10px;font-size:12px;font-weight:700}
.big-number{font-size:40px;font-weight:900;margin:4px 0}
.link{color:#4f46e5;font-weight:800;text-decoration:none}
.warning-strip{display:flex;gap:12px;align-items:center;background:#fff7ed;border:1px solid #fed7aa;border-radius:13px;padding:14px;color:#9a3412}
/* --- Auth (login page + forced password change) --- */
.auth-screen{min-height:100vh;display:grid;place-items:center;background:linear-gradient(180deg,var(--navy),var(--navy2));padding:24px}
.auth-card{width:100%;max-width:404px;background:var(--card);border-radius:18px;padding:30px 30px 24px;box-shadow:0 24px 60px rgba(7,20,41,.45)}
.auth-brand{display:flex;align-items:center;gap:12px;margin-bottom:18px}
/* On the dark sidebar the title's second word is light lavender; on the white
   auth card that's nearly invisible, so darken it to the brand purple here. */
.auth-brand .brand-title span{color:var(--purple)}
.auth-title{font-size:24px;margin:6px 0 2px}
.auth-sub{margin:0 0 18px;color:var(--muted);font-size:14px}
.auth-label{display:block;font-size:13px;font-weight:700;color:#344054;margin:12px 0 6px}
.auth-input{width:100%;height:46px;border:1px solid var(--line);border-radius:10px;padding:0 14px;font-size:15px;color:var(--text);background:#fff}
.auth-input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.auth-submit{width:100%;height:46px;margin-top:20px;font-size:15px}
.auth-foot{text-align:center;color:var(--muted);font-size:12px;margin:18px 0 0}
.auth-error{background:#ffecef;border:1px solid #ffc9d2;color:#b42318;border-radius:10px;padding:10px 12px;font-size:13px;margin-bottom:6px}
.auth-warn{background:#fff3e0;border:1px solid #fdd9a8;color:#b54708;border-radius:10px;padding:10px 12px;font-size:13px;margin-bottom:6px}
/* Health banner: reuses auth-error/auth-warn palette; adds a title row + issue list. */
.health-banner{margin-bottom:12px}
.health-banner .hb-title{font-weight:700;display:flex;align-items:center;gap:8px}
.health-banner ul{margin:6px 0 0;padding-left:18px}
.health-banner li{margin:2px 0}
.health-banner li b{font-weight:700}

/* --- Account chip + dropdown menu --- */
.top-actions{position:relative}
.user-chip-btn{cursor:pointer;padding:6px 8px;border-radius:12px;user-select:none}
.user-chip-btn:hover{background:#f2f4f8}
.user-menu-pop{position:absolute;top:calc(100% + 10px);right:0;width:268px;background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);padding:8px;z-index:60}
.user-menu-head{padding:10px 10px 12px;border-bottom:1px solid var(--line);margin-bottom:6px}
.user-menu-name{font-weight:800;font-size:15px}
.user-menu-meta{color:var(--muted);font-size:12px;margin-top:3px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.user-menu-list{display:flex;flex-direction:column;gap:2px}
.user-menu-item{display:flex;align-items:center;gap:10px;width:100%;border:0;background:none;text-align:left;padding:10px;border-radius:9px;font-size:14px;font-weight:600;color:#344054;cursor:pointer}
.user-menu-item:hover{background:#f2f4f8}
.user-menu-item.danger{color:var(--red)}
.user-menu-item.danger:hover{background:#ffecef}
.user-menu-item .menu-sub{margin-left:auto;color:var(--muted);font-weight:600;font-size:12px}
.user-menu-sep{height:1px;background:var(--line);margin:6px 0}

/* --- Notifications bell dropdown (matches the account menu; OmniCare tokens) --- */
.notif-pop{position:absolute;top:calc(100% + 10px);right:0;width:360px;max-width:calc(100vw - 32px);background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);z-index:60;overflow:hidden}
.notif-head{display:flex;align-items:center;justify-content:space-between;padding:12px 14px;border-bottom:1px solid var(--line)}
.notif-head-title{font-weight:800;font-size:15px}
.notif-head-actions{display:flex;align-items:center;gap:2px}
.notif-scope{display:flex;align-items:center;gap:6px;padding:8px 14px;border-bottom:1px solid var(--line);font-size:12px;font-weight:600;color:var(--muted)}
.notif-readall{border:0;background:none;color:var(--purple);font-weight:700;font-size:12px;cursor:pointer;padding:4px 6px;border-radius:7px}
.notif-readall:hover{background:#f2f4f8}
.notif-clearall{border:0;background:none;color:var(--muted);font-weight:700;font-size:12px;cursor:pointer;padding:4px 6px;border-radius:7px}
.notif-clearall:hover{background:#fdecef;color:#b42318}
.notif-readall:disabled,.notif-clearall:disabled{opacity:.4;pointer-events:none}
.notif-list{max-height:420px;overflow-y:auto}
.notif-empty{padding:34px 16px;text-align:center;color:var(--muted);font-size:13px}
.notif-item{display:flex;gap:11px;align-items:flex-start;padding:12px 14px 12px 18px;border-bottom:1px solid var(--line);cursor:pointer;position:relative}
.notif-item:last-child{border-bottom:0}
.notif-item:hover{background:#f7f8fb}
.notif-item.unread{background:#f5f4ff}
.notif-item.unread:hover{background:#efeefe}
.notif-item.unread::before{content:"";position:absolute;left:6px;top:19px;width:6px;height:6px;border-radius:50%;background:var(--purple)}
.notif-ic{flex:0 0 32px;width:32px;height:32px;border-radius:9px;display:grid;place-items:center;font-size:15px;background:#edf4ff;border:1px solid #bcd5fb}
.notif-sev-info{background:#edf4ff;border-color:#bcd5fb}
.notif-sev-success{background:#e7f7ee;border-color:#abe0c2}
.notif-sev-warning{background:#fff4e6;border-color:#fed7aa}
.notif-sev-critical{background:#ffecef;border-color:#fdc9d2}
.notif-main{min-width:0;flex:1}
.notif-title{font-weight:700;font-size:13.5px;color:var(--text);line-height:1.3}
.notif-text{color:var(--muted);font-size:12.5px;margin-top:2px;line-height:1.4;white-space:pre-wrap;overflow-wrap:anywhere}
.notif-time{color:#98a2b3;font-size:11px;margin-top:5px}
.notif-x{flex:0 0 auto;border:0;background:none;color:#98a2b3;font-size:18px;line-height:1;cursor:pointer;padding:2px 5px;border-radius:7px;opacity:0;transition:opacity .1s}
.notif-item:hover .notif-x{opacity:1}
.notif-x:hover{background:#eceff3;color:#475467}

/* --- UI confirm modal (replaces window.confirm; shared tenant + platform) --- */
.oc-confirm-overlay{position:fixed;inset:0;z-index:200;background:rgba(7,20,41,.45);display:grid;place-items:center;padding:24px;animation:ocConfirmFade .12s ease-out}
.oc-confirm-box{width:100%;max-width:420px;background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:0 24px 60px rgba(7,20,41,.45);padding:24px}
.oc-confirm-title{margin:0 0 8px;font-size:17px;font-weight:800;color:var(--text)}
.oc-confirm-msg{margin:0 0 22px;color:var(--muted);font-size:14px;line-height:1.5}
.oc-confirm-actions{display:flex;justify-content:flex-end;gap:10px}
/* Optional opt-in checkbox inside a confirm dialog (e.g. "copy live data"). */
.oc-confirm-check{display:flex;gap:10px;align-items:flex-start;margin:-8px 0 22px;padding:12px 14px;background:var(--bg);border:1px solid var(--line);border-radius:10px;cursor:pointer;font-size:14px;color:var(--text)}
.oc-confirm-check input{margin-top:2px;flex:none;width:16px;height:16px;cursor:pointer}
.oc-confirm-check-hint{display:block;margin-top:4px;color:var(--muted);font-size:12.5px;line-height:1.45}
.oc-confirm-check.is-disabled{cursor:default;opacity:.55}
.oc-confirm-check.is-disabled input{cursor:default}
/* Optional text input / dropdown inside a confirm dialog (e.g. a group name, or a
   workspace picker for Link Workspace). */
.oc-confirm-input{display:block;margin:0 0 16px}
.oc-confirm-input:first-of-type{margin-top:-8px}
.oc-confirm-input-label{display:block;margin-bottom:6px;font-size:13px;font-weight:700;color:var(--text)}
.oc-confirm-input input,.oc-confirm-input select{width:100%;height:42px;border:1px solid var(--line);border-radius:10px;background:#fff;padding:0 14px;color:var(--text);font-size:14px}
.oc-confirm-input input:focus,.oc-confirm-input select:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
@keyframes ocConfirmFade{from{opacity:0}to{opacity:1}}

/* Call Logs — call detail popup. Above page content and the nav popovers, but BELOW
   .oc-confirm-overlay (200) so a confirm raised from inside it still layers over. */
.cl-modal-overlay{position:fixed;inset:0;z-index:150;background:rgba(7,20,41,.45);display:grid;place-items:center;padding:24px;animation:ocConfirmFade .12s ease-out}
.cl-modal-box{position:relative;width:100%;max-width:720px;max-height:calc(100vh - 48px);overflow-y:auto;background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:0 24px 60px rgba(7,20,41,.45);padding:24px}
.cl-modal-box h2{margin-top:0;padding-right:32px}
.cl-modal-close{position:absolute;top:12px;right:12px;border:0;background:transparent;color:var(--muted);font-size:24px;line-height:1;cursor:pointer;padding:2px 8px;border-radius:8px}
.cl-modal-close:hover{background:var(--bg);color:var(--text)}

/* --- Role badge (tinted: light bg, dark text, thin same-color border) --- */
.role-badge{display:inline-flex;align-items:center;border-radius:999px;padding:3px 9px;font-size:11px;font-weight:800;background:#edf4ff;color:#175cd3;border:1px solid #bcd5fb}
.role-badge.admin{background:#f0ecff;color:#5e3eca;border-color:#d6caff}
/* Ghost = a Quantum Connect platform admin acting inside a tenant (amber, deliberately not the
   admin purple) so the operator always knows they're in someone else's workspace. */
.role-badge.ghost{background:#fff4e6;color:#b54708;border-color:#fed7aa}

/* --- Users page bits --- */
.online-dot{display:inline-block;width:9px;height:9px;border-radius:50%;background:var(--green);vertical-align:middle}
.row-actions{display:flex;gap:6px;flex-wrap:wrap}
.btn.sm{height:32px;padding:0 10px;font-size:12px;font-weight:700}

/* --- Audit log page --- */
.audit-sub{font-size:12px;color:var(--muted,#667085)}
.audit-flabel{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:#475467}
.audit-flabel input{height:36px}
.audit-detail{margin-top:4px}
.audit-detail summary{cursor:pointer;font-size:12px;font-weight:600;color:#175cd3;list-style:none}
.audit-detail summary::-webkit-details-marker{display:none}
.audit-detail pre{margin:6px 0 0;padding:10px;background:#f7f8fb;border:1px solid #eaecf0;border-radius:8px;font-size:12px;white-space:pre-wrap;word-break:break-word}
/* Inline field-level diffs in the data-change audit (old → new per field). */
.audit-changes{display:flex;flex-direction:column;gap:4px}
.audit-diff{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;font-size:13px}
.audit-diff-k{font-weight:700;color:#475467;min-width:96px}
.audit-diff-arrow{color:#98a2b3}
.audit-diff .diff-old{color:#b42318;text-decoration:line-through}
.audit-diff .diff-new{color:#087443;font-weight:700}
/* Fixed column widths so the layout stays put when a row's Raw detail expands.

   Anchored from the RIGHT (nth-last-child) because of the MODE, not the tab. The
   left edge is what moves: "All locations" PREPENDS a Workspace column, so that
   table is six columns starting at Workspace while a single location is five
   starting at Time. Counting from the front pinned Time's 160px onto Workspace and
   slid every other width one column right, squeezing the tail of the row; counting
   from the end pins the same column in either mode.

   The two tabs that render into #audit-panel do NOT differ on the left — they agree
   on the first column and the last, and differ in the MIDDLE (pages/audit.js, the
   `headers` arrays in renderAudit ~line 207 and renderRecords ~line 487):
     Security     Time · Event  · User · IP     · Details
     Data changes Time · Action · User · Record · Details
   Same column COUNT and the same positional roles — timestamp, badge, user, short
   value, free text — which is why one set of widths serves both tabs and why the
   per-column notes below name each tab's pair rather than one tab's column. Details
   is last in both and absorbs the remainder, so it is the one column with no width
   here. Adding a column to ONE tab breaks that: the widths would land on different
   things in each, so both header arrays have to stay the same length. */
/* Any table given {cols:[...]} scrolls inside its own box. The widths are a floor, so
   without this the table would push the page body sideways at any viewport narrower
   than their sum. Kept out of the mobile block on purpose — the overflow it prevents
   is a DESKTOP one (the all-locations audit table needs ~810px of pinned columns and
   the content area is under that from roughly 800px to 1200px). */
#audit-panel .table{table-layout:fixed}
/* …and a floor under the table so the one column WITHOUT a pinned width still gets a
   column. Fixed layout hands Details whatever is left after the pinned widths, which is
   exactly ZERO until the table box exceeds their sum — and a zero-width cell does not
   clip, it wraps one word per line, so every row grew to ~760px tall anywhere between
   roughly 800px and 1250px of viewport. Floor = pinned sum + 320px of readable Details;
   the wrapper above absorbs the difference, and width:100% still takes over past the
   floor so wide screens are unaffected. Selected by column COUNT because the two tabs
   pin different totals: 6 cols = all-locations (810px), 5 = single location (660px). */
#audit-panel .table:has(colgroup col:nth-child(6)){min-width:1130px}
#audit-panel .table:has(colgroup col:nth-child(5)):not(:has(colgroup col:nth-child(6))){min-width:980px}
/* Column widths now travel with the header arrays in pages/audit.js as a <colgroup>,
   not as nth-last-child rules counted from the right edge. The two tabs no longer have
   to keep identical column counts to avoid reassigning each other's widths. */
#audit-panel .table td{vertical-align:top;word-break:break-word}
/* .pt-ws is nowrap where it was born (the Patients grid); inside a pinned column a
   long workspace name would spill across the next one, so let the chip wrap here. */
#audit-panel .table .pt-ws{white-space:normal}

/* ---- Patients page ---- */
.pt-table th.pt-sort{cursor:pointer;user-select:none;white-space:nowrap}
.pt-table th.pt-sort:hover{color:var(--purple)}
.pt-table th.pt-sort.active{color:var(--purple)}
.pt-table th.pt-sort:focus-visible{outline:2px solid var(--purple);outline-offset:-2px}
.pt-table th .pt-sort-ind{display:inline-block;width:12px;margin-left:4px;font-size:10px;vertical-align:middle}
.pt-table tbody tr{cursor:pointer}
.pt-table tbody tr:hover{background:#fafbff}
.pt-table tbody tr.sel{background:#f0ecff}
.pt-table tbody tr.sel td{border-bottom-color:#e0d8ff}
/* Workspace chip in the combined "All locations" patient view (tinted badge). */
.pt-ws{display:inline-block;padding:1px 8px;border-radius:10px;font-size:12px;font-weight:600;
  background:#f0ecff;color:var(--purple);border:1px solid #e0d8ff;white-space:nowrap}

/* ---- Campaigns page ---- */
/* Generic sortable table header. Applied by helpers.js makeSortable() to every
   <table class="sortable"> app-wide (audit log, call logs, reports, users,
   uploads, knowledge, escalations, …), and used directly by Campaigns. */
table.sortable thead th{cursor:pointer}
.th-sort{cursor:pointer;user-select:none;white-space:nowrap}
.th-sort:hover{color:var(--purple)}
.th-sort.active{color:var(--purple)}
.th-sort:focus-visible{outline:2px solid var(--purple);outline-offset:-2px}
.th-sort-ind{display:inline-block;width:12px;margin-left:4px;font-size:10px;vertical-align:middle}
#cm-list tbody tr{cursor:pointer}
#cm-list tbody tr:hover{background:#fafbff}
#cm-list tbody tr.sel{background:#f0ecff}
#cm-list tbody tr.sel td{border-bottom-color:#e0d8ff}
.cm-ch span{margin-right:2px}
.cm-chans{display:flex;gap:16px;flex-wrap:wrap;margin-top:6px}
.cm-chk{display:inline-flex;align-items:center;gap:6px;font-weight:600;cursor:pointer}
.cm-chk input{width:auto;margin:0}
/* Dynamic audience builder (campaign targeting) */
.aud-label{font-size:12px;font-weight:700;color:#344054;margin-bottom:6px}
.aud-builder{border:1px solid var(--line);border-radius:10px;padding:12px;background:#fff}
.aud-match{font-size:13px;font-weight:600;color:#344054;margin-bottom:10px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.aud-empty{margin:2px 0 4px}
.aud-row{display:flex;gap:8px;align-items:center;margin-bottom:8px;flex-wrap:wrap}
.aud-row select,.aud-row input{height:38px;border:1px solid var(--line);border-radius:9px;background:#fff;padding:0 12px;font-size:14px;color:var(--text);font-weight:500}
.aud-row select:focus,.aud-row input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.aud-field{min-width:160px}
.aud-op{min-width:140px}
.aud-vals{display:flex;align-items:center;gap:6px;flex:1;flex-wrap:wrap;min-width:160px}
.aud-vals .aud-v{flex:1;min-width:120px}
.aud-pre{color:var(--muted);font-weight:700;margin-right:-2px}
.aud-and{color:var(--muted);font-size:13px}
.aud-enum{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
.aud-ck{display:inline-flex;align-items:center;gap:6px;font-weight:600;font-size:13px;cursor:pointer;color:#344054}
.aud-ck input{width:auto;height:auto;margin:0;padding:0;box-shadow:none}
.aud-rm{flex:0 0 auto;width:34px;height:34px;border:1px solid var(--line);background:#fff;border-radius:8px;color:var(--muted);cursor:pointer;font-size:14px;line-height:1}
.aud-rm:hover{border-color:#f0a0a0;color:#d64545;background:#fdf3f3}
.aud-foot{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:4px}
.aud-count{font-size:13px;font-weight:600;color:var(--text)}
@media(max-width:700px){.aud-field,.aud-op{min-width:0;flex:1}}
/* Campaign schedule builder */
.sched-builder{border:1px solid var(--line);border-radius:10px;padding:12px;background:#fff}
.sched-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px 16px}
.sched-grid label{display:flex;flex-direction:column;gap:6px;font-size:12px;font-weight:700;color:#344054}
.sched-grid input{height:38px;border:1px solid var(--line);border-radius:9px;background:#fff;padding:0 12px;font-size:14px;color:var(--text);font-weight:500}
.sched-grid input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.sched-win{display:flex;align-items:center;gap:8px}
.sched-win input{flex:1;min-width:0}
.sched-cooldown{display:flex;align-items:center;gap:8px;font-weight:600;font-size:13px;color:#344054}
.sched-cooldown input{width:80px;flex:0 0 auto}
.sched-days{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:12px}
.sched-days-lbl{font-size:12px;font-weight:700;color:#344054}
.sched-legal{margin:12px 0 0;line-height:1.5}
@media(max-width:700px){.sched-grid{grid-template-columns:1fr}}
.pt-notes{white-space:pre-wrap}
.pt-form{margin-bottom:16px}
.pt-form-title{font-weight:800;font-size:15px;margin-bottom:12px}
.pt-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px 16px}
.pt-form-grid label{display:flex;flex-direction:column;gap:6px;font-size:12px;font-weight:700;color:#344054}
.pt-form-grid .pt-wide{grid-column:1 / -1}
.pt-form-grid input,.pt-form-grid select{height:40px;border:1px solid var(--line);border-radius:9px;background:#fff;padding:0 12px;font-size:14px;color:var(--text);font-weight:500}
.pt-form-grid input:focus,.pt-form-grid select:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
@media(max-width:700px){.pt-form-grid{grid-template-columns:1fr}}

/* ---- Patients: list ---- */
/* The list is full width now (no detail rail), so a workspace with many columns can
   scroll sideways inside the panel instead of stretching the page. */
.pt-table-wrap{overflow-x:auto}
.pt-mono{font-variant-numeric:tabular-nums;letter-spacing:.02em}
.pt-dash{color:#98a2b3}
.pt-num{text-align:right;font-variant-numeric:tabular-nums}
.pt-cell-name{font-weight:700}
.pt-cell-bal{font-weight:700;font-variant-numeric:tabular-nums}
.pt-head-actions{display:flex;gap:8px;align-items:center}
.pt-filterbar{flex-wrap:wrap}
.pt-sortbar{display:inline-flex;align-items:center;gap:8px;margin-left:auto}
.pt-hint{margin:-6px 0 12px}
.pt-more{margin-top:12px}

/* ---- Patients: one record ---- */
.pt-rec-bar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:14px;flex-wrap:wrap}
.pt-pager{display:inline-flex;align-items:center;gap:10px}
.pt-rec-head{padding-bottom:8px}
.pt-rec-top{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;flex-wrap:wrap}
.pt-rec-id{display:flex;align-items:center;gap:16px;min-width:0}
.pt-rec-name{font-size:26px;font-weight:800;margin:0 0 8px;line-height:1.15;word-break:break-word}
.pt-rec-chips{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pt-rec-acct{margin-top:8px}
.pt-rec-money{text-align:right;flex:0 0 auto}
.pt-rec-bal{font-size:30px;font-weight:800;font-variant-numeric:tabular-nums;line-height:1.1;margin-top:2px}
.pt-rec-actions{justify-content:flex-end;margin-top:12px}

/* Fact grid: the at-a-glance identity block under the header. Auto-fit so it reflows
   from four columns to one without a breakpoint per width. */
.pt-facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:14px 24px;
  margin-top:20px;padding-top:18px;border-top:1px solid var(--line)}
.pt-fact{min-width:0}
.pt-fact-wide{grid-column:span 2}
.pt-fact-k{display:block;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.pt-fact-v{display:block;margin-top:3px;font-size:14px;font-weight:600;color:var(--text);word-break:break-word}
@media(max-width:760px){.pt-fact-wide{grid-column:span 1}.pt-rec-money{text-align:left}.pt-rec-actions{justify-content:flex-start}}

/* Additional phones & addresses (record Overview side panel). Two labelled groups of
   rows, each with a Remove and an inline add form that toggles open in place. */
.pt-contacts h2{margin-bottom:2px}
.pt-contact-group{margin-top:16px}
.pt-contact-group:first-of-type{margin-top:8px}
.pt-contact-h{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);margin:0 0 6px}
.pt-contact-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 0;border-bottom:1px solid var(--line)}
.pt-contact-row:last-of-type{border-bottom:0}
.pt-contact-main{min-width:0;display:flex;flex-direction:column;gap:2px}
.pt-contact-main b{font-size:14px;font-weight:600;color:var(--text);word-break:break-word}
.pt-contact-empty{margin:2px 0 0}
.pt-contact-add{display:flex;flex-direction:column;gap:8px;margin-top:10px;padding:12px;border:1px dashed var(--line);border-radius:10px;background:var(--bg)}
.pt-contact-add input{height:38px;border:1px solid var(--line);border-radius:8px;background:#fff;padding:0 11px;font-size:14px;color:var(--text);font-weight:500}
.pt-contact-add input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.pt-contact-city{display:grid;grid-template-columns:1fr .5fr .7fr;gap:8px}
.pt-contacts>.btn.sm,.pt-contact-group>.btn.sm{margin-top:10px}

.pt-rec-tabs{margin:22px 0 18px}
/* Count bubble on a tab, so "3 calls" is visible without opening the tab. */
.pt-tab-n{display:inline-block;min-width:18px;padding:0 5px;margin-left:6px;border-radius:9px;
  background:color-mix(in srgb, var(--purple) 12%, #fff);color:var(--purple);
  font-size:11px;font-weight:800;text-align:center;vertical-align:1px}
.pt-rec-grid{align-items:start}
@media(max-width:1100px){.pt-rec-grid{grid-template-columns:1fr}}

/* ---- Timeline (Overview) ---- */
.pt-timeline{display:flex;flex-direction:column}
.pt-tl-item{display:grid;grid-template-columns:34px 1fr;gap:12px;padding:12px 0;border-bottom:1px solid var(--line)}
.pt-tl-item:last-child{border-bottom:0;padding-bottom:0}
.pt-tl-dot{width:30px;height:30px;border-radius:50%;display:grid;place-items:center;font-size:14px;
  background:var(--bg);border:1px solid var(--line)}
.pt-tl-call .pt-tl-dot{background:color-mix(in srgb, var(--purple) 10%, #fff);border-color:color-mix(in srgb, var(--purple) 22%, #fff)}
.pt-tl-msg .pt-tl-dot{background:color-mix(in srgb, var(--blue) 10%, #fff);border-color:color-mix(in srgb, var(--blue) 22%, #fff)}
.pt-tl-body{min-width:0}
.pt-tl-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap}
.pt-tl-text{margin-top:4px;font-size:13px;color:#344054;line-height:1.5;white-space:pre-wrap;word-break:break-word}

/* ---- Charges ---- */
.pt-charge-total{display:flex;align-items:center;gap:24px;margin-bottom:8px}
.pt-charge-sum{font-size:18px;font-variant-numeric:tabular-nums}

/* ---- Calls ---- */
.pt-calls{display:flex;flex-direction:column;gap:12px}
.pt-call{border:1px solid var(--line);border-radius:12px;padding:14px;background:var(--card)}
.pt-call.open{border-color:color-mix(in srgb, var(--purple) 35%, #fff);box-shadow:var(--shadow)}
.pt-call-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.pt-call-when{display:flex;align-items:baseline;gap:8px}
.pt-call-badges{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.pt-call-summary{margin:8px 0 10px;font-size:13px;color:#344054;line-height:1.55;white-space:pre-wrap}
.pt-call-detail{margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
.pt-dh{font-size:11px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);margin:12px 0 6px}
.pt-dh:first-child{margin-top:0}
.pt-kv{width:100%;border-collapse:collapse;font-size:13px}
.pt-kv td{padding:5px 0;border-bottom:1px solid var(--line);vertical-align:top}
.pt-kv td:first-child{width:38%;color:var(--muted);font-weight:600;padding-right:12px}
.pt-kv tr:last-child td{border-bottom:0}
.pt-audio{width:100%;margin-bottom:4px}
.pt-transcript{max-height:360px;overflow-y:auto;border:1px solid var(--line);border-radius:10px;
  background:var(--bg);padding:12px;display:flex;flex-direction:column;gap:10px}
.pt-turn{font-size:13px;line-height:1.5}
.pt-turn-who{font-size:11px;font-weight:800;letter-spacing:.03em;text-transform:uppercase;color:var(--muted)}
.pt-turn.ai .pt-turn-who{color:var(--purple)}
.pt-turn-text{margin-top:2px;color:#344054;white-space:pre-wrap;word-break:break-word}

/* ---- Texts & Email (read-only history) ---- */
.pt-thread{display:flex;flex-direction:column;gap:14px;max-height:520px;overflow-y:auto;padding:4px 2px}
.pt-msg{display:flex;flex-direction:column;align-items:flex-start;max-width:min(560px,80%)}
.pt-msg.out{align-self:flex-end;align-items:flex-end}
.pt-msg-bubble{padding:10px 14px;border-radius:14px;background:var(--bg);border:1px solid var(--line);
  font-size:13px;line-height:1.5;color:var(--text)}
.pt-msg.out .pt-msg-bubble{background:color-mix(in srgb, var(--purple) 10%, #fff);
  border-color:color-mix(in srgb, var(--purple) 22%, #fff)}
.pt-msg-subject{font-weight:800;margin-bottom:4px}
.pt-msg-text{white-space:pre-wrap;word-break:break-word}
.pt-msg-meta{margin-top:4px}

/* ---- Activity ---- */
.pt-acts{display:flex;flex-direction:column}
.pt-act{display:flex;align-items:baseline;justify-content:space-between;gap:16px;flex-wrap:wrap;
  padding:10px 0;border-bottom:1px solid var(--line)}
.pt-act:last-child{border-bottom:0}
.pt-act-main{min-width:0}

/* ---- Activity: staff-authored notes log ---- */
.pt-note-new{display:flex;flex-direction:column;gap:8px;margin-bottom:16px}
.pt-note-new textarea,.pt-note-editing textarea{width:100%;box-sizing:border-box;border:1px solid var(--line);
  border-radius:9px;background:#fff;padding:9px 11px;font:inherit;font-size:14px;color:var(--text);
  line-height:1.5;resize:vertical;min-height:64px}
.pt-note-new textarea:focus,.pt-note-editing textarea:focus{outline:none;border-color:var(--blue);
  box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.pt-note-list{display:flex;flex-direction:column}
.pt-note{padding:12px 0;border-bottom:1px solid var(--line)}
.pt-note:last-child{border-bottom:0}
.pt-note-editing{padding:12px;border:1px dashed var(--line);border-radius:10px;background:var(--bg);
  margin:12px 0;display:flex;flex-direction:column;gap:8px}
.pt-note-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap}
.pt-note-who{min-width:0}
.pt-note-actions{display:flex;gap:6px;flex-wrap:wrap;flex:0 0 auto}
.pt-note-body{margin-top:5px;font-size:13px;color:#344054;line-height:1.55;white-space:pre-wrap;word-break:break-word}
.pt-note-empty{margin:4px 0 0}

/* ---- Verification PIN (admin only) ---- */
.pt-pin{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:16px;font-weight:700;
  letter-spacing:.14em;margin-right:10px}
.pt-pin-row{display:flex;gap:8px;align-items:center}
.pt-pin-row input{flex:1;min-width:0}

/* ---- Upload page ---- */
.upload-zone.drag{border-color:var(--blue);background:#f0f5ff}
.up-controls{display:flex;gap:12px;align-items:center;justify-content:center;flex-wrap:wrap;margin-top:8px}
.up-cat{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:700;color:#344054}
.up-cat[hidden]{display:none}
.up-cat select{height:40px;border:1px solid var(--line);border-radius:9px;background:#fff;padding:0 12px;font-weight:600;color:var(--text)}
.up-actions{display:inline-flex;gap:12px;font-size:16px}
.up-actions a{text-decoration:none}
/* A file row is the handle for that file's dialog — the whole row, because the
   question people arrive with is “what IS this one?” and a 16px arrow is a poor
   target for it. The name is also a real link, so the same thing is reachable
   with a keyboard and reads as clickable without a hover. */
.table tbody tr.is-clickable{cursor:pointer}
.table tbody tr.is-clickable:hover{background:#fafbff}
.up-name{color:var(--text);font-weight:700;text-decoration:none}
.up-name:hover{color:var(--blue);text-decoration:underline}
.up-actions a.danger-link{filter:grayscale(.1)}

/* Storage meter (Files sidebar). NOT .meter — that track is a white wash built for the
   dark sidebar plan card and disappears on a white panel. One block per pool; the bar
   is segmented by category and its pieces are shares of the ALLOWANCE, so the free
   space at the right of the track is the point of the picture. */
.st-pool{margin-top:16px}
.st-pool:first-of-type{margin-top:12px}
.st-pool-head{display:flex;justify-content:space-between;align-items:baseline;gap:10px;font-size:12px}
.st-pool-head span{font-weight:700;color:var(--text)}
.st-pool-head strong{font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums}
.st-legend{display:flex;flex-wrap:wrap;gap:4px 12px;margin:8px 0 7px;font-size:11px;color:var(--muted)}
.st-key{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
.st-key i{width:8px;height:8px;border-radius:2px;flex:none}
.st-key b{color:var(--text);font-weight:700;font-variant-numeric:tabular-nums}
.st-none{font-style:italic}
.st-bar{display:flex;height:9px;border-radius:999px;background:var(--line);overflow:hidden}
/* flex:none + a floor, so a category that rounds to 0.02% is still a visible sliver
   rather than a legend entry pointing at nothing. */
.st-bar span{display:block;height:100%;flex:none;min-width:3px}
.st-bar span+span{box-shadow:inset 1px 0 0 var(--card)}
/* The row's ⋯ trigger — one definition, both file lists (Files and Knowledge Base),
   rendered by ocRowMenuBtn so the two can't drift. A square target rather than a bare
   glyph: it is the only control left in the column now that Download lives inside the
   menu, so it has to look pressable before the pointer arrives. It stays lit while its
   menu is open, so the row you are acting on is obvious behind the list. */
.row-menu{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;
  padding:0;border:1px solid transparent;border-radius:9px;background:transparent;
  color:var(--muted);font-size:18px;line-height:1;cursor:pointer;
  transition:background .12s,color .12s,border-color .12s}
.row-menu:hover,.row-menu[aria-expanded="true"]{background:color-mix(in srgb,var(--blue) 12%,#fff);
  border-color:color-mix(in srgb,var(--blue) 28%,#fff);color:var(--blue)}
.row-menu:focus-visible{outline:2px solid var(--blue);outline-offset:1px}
/* Field mapping list (read-only view) */
.map-list{display:flex;flex-direction:column;gap:2px;margin-top:8px}
.map-row{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:8px;padding:6px 0;border-bottom:1px solid var(--line);font-size:13px}
.map-row:last-child{border-bottom:none}
.map-target{font-weight:700;color:#344054}.map-target em{color:var(--red);font-style:normal}
.map-arrow{color:#98a2b3}
.map-source{color:var(--text)}
/* Field mapping editor (request / Quantum Connect edit) */
.map-edit-list{display:flex;flex-direction:column;gap:8px;margin-top:8px}
.map-edit-row{display:grid;grid-template-columns:160px 1fr;align-items:center;gap:10px;font-size:13px;font-weight:700;color:#344054}
.map-edit-row em{color:var(--red);font-style:normal}
.map-edit-row input{height:38px;border:1px solid var(--line);border-radius:9px;background:#fff;padding:0 12px;font-weight:500;color:var(--text)}
.map-edit-row input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
/* Before/after diff */
.diff-table{margin-top:10px}
.diff-table td.diff-from{color:#b42318;text-decoration:line-through}
.diff-table td.diff-to{color:#087443;font-weight:700}
.req-card{margin-bottom:14px}
@media(max-width:700px){.map-edit-row{grid-template-columns:1fr}}

/* Little ⓘ info bubble (native title tooltip) */
.info-i{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border-radius:50%;
  background:#cbd5e1;color:#fff;font-size:10px;font-weight:700;font-style:normal;line-height:1;cursor:help;
  margin-left:5px;vertical-align:middle;user-select:none}
.info-i:hover{background:var(--blue)}

/* Parse settings bar (delimiter + end-of-record) above the mapping sheet */
.map-settings{display:flex;flex-wrap:wrap;gap:16px;align-items:flex-end;margin:4px 0 14px;padding:12px 14px;
  background:#fbfcff;border:1px solid var(--line);border-radius:10px}
.map-set{display:flex;flex-direction:column;gap:5px;font-size:12px;font-weight:700;color:#344054}
.map-set>span{display:inline-flex;align-items:center}
.map-set select,.map-set input{height:34px;border:1px solid var(--line);border-radius:8px;background:#fff;
  padding:0 9px;font-size:13px;font-weight:500;color:var(--text);min-width:150px}
.map-set select:focus,.map-set input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.map-set.hint-note{font-weight:500;color:#667085;max-width:280px;align-self:center}

/* Wide spreadsheet editor: one column per patient field, one editable cell row */
.map-sheet-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:10px;margin-top:2px}
.map-sheet{border-collapse:separate;border-spacing:0;width:100%}
.map-sheet th{background:#f4f6fb;border-bottom:1px solid var(--line);border-right:1px solid var(--line);
  padding:9px 11px;font-size:12px;font-weight:700;color:#344054;text-align:left;white-space:nowrap}
.map-sheet th em{color:var(--red);font-style:normal;margin-left:1px}
.map-sheet td{border-right:1px solid var(--line);padding:0}
.map-sheet th:last-child,.map-sheet td:last-child{border-right:none}
.map-sheet input{width:100%;min-width:160px;height:42px;border:0;background:#fff;padding:0 11px;
  font-size:13px;color:var(--text);box-sizing:border-box}
.map-sheet input:focus{outline:none;background:#f0f5ff;box-shadow:inset 0 0 0 2px var(--blue)}
.map-sheet input::placeholder{color:#b0b8c4}

/* Column-management controls in the Quantum Connect mapping editor (add/hide/delete). */
.map-sheet th .col-head{display:flex;align-items:center;gap:5px}
.col-tag{font-weight:700;font-size:9px;letter-spacing:.04em;text-transform:uppercase;color:#6b46d6;
  background:#efeafe;border:1px solid #d9ccfb;border-radius:5px;padding:1px 4px}
.col-ctrls{display:flex;gap:5px;margin-top:6px}
.col-ctrl{border:1px solid var(--line);background:#fff;color:#475467;border-radius:6px;
  padding:2px 7px;font-size:11px;font-weight:700;cursor:pointer;line-height:1.6}
.col-ctrl:hover{background:#f4f6fb;color:#1d2939}
.col-ctrl.danger{color:var(--red);border-color:#f3c6c6}
.col-ctrl.danger:hover{background:#fdeaea}
/* Hidden columns stay in the sheet but are greyed out in place. */
.col-tag.muted-tag{color:#667085;background:#eef1f6;border-color:#dde2ea}
.map-sheet th.col-hidden{background:#f0f1f4;color:#98a2b3}
.map-sheet th.col-hidden .col-head{opacity:.6}
.map-sheet td.col-hidden{background:#f6f7f9}
.map-sheet td.col-hidden input{background:#f6f7f9;color:#98a2b3;cursor:not-allowed}

/* Drag-to-reorder columns (mapping editor) — modern grip + ghost + glow line. */
.map-sheet th .col-head .col-name{display:inline-flex;align-items:center}
.col-grip{display:inline-flex;align-items:center;margin-right:5px;color:#c0c6d2;font-size:14px;
  line-height:1;letter-spacing:-1px;cursor:grab;transition:color .15s,transform .15s}
.map-sheet th.col-draggable{transition:background .15s}
.map-sheet th.col-draggable .col-head{cursor:grab;touch-action:none}
.map-sheet th.col-draggable:hover{background:#eef2fb}
.map-sheet th.col-draggable:hover .col-grip{color:var(--blue);transform:scale(1.12)}
.map-sheet [data-key].col-dragging{opacity:.32;transition:opacity .12s}
body.col-drag-active,body.col-drag-active *{cursor:grabbing !important;user-select:none}
.col-drag-ghost{position:fixed;z-index:300;pointer-events:none;display:inline-flex;align-items:center;gap:7px;
  transform:translate(12px,-50%) rotate(-2.5deg);background:var(--card);border:1px solid var(--blue);border-radius:10px;
  padding:7px 13px;font-size:12px;font-weight:800;color:var(--text);white-space:nowrap;
  box-shadow:0 14px 34px rgba(37,99,235,.30),0 0 0 4px rgba(37,99,235,.10)}
.col-drag-ghost .col-grip{color:var(--blue);margin:0}
.col-drop-line{position:fixed;z-index:299;width:3px;border-radius:3px;pointer-events:none;
  background:linear-gradient(180deg,var(--blue),var(--purple));
  box-shadow:0 0 0 1px rgba(37,99,235,.25),0 0 14px 2px rgba(109,77,252,.55);
  animation:colDropPulse .9s ease-in-out infinite}
.col-drop-line::before{content:"";position:absolute;top:-5px;left:50%;width:11px;height:11px;
  transform:translateX(-50%) rotate(45deg);border-radius:3px;background:var(--blue);
  box-shadow:0 0 10px 1px rgba(37,99,235,.7)}
@keyframes colDropPulse{0%,100%{opacity:.85}50%{opacity:1}}
.addcol-row{margin-top:14px}
.addcol-form{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.addcol-form input{height:36px;border:1px solid var(--line);border-radius:8px;padding:0 12px;font-size:13px;min-width:240px}

/* Platform console tab strip (Overview / Workspaces). */
.plat-tabs{display:flex;gap:6px;margin-bottom:18px;border-bottom:1px solid var(--line)}
.plat-tab{background:none;border:0;border-bottom:2px solid transparent;padding:10px 14px;margin-bottom:-1px;
  font-weight:700;font-size:14px;color:#667085;cursor:pointer}
.plat-tab.active{color:#4f46e5;border-bottom-color:#4f46e5}
.plat-tab:hover{color:#344054}

/* "Viewing as a workspace" banner (platform admin impersonation, read-only). */
.imp-banner{display:flex;align-items:center;justify-content:space-between;gap:16px;
  background:linear-gradient(90deg,#3b2f8f,#5b46d6);color:#fff;padding:9px 22px;font-weight:700;font-size:14px;flex:0 0 auto}
.imp-banner .imp-msg{display:flex;align-items:center;gap:8px}
.imp-banner .imp-msg b{font-weight:800}
.imp-banner .imp-actions{display:flex;align-items:center;gap:10px}
.imp-banner .imp-switch{height:32px;border:1px solid rgba(255,255,255,.55);background:rgba(255,255,255,.12);
  color:#fff;border-radius:8px;padding:0 10px;font-weight:700;cursor:pointer;max-width:220px}
.imp-banner .imp-switch option{color:#101828;background:#fff} /* readable in the OS dropdown */
.imp-banner .imp-exit{height:32px;border:1px solid rgba(255,255,255,.55);background:rgba(255,255,255,.12);
  color:#fff;border-radius:8px;padding:0 14px;font-weight:800;cursor:pointer}
.imp-banner .imp-exit:hover{background:rgba(255,255,255,.22)}

/* Test-workspace banner — shown to a test tenant's OWN users (amber, distinct
   from the purple ghost banner). Hosts the Testing Center on the right. */
.test-banner{display:flex;align-items:center;justify-content:space-between;gap:16px;
  background:linear-gradient(90deg,#b45309,#ea7a0c);color:#fff;padding:9px 22px;font-weight:700;font-size:14px;flex:0 0 auto}
.test-banner .test-msg{display:flex;align-items:center;gap:8px}
.test-banner .test-msg b{font-weight:800}
.test-banner .test-actions{display:flex;align-items:center;gap:10px}

/* Past-due billing banner (customer-facing). grace = amber heads-up (nothing paused,
   dismissible); restricted = red "outbound paused" notice (persistent). Semantic status
   colors, hardcoded like the impersonation/test bars above — not the brand palette. */
.bill-banner{display:flex;align-items:center;justify-content:space-between;gap:16px;
  color:#fff;padding:9px 22px;font-weight:700;font-size:14px;flex:0 0 auto}
.bill-banner.grace{background:linear-gradient(90deg,#a16207,#d97706)}
.bill-banner.restricted{background:linear-gradient(90deg,#b42318,#e04236)}
.bill-banner .bill-msg{display:flex;align-items:center;gap:8px;line-height:1.35}
.bill-banner .bill-msg b{font-weight:800}
.bill-banner .bill-actions{display:flex;align-items:center;gap:8px;flex:0 0 auto}
.bill-banner .bill-help{height:32px;border:1px solid rgba(255,255,255,.55);background:rgba(255,255,255,.12);
  color:#fff;border-radius:8px;padding:0 14px;font-weight:800;cursor:pointer;white-space:nowrap}
.bill-banner .bill-help:hover{background:rgba(255,255,255,.22)}
.bill-banner .bill-dismiss{height:32px;width:32px;border:1px solid rgba(255,255,255,.45);
  background:rgba(255,255,255,.10);color:#fff;border-radius:8px;font-weight:800;cursor:pointer;line-height:1}
.bill-banner .bill-dismiss:hover{background:rgba(255,255,255,.22)}

/* Checkboxes inside a .filterbar. The bar's global `.filterbar input` sizing
   (height:43px, padding:0 14px, min-width:300px) is meant for text inputs; on a
   checkbox it inflates the box into a large square and shoves its label 300px to
   the right. This is a TRAP every filterbar checkbox falls into, so reset them
   all once here rather than per page — the new-workspace form and the Costs &
   Margin "include test workspaces" toggle both hit it. Outranks `.filterbar
   input` on specificity (class + attribute + type), so this wins. */
.filterbar input[type=checkbox],
.nt-test-opt input[type=checkbox]{width:16px;height:16px;min-width:0;margin:0;padding:0;accent-color:var(--purple);cursor:pointer}

/* Label + box pair that reads as one control. .nt-test-opt is the original
   new-workspace-form name kept for its existing markup; .check-opt is the same
   thing under a name any page can use. */
.nt-test-opt,
.check-opt{display:flex;align-items:center;gap:8px;font-weight:700;color:var(--text);white-space:nowrap}
.check-opt{font-weight:600;color:var(--muted)}

/* Linked workspaces (named groups) in the Quantum Connect console: a group header row above its
   member workspace rows. */
.table tr.grp-head td{background:#f4f2ff;border-top:2px solid rgba(109,77,252,.2)}
.grp-name{font-weight:800;color:var(--text);font-size:14px}
.table tr.loc-member td{background:#fbfcfe}
.loc-branch{color:var(--muted);margin-right:2px}

/* ==== SHARED workspace-table SKIN ================================================
   ONE palette + ONE set of region colours for BOTH variations of the workspace
   table — the client "Locations & Names" table (Settings › General, .setg-* below)
   and the Quantum Connect console's per-workspace inner tables (.ws-console-table, below). The
   two DOMs differ on purpose: the client is a flat title-card + one table; the Quantum Connect
   console wraps each workspace in a COLLAPSIBLE fence (fold/unfold, ▶/▼ caret) and
   adds an ID column, a Status column, and a stack of admin action buttons the client
   hides. Structure stays per-side, but both pull the three region colours from the
   vars here — so a colour change to any region lands on BOTH sides at once. The
   sortable-header + in-place-search behaviour is the other half of the shared module,
   in JS: public/js/components/workspacetable.js.
   Two regions, colours pinned to existing brand sources:
     • title  — navy identity "title piece", the SAME var(--navy) gradient as the app
                sidebar (client: a rounded card; Quantum Connect: the collapsible fence bar). The
                white search input lives INSIDE this piece (.wt-title-search below) —
                there is no separate search strip any more.
     • header — the column headers, in the OmniCare-logo gradient (matches .brand-mark) */
:root{
  --wt-title:linear-gradient(180deg,var(--navy),var(--navy2));
  --wt-title-fg:#fff;
  --wt-title-sub:#aeb9dd;                 /* muted sub-line / caret / copy-btn on navy */
  --wt-title-id:#c9d4f2;                  /* the workspace-id mono code on navy */
  --wt-header:linear-gradient(135deg,#7857ff,#12b8a6);
  --wt-header-fg:#fff;
}

/* Search row INSIDE the navy title piece — shared by all three tables (client Locations
   & Names card, Quantum Connect console fences, Overview card fences). The white input sits directly
   on the navy: the old lavender strip that was smooshed between the title card and the
   column headers is gone. width:100% wraps the row onto its own line inside the console's
   flex fence card and fills the client's stacked title card; the count note lights up to
   read on navy. Quantum Connect fences hide this row while folded (fold handlers toggle [hidden]),
   so the fence bar visibly grows downward on unfold — display:flex overrides the UA's
   [hidden] rule, hence the explicit [hidden] line. */
.wt-title-search{display:flex;align-items:center;gap:10px;flex-wrap:wrap;width:100%;margin-top:10px}
.wt-title-search[hidden]{display:none}
.wt-title-search .right-note{color:var(--wt-title-sub)}

/* -- TEST-workspace hazard ribbons (.wt-tape) — shared by all three title cards --
   Purely cosmetic: the large-format echo of the TEST pill, on workspaces in test mode
   only. The <i> elements come from OCWorkspaceTable.hazardTape(n), which owns the count
   (2 on a full-width card, 1 on the narrow Overview card) and the offsets — placed
   down the card's RIGHT side. Band WIDTH lives here and hazardTape's offsets are
   DERIVED from it (its TAPE_W must match this width), so change one and change the
   other. Bands are deliberately wide — the card should read as partially FILLED with
   tape rather than wearing two thin stripes.

   The WRAP illusion: the band overhangs the card by --tape-top / --tape-bot, and ::after
   darkens exactly that overhang plus a short fade onto the face — so each end reads as
   the ribbon curving over the edge and running on behind the card, rather than being
   painted flat on it. The 90deg shading inside the band gives it the roundness of a real
   strip of tape (lit down the middle, falling off at both long edges), and the drop
   shadow lifts it off the navy.

   Two things the hosting card MUST provide (see .setg-ws-title and .ws-fence-card below):
   position:relative AND z-index:0. The bands sit at z-index:-1 so the card's own text
   paints OVER them; without a stacking context on the card, a negative-z child escapes
   to the ancestor and vanishes UNDER the navy background entirely. The card must also
   never clip (no overflow:hidden) or the overhang — the whole point — is cut off. */
.wt-tape{
  --tape-top:4px; --tape-bot:4px;
  position:absolute;z-index:-1;pointer-events:none;   /* never eat the fold click */
  top:calc(-1 * var(--tape-top));bottom:calc(-1 * var(--tape-bot));
  width:120px;transform:skewX(16deg);border-radius:6px;
  background:
    linear-gradient(90deg,rgba(0,0,0,.34) 0%,rgba(255,255,255,.22) 38%,rgba(255,255,255,.04) 64%,rgba(0,0,0,.38) 100%),
    repeating-linear-gradient(-45deg,#181818 0 16px,#ffd21f 16px 32px);
  box-shadow:0 3px 8px rgba(0,0,0,.45),0 0 0 1px rgba(0,0,0,.45);
}
.wt-tape::after{
  content:"";position:absolute;inset:0;border-radius:inherit;
  background:linear-gradient(to bottom,
    rgba(0,0,0,.74) 0,
    rgba(0,0,0,.28) var(--tape-top),
    rgba(0,0,0,0) calc(var(--tape-top) + 7px),
    rgba(0,0,0,0) calc(100% - var(--tape-bot) - 7px),
    rgba(0,0,0,.28) calc(100% - var(--tape-bot)),
    rgba(0,0,0,.74) 100%);
}

/* -- Variation A: client "Locations & Names" table (Settings › General) -- */
/* position+z-index:0 host the TEST hazard ribbons (.wt-tape above) — harmless when
   there are none, required (stacking context) when there are. */
.setg-ws-title{background:var(--wt-title);color:var(--wt-title-fg);position:relative;z-index:0;
  border-radius:12px;padding:13px 18px;margin:0 0 12px;display:flex;flex-direction:column;gap:3px}
.setg-ws-name{font-weight:800;font-size:16px;line-height:1.2}
.setg-ws-sub{font-size:12px;font-weight:600;color:var(--wt-title-sub)}
/* Gradient painted ONCE on the header ROW, with transparent cells, so it sweeps the FULL
   width as a single continuous band instead of restarting inside each <td> (which made it
   "fit to the column" and leave a gap over the blank action column). Over a wide, short
   row a 135deg sweep reads purple → teal, left → right. */
.setg-names-table thead tr{background:var(--wt-header)}
.setg-names-table thead td{background:transparent;color:var(--wt-header-fg);font-weight:700;border-bottom:0}
/* Translucent white wash = per-column hover feedback that reads over the row gradient
   (brightness filters do nothing on a transparent cell). Blank action header: no hover. */
.setg-names-table thead td.oc-wt-sort:hover{background:rgba(255,255,255,.14)}

/* Sort-arrow slot — SHARED by both tables. headerCell (workspacetable.js) ALWAYS emits this
   span; it sits empty until its column is the active sort, then it holds ▲/▼. A FIXED width
   keeps the header's content width constant whether or not the arrow is showing, so a column
   claiming or losing the arrow no longer reflows every column of the auto-layout table on sort.
   width (not min-width) is deliberate: the box stays 1.2em even if the glyph+space were wider,
   so the column can never grow. */
.oc-wt-arrow{display:inline-block;width:1.2em;text-align:center}

/* -- Variation B: Quantum Connect console inner workspace tables (.ws-console-table) --
   Same three regions, same three colours as Variation A — but each region is a
   full-width table ROW here (not a card), inside a COLLAPSIBLE fence. Quantum Connect-only extras
   kept: the fold caret, the Workspace ID, the Status column, and the action buttons. */
/* Fence bar = the navy "title piece" (Quantum Connect-only: click the bar to fold/unfold). Light up
   the name, counts note, caret, and the workspace-id block so they read on navy. The id
   code + copy button + caret set their colour inline (that markup is shared with the
   tinted house rows), so those three need !important; the class-styled bits don't. The
   action buttons keep their own backgrounds and sit fine on navy.
   The fence bar renders as a ROUNDED FLOATING CARD to match the client's div card: the
   colour + radius live on an INNER wrapper (.ws-fence-card) and the <td> is transparent
   padding so the card floats with a gap. (border-collapse ignores border-radius on the
   cell itself, so the round has to sit on content, not the <td>.) The per-workspace
   search input lives inside this card too (.wt-title-search, shared skin above). */
/* border-top:0 overrides the base .table tr.grp-head td's 2px purple top rule (line ~1253) so
   NO line rules between fence cards — the header's border-bottom is the list's only divider. */
.ws-console-table tr.grp-head.ws-fence td{background:transparent;padding:3px 0;border-top:0;border-bottom:0}
/* The FIRST fence gets the same breathing room BELOW the divider as the title card has ABOVE it
   (the th's 10px padding-bottom), so the divider reads as centred between the header and the
   first workspace. Only the first — the rest stay tight (3px) against each other. */
.ws-console-table tbody tr.grp-head.ws-fence:first-child td{padding-top:10px}
.ws-console-table tr.grp-head.ws-fence .ws-fence-card{background:var(--wt-title);border-radius:12px;padding:12px 16px;position:relative;z-index:0}
/* OPEN state — the navy card squares its bottom and drops its bottom gap so the gradient
   body below butts flat against it: the purple→teal header appears to come OUT of the navy
   title card as one continuous card (see .ws-reveal below for the roll-out + rounded base). */
.ws-console-table tr.grp-head.ws-fence.open:not(.ws-empty) td{padding-bottom:0}
.ws-console-table tr.grp-head.ws-fence.open:not(.ws-empty) .ws-fence-card{border-radius:12px 12px 0 0}
/* An OPEN fence has no bottom edge — the card runs straight into the gradient body — so
   the ribbon must stop at the seam instead of wrapping around a corner that isn't there. */
.ws-console-table tr.grp-head.ws-fence.open:not(.ws-empty) .wt-tape{
  --tape-bot:0px;border-bottom-left-radius:0;border-bottom-right-radius:0;  /* square into the seam */
}
.ws-console-table tr.grp-head.ws-fence .grp-name{color:var(--wt-title-fg)}
.ws-console-table tr.grp-head.ws-fence .right-note{color:var(--wt-title-sub)}
.ws-console-table tr.grp-head.ws-fence .ws-caret{color:var(--wt-title-sub)!important}
.ws-console-table tr.grp-head.ws-fence code{color:var(--wt-title-id)!important}
.ws-console-table tr.grp-head.ws-fence .ws-id-copy{color:var(--wt-title-sub)!important;border-color:rgba(255,255,255,.28)!important}
/* Fence BODY row — ONE transparent container cell holding the scroll region with the
   fence's OWN inner table (gradient subhdr + location rows). The nesting exists for the
   10-row cap: rows of every fence share the OUTER <table>, so a per-fence scroll region
   needs its own block container — capRows (workspacetable.js) sets max-height/overflow on
   .ws-inner-scroll. The per-fence search sits up in the fence bar (.wt-title-search),
   outside the scroll entirely.
   Outer container cell for BOTH the populated (.ws-body) and the empty ("No locations yet")
   fence body — child combinators (>tbody>tr) so the NESTED table's own house-row cells are
   never touched. Zero padding/no fill: a FOLDED fence's body must occupy zero height (the
   .ws-reveal below collapses to 0), so all body spacing lives on the reveal, applied only
   when open. */
.ws-console-table>tbody>tr.loc-member[data-ws-parent]>td{background:transparent;padding:0;border-bottom:0}
/* Accordion reveal — the fence body "rolls out" downward on unfold (grid 0fr → 1fr), and
   because it grows in normal flow it pushes the next fence card down as it opens. reveal-inner
   clips to the animating track (min-height:0 + overflow:hidden). OPEN adds the bottom breathing
   room, rounds the body's bottom corners, and lifts it on a soft shadow so navy card + gradient
   header + rows read as ONE card the body emerged from (top corners stay square = butt the navy
   card). Honors reduced-motion by dropping the transition (still opens/closes, just instantly). */
.ws-reveal{display:grid;grid-template-rows:0fr;transition:grid-template-rows .28s ease,margin-bottom .28s ease}
.ws-reveal-inner{min-height:0;overflow:hidden}
.ws-reveal.open{grid-template-rows:1fr;margin-bottom:9px}
.ws-body .ws-reveal.open .ws-reveal-inner{border-radius:0 0 12px 12px;box-shadow:0 14px 22px -14px rgba(2,8,23,.28)}
.ws-empty-note{padding:12px 0}
@media (prefers-reduced-motion:reduce){.ws-reveal{transition:none}}
/* The SHARED 10-row scroll region (Quantum Connect fences + the client Locations table). No height
   here — capRows measures the first 10 visible rows and sets max-height inline; uncapped
   it's a plain wrapper. overscroll-behavior stops a wheel that hits the region's end from
   scrolling the whole page mid-list. */
.ws-inner-scroll{overscroll-behavior:contain}
.ws-inner-scroll>table{margin:0}
/* Inner column headers = the logo-gradient band, painted once on the ROW with transparent
   cells so it sweeps full width; white labels. fenceBlock's iTh passes muted:false so
   headerCell injects no inline colour and this CSS fully owns the look (as on the client).
   NON-STICKY on purpose: sticky needs per-<td> backgrounds, which restart the gradient
   inside every cell (striped) — the header scrolls with the rows instead. */
.ws-console-table tr.ws-subhdr{background:var(--wt-header)}
.ws-console-table tr.ws-subhdr td{background:transparent;color:var(--wt-header-fg);font-weight:700;border-bottom:0}
.ws-console-table tr.ws-subhdr td.oc-wt-sort:hover{background:rgba(255,255,255,.14)}
/* Outer master-sort header — Quantum Connect-only (the client table orders no fence LIST, so it has no
   outer header at all). A LIGHT grey card with a bold slate border: the earlier dark fill
   (#1f2937) blended into the navy fences right below it, so it's inverted — a pale bordered
   header now pops against the dark navy workspace cards (light-on-dark contrast does the
   separating). Marked as the LIST HEADER: a bold uppercase, letter-spaced label, no badges or
   buttons. Rounded card via the same transparent-<td> + inner-wrapper trick the fence bar uses
   (border-collapse ignores radius on the cell). The th's border-bottom is the ONE divider — a
   single full-width bar between the header and the FIRST workspace; the fences carry no top
   border of their own (below), so nothing rules BETWEEN workspaces. Click still lands on the
   <th> (the sort handler's target). */
.ws-console-table th.ws-outer-sort{background:transparent;border-bottom:2px solid rgba(109,77,252,.2);padding:0 0 10px}
.ws-console-table .ws-outer-card{display:flex;align-items:center;justify-content:flex-start;gap:8px;
  background:#e9edf4;color:#344054;border:2px solid #b9c4d4;border-radius:12px;padding:12px 16px;
  cursor:pointer;user-select:none;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}
.ws-console-table .ws-outer-card:hover{background:#e1e7f0;border-color:#a7b4c8}
.ws-console-table .ws-outer-card .right-note{color:#667085;letter-spacing:normal}
.loc-tag{display:inline-flex;align-items:center;border-radius:999px;padding:2px 8px;font-size:11px;font-weight:700;background:rgba(109,77,252,.10);color:var(--purple);border:1px solid rgba(109,77,252,.25);margin-left:4px}

/* Group vs. individual mapping scope chip (Mappings tree). Neutral = inherits the
   group mapping; purple = this location holds its own override. */
.map-scope-chip{display:inline-flex;align-items:center;border-radius:999px;padding:2px 9px;font-size:11px;font-weight:700;
  background:color-mix(in srgb, var(--muted) 12%, transparent);color:var(--muted);
  border:1px solid color-mix(in srgb, var(--muted) 30%, transparent)}
.map-scope-chip.is-individual{background:color-mix(in srgb, var(--purple) 12%, transparent);color:var(--purple);
  border-color:color-mix(in srgb, var(--purple) 30%, transparent)}

/* Group ⟷ Individual toggle slider (per-location mapping override). Visually-hidden
   checkbox drives an accessible track+knob; ON = purple. */
.oc-switch{display:inline-flex;align-items:center;gap:7px;cursor:pointer;vertical-align:middle;margin-right:8px;user-select:none}
.oc-switch input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.oc-switch-track{position:relative;width:34px;height:19px;border-radius:999px;flex:none;
  background:var(--line);border:1px solid color-mix(in srgb, var(--muted) 35%, transparent);
  transition:background .15s ease,border-color .15s ease}
.oc-switch-knob{position:absolute;top:1px;left:1px;width:15px;height:15px;border-radius:50%;background:#fff;
  box-shadow:0 1px 3px rgba(16,24,40,.28);transition:transform .15s ease}
.oc-switch input:checked + .oc-switch-track{background:var(--purple);border-color:var(--purple)}
.oc-switch input:checked + .oc-switch-track .oc-switch-knob{transform:translateX(15px)}
.oc-switch input:focus-visible + .oc-switch-track{box-shadow:0 0 0 3px color-mix(in srgb, var(--purple) 35%, transparent)}
.oc-switch-label{font-size:12px;font-weight:700;color:var(--muted);min-width:64px;text-align:left}
.oc-switch input:checked ~ .oc-switch-label{color:var(--purple)}

/* Testing Center — Quantum Connect-staff dev control inside the ghost banner. The button
   matches the banner's translucent controls; the dropdown is a normal white
   card (so its forms read clearly against the purple bar). */
.imp-test-wrap{position:relative;display:flex;align-items:center}
.imp-test{height:32px;border:1px solid rgba(255,255,255,.55);background:rgba(255,255,255,.12);
  color:#fff;border-radius:8px;padding:0 12px;font-weight:800;cursor:pointer}
.imp-test:hover{background:rgba(255,255,255,.22)}
.imp-test-pop{position:absolute;top:calc(100% + 8px);right:0;width:340px;max-height:72vh;overflow:auto;
  background:var(--card,#fff);color:var(--text,#101828);border:1px solid var(--line,#e5e7eb);
  border-radius:12px;box-shadow:var(--shadow,0 18px 50px rgba(16,24,40,.18));z-index:1200;font-size:14px}
.imp-test-head{display:flex;align-items:center;gap:8px;padding:12px 14px;border-bottom:1px solid var(--line);font-weight:800}
.imp-test-back{border:1px solid var(--line);background:#fff;border-radius:8px;width:28px;height:28px;cursor:pointer;font-size:15px;line-height:1}
.imp-test-list{display:flex;flex-direction:column;padding:6px}
.imp-test-item{display:flex;align-items:flex-start;gap:10px;text-align:left;width:100%;
  border:0;background:transparent;border-radius:8px;padding:9px 10px;cursor:pointer}
.imp-test-item:hover{background:var(--bg,#f6f7fb)}
.imp-test-ic{font-size:18px;line-height:1.2}
.imp-test-meta{display:flex;flex-direction:column;gap:2px}
.imp-test-meta b{font-weight:800}
.imp-test-meta small{color:var(--muted,#667085)}
.imp-test-note{padding:8px 14px;border-top:1px solid var(--line);color:var(--muted);font-size:12px}
.imp-test-body{padding:12px 14px;display:flex;flex-direction:column;gap:10px}
.imp-test-desc{margin:0;color:var(--muted);font-size:13px}
.imp-test-field{display:flex;flex-direction:column;gap:4px;font-size:13px;font-weight:700}
.imp-test-field input,.imp-test-field select{height:36px;border:1px solid var(--line);border-radius:8px;padding:0 10px;font-weight:500;background:#fff}
/* Checklist field (the demo_dataset "check what you want, how many of each" control). */
.imp-test-fieldgroup{display:flex;flex-direction:column;gap:6px}
.imp-test-ck-head{font-size:13px;font-weight:700}
.imp-test-checklist{display:flex;flex-direction:column;gap:6px;border:1px solid var(--line);border-radius:10px;padding:6px;background:#f7f7fb;max-height:340px;overflow-y:auto}
.imp-test-ck-row{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:8px;background:#fff;border:1px solid var(--line)}
.imp-test-ck-row.off{opacity:.55}
.imp-test-ck-main{display:flex;align-items:center;gap:8px;flex:1 1 auto;min-width:0;cursor:pointer;font-weight:700;font-size:13px}
.imp-test-ck-main input[type=checkbox]{width:16px;height:16px;flex:0 0 auto;cursor:pointer;accent-color:var(--purple,#6d4dfc)}
.imp-test-ck-ic{flex:0 0 auto;font-size:15px;line-height:1}
.imp-test-ck-label{display:flex;flex-direction:column;min-width:0}
.imp-test-ck-note{font-weight:500;color:var(--muted);font-size:11px;margin-top:1px;white-space:normal}
.imp-test-ck-count{width:78px;flex:0 0 auto;height:32px;border:1px solid var(--line);border-radius:8px;padding:0 8px;font-weight:600;background:#fff;text-align:right}
.imp-test-ck-count:disabled{opacity:.5;background:#f0f0f4}
.imp-test-run{height:38px;border:0;border-radius:8px;background:var(--purple,#6d4dfc);color:#fff;font-weight:800;cursor:pointer;margin-top:2px}
.imp-test-run:disabled{opacity:.7;cursor:default}
.imp-test-result{border-radius:8px;padding:8px 10px;font-size:13px;font-weight:700}
.imp-test-result.ok{background:#ecfdf3;color:#067647;border:1px solid #abefc6}
.imp-test-result.err{background:#fef3f2;color:#b42318;border:1px solid #fecdca}
/* List-screen search + collapsible category sections */
.imp-test-total{margin-left:auto;font-size:12px;font-weight:700;color:var(--muted,#667085)}
.imp-test-search{margin:8px 10px 2px;height:34px;border:1px solid var(--line,#e5e7eb);border-radius:8px;
  padding:0 10px;font-size:13px;font-weight:500;background:#fff;width:calc(100% - 20px);box-sizing:border-box}
.imp-test-search:focus{outline:2px solid color-mix(in srgb, var(--purple,#6d4dfc) 35%, transparent);outline-offset:0}
.imp-test-cat{display:flex;align-items:center;gap:8px;width:100%;text-align:left;border:0;cursor:pointer;
  background:var(--bg,#f6f7fb);border-radius:8px;padding:8px 10px;margin-top:4px;font-weight:800;font-size:13px}
.imp-test-cat:hover{background:var(--line,#e5e7eb)}
.imp-test-caret{width:12px;color:var(--muted,#667085);font-size:11px}
.imp-test-cat-name{flex:1}
.imp-test-cat-n{font-size:11px;font-weight:800;color:var(--muted,#667085);background:#fff;
  border:1px solid var(--line,#e5e7eb);border-radius:999px;padding:1px 8px}
.imp-test-cat-body{display:flex;flex-direction:column;padding-left:4px}
.imp-test-cat-body[hidden]{display:none}
.imp-test-cattag{color:var(--purple,#6d4dfc);font-weight:700;font-size:11px}
.imp-test-empty{padding:14px 10px;color:var(--muted,#667085);font-size:13px}

/* AI Receptionist — config forms, capability toggles, business-hours table. */
.rx-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:16px}
.rx-grid.one{grid-template-columns:1fr}
.rx-grid[hidden]{display:none}
.rx-grid label{display:flex;flex-direction:column;gap:6px;font-size:12px;font-weight:700;color:#344054}
.rx-grid label.full{grid-column:1/-1}
.rx-grid input,.rx-grid select,.rx-grid textarea{border:1px solid var(--line);border-radius:9px;background:#fff;
  padding:10px 12px;font-size:14px;color:var(--text);font-weight:500;font-family:inherit}
.rx-grid input:focus,.rx-grid select:focus,.rx-grid textarea:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.rx-grid textarea{min-height:84px;resize:vertical;line-height:1.5}
.rx-grid input:disabled,.rx-grid select:disabled,.rx-grid textarea:disabled{background:#f6f7f9;color:#98a2b3;cursor:not-allowed}
.rx-grid .right-note code{background:#eef1f7;border-radius:4px;padding:1px 5px;font-size:12px}
.rx-caps{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}
.rx-cap{display:flex;align-items:center;gap:10px;padding:12px 14px;border:1px solid var(--line);border-radius:10px;
  font-weight:600;font-size:14px;color:#344054;cursor:pointer}
.rx-cap input{width:17px;height:17px;accent-color:#4f46e5;cursor:pointer}
.rx-hours{width:100%;border-collapse:collapse;max-width:520px}
.rx-hours th{text-align:left;font-size:12px;font-weight:700;color:#667085;padding:6px 10px}
.rx-hours td{padding:8px 10px;border-top:1px solid var(--line);font-size:14px}
.rx-hours td.day label{display:flex;align-items:center;gap:9px;font-weight:700;color:#344054;cursor:pointer}
.rx-hours td.day input{width:16px;height:16px;accent-color:#4f46e5;cursor:pointer}
.rx-hours input[type=time]{height:36px;border:1px solid var(--line);border-radius:8px;padding:0 8px;color:var(--text);font-weight:500}
.rx-hours input:disabled{background:#f6f7f9;color:#98a2b3}
.rx-save-row{display:flex;align-items:center;gap:14px;margin-top:20px;flex-wrap:wrap}
.rx-saved{color:var(--green);font-weight:700;font-size:13px}
.rx-err{margin:0}
@media(max-width:700px){.rx-grid,.rx-caps{grid-template-columns:1fr}}

/* All-mode unified settings editor: a searchable location checklist that scopes
   which locations the one form below writes to (Settings › Practice / Plan). */
.setg-scope{border:1px solid var(--line);border-radius:10px;padding:12px 14px;background:#fafbfd}
.setg-scope-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.setg-scope-head strong{font-size:13px;color:#344054}
.setg-loc-list{max-height:210px;overflow:auto;border:1px solid var(--line);border-radius:9px;background:var(--card)}
.setg-loc-row{display:flex;align-items:center;gap:10px;padding:9px 12px;border-bottom:1px solid var(--line);
  cursor:pointer;font-size:13px;color:#344054}
.setg-loc-row:last-child{border-bottom:0}
.setg-loc-row:hover{background:#f6f7f9}
.setg-loc-row input{width:16px;height:16px;accent-color:#4f46e5;cursor:pointer;margin:0}
.setg-mixed{display:inline-block;padding:1px 7px;border-radius:999px;font-size:10.5px;font-weight:700;
  letter-spacing:.03em;text-transform:uppercase;color:#667085;background:#eef1f7;border:1px solid var(--line);vertical-align:middle}

/* Top-bar "?" Help Center button — same ghost shell as the bell, bolder glyph. */
.help-btn{font-size:20px;font-weight:800;line-height:1;color:#475467}
.help-btn:hover{color:var(--purple);border-color:var(--purple)}

/* Help Center page */
.help-areas{display:grid;grid-template-columns:1fr 1fr;gap:14px 20px}
.help-area{display:flex;gap:11px;align-items:flex-start}
.help-area-ic{font-size:17px;line-height:1.35;width:22px;text-align:center;flex:0 0 auto}
.help-area-name{font-weight:700;font-size:14px;color:var(--text)}
.help-area-desc{font-size:12.5px;color:var(--muted);line-height:1.45;margin-top:2px}
/* Section label inside .help-areas — the Quantum Connect console's Help tour mirrors the left
   menu's sections, so it needs a full-width divider inside that two-column grid
   (grid-column:1/-1; without it the label would take one cell and an area would
   sit beside its own heading). Same micro-label idiom as .sidebar #nav
   .nav-group-label, retuned for a white panel: --muted instead of translucent
   white, and it DOES take a hairline — the nav omits one because the dark ground
   and the extra margin already separate the runs, which is not true here.
   :first-child drops the rule and the margin so a leading section cannot open a
   gap under the panel's own intro note. */
.help-area-group{grid-column:1/-1;margin-top:6px;padding-top:14px;border-top:1px solid var(--line);
  font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}
.help-area-group:first-child{margin-top:0;padding-top:0;border-top:0}
.help-tasks{display:flex;flex-direction:column}
.help-task{padding:14px 0;border-bottom:1px solid var(--line)}
.help-task:first-child{padding-top:0}
.help-task:last-child{border-bottom:0;padding-bottom:0}
.help-task-t{font-weight:700;font-size:14.5px;color:var(--text);margin-bottom:4px}
.help-task-b{font-size:13px;color:var(--muted);line-height:1.55}
.help-task-b strong{color:#344054}
.help-support .btn{width:100%}
.help-support-note{font-size:12.5px;color:var(--muted);line-height:1.55;margin-top:8px}
.help-support-t{font-weight:700;font-size:14px;color:var(--text)}
.help-support hr{border:none;border-top:1px solid var(--line);margin:16px 0}

/* ---- Custom Report builder (Reports › Custom Reports) ----------------------
   Reuses the audience-builder (.aud-*) filter row + .pt-form-grid form styles;
   these are the pieces unique to the report builder. */
.rb-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:14px}
.rb-head h2{margin:0}
.rb-list-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.rb-sec{margin:0 0 18px}
.rb-sec-label{font-size:12px;font-weight:700;color:#344054;margin-bottom:8px;text-transform:uppercase;letter-spacing:.03em}
.rb-sec-hint{font-weight:500;font-size:12px;line-height:1.5;text-transform:none;letter-spacing:0;color:var(--muted);margin-left:6px}
/* Standalone hint paragraphs (the grouping example, "Add at least one column", the
   empty-filter note) read as small italic notes rather than body copy. The emphasised
   phrase inside stays upright + a touch bolder so it still stands out in the italics. */
p.rb-sec-hint{font-style:italic;margin-left:0}
p.rb-sec-hint em{font-style:normal;font-weight:600;color:#475467}
.rb-picker{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:10px}
.rb-picker-lead{font-size:14px;font-weight:600;color:var(--text);flex:0 0 auto}
.rb-picker select{height:38px;border:1px solid var(--line);border-radius:9px;background:#fff;padding:0 12px;font-size:14px;color:var(--text);font-weight:500;min-width:220px}
.rb-picker select:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.rb-cols{display:flex;flex-direction:column;gap:8px}
.rb-col-row{display:flex;align-items:center;gap:10px;border:1px solid var(--line);border-radius:9px;background:#fff;padding:8px 10px}
.rb-col-grip{color:#c0c6d2;font-size:13px;cursor:default;flex:0 0 auto}
.rb-col-name{flex:1;font-weight:600;font-size:14px;color:var(--text)}
.rb-col-tag{font-size:11px;font-weight:700;color:#4f46e5;background:#eef2ff;border-radius:6px;padding:2px 7px;flex:0 0 auto}
.rb-col-row select{height:34px;border:1px solid var(--line);border-radius:8px;background:#fff;padding:0 10px;font-size:13px;color:var(--text);font-weight:600;flex:0 0 auto}
.rb-col-row select:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.rb-chips{display:flex;gap:8px;flex-wrap:wrap}
.rb-chip{display:inline-flex;align-items:center;gap:7px;background:#eef2ff;color:#4f46e5;border-radius:999px;padding:6px 8px 6px 12px;font-size:12px;font-weight:700}
.rb-chip button{border:0;background:rgba(79,70,229,.16);color:#4f46e5;width:18px;height:18px;border-radius:999px;cursor:pointer;font-size:12px;line-height:1;display:flex;align-items:center;justify-content:center;padding:0}
.rb-chip button:hover{background:#4f46e5;color:#fff}
.rb-datewrap{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.rb-datewrap select,.rb-datewrap input{height:38px;border:1px solid var(--line);border-radius:9px;background:#fff;padding:0 12px;font-size:14px;color:var(--text);font-weight:500}
.rb-datewrap select:focus,.rb-datewrap input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.rb-foot{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:8px}
.rb-foot .rb-spacer{flex:1}
.rb-err{color:#b42318;font-weight:600;font-size:13px;background:#fef3f2;border:1px solid #fecdc9;border-radius:9px;padding:9px 12px;margin:0 0 12px}
.rb-result-note{font-size:12.5px;color:var(--muted);margin:0 0 10px}
.rb-num{text-align:right;font-variant-numeric:tabular-nums}
.rb-vis-badge{font-size:11px;font-weight:700;border-radius:999px;padding:3px 9px;border:1px solid transparent}
.rb-vis-private{background:#f2f4f7;color:#475467;border-color:#e6e9f0}
.rb-vis-shared{background:#eafaf1;color:#12805c;border-color:#bfe9d3}
.rb-vis-restricted{background:#fef3e6;color:#b45309;border-color:#fbd9a8}
/* Published-to-me (from another workspace in the group) + the "I've shared this onward"
   footprint pill. Teal/indigo so neither reads as one of the private/shared/restricted
   states — this is a cross-workspace relationship, not a visibility tier. */
.rb-vis-published{background:#eef4ff;color:#3538cd;border-color:#c7d2fe}
.rb-pub-badge{display:inline-block;font-size:11px;font-weight:700;border-radius:999px;padding:3px 9px;background:#e6fbf6;color:#0f766e;border:1px solid #b6ece2;margin-left:2px}
/* Category: taxonomy badge on the list, filter chips above it, pick-chips in the builder. */
.rb-cat-badge{display:inline-block;font-size:11px;font-weight:700;border-radius:999px;padding:3px 9px;background:#eef2ff;color:#4f46e5;border:1px solid #dfe3fb}
.rb-meta-head{font-size:11px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#667085;margin-top:6px;padding-top:12px;border-top:1px solid var(--line)}
.rb-cat-dupe{margin-top:6px;font-size:12px;font-weight:600;color:#b54708}
.rb-link{border:0;background:none;color:var(--blue);font-weight:700;cursor:pointer;padding:0;font:inherit;text-decoration:underline}
.rb-catfilter{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 14px}
.rb-catf{border:1px solid var(--line);background:#fff;color:#475467;border-radius:999px;padding:5px 12px;font-size:12.5px;font-weight:600;cursor:pointer}
.rb-catf:hover{border-color:#c7cbd8;background:#f7f8fb}
.rb-catf-on{background:#eef2ff;color:#4f46e5;border-color:#c7ccf7}
.rb-catf-none{font-style:italic}
/* Restricted visibility: page-DOM audience picker (screen-share safe — native popups
   are invisible in Teams/Zoom capture). Selected teammates use the amber "restricted" tint. */
.rb-restrict-box{display:flex;flex-direction:column;gap:6px;background:#fdfbf7;border:1px solid #f2e3cf;border-radius:10px;padding:12px}
.rb-restrict-label{font-size:12.5px;font-weight:600;color:#344054}
.rb-user-filter{max-width:280px}
.rb-user-picks{display:flex;gap:6px;flex-wrap:wrap;margin-top:2px}
.rb-user-chip{border:1px solid var(--line);background:#fff;color:#475467;border-radius:999px;padding:4px 11px;font-size:12px;font-weight:600;cursor:pointer}
.rb-user-chip:hover{border-color:#c7cbd8;background:#f7f8fb}
/* Selected chip = green everywhere (clearer than the old amber). Used by every chip
   picker: location visibility, restricted audience, publish-to-locations, transfer. */
.rb-user-chip-on{background:#e7f6ec;color:#137a3e;border-color:#b6e2c6}

/* Location visibility: All ⇄ Specific scope picker. Slate/blue tint sets the box apart
   from the cream Restricted box when both controls appear together. */
.rb-scope-box{background:#f7f9fc;border-color:#dbe4f0}
.rb-picks-head{font-size:12px;font-weight:700;color:#475467}
.rb-picks-scroll{max-height:190px;overflow-y:auto;align-content:flex-start;padding:8px;background:#fff;border:1px solid var(--line);border-radius:8px}
/* Live "one row per <field>" preview under the Summarize picker. Neutral by default;
   the -warn variant flags exact-value groupings that rarely collapse anything. */
.rb-grp-preview{margin-top:8px;font-size:12.5px;line-height:1.45;color:#475467;background:#f4f7fb;border:1px solid #e3e9f2;border-radius:8px;padding:8px 10px}
.rb-grp-preview-warn{color:#92400e;background:#fff7ed;border-color:#fde3c2}
.rb-scope-modes{display:flex;gap:6px;flex-wrap:wrap}
.rb-scope-mode{border:1px solid var(--line);background:#fff;color:#475467;border-radius:999px;padding:4px 13px;font-size:12px;font-weight:600;cursor:pointer}
.rb-scope-mode:hover{border-color:#c7cbd8;background:#f7f8fb}
.rb-scope-mode-on{background:#eff4fb;color:#1d4ed8;border-color:#bcd0ee}
/* List pill flagging a location-scoped report */
.rb-loc-badge{display:inline-block;background:#eff4fb;color:#1d4ed8;border:1px solid #bcd0ee;border-radius:999px;padding:1px 8px;font-size:11px;font-weight:600;white-space:nowrap;vertical-align:middle}

/* Transfer-ownership modal — page-DOM (screen-share safe), same overlay depth as
   the confirm dialog so it layers correctly over the report list. */
.rb-modal-overlay{position:fixed;inset:0;z-index:200;background:rgba(7,20,41,.45);display:grid;place-items:center;padding:24px;animation:ocConfirmFade .12s ease-out}
.rb-modal{width:100%;max-width:460px;background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:0 24px 60px rgba(7,20,41,.45);padding:24px}
.rb-modal-title{margin:0 0 8px;font-size:17px;font-weight:800;color:var(--text)}
.rb-modal .rb-user-filter{margin-bottom:8px}
.rb-modal .rb-user-picks{max-height:220px;overflow-y:auto;margin:0 0 4px}
.rb-keep{display:flex;gap:10px;align-items:flex-start;margin:12px 0 0;padding:12px 14px;background:var(--bg);border:1px solid var(--line);border-radius:10px;cursor:pointer;font-size:14px;color:var(--text)}
.rb-keep input{margin-top:2px;flex:none;width:16px;height:16px;cursor:pointer}
.rb-modal-err{margin:12px 0 0;color:var(--bad,#b91c1c)}
.rb-modal-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:18px}

/* --- Spreadsheet-style column builder: the report's columns rendered as row 1
   of a little worksheet (grey A/B/C letter band, header cells, ghost rows). --- */
.rb-sheet-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:11px;background:#fff}
.rb-sheet{display:grid;min-width:max-content}
.rb-sheet>div{border-right:1px solid var(--line);border-bottom:1px solid var(--line)}
.rb-sheet .rb-sh-letter-add,.rb-sheet .rb-sh-add,.rb-sheet .rb-sh-ghost-add{border-right:0}
.rb-sh-corner,.rb-sh-letter,.rb-sh-rownum{background:#f4f6f9;color:#8a94a6;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;text-align:center;user-select:none}
.rb-sh-corner,.rb-sh-letter{height:22px;text-transform:uppercase;letter-spacing:.04em}
.rb-sh-letter-add{color:#4f46e5}
.rb-sh-ghostnum{color:#c3cad6}
.rb-sh-cell{background:#fff;padding:9px 10px;display:flex;flex-direction:column;gap:7px;min-height:66px;min-width:0}
.rb-sh-calc{background:#fbfbff}
.rb-sh-name{font-weight:700;font-size:13.5px;color:var(--text);line-height:1.25;display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0;word-break:break-word}
.rb-sh-fx{font-size:10px;font-weight:800;font-style:italic;color:#4f46e5;background:#eef2ff;border-radius:5px;padding:1px 5px;flex:0 0 auto}
.rb-sh-cellfoot{display:flex;align-items:center;gap:6px;margin-top:auto}
.rb-sh-sp{flex:1}
.rb-sh-agg{height:28px;max-width:100%;border:1px solid var(--line);border-radius:7px;background:#fff;padding:0 8px;font-size:12px;color:var(--text);font-weight:600}
.rb-sh-agg:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.rb-sh-btn{width:24px;height:24px;padding:0;border:1px solid transparent;border-radius:6px;background:transparent;color:#98a2b3;cursor:pointer;font-size:12px;line-height:1;display:flex;align-items:center;justify-content:center;flex:0 0 auto}
.rb-sh-btn:hover{background:#f2f4f7;color:var(--text)}
.rb-sh-rm:hover{background:#fef3f2;color:#b42318;border-color:#fecdc9}
.rb-sh-add{align-items:center;justify-content:center;flex-direction:row;gap:8px;cursor:pointer;color:#4f46e5;font-weight:700;background:#fbfcff}
.rb-sh-add:hover{background:#eef2ff}
.rb-sh-add:focus-visible{outline:2px solid var(--blue);outline-offset:-2px}
.rb-sh-plus{font-size:18px;line-height:1}
.rb-sh-addlbl{font-size:13px}
.rb-sh-ghost{background:#fff;min-height:30px}
/* Drag-to-reorder: grip handle, dimmed source gap, and the floating cell clone that
   follows the pointer. The whole header cell is a drag surface (grab cursor); its
   inner controls keep the pointer cursor so they still read as clickable. */
.rb-sh-grip{cursor:grab;color:#cbd2de;font-size:12px;line-height:1;flex:0 0 auto;user-select:none;touch-action:none}
.rb-sh-grip:hover{color:#8a94a6}
.rb-sh-cell[data-rb-col-idx]{cursor:grab}
.rb-sh-cell[data-rb-col-idx] .rb-sh-agg,.rb-sh-cell[data-rb-col-idx] .rb-sh-btn{cursor:pointer}
.rb-sh-cell.rb-col-src{opacity:.4}
.rb-col-ghost{position:fixed;top:0;left:0;z-index:400;pointer-events:none;box-sizing:border-box;background:#fff;border:1px solid #4f46e5;border-radius:10px;box-shadow:0 14px 34px rgba(16,24,40,.22);padding:9px 10px;display:flex;flex-direction:column;gap:7px;opacity:.97}
body.rb-col-dragging-active{cursor:grabbing;user-select:none}
body.rb-col-dragging-active .rb-sh-cell[data-rb-col-idx]{cursor:grabbing}

/* --- Report-builder modal (add-a-column menu + calculated-field editor) --- */
.rb-modal-overlay{position:fixed;inset:0;background:rgba(16,24,40,.45);display:flex;align-items:flex-start;justify-content:center;padding:60px 16px 24px;z-index:260;overflow-y:auto}
.rb-modal{width:100%;background:#fff;border:1px solid var(--line);border-radius:14px;box-shadow:0 20px 60px rgba(16,24,40,.25);overflow:hidden}
.rb-modal-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:15px 18px;border-bottom:1px solid var(--line)}
.rb-modal-head h3{margin:0;font-size:16px;font-weight:700;color:var(--text)}
.rb-modal-x{width:30px;height:30px;padding:0;border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--muted);cursor:pointer;font-size:13px;display:flex;align-items:center;justify-content:center}
.rb-modal-x:hover{background:#f2f4f7;color:var(--text)}
.rb-modal-body{padding:16px 18px}
.rb-modal-search{width:100%;height:40px;border:1px solid var(--line);border-radius:9px;padding:0 12px;font-size:14px;color:var(--text);margin-bottom:10px}
.rb-modal-search:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.rb-modal-list{display:flex;flex-direction:column;gap:2px;max-height:min(52vh,360px);overflow-y:auto}
.rb-modal-grouplabel{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:10px 4px 3px}
.rb-modal-grouplabel:first-child{margin-top:0}
.rb-modal-item{display:flex;align-items:center;gap:8px;width:100%;text-align:left;border:1px solid transparent;border-radius:8px;background:transparent;padding:9px 10px;font-size:14px;color:var(--text);cursor:pointer}
.rb-modal-item:hover{background:#f4f6f9;border-color:var(--line)}
.rb-modal-type{margin-left:auto;font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.03em}
.rb-modal-foot{display:flex;align-items:center;gap:10px;margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
.rb-calc-grid{display:grid;grid-template-columns:1fr 160px;gap:12px;margin-bottom:14px}
.rb-calc-lbl{display:flex;flex-direction:column;gap:5px;font-size:12px;font-weight:700;color:#344054}
.rb-calc-lbl input,.rb-calc-lbl select{height:40px;border:1px solid var(--line);border-radius:9px;padding:0 12px;font-size:14px;font-weight:500;color:var(--text);background:#fff}
.rb-calc-lbl input:focus,.rb-calc-lbl select:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.rb-calc-formula{min-height:52px;border:1px solid var(--line);border-radius:10px;background:#fbfcff;padding:11px 12px;display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.rb-calc-empty{color:var(--muted);font-size:13px}
.rb-calc-tok{display:inline-flex;align-items:center;height:28px;padding:0 10px;border-radius:7px;font-size:13px;font-weight:600;font-variant-numeric:tabular-nums}
.rb-calc-tok-field{background:#eef2ff;color:#4f46e5}
.rb-calc-tok-num{background:#ecfdf3;color:#12805c}
.rb-calc-tok-op{background:#f2f4f7;color:#344054;font-weight:800}
.rb-calc-tok-lp,.rb-calc-tok-rp{background:#fff7ed;color:#c2410c;font-weight:800}
.rb-calc-preview{font-size:12px;color:var(--muted);margin:8px 2px 0;min-height:16px;font-variant-numeric:tabular-nums}
.rb-calc-pad{margin-top:12px;display:flex;flex-direction:column;gap:8px}
.rb-calc-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.rb-calc-row>select{height:38px;min-width:180px;border:1px solid var(--line);border-radius:9px;background:#fff;padding:0 12px;font-size:14px;color:var(--text);font-weight:500}
.rb-calc-row>input[data-cf-num]{height:38px;width:130px;border:1px solid var(--line);border-radius:9px;padding:0 12px;font-size:14px;color:var(--text)}
.rb-calc-op{min-width:38px;height:38px;padding:0 10px;border:1px solid var(--line);border-radius:9px;background:#fff;color:var(--text);font-size:15px;font-weight:700;cursor:pointer}
.rb-calc-op:hover{background:#f2f4f7;border-color:#cfd4dc}
.rb-calc-err{color:#b42318;font-weight:600;font-size:12.5px;margin:10px 2px 0;min-height:16px}
.rb-calc-foot{margin-top:6px}

/* --- Report results rendered as a worksheet (letter band + row numbers) --- */
.rb-grid-letters th{background:#f4f6f9;color:#8a94a6;font-size:11px;font-weight:700;text-align:center;letter-spacing:.04em;padding:4px 12px}
.rb-grid-corner{background:#f4f6f9}
.rb-grid thead tr:last-child th{background:#f8fafc;color:#344054}
.rb-grid tbody{counter-reset:rbrow}
.rb-grid-rownum{background:#f8fafc;color:#98a2b3;font-size:11px;font-weight:700;text-align:center;width:44px;font-variant-numeric:tabular-nums}
.rb-grid-rownum::before{counter-increment:rbrow;content:counter(rbrow)}
.rb-grid td,.rb-grid th{border-right:1px solid var(--line)}
.rb-grid td:last-child,.rb-grid th:last-child{border-right:0}

/* --- Reports: grouped left rail (replaces the flat top tab row) ---
   Deliberately LIGHTER than the app sidebar so it reads page-local: no card ground,
   small-caps group labels (the nav-group-label idiom), selected-row active state.
   .rep-main needs min-width:0 so a wide report table scrolls inside its own panel
   instead of widening the flex row. Sticky works because .content is the scroll
   container. At narrow widths the rail collapses to a wrapping pill-chip row and
   the group labels drop out. */
.rep-layout{display:flex;gap:24px;align-items:flex-start}
.rep-rail{flex:0 0 188px;position:sticky;top:4px;display:flex;flex-direction:column;gap:14px}
.rep-rail-group{display:flex;flex-direction:column}
.rep-rail-label{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--text);padding:0 12px;margin:0 0 4px}
.rep-rail-item{display:block;width:100%;text-align:left;background:none;border:0;font:inherit;padding:8px 12px;border-radius:9px;color:#344054;font-weight:600;font-size:13.5px;cursor:pointer;margin:1px 0}
.rep-rail-item:hover{background:#f6f7f9}
.rep-rail-item.active{background:#eef2ff;color:#4f46e5}
.rep-rail-locked{opacity:.45;filter:grayscale(1)}
.rep-rail-locked:hover{opacity:.7;background:#f6f7f9}
.rep-main{flex:1 1 auto;min-width:0}
@media (max-width:1000px){
  .rep-layout{display:block}
  .rep-rail{position:static;flex-direction:row;flex-wrap:wrap;gap:6px;margin-bottom:16px}
  .rep-rail-group{display:contents}
  .rep-rail-label{display:none}
  .rep-rail-item{display:inline-block;width:auto;border:1px solid var(--line);background:#fff;border-radius:999px;padding:6px 14px;font-size:13px;margin:0}
  .rep-rail-item.active{border-color:#c7ccf7}
}

/* --- Reports › Trends (pre-built, gt* module): metric cards with mini month bars --- */
.gt-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}
.gt-card{padding:16px 18px}
.gt-head{display:flex;align-items:center;gap:8px;font-size:14px}
.gt-ico{width:28px;height:28px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;font-size:15px;background:#eef2ff}
.gt-ico-teal{background:#e6f7f5}
.gt-ico-green{background:#e8f7ee}
.gt-chart{display:flex;align-items:flex-end;gap:3px;height:64px;margin:12px 0 4px}
.gt-bar-wrap{flex:1 1 0;height:100%;display:flex;align-items:flex-end;min-width:4px}
.gt-bar{width:100%;border-radius:3px 3px 0 0;background:#818cf8;min-height:0}
.gt-bar-mtd{background:#c7ccf7}
.gt-bar-null{height:2px;background:var(--line)}
.gt-bar-wrap:hover .gt-bar{background:#4f46e5}
.gt-bar-wrap:hover .gt-bar-mtd{background:#a5acf2}
.gt-bar-wrap:hover .gt-bar-null{background:#c7cbd8}
.gt-axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted);margin-bottom:10px}
.gt-stats{display:flex;flex-direction:column;gap:5px;border-top:1px solid var(--line);padding-top:10px}
.gt-stat{display:flex;align-items:baseline;gap:6px;font-size:13px}
.gt-stat>span:first-child{color:var(--muted);min-width:86px}
.gt-up{color:#12805c;font-weight:700}
.gt-down{color:#b42318;font-weight:700}
.gt-empty{color:var(--muted);font-size:13px;margin-top:12px}

/* --- Custom Reports: .rb-subtabs slot — the Reports|Past pills moved into the left
   rail, but the builder's Back control (rbBackBarHtml) still uses this slot. --- */
.rb-subtabs{display:flex;gap:6px;margin:0 0 14px;flex-wrap:wrap}
.rb-subtab{border:1px solid var(--line);background:#fff;color:#475467;border-radius:999px;padding:6px 16px;font-size:13px;font-weight:700;cursor:pointer}
.rb-subtab:hover{border-color:#c7cbd8;background:#f7f8fb}
.rb-subtab-on{background:#eef2ff;color:#4f46e5;border-color:#c7ccf7}

/* --- Past Reports: retention toolbar + status badges --- */
.rb-runs-retention{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 14px;padding:10px 14px;background:var(--bg);border:1px solid var(--line);border-radius:10px}
.rb-runs-retention-lbl{display:inline-flex;align-items:center;gap:8px;font-size:13px;font-weight:700;color:#344054}
.rb-ret-input{width:74px;height:34px;border:1px solid var(--line);border-radius:8px;padding:0 10px;font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}
.rb-ret-input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.rb-ret-hint{margin-left:2px}
.rb-runs-retention-note{margin:0 0 14px}
.rb-run-badge{display:inline-block;font-size:11px;font-weight:700;border-radius:999px;padding:3px 9px;border:1px solid transparent;white-space:nowrap}
.rb-run-kept{background:#eef7ee;color:#1b7d3f;border-color:#bfe2c6}
.rb-run-expires{background:#fff4e6;color:#b25b00;border-color:#f4d19a}

/* --- Persisted-run loading cover ("Running report…"). Its own depth above the run
   modal's overlay so nothing shows through while a big report runs. --- */
.rb-busy-overlay{z-index:280}
.rb-busy-card{background:#fff;border:1px solid var(--line);border-radius:14px;box-shadow:0 20px 60px rgba(16,24,40,.25);padding:26px 30px;margin:auto}

/* --- Run result modal (ajax preview + download): wider than the builder modals and a
   flex column so the header/footer pin while the row grid scrolls inside. --- */
.rb-run-modal{max-width:min(1100px,96vw);padding:0;display:flex;flex-direction:column;max-height:calc(100vh - 84px)}
.rb-run-modal-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:15px 20px;border-bottom:1px solid var(--line);flex:0 0 auto}
.rb-run-modal-sub{padding:0 20px;margin:12px 0 0}
.rb-run-modal-note{padding:0 20px;margin:8px 0 0}
.rb-run-modal-body{padding:12px 20px 4px;overflow:auto;flex:1 1 auto}
.rb-run-modal-foot{display:flex;align-items:center;gap:10px;padding:14px 20px;border-top:1px solid var(--line);flex:0 0 auto}
.rb-run-modal-foot .rb-spacer{flex:1}

@media(max-width:700px){.rb-picker select,.rb-datewrap select{min-width:0;flex:1}
  .rb-calc-grid{grid-template-columns:1fr}
  .rb-calc-row>select,.rb-calc-row>input[data-cf-num]{min-width:0;width:100%;flex:1}}

@media(max-width:1200px){.cards{grid-template-columns:repeat(3,1fr)}.grid,.grid.three,.split,.two-col,.now-row{grid-template-columns:1fr}.settings-grid{grid-template-columns:repeat(2,1fr)}.help-areas{grid-template-columns:1fr}}
/* --- Console content scroller: kill the scrollbar-reflow jitter (2026-09-03).
   .app-shell/.main are locked to height:100vh, so .content is the console's ONLY
   vertical scroller. With overflow:auto its scrollbar shows only when a list
   overflows, and on Windows that ~15px bar steals width from the pane — the card
   reflows narrower and the right-aligned row buttons jump left whenever a group is
   expanded. Desktop-only + scoped to the console (body.console) so the tenant app's
   own scroll look is untouched: keep the scrollbar ALWAYS on and slim it, so the pane
   width is constant (no shift) and the permanent lane reads as a real scrollbar
   rather than blank space. */
@media(min-width:801px){
  body.console .content{overflow-y:scroll;scrollbar-width:thin;scrollbar-color:#c3ccd9 #edf0f6}
  body.console .content::-webkit-scrollbar{width:12px}
  body.console .content::-webkit-scrollbar-track{background:#edf0f6}
  body.console .content::-webkit-scrollbar-thumb{background:#c3ccd9;border:3px solid #edf0f6;border-radius:999px;background-clip:padding-box}
  body.console .content::-webkit-scrollbar-thumb:hover{background:#a7b2c3;background-clip:padding-box}
}
@media(max-width:800px){
  /* Generic reflow — used by the platform console (no drawer): the sidebar
     stacks above the content and the topbar goes vertical. */
  .app-shell{grid-template-columns:1fr;height:auto;overflow:visible}
  .sidebar{position:relative;height:auto;overflow:visible}
  .sidebar #nav{overflow:visible}
  .main{height:auto}
  .topbar{height:auto;padding:20px;align-items:flex-start;gap:20px;flex-direction:column}
  .cards,.cards.fit{grid-template-columns:1fr}
  /* Stack the Totals header over its period selector, and let the selector use the
     full width so all four periods stay comfortably tappable. */
  .kpi-bar{align-items:stretch;flex-direction:column;gap:10px}
  .range-seg{width:100%}
  .seg-btn{flex:1 1 0;padding:9px 8px;text-align:center}
  .content{padding:20px;overflow:visible}
  .filterbar{flex-wrap:wrap}
  .filterbar input{min-width:100%}

  /* Wide data tables (Patients, Call Logs, Audit, …) scroll inside their own
     box on a phone instead of forcing the whole page wider than the screen. */
  .content table{display:block;width:100%;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}
  /* …except one already inside a .table-wrap, which scrolls at every viewport. The rule
     above makes the table a BLOCK box, and a block box is no longer a table box: it drops
     table-layout:fixed and every <colgroup> width with it, so the pinned columns would
     collapse to content width on a phone and nest a second scroller inside the first.
     Leave it a table and let the wrapper do the scrolling, exactly as on desktop. */
  .content .table-wrap table{display:table;width:100%;overflow-x:visible}

  /* iOS Safari zooms the page whenever a focused field is under 16px. Keep form
     controls at 16px on touch layouts so tapping a field never jumps the view. */
  input,select,textarea{font-size:16px}

  /* Tenant app shell (.has-drawer): instead of stacking, the sidebar becomes an
     off-canvas drawer opened by the top-bar hamburger. Higher-specificity rules
     below override the generic reflow above for this shell only. */
  .has-drawer .nav-toggle{display:inline-flex}
  /* padding-top/right honour the notch/status bar when installed as a PWA. */
  .has-drawer .topbar{flex-direction:row;align-items:center;justify-content:flex-start;height:auto;gap:12px;padding:12px 16px;padding-top:max(12px,env(safe-area-inset-top));padding-right:max(16px,env(safe-area-inset-right))}
  .has-drawer .topbar h1{font-size:20px;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .has-drawer .topbar>div{min-width:0}
  .has-drawer .top-actions{margin-left:auto;gap:8px;flex:0 0 auto}
  .has-drawer #page-subtitle{display:none}
  /* Keep clear of the home indicator / landscape notch inside the scroll area. */
  .has-drawer .content{padding-left:max(20px,env(safe-area-inset-left));padding-right:max(20px,env(safe-area-inset-right));padding-bottom:max(20px,calc(env(safe-area-inset-bottom) + 20px))}
  .has-drawer .sidebar{position:fixed;top:0;left:0;bottom:0;height:100vh;height:100dvh;width:282px;max-width:85vw;overflow-y:auto;transform:translateX(-100%);transition:transform .25s ease;z-index:1000;box-shadow:0 0 40px rgba(7,20,41,.35);padding-top:max(18px,env(safe-area-inset-top));padding-bottom:max(18px,env(safe-area-inset-bottom))}
  .has-drawer .sidebar.open{transform:translateX(0)}
  .has-drawer .sidebar-backdrop.open{display:block;position:fixed;inset:0;background:rgba(7,20,41,.5);z-index:999}
}
/* Very small phones: keep the top bar to one tidy row by dropping the name/role
   text next to the avatar (the avatar itself stays, and opens the user menu). */
@media(max-width:560px){
  .has-drawer .user-chip>div{display:none}
  .has-drawer .topbar h1{font-size:18px}
}

/* ---- Unsaved-changes banner (js/components/dirtyguard.js) ----
   Sits between the top bar and the scrolling #content, so it's always in view while
   a tracked form is dirty. z-index 50 keeps it above ordinary positioned content
   in #content but BELOW the bell / user-menu popovers (60) and .oc-confirm-overlay
   (200), so those always layer over it. Colours are the .auth-warn amber trio
   (semantic warning palette). */
.dirty-banner{position:sticky;top:0;z-index:50;flex:0 0 auto;display:flex;align-items:center;gap:12px;
  padding:10px 34px;background:#fff3e0;border-bottom:1px solid #fdd9a8;color:#b54708;font-size:14px;font-weight:600}
.dirty-banner[hidden]{display:none}
.dirty-banner-icon{font-size:11px;line-height:1}
.dirty-banner-msg{flex:1 1 auto;min-width:0}
.dirty-banner .btn{flex:0 0 auto}
@media(max-width:560px){
  .dirty-banner{padding:8px 14px;gap:8px;font-size:13px}
}

/* ---- Files page: browse filters + category editor ---- */
.up-filters{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:12px}
.up-filters input[type=search],.up-filters select{height:38px;border:1px solid var(--line);border-radius:9px;
  background:#fff;padding:0 12px;font-size:13px;color:var(--text)}
.up-filters input[type=search]{flex:1;min-width:200px;font-weight:500}
.up-filters select{font-weight:600;min-width:170px}
.up-filters input:focus,.up-filters select:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}

.cat-list{display:flex;flex-direction:column;gap:2px;margin-top:6px}
.cat-row{display:grid;grid-template-columns:1fr auto auto;align-items:center;gap:10px;
  padding:9px 2px;border-bottom:1px solid var(--line);font-size:13px}
.cat-row:last-child{border-bottom:none}
.cat-row.reserved{color:#667085}
.cat-name{font-weight:700;color:var(--text);display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cat-row.reserved .cat-name{color:#475467}
.cat-lock{display:inline-block;padding:1px 8px;border-radius:999px;font-size:11px;font-weight:600;
  background:#f2f4f7;color:#667085;border:1px solid var(--line)}
.cat-count{color:#667085;font-weight:500;font-size:12px;white-space:nowrap}

.cat-add{display:flex;gap:10px;align-items:center;margin-top:14px}
.cat-add input{flex:1;height:38px;border:1px solid var(--line);border-radius:9px;background:#fff;
  padding:0 12px;font-size:13px;color:var(--text)}
.cat-add input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.cat-actions{display:flex;gap:10px;align-items:center;margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}

/* ---- ocFilterList (helpers.js): search + live counts over a long checklist ----
   The cap is the whole point: seventy-five rows must not be able to stretch a
   dialog past the bottom of the screen. Roughly eight rows, then scroll. */
.oc-filter{display:flex;flex-direction:column;gap:8px;margin-top:8px}
.oc-filter-bar{display:flex;align-items:center;gap:8px}
.oc-filter-q{flex:1;min-width:0;box-sizing:border-box;height:34px;padding:0 10px;
  border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--text);
  font-family:inherit;font-size:13px}
.oc-filter-q:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
/* The master tick keeps the rows' own checkbox metrics (no custom margin) so it lands in
   the same column as them — it should read as the checklist's header, not a toolbar item. */
.oc-filter-master{flex:none;cursor:pointer}
.oc-filter-acts{display:flex;gap:6px;flex:none}
.oc-filter-btn{flex:none;height:34px;padding:0 10px;border:1px solid var(--line);border-radius:8px;
  background:#fff;color:var(--text);font-family:inherit;font-size:12px;font-weight:600;cursor:pointer}
.oc-filter-btn:hover{border-color:var(--blue);color:var(--blue)}
.oc-filter-list{max-height:264px;overflow-y:auto;overscroll-behavior:contain;margin-top:0}
.oc-filter-count{margin:0}
.oc-filter-hide{display:none !important}
.oc-filter-list .oc-filter-last{border-bottom:none}

.cat-locs{display:flex;flex-direction:column;gap:2px;margin-top:8px}
.cat-loc{display:flex;align-items:center;gap:9px;padding:7px 2px;font-size:13px;font-weight:500;
  color:var(--text);cursor:pointer;border-bottom:1px solid var(--line)}
.cat-loc:last-child{border-bottom:none}
.cat-loc.all{font-weight:700}
.cat-loc input{width:15px;height:15px;accent-color:var(--blue);cursor:pointer}

/* Inline form error (category editor, and anywhere else a field-level message is needed) */
.form-error{margin:0;font-size:13px;font-weight:600;color:var(--red)}

@media(max-width:700px){.cat-row{grid-template-columns:1fr auto}.cat-count{grid-column:1/-1}}

/* ---- ocselect.js: in-page dropdown list (see the file header for why) ----
   Sits above everything, including the confirm modal (z 1200) — a <select>
   inside a dialog still needs its list on top. It is body-mounted and fixed,
   so it is never clipped by the scrolling nav rail or a panel's overflow.
   A flex COLUMN, because a long list carries a filter field that has to stay put
   while the rows scroll under it: the popup clips, .ocsel-list is the scroller. */
.ocsel-pop{position:fixed;z-index:1400;display:flex;flex-direction:column;overflow:hidden;
  background:#fff;border:1px solid var(--line);border-radius:10px;padding:5px;
  box-shadow:0 12px 32px rgba(16,24,40,.18);font-size:13px;color:var(--text);
  min-width:140px;max-width:min(420px,calc(100vw - 16px))}
/* min-height:0 or a flex child refuses to shrink below its content and the list
   grows straight through the popup's max-height. position:relative so an option's
   offsetTop is measured from the scroller — that is what scrollTop is compared to. */
.ocsel-list{position:relative;min-height:0;overflow-y:auto;overscroll-behavior:contain}
.ocsel-search{flex:none;padding:1px 1px 6px}
.ocsel-search input{width:100%;box-sizing:border-box;height:32px;padding:0 10px;
  border:1px solid var(--line);border-radius:7px;background:#fff;color:var(--text);
  font-family:inherit;font-size:13px}
.ocsel-search input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.ocsel-empty{padding:9px 10px;color:var(--muted);font-size:12px}
.ocsel-opt{padding:8px 10px;border-radius:7px;cursor:pointer;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;font-weight:500;line-height:1.3}
.ocsel-opt.sel{font-weight:700}
.ocsel-opt.active{background:var(--blue);color:#fff}
.ocsel-opt.sel::after{content:'✓';float:right;margin-left:12px;font-weight:700}
/* A locked (opted-in disabled) row: muted and non-interactive, with a trailing (i)
   that carries the "why". It never gets the .active highlight — ocselect skips it. */
.ocsel-opt.is-locked{cursor:default;color:var(--muted)}
.ocsel-info{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;vertical-align:middle;border-radius:50%;border:1px solid var(--line);color:var(--muted);font-size:10px;font-style:italic;font-weight:800;font-family:Georgia,'Times New Roman',serif;line-height:1;cursor:pointer}
.ocsel-info:hover{color:var(--text);border-color:var(--muted)}

/* ---- filedialog.js: the small options menu behind a row's ⋯ ----
   Deliberately the same body-mounted fixed popup as ocselect above, with the
   same radius, padding, shadow and active row — one popup idiom in this app,
   not two that almost match. Rows are text only: an icon column here would be
   six glyphs competing for a decision that six words already make. */
.fdmenu{position:fixed;z-index:1400;background:#fff;border:1px solid var(--line);
  border-radius:10px;padding:5px;box-shadow:0 12px 32px rgba(16,24,40,.18);
  font-size:13px;color:var(--text);min-width:172px;outline:none}
.fdmenu-item{padding:8px 10px;border-radius:7px;cursor:pointer;white-space:nowrap;
  font-weight:600;line-height:1.3;outline:none}
.fdmenu-item:hover,.fdmenu-item.active{background:var(--blue);color:#fff}
/* Delete carries its colour at rest, not only under the cursor: it sits one
   keystroke from the rows above it, so it has to read as different before the
   pointer arrives. */
.fdmenu-item.danger{color:var(--red)}
.fdmenu-item.danger:hover,.fdmenu-item.danger.active{background:var(--red);color:#fff}
.fdmenu-sep{height:1px;background:var(--line);margin:5px 4px}

/* ---- Receptionist test-call pill (Quantum Connect-only) ----
   The embedded voice widget mounts straight on <body> (it is its own
   full-viewport fixed overlay and breaks inside any transformed wrapper) and
   is positioned by its native `placement` attribute. This pill is our own
   control next to it: a "Test call" label, a move button that cycles the
   widget through the four corners, and a close button. It follows the widget
   via data-corner, offset 104px vertically so it clears the collapsed orb.
   z-index 181: the widget host is a z-auto stacking context, so nothing inside
   it can outrank the pill — and ocConfirm (200) still covers both. */
#rx-widget-pill{position:fixed;z-index:181;display:inline-flex;align-items:center;gap:8px;
  padding:8px 12px;background:var(--card);border:1px solid var(--line);border-radius:999px;
  box-shadow:var(--shadow,0 10px 28px rgba(16,24,40,.18));user-select:none}
#rx-widget-pill[data-corner="bottom-left"]{left:20px;bottom:104px}
#rx-widget-pill[data-corner="top-left"]{left:20px;top:104px}
#rx-widget-pill[data-corner="top-right"]{right:20px;top:104px}
#rx-widget-pill[data-corner="bottom-right"]{right:20px;bottom:104px}
#rx-widget-pill .rx-widget-title{font-size:13px;font-weight:700;color:var(--text);white-space:nowrap}
#rx-widget-move,#rx-widget-close{border:0;background:transparent;color:var(--muted);font-size:13px;
  line-height:1;cursor:pointer;padding:4px 6px;border-radius:999px}
#rx-widget-move:hover{color:var(--text);background:var(--bg)}
#rx-widget-close:hover{color:var(--red);background:var(--bg)}

/* ============================================================
   Left-nav section headers — grouped nav (Work / Configure / Records / Account)
   ------------------------------------------------------------
   MARKUP: renderNav (app.js) emits a header as a flat sibling of the .nav-item
   anchors inside #nav, from the config.js NAV_GROUPS map:
       <div class="nav-group-label" role="heading" aria-level="2">Work</div>
   .nav-group is matched as well, as the one plausible shortening of that name.

   A header is a LABEL, not a button — no href, no data-page, nothing focusable —
   so it gets no hover, no focus ring and no pointer affordance here either. It
   reuses the micro-label idiom already established by .sidebar-location
   .loc-label (11px / 700 / uppercase / .05em tracking) so the two small labels in
   this rail read as one family. No hairline rule: the extra top margin alone does
   the dividing, which also keeps a 1px line from showing up half-faded inside the
   #nav scroll mask at the list edges.

   Colour is translucent white rather than a token because theme.css has no
   on-navy neutral (--muted is tuned for light surfaces), and rgba(255,255,255,x)
   is already this rail's own idiom (.brand border, .plan-card, the nav
   scrollbar). No new brand hex is introduced. .55 clears ~6:1 against the navy
   gradient, which 11px bold text needs to stay legible.

   :not(:has(.nav-item)) is a fail-safe, not a fit: today the header is a bare
   label, but if it is ever reworked into a WRAPPER around its items, the label
   typography is skipped rather than inherited down onto them. Failing to style a
   header is cosmetic; shrinking the whole nav to 11px uppercase is not.

   No orphan-header guard is needed: renderNav emits a header at a group BOUNDARY
   while walking the already-filtered list, so a group whose every item is hidden
   (adminOnly) prints no header at all, and a header always has its item attached.

   SCROLL MODEL UNCHANGED: .sidebar stays overflow:hidden with #nav as the only
   scroller (brand pinned top, .plan-card pinned bottom). These are ordinary
   static blocks in normal flow — no position:sticky, no new scroll container, no
   height/flex/overflow change on #nav — so the pinning and the nav-more-above /
   nav-more-below fade hints behave exactly as before. The headers simply make the
   list overflow a little sooner, which is precisely what those hints are for.
   ============================================================ */
.sidebar #nav .nav-group-label:not(:has(.nav-item)),
.sidebar #nav .nav-group:not(:has(.nav-item)){
  display:block;margin:16px 0 6px;padding:0 14px;
  font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:rgba(255,255,255,.55);user-select:none}
/* The first header ('Work') is #nav's first child and sits right under the Location
   block, with .sidebar's own flex gap:14px already between them — so it keeps
   .nav-item's 2px rhythm instead of opening a second gap the eye reads as a mistake.
   That reasoning holds at EVERY width: the drawer keeps the same flex column and the
   same gap, so the doubled gap would read just as wrong on a phone.
   The guard is repeated here to OUT-WEIGH the header rule, not merely to follow it:
   :not(:has(.nav-item)) and :first-child are both class-level, so the ≤800px
   restatement below tied this rule on specificity and won on source order — its
   `margin` shorthand was quietly resetting this 2px back to 12px in the drawer, the
   one place the tightening was never meant to reach. With the guard this is the more
   specific selector, so it holds at both widths whatever the source order. */
.sidebar #nav .nav-group-label:first-child:not(:has(.nav-item)),
.sidebar #nav .nav-group:first-child:not(:has(.nav-item)){margin-top:2px}
@media(max-width:800px){
  /* In the ≤800px drawer the whole sidebar scrolls (.has-drawer .sidebar) and
     vertical room is tighter on a phone, so the group gaps tighten. Restated as a
     normal class rule inside the media block — never an inline style, which would
     outrank it — the same pattern as .cards / .cards.fit above. */
  .sidebar #nav .nav-group-label:not(:has(.nav-item)),
  .sidebar #nav .nav-group:not(:has(.nav-item)){margin:12px 0 5px}
}

/* ---- File dialog (components/filedialog.js) --------------------------------
   Sits on .oc-confirm-overlay / .oc-confirm-box, so only the inside is styled
   here: a wider box with its own head / tab strip / scrolling body / action bar.
   Every colour is a token — the dialog has to look right in whichever app theme
   the workspace is running. ---- */
.fd-box{max-width:760px;padding:0;overflow:hidden;display:flex;flex-direction:column;max-height:min(88vh,860px)}
.fd-head{display:flex;align-items:flex-start;gap:14px;padding:20px 22px 14px;border-bottom:1px solid var(--line)}
.fd-title{min-width:0;flex:1}
.fd-title h3{margin:0;font-size:16px;font-weight:800;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fd-sub{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px;font-size:12.5px;color:var(--muted)}
.fd-sub>span:not(.fd-cat)::before{content:"·";margin-right:8px;color:var(--line)}
.fd-sub>span:not(.fd-cat):first-child::before{content:none;margin:0}
.fd-cat{display:inline-block;padding:1px 9px;border-radius:999px;font-size:11px;font-weight:700;
  background:var(--bg);color:var(--text);border:1px solid var(--line)}
.fd-x{flex:none;border:0;background:transparent;color:var(--muted);font-size:24px;line-height:1;
  cursor:pointer;padding:0 2px;border-radius:8px}
.fd-x:hover{color:var(--text)}
.fd-x:focus-visible{outline:2px solid var(--purple);outline-offset:2px}
.fd-tabs{display:flex;gap:4px;padding:0 14px;border-bottom:1px solid var(--line);background:var(--bg)}
.fd-tab{border:0;background:transparent;padding:11px 12px;font:inherit;font-size:13.5px;font-weight:600;
  color:var(--muted);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}
.fd-tab:hover{color:var(--text)}
.fd-tab.active{color:var(--purple);border-bottom-color:var(--purple)}
.fd-tab:focus-visible{outline:2px solid var(--purple);outline-offset:-2px;border-radius:6px}
.fd-body{padding:20px 22px;overflow:auto;flex:1;min-height:220px}
.fd-foot{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:14px 22px;border-top:1px solid var(--line);background:var(--bg)}
.fd-foot-left{display:flex;flex-wrap:wrap;gap:8px}
.fd-danger{color:var(--red);border-color:var(--red)}
.fd-flash{margin:14px 22px -6px;padding:10px 13px;border-radius:10px;font-size:13px;
  background:var(--bg);border:1px solid var(--line);color:var(--text)}
.fd-flash.err{border-color:var(--red);color:var(--red)}
.fd-note{padding:26px 20px;text-align:center;color:var(--muted);font-size:13.5px;line-height:1.55}
.fd-intro{margin:0 0 14px;color:var(--muted);font-size:13px;line-height:1.55}
/* Preview surfaces. A checker-free flat ground so a transparent PNG still reads as
   an image rather than as part of the dialog. */
.fd-frame{display:grid;place-items:center;background:var(--bg);border:1px solid var(--line);
  border-radius:10px;padding:12px;min-height:240px}
.fd-frame img{max-width:100%;max-height:52vh;object-fit:contain;border-radius:6px}
.fd-frame.pdf{padding:0;min-height:0}
.fd-frame.pdf iframe{width:100%;height:56vh;border:0;border-radius:10px;display:block}
.fd-text{margin:0;padding:14px;background:var(--bg);border:1px solid var(--line);border-radius:10px;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;line-height:1.55;
  color:var(--text);white-space:pre-wrap;word-break:break-word;max-height:52vh;overflow:auto}
.fd-scroll{overflow:auto;max-height:52vh;border:1px solid var(--line);border-radius:10px}
.fd-table{margin:0;font-size:12.5px}
.fd-table th{position:sticky;top:0;background:var(--card);z-index:1}
.fd-table td{white-space:nowrap;max-width:260px;overflow:hidden;text-overflow:ellipsis}
/* Details form */
.fd-field{display:block;margin-bottom:16px}
.fd-field>span:first-child{display:block;margin-bottom:6px;font-size:13px;font-weight:700;color:var(--text)}
.fd-field input[type=text],.fd-field select{width:100%;height:42px;border:1px solid var(--line);border-radius:10px;
  background:var(--card);padding:0 14px;color:var(--text);font:inherit;font-size:14px}
.fd-field input[type=text]:focus,.fd-field select:focus{outline:none;border-color:var(--blue);
  box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.fd-field input[disabled],.fd-field select[disabled]{background:var(--bg);color:var(--muted);cursor:default}
.fd-field .right-note{display:block;margin-top:6px}
.fd-meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px 18px;
  padding:14px;background:var(--bg);border:1px solid var(--line);border-radius:10px}
.fd-meta>div{min-width:0}
.fd-meta span{display:block;font-size:11.5px;font-weight:600;text-transform:uppercase;
  letter-spacing:.04em;color:var(--muted)}
.fd-meta strong{display:block;margin-top:3px;font-size:13.5px;font-weight:600;color:var(--text);
  overflow:hidden;text-overflow:ellipsis}
.fd-save{margin-top:18px;display:flex;justify-content:flex-end}
/* The Save block is drawn on every render and revealed only once something has
   actually changed. .fd-save sets display:flex, and an author display beats the
   UA sheet[hidden] whatever the specificity says, so hiding it has to be said here. */
.fd-save[hidden]{display:none}
@media (max-width:640px){
  .fd-box{max-height:94vh}
  .fd-foot{flex-direction:column;align-items:stretch}
  .fd-foot-left{justify-content:stretch}
  .fd-foot-left .btn{flex:1}
}

/* ============================================================
   SCREEN LOCK (sessionlock.js)
   ------------------------------------------------------------
   What the idle deadline does INSTEAD of navigating to the login page. The app is
   left standing exactly as it was and put behind glass; signing back in takes the
   glass away and the page carries on mid-sentence.

   The obscuring is deliberately two things at once, because either alone is weak:
   a 16px blur destroys the shape of 13px text (no amount of squinting recovers a
   patient name), and the scrim on top drops the contrast of whatever survives it.
   Together nothing on the page is legible from across a room, over a shoulder, or
   in a photograph of the monitor.

   The blur is hung on body's CHILDREN, not on body itself, for two reasons: the
   shield is a sibling and must stay sharp, and a filter on an ancestor becomes the
   containing block for its fixed-position descendants — blurring body would drag
   every popover and modal in the app into a new coordinate space on the way past.
   Selecting the covered page with the mouse or the keyboard is off for the same
   reason the pixels are: nothing under the shield is meant to leave it.

   z-index sits above every layer this app defines (top is 1400) AND above the
   embedded voice-test widget, which mounts itself on body with its own stacking
   and is not ours to bound. Whatever else is on screen, the lock is over it.
   ------------------------------------------------------------ */
body.oc-locked{overflow:hidden}
body.oc-locked>*:not(#oc-lock){
  filter:blur(16px) saturate(.55);
  pointer-events:none;
  user-select:none;-webkit-user-select:none;
}
/* Only the lock fades in — the app is not animated on the way behind the glass,
   because a transition on a full-page filter janks on a long patient table. */
.oc-lock{
  position:fixed;inset:0;z-index:2147483000;
  display:grid;place-items:center;padding:24px;
  background:rgba(7,20,41,.72);
  animation:ocLockIn .18s ease-out;
}
@keyframes ocLockIn{from{opacity:0}to{opacity:1}}
@media (prefers-reduced-motion:reduce){.oc-lock{animation:none}}

.oc-lock-card{
  width:100%;max-width:400px;background:var(--card);border:1px solid var(--line);
  border-radius:16px;box-shadow:0 32px 80px rgba(7,20,41,.55);padding:28px;text-align:center;
}
.oc-lock-mark{
  width:52px;height:52px;margin:0 auto 16px;border-radius:14px;
  display:grid;place-items:center;color:var(--blue);
  background:rgba(37,99,235,.10);border:1px solid rgba(37,99,235,.22);
}
.oc-lock-title{margin:0 0 8px;font-size:19px;font-weight:800;color:var(--text)}
.oc-lock-why{margin:0 0 20px;font-size:13.5px;line-height:1.55;color:var(--muted)}

/* Who is being asked for a password. Shown, not editable: this proves the person
   already signed in is still at the desk. Switching accounts is Sign out. */
.oc-lock-who{
  display:flex;align-items:center;gap:11px;text-align:left;margin:0 0 18px;
  padding:11px 13px;background:var(--bg);border:1px solid var(--line);border-radius:11px;
}
.oc-lock-avatar{
  flex:none;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;
  background:var(--navy);color:#fff;font-weight:800;font-size:14px;
}
.oc-lock-who-text{min-width:0;display:flex;flex-direction:column;line-height:1.35}
.oc-lock-who-text b{font-size:13.5px;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.oc-lock-who-text span{font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

.oc-lock-form{text-align:left}
.oc-lock-label{display:block;margin-bottom:6px;font-size:13px;font-weight:700;color:var(--text)}
.oc-lock-input{
  width:100%;height:44px;border:1px solid var(--line);border-radius:10px;background:var(--card);
  padding:0 14px;color:var(--text);font-size:14px;margin-bottom:14px;
}
.oc-lock-input:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.oc-lock-input[hidden],.oc-lock-label[hidden]{display:none}
.oc-lock-err{
  margin:-4px 0 14px;padding:10px 12px;border-radius:10px;font-size:13px;line-height:1.45;
  color:var(--red);background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.22);
}
.oc-lock-err[hidden]{display:none}
.oc-lock-actions{display:flex;gap:10px}
.oc-lock-actions .btn{flex:1}

/* ------------------------------------------------------------
   The heads-up, one minute out. Deliberately a real dialog rather than a corner
   toast: the whole point is that it is seen by someone who has stopped looking,
   and losing a half-written note to a toast nobody noticed is the failure this
   feature exists to prevent. It sits under the shield's layer but over the app's.
   ------------------------------------------------------------ */
.oc-idle-warn{display:none}
.oc-idle-warn.open{
  display:grid;place-items:center;
  position:fixed;inset:0;z-index:2147482000;padding:24px;
  background:rgba(7,20,41,.35);
}
.oc-idle-warn-box{
  width:100%;max-width:380px;background:var(--card);border:1px solid var(--line);
  border-radius:14px;box-shadow:0 24px 60px rgba(7,20,41,.4);padding:22px;
}
.oc-idle-warn-title{margin:0 0 8px;font-size:16.5px;font-weight:800;color:var(--text)}
.oc-idle-warn-msg{margin:0 0 18px;font-size:13.5px;line-height:1.55;color:var(--muted)}
.oc-idle-warn-msg b{color:var(--text);font-variant-numeric:tabular-nums}
.oc-idle-warn-actions{display:flex;justify-content:flex-end}

@media (max-width:480px){
  .oc-lock-card{padding:22px}
  .oc-lock-actions{flex-direction:column-reverse}
}

/* ============================================================
   Appointments — the practice's own schedule (js/pages/appointments.js).
   Days across, time down. Row height is set by the page (--ap-row) so a practice
   on 15-minute slots gets more rows, not thinner ones; --ap-hour draws the heavier
   line on the hour. Every colour here comes from theme.css.
   ============================================================ */

/* ---- Toolbar ---- */
.ap-toolbar{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;padding:2px 2px 6px;margin-bottom:8px}
.ap-tb-left,.ap-tb-right{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ap-toolbar .ap-range{margin:0;font-size:18px;font-weight:800;white-space:nowrap;text-align:center;min-width:104px}
.ap-toolbar .btn.ap-nav{padding:7px 13px;font-size:17px;line-height:1}
/* "Today" is a jump-back-to-now reset, not part of the ‹ › pager - nudge it clear of the arrows. */
.ap-toolbar .btn.ap-today{margin-left:6px}
.ap-toolbar select{padding:8px 10px;border:1px solid var(--line);border-radius:10px;background:#fff;color:var(--text);font:inherit;font-size:13px}

/* Segmented control — also the form's "existing patient / new caller" switch. */
.ap-zoom{display:inline-flex;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--bg)}
.ap-zoom-btn{border:0;background:transparent;padding:8px 14px;font:inherit;font-size:13px;font-weight:700;color:var(--muted);cursor:pointer}
.ap-zoom-btn+.ap-zoom-btn{border-left:1px solid var(--line)}
.ap-zoom-btn:hover{color:var(--text)}
.ap-zoom-btn.active{background:#fff;color:var(--purple);box-shadow:inset 0 -2px 0 var(--purple)}

.ap-panel{padding:0;overflow:hidden}
.ap-hint{margin:0;padding:10px 16px;border-top:1px solid var(--line);background:var(--bg)}

/* ---- Week grid ---- */
/* The grid draws only the working-hours band (widened for any off-hours visit that week;
   see apDrawWindow in appointments.js) at natural height and sits flat on the page, so the
   PAGE scrolls as one — there is no capped inner scrollbox to trap the wheel. Only sideways
   overflow is contained, so a narrow viewport scrolls the columns without widening the page. */
.ap-week{--ap-gutter:66px}
.ap-weekwrap{position:relative}
.ap-week-grid{overflow-x:auto}
.ap-week-head,.ap-week-body{display:grid;grid-template-columns:var(--ap-gutter) repeat(7,minmax(96px,1fr));min-width:760px}
.ap-week-head{position:sticky;top:0;z-index:5;background:#fff;border-bottom:1px solid var(--line)}
.ap-gutter-head{border-right:1px solid var(--line)}
.ap-dayhead{display:flex;align-items:baseline;justify-content:center;gap:7px;padding:12px 6px;border-right:1px solid var(--line);position:relative}
.ap-dayhead:last-child{border-right:0}
.ap-dh-day{font-size:12px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
.ap-dh-date{font-size:20px;font-weight:800;color:var(--text);font-variant-numeric:tabular-nums}
.ap-dayhead.closed .ap-dh-day,.ap-dayhead.closed .ap-dh-date{color:#98a2b3}
.ap-dh-note{position:absolute;bottom:2px;left:0;right:0;text-align:center;font-size:10px;font-weight:700;color:#98a2b3;text-transform:uppercase;letter-spacing:.05em}
.ap-dayhead.today{background:var(--bg)}
.ap-dayhead.today .ap-dh-date{color:var(--purple)}

.ap-gutter{border-right:1px solid var(--line)}
.ap-rowlabel{display:flex;align-items:flex-start;justify-content:flex-end;padding:0 8px;font-size:11px;font-weight:700;color:var(--muted);transform:translateY(-6px);font-variant-numeric:tabular-nums;white-space:nowrap}

/* The hour rule is listed FIRST so it paints on top of the coincident slot rule. */
.ap-daycol{position:relative;border-right:1px solid var(--line);
  background-image:
    repeating-linear-gradient(to bottom,var(--ap-hourline) 0 1px,transparent 1px var(--ap-hour)),
    repeating-linear-gradient(to bottom,var(--ap-line) 0 1px,transparent 1px var(--ap-row));
  /* Slot rule stays anchored at the top; the hour rule shifts to the first whole hour when
     the band opens on a :30 (see --ap-hourshift in appointments.js). */
  background-position:0 var(--ap-hourshift,0px),0 0;
  cursor:copy}
.ap-daycol:last-child{border-right:0}
.ap-daycol.today{background-color:rgba(109,93,252,.03)}
.ap-daycol.closed{cursor:default}

/* Outside the practice's hours: greyed AND inert, drawn from the same business hours
   the booking route refuses with. */
.ap-closed-band{position:absolute;left:0;right:0;z-index:1;background:var(--ap-closed);
  background-image:repeating-linear-gradient(135deg,transparent 0 6px,rgba(102,112,133,.06) 6px 12px)}
/* A partial-day block-out (lunch, half day out): same closed grey, hatched a touch
   heavier so it reads as deliberate inside an otherwise-open day, with its reason
   printed when the band is tall enough (full detail on hover title). */
.ap-bo-band{background-image:repeating-linear-gradient(135deg,transparent 0 6px,rgba(102,112,133,.14) 6px 12px);
  overflow:hidden;text-align:right}
.ap-bo-label{display:inline-block;max-width:100%;padding:1px 6px;font-size:10px;font-weight:700;
  color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.ap-nowline{position:absolute;left:0;right:0;height:0;border-top:2px solid var(--red);z-index:4;pointer-events:none}
.ap-nowline span{position:absolute;left:-4px;top:-4px;width:7px;height:7px;border-radius:50%;background:var(--red)}

/* ---- A block ---- */
.ap-blk{position:absolute;z-index:2;box-sizing:border-box;overflow:hidden;padding:3px 6px;border:1px solid;border-radius:8px;
  font-size:11.5px;line-height:1.3;cursor:pointer;transition:box-shadow .12s ease,transform .12s ease}
.ap-blk:hover{box-shadow:0 4px 12px rgba(16,24,40,.16);z-index:3}
.ap-blk:focus-visible{outline:2px solid var(--purple);outline-offset:1px}
.ap-blk-time{font-weight:800;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ap-blk-who{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ap-blk-sub{opacity:.75;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ap-blk-flag{font-weight:700}
/* An appointment that runs past the drawn band keeps a flat edge, so a clipped block
   never reads as one that genuinely ends at the top or bottom of the day. */
.ap-blk.clip-top{border-top-left-radius:0;border-top-right-radius:0;border-top-style:dashed}
.ap-blk.clip-bottom{border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-style:dashed}
/* Not attached to a patient account — visible at a glance across the whole week. */
.ap-blk.unlinked,.ap-chip.unlinked{border-style:dashed;border-width:1.5px}
.ap-blk[data-status="cancelled"]{opacity:.5}
.ap-blk[data-status="cancelled"] .ap-blk-who{text-decoration:line-through}
.ap-blk[data-status="completed"]{opacity:.72}
.ap-blk[data-status="checked_in"]{box-shadow:inset 3px 0 0 var(--green)}
.ap-blk[data-status="no_show"]{opacity:.55}
.ap-blk[data-status="no_show"] .ap-blk-who{text-decoration:line-through}

/* ---- Palette (theme.css owns the values) ---- */
.ap-c-sky{background:var(--ap-sky-bg);border-color:var(--ap-sky-bd);color:var(--ap-sky-fg)}
.ap-c-violet{background:var(--ap-violet-bg);border-color:var(--ap-violet-bd);color:var(--ap-violet-fg)}
.ap-c-emerald{background:var(--ap-emerald-bg);border-color:var(--ap-emerald-bd);color:var(--ap-emerald-fg)}
.ap-c-amber{background:var(--ap-amber-bg);border-color:var(--ap-amber-bd);color:var(--ap-amber-fg)}
.ap-c-rose{background:var(--ap-rose-bg);border-color:var(--ap-rose-bd);color:var(--ap-rose-fg)}
.ap-c-teal{background:var(--ap-teal-bg);border-color:var(--ap-teal-bd);color:var(--ap-teal-fg)}
.ap-c-indigo{background:var(--ap-indigo-bg);border-color:var(--ap-indigo-bd);color:var(--ap-indigo-fg)}
.ap-c-slate{background:var(--ap-slate-bg);border-color:var(--ap-slate-bd);color:var(--ap-slate-fg)}

/* ---- Month zoom ---- */
.ap-month{overflow-x:auto}
.ap-mhead,.ap-mrow{display:grid;grid-template-columns:repeat(7,minmax(104px,1fr));min-width:760px}
.ap-mhead{position:sticky;top:0;z-index:5;background:#fff;border-bottom:1px solid var(--line)}
.ap-mhead-cell{padding:11px 10px;font-size:12px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;border-right:1px solid var(--line)}
.ap-mhead-cell:last-child{border-right:0}
.ap-mrow{border-bottom:1px solid var(--line)}
.ap-mrow:last-of-type{border-bottom:0}
.ap-mcell{min-height:114px;padding:8px;border-right:1px solid var(--line);cursor:pointer}
.ap-mcell:last-child{border-right:0}
.ap-mcell:hover{background:var(--bg)}
.ap-mcell.out{background:var(--bg)}
.ap-mcell.out .ap-mdate{color:#c3cad6}
.ap-mcell.closed{background-image:repeating-linear-gradient(135deg,transparent 0 6px,rgba(102,112,133,.05) 6px 12px)}
.ap-mdate{font-size:13px;font-weight:800;color:var(--text);font-variant-numeric:tabular-nums;margin-bottom:5px}
.ap-mcell.today .ap-mdate{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;padding:0 5px;border-radius:999px;background:var(--purple);color:#fff}
.ap-mchips{display:flex;flex-direction:column;gap:3px}
.ap-chip{padding:2px 6px;border:1px solid;border-radius:6px;font-size:11px;line-height:1.35;font-weight:600;cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ap-chip:focus-visible{outline:2px solid var(--purple);outline-offset:1px}
.ap-chip-t{font-weight:800;font-variant-numeric:tabular-nums}
.ap-chip[data-status="cancelled"],.ap-chip[data-status="no_show"]{opacity:.5;text-decoration:line-through}
.ap-more{border:0;background:transparent;padding:1px 4px;font:inherit;font-size:11px;font-weight:700;color:var(--purple);cursor:pointer;text-align:left}

/* ---- Popover ---- */
.ap-pop{position:fixed;z-index:140;width:352px;max-width:calc(100vw - 20px);max-height:calc(100vh - 20px);overflow:auto;
  background:#fff;border:1px solid var(--line);border-radius:14px;box-shadow:0 18px 44px rgba(16,24,40,.22)}
.ap-pop-head{position:relative;padding:14px 40px 12px 16px;border-bottom:1px solid var(--line)}
.ap-pop-title{font-size:15px;font-weight:800;line-height:1.3}
.ap-pop-when{margin-top:3px;font-size:12.5px;color:var(--muted);font-weight:600}
.ap-pop-x{position:absolute;top:9px;right:9px;width:26px;height:26px;border:0;border-radius:8px;background:transparent;
  font-size:19px;line-height:1;color:var(--muted);cursor:pointer}
.ap-pop-x:hover{background:var(--bg);color:var(--text)}
.ap-pop-body{padding:12px 16px;display:flex;flex-direction:column;gap:8px}
.ap-pop-row{display:flex;gap:10px;align-items:baseline;font-size:13px}
.ap-pop-k{flex:0 0 92px;color:var(--muted);font-weight:700;font-size:12px}
.ap-pop-v{flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
.ap-link{color:var(--blue);font-weight:700;text-decoration:none}
.ap-link:hover{text-decoration:underline}
.ap-warn-text{color:var(--orange);font-weight:700}
.ap-pop-intake{margin-top:4px;padding:10px 12px;border:1px dashed var(--line);border-radius:10px;background:var(--bg);display:flex;flex-direction:column;gap:6px}
.ap-pop-intake-h{font-size:11px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.05em}
.ap-pop-verbatim{margin-top:2px;padding:8px 10px;border-left:3px solid var(--line);background:#fff;border-radius:0 8px 8px 0;
  font-size:12.5px;color:#344054;white-space:pre-wrap}
.ap-pop-ext{margin:2px 0 0}
.ap-pop-foot{display:flex;flex-wrap:wrap;gap:7px;padding:12px 16px;border-top:1px solid var(--line);background:var(--bg)}
.btn.ap-mini{padding:6px 11px;font-size:12.5px}
.btn.secondary.ap-danger{color:var(--red);border-color:#fbc7c7}
.btn.secondary.ap-danger:hover{background:#fef2f2}
.ap-pop-link{width:360px}
/* Click-a-slot chooser + quick block-out form (calendar, admin) */
.ap-pop-menu{width:236px}
.ap-slot-when{font-size:11.5px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;padding:2px 2px 5px}
.ap-slot-choice{width:100%;padding:10px 12px;font-size:13.5px}
.ap-pop-bo{width:308px}
.ap-bo-form label{display:flex;flex-direction:column;gap:4px;font-size:11.5px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.03em}
.ap-bo-form input,.ap-bo-form select{font-size:13.5px;font-weight:600;color:var(--text);text-transform:none;letter-spacing:normal;padding:8px 10px;border:1px solid var(--line);border-radius:9px;background:#fff;width:100%}
.ap-bo-two{display:flex;gap:8px}
.ap-bo-two label{flex:1 1 0}
.ap-bo-form .ap-form-actions{display:flex;gap:8px;margin-top:6px}
.ap-bo-form .ap-form-actions .btn{flex:1 1 0}

/* ---- Patient picker ---- */
.ap-psearch{position:relative}
.ap-psearch-in{width:100%;padding:9px 11px;border:1px solid var(--line);border-radius:10px;font:inherit;font-size:13px;background:#fff;color:var(--text)}
.ap-psearch-in:focus{outline:0;border-color:var(--purple);box-shadow:0 0 0 3px rgba(109,93,252,.14)}
.ap-psearch-results{position:absolute;z-index:60;top:calc(100% + 4px);left:0;right:0;max-height:236px;overflow:auto;
  background:#fff;border:1px solid var(--line);border-radius:11px;box-shadow:0 12px 30px rgba(16,24,40,.16)}
.ap-psearch-results[hidden]{display:none}
.ap-psearch-row{display:flex;flex-direction:column;gap:1px;width:100%;padding:8px 11px;border:0;border-bottom:1px solid var(--line);
  background:transparent;font:inherit;text-align:left;cursor:pointer}
.ap-psearch-row:last-child{border-bottom:0}
.ap-psearch-row:hover{background:var(--bg)}
.ap-ps-name{font-size:13px;font-weight:700;color:var(--text)}
.ap-ps-meta{font-size:12px;color:var(--muted)}
.ap-psearch-empty{padding:10px 12px;font-size:12.5px;color:var(--muted)}

/* ---- Booking form ---- */
.ap-form-grid{display:flex;flex-wrap:wrap;gap:12px 16px;align-items:flex-end}
.ap-form-grid label,.ap-intake-grid label{display:flex;flex-direction:column;gap:5px;font-size:12px;font-weight:700;color:var(--muted);position:relative}
.ap-form-grid label.ap-wide,.ap-intake-grid label.ap-wide{flex:1 1 100%}
.ap-form-grid input,.ap-form-grid select,.ap-form-grid textarea,
.ap-intake-grid input{padding:9px 11px;border:1px solid var(--line);border-radius:10px;font:inherit;font-size:13px;
  font-weight:500;color:var(--text);background:#fff}
.ap-form-grid input:focus,.ap-form-grid select:focus,.ap-form-grid textarea:focus,.ap-intake-grid input:focus{
  outline:0;border-color:var(--purple);box-shadow:0 0 0 3px rgba(109,93,252,.14)}
.ap-form-grid textarea{resize:vertical;min-height:52px}
.ap-suffix{position:absolute;right:11px;bottom:10px;font-size:11px;font-weight:700;color:var(--muted);pointer-events:none}
.ap-form-grid input[type=number]{padding-right:38px;width:118px}
.ap-who-head{display:flex;justify-content:space-between;align-items:center;gap:14px;flex-wrap:wrap;margin-bottom:12px}
.ap-who-head h3{margin:0;font-size:14px;font-weight:800}
.ap-intake-grid{display:flex;flex-wrap:wrap;gap:12px 16px}
.ap-intake-grid label{flex:1 1 190px}
.ap-chosen{display:inline-flex;align-items:center;gap:9px;padding:8px 10px 8px 13px;border:1px solid var(--line);border-radius:11px;background:var(--bg)}
.ap-chosen-name{font-size:13.5px;font-weight:700}
.ap-chosen-x{width:22px;height:22px;border:0;border-radius:7px;background:transparent;font-size:16px;line-height:1;color:var(--muted);cursor:pointer}
.ap-chosen-x:hover{background:#fff;color:var(--text)}
.ap-form-actions{display:flex;gap:9px;margin-top:16px}
.ap-form #ap-form-pick{max-width:420px}

/* Booking form as a centered AJAX popup: opening it never scrolls the schedule.
   Above the grid and the detail popover (140), below the confirm modal (200) — same
   scrim the app's other overlays use. The .ap-form panel itself is the dialog box. */
.ap-modal-back{position:fixed;inset:0;z-index:160;background:rgba(7,20,41,.45);display:grid;place-items:center;padding:24px;overflow:auto;animation:ocConfirmFade .12s ease-out}
.ap-modal-back .ap-form{width:min(640px,calc(100vw - 32px));max-height:calc(100vh - 48px);overflow:auto;margin:0;box-shadow:0 24px 60px rgba(7,20,41,.45)}
.ap-form-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.ap-modal-x{border:0;background:transparent;color:var(--muted);font-size:24px;line-height:1;cursor:pointer;padding:2px 8px;border-radius:8px;margin:-4px -4px 0 0}
.ap-modal-x:hover{background:var(--bg);color:var(--text)}
.ap-form #ap-form-note{margin:0 0 14px}
.ap-cap{margin-top:12px;border-top:1px solid var(--line);padding-top:12px}
.ap-cap-head{margin:12px 0 2px;font-size:.95rem}
.ap-cap-head:first-child{margin-top:0}
.ap-cap-week{display:flex;flex-wrap:wrap;gap:10px;margin:8px 0 2px}
.ap-cap-day{display:flex;flex-direction:column;gap:4px;font-size:.78rem;color:var(--muted);width:62px}
.ap-cap-day input{width:100%}
.ap-cap-dates{display:flex;flex-direction:column;gap:8px;margin:8px 0}
.ap-cap-date{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ap-cap-date input[data-cap-date-n]{width:84px}
.ap-cap-add-wrap{margin-top:4px}

/* ---- Holiday closures (Configuration tab) ---- */
.ap-hol-rows{display:flex;flex-direction:column;gap:8px;margin:8px 0}
.ap-hol-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.ap-hol-row input.ap-hol-name{flex:1 1 180px;min-width:150px}
.ap-hol-annual{display:inline-flex;align-items:center;gap:6px;font-size:.82rem;color:var(--muted);white-space:nowrap}
.ap-hol-annual input{margin:0}
.ap-hol-actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:4px}
.ap-hol-presets{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}
.ap-hol-presets-label{font-size:.82rem;color:var(--muted)}
/* Block-out rows reuse the holiday row layout; the start–end pair stays glued together. */
.ap-bo-range{display:inline-flex;align-items:center;gap:4px}
.ap-bo-dash{color:var(--muted)}
/* Day-of-month spinner in a Configuration block-out row — kept compact like the time inputs. */
.ap-bo-row input[data-bo-monthday]{width:72px}
/* Holiday name in the week header: truncate with an ellipsis, full text on hover title. */
.ap-dh-note{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:0 4px}
/* Holiday name inside a month cell, under the date. */
.ap-mhol{font-size:11px;font-weight:700;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:4px}

/* ---- Unlinked worklist ---- */
.ap-unlist{display:flex;flex-direction:column;gap:10px;margin-top:12px}
.ap-unrow{display:grid;grid-template-columns:150px 1fr 150px 240px;gap:16px;align-items:start;
  padding:13px 14px;border:1px solid var(--line);border-left:3px solid var(--orange);border-radius:12px;background:var(--bg)}
.ap-un-day{font-size:13.5px;font-weight:800}
.ap-un-who{font-size:13.5px;font-weight:700;margin-bottom:2px}
.ap-un-status{display:flex;flex-direction:column;gap:5px;align-items:flex-start}
.ap-un-act{display:flex;flex-direction:column;gap:8px}
@media (max-width:1180px){.ap-unrow{grid-template-columns:1fr 1fr}}
@media (max-width:760px){.ap-unrow{grid-template-columns:1fr}}

/* ---- Setup catalogs ---- */
.ap-cat-list{display:flex;flex-direction:column;gap:2px;margin-top:10px}
.ap-cat-row{display:flex;align-items:center;gap:11px;padding:9px 4px;border-bottom:1px solid var(--line)}
.ap-cat-row:last-child{border-bottom:0}
.ap-cat-name{font-size:13.5px;font-weight:700}
.ap-cat-act{margin-left:auto;display:flex;gap:7px}
.ap-dot{flex:0 0 auto;width:13px;height:13px;border-radius:4px;border:1px solid}
.ap-cat-form{margin:12px 0 4px;padding:14px;border:1px solid var(--line);border-radius:12px;background:var(--bg)}
.ap-swatch-label{display:flex;flex-direction:column;gap:7px;margin-top:14px;font-size:12px;font-weight:700;color:var(--muted)}
.ap-swatches{display:flex;gap:7px;flex-wrap:wrap}
.ap-swatch{width:28px;height:28px;border-radius:8px;border:1px solid;cursor:pointer}
.ap-swatch.active{box-shadow:0 0 0 2px #fff,0 0 0 4px var(--purple)}
.ap-check{display:flex;align-items:center;gap:9px;margin-top:14px;font-size:13px;font-weight:600;color:var(--text)}
.ap-check input{width:16px;height:16px;accent-color:var(--purple)}

@media (max-width:900px){
  .ap-toolbar{padding:2px 0 6px}
  .ap-tb-left,.ap-tb-right{width:100%}
  .ap-toolbar .ap-range{font-size:16px}
  .ap-pop{width:min(352px,calc(100vw - 20px))}
}

/* Appointments tab on the patient record. Three columns - when / what / status - with
   the when column fixed so a run of visits reads as a column of dates rather than
   ragged text. Upcoming rows carry a left rule in the brand accent; past rows stay
   quiet, because history is reference and the next visit is the answer. */
.pt-appt-group{margin-top:14px}
.pt-appt-group:first-child{margin-top:0}
.pt-appt-h{font-weight:700;font-size:13px;margin-bottom:8px}
.pt-appt{display:grid;grid-template-columns:190px 1fr auto;gap:12px;align-items:start;
  padding:11px 12px;border:1px solid var(--line);border-left:3px solid var(--line);
  border-radius:10px;background:var(--card);margin-bottom:8px}
.pt-appt.upcoming{border-left-color:var(--purple)}
.pt-appt-when{display:flex;flex-direction:column;gap:2px}
.pt-appt-what{font-size:13px;line-height:1.5;min-width:0}
.pt-appt-what>div{overflow-wrap:anywhere}
.pt-appt-side{display:flex;align-items:center}
@media (max-width:760px){
  .pt-appt{grid-template-columns:1fr auto}
  .pt-appt-when{grid-column:1/-1;flex-direction:row;align-items:baseline;gap:8px}
}

/* ── Modern dropdowns ──────────────────────────────────────────────────────────
   The sidebar location switcher hides the native OS <select> chevron
   (appearance:none) and paints a clean custom caret — that's the "modern" look.
   These rules give the same treatment, in the light page palette, to the
   standalone filter / range / toolbar dropdowns that were still rendering the raw
   native control (the reports date range, list-page filters, the Files filters,
   and the per-page working-location bar). Appended at end-of-file on purpose: the
   base rules for these selects live earlier, so a later longhand (padding-right /
   background-image) cleanly overrides their `padding` / `background` shorthands.
   Scope is deliberate — page-level SINGLE-select dropdowns only. Form-grid, dialog,
   report-builder and multi-selects keep the native control (a custom caret would
   crowd those denser contexts, and means nothing on a multi-select list box). */
.top-actions select,
.filterbar select,
.up-filters select,
.loc-scope-bar select{
  appearance:none;-webkit-appearance:none;padding-right:34px;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center;
}
/* Reports date-range picker: the switcher's modern look, lighter and one size
   smaller (36px vs the rail's 42px) so it sits neatly in the report toolbar. It
   had NO styling before (raw native control), so this rule provides all of it. */
[data-rep-preset]{
  height:36px;padding:0 34px 0 12px;border:1px solid var(--line);border-radius:9px;
  background-color:#fff;color:var(--text);font-weight:600;font-size:13px;cursor:pointer;
  appearance:none;-webkit-appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center;
}
[data-rep-preset]:hover{border-color:#cbd2dc}
[data-rep-preset]:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}

/* ============================================================
   User Guide (pages/guide.js) — the rendered docs/SOP.md handbook.
   Two-column: sticky Contents rail + the document. Collapses to one
   column on narrow screens (TOC on top). All colors via theme vars.
   ============================================================ */
.gd-layout{display:grid;grid-template-columns:250px minmax(0,1fr);gap:20px;align-items:start}
.gd-toc{position:sticky;top:16px;max-height:calc(100vh - 32px);overflow-y:auto;padding:16px}
.gd-toc-title{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-bottom:10px}
.gd-toc-nav{display:flex;flex-direction:column;gap:2px}
.gd-toc-item{display:block;padding:5px 10px;border-radius:8px;font-size:13px;color:var(--text);text-decoration:none;line-height:1.35}
.gd-toc-item:hover{background:var(--bg)}
.gd-toc-item.active{background:var(--bg);color:var(--blue);font-weight:600}
.gd-toc-l1{font-weight:700;margin-top:10px;font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.gd-toc-l1:first-child{margin-top:0}
.gd-toc-l2{padding-left:16px}
.gd-updated{margin-top:14px;padding-top:12px;border-top:1px solid var(--line);font-size:12px;color:var(--muted)}
.gd-doc{padding:28px 34px;max-width:860px;line-height:1.65;font-size:14px}
.gd-doc h1,.gd-doc h2,.gd-doc h3,.gd-doc h4{scroll-margin-top:16px;line-height:1.3}
.gd-doc h1{font-size:24px;margin:34px 0 12px;padding-bottom:10px;border-bottom:2px solid var(--line)}
.gd-doc h1:first-child{margin-top:0}
.gd-doc h2{font-size:19px;margin:30px 0 10px}
.gd-doc h3{font-size:15px;margin:22px 0 8px}
.gd-doc h4{font-size:14px;margin:18px 0 6px}
.gd-doc p{margin:0 0 12px}
.gd-doc ul,.gd-doc ol{margin:0 0 12px;padding-left:24px}
.gd-doc li{margin-bottom:6px}
.gd-doc hr{border:none;border-top:1px solid var(--line);margin:26px 0}
.gd-doc code{background:var(--bg);border:1px solid var(--line);border-radius:5px;padding:1px 5px;font-size:12.5px}
.gd-note{margin:0 0 14px;padding:10px 14px;border-left:3px solid var(--orange);background:var(--bg);border-radius:0 8px 8px 0}
.gd-note p{margin:0}
.gd-note p+p{margin-top:8px}
.gd-table-wrap{overflow-x:auto;margin:0 0 14px}
.gd-table-wrap .table{margin:0;min-width:420px}
.gd-jump,.gd-navlink{color:var(--blue);text-decoration:none;font-weight:600}
.gd-jump:hover,.gd-navlink:hover{text-decoration:underline}
/* Guide illustration figures ({{FIG:...}} in the markdown). The image is an
   SVG mockup served by /api/guide/fig; click to enlarge (guide.js lightbox). */
.gd-fig{margin:6px 0 18px;border:1px solid var(--line);border-radius:12px;overflow:hidden;background:#fff;box-shadow:var(--shadow)}
.gd-fig img{display:block;width:100%;height:auto;cursor:zoom-in}
.gd-fig figcaption{padding:9px 14px;font-size:12.5px;color:var(--muted);border-top:1px solid var(--line);background:var(--bg)}
.gd-lightbox{position:fixed;inset:0;z-index:400;background:rgba(7,20,41,.72);display:grid;place-items:center;padding:28px;cursor:zoom-out}
.gd-lightbox img{max-width:min(1300px,100%);max-height:100%;border-radius:12px;background:#fff;box-shadow:0 24px 64px rgba(0,0,0,.45)}
@media (max-width:900px){
  .gd-layout{grid-template-columns:1fr}
  .gd-toc{position:static;max-height:220px}
  .gd-doc{padding:20px}
}

/* ============================================================
   Help Center front page (pages/help.js) — hero search + results,
   FAQ accordion (shared with pages/faq.js), and Contact Support
   (pages/support.js). All colors via theme vars.
   ============================================================ */
.help-hero{padding:34px 34px 26px;margin-bottom:20px;text-align:center}
.help-hero-t{font-size:24px;font-weight:800;margin-bottom:4px}
.help-hero-sub{margin-bottom:18px}
.help-search-wrap{position:relative;max-width:640px;margin:0 auto}
.help-search-ic{position:absolute;left:16px;top:50%;transform:translateY(-50%);font-size:15px;opacity:.55;pointer-events:none}
.help-search{width:100%;height:48px;padding:0 18px 0 44px;border:1px solid var(--line);border-radius:12px;
  background:var(--bg);color:var(--text);font-size:15px}
.help-search:focus{outline:none;border-color:var(--blue);background:var(--card);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
.help-results{max-width:640px;margin:10px auto 0;text-align:left;border:1px solid var(--line);
  border-radius:12px;background:var(--card);overflow:hidden;max-height:420px;overflow-y:auto}
.help-sr{display:flex;gap:12px;align-items:flex-start;width:100%;padding:11px 14px;border:none;
  border-bottom:1px solid var(--line);background:none;cursor:pointer;text-align:left;font:inherit;color:var(--text)}
.help-sr:last-child{border-bottom:none}
.help-sr:hover{background:var(--bg)}
.help-sr mark{background:rgba(245,158,11,.3);color:inherit;border-radius:3px;padding:0 1px}
.help-sr-tag{flex:0 0 auto;font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;
  padding:2px 8px;border-radius:999px;margin-top:2px;border:1px solid transparent}
.help-sr-guide{background:rgba(37,99,235,.1);color:var(--blue);border-color:rgba(37,99,235,.25)}
.help-sr-faq{background:rgba(25,178,107,.12);color:var(--green);border-color:rgba(25,178,107,.3)}
.help-sr-task{background:rgba(109,77,252,.1);color:var(--purple);border-color:rgba(109,77,252,.25)}
.help-sr-body{min-width:0;display:flex;flex-direction:column;gap:2px}
.help-sr-title{font-weight:700;font-size:13.5px;line-height:1.35}
.help-sr-snip{font-size:12.5px;color:var(--muted);line-height:1.45}
.help-task-flash{animation:helpTaskFlash 1.6s ease}
@keyframes helpTaskFlash{0%,60%{background:rgba(245,158,11,.18);border-radius:10px}100%{background:transparent}}

/* FAQ accordion — used by the FAQ page and the Help front-page widget. */
.faq-layout{max-width:860px}
.faq-cat{margin-bottom:16px}
.faq-cat-t{font-size:16px;margin:0 0 6px}
.faq-item{border-bottom:1px solid var(--line)}
.faq-item:last-child{border-bottom:none}
.faq-q{display:flex;justify-content:space-between;align-items:center;gap:12px;width:100%;
  padding:12px 4px;border:none;background:none;cursor:pointer;text-align:left;font:inherit;
  font-weight:600;font-size:13.5px;color:var(--text);line-height:1.4}
.faq-q:hover{color:var(--blue)}
.faq-chev{flex:0 0 auto;font-size:16px;color:var(--muted);transform:rotate(90deg);transition:transform .15s}
.faq-item.open .faq-chev{transform:rotate(-90deg)}
.faq-a{display:none;padding:0 4px 14px;font-size:13.5px;line-height:1.6}
.faq-item.open .faq-a{display:block}
.faq-a p{margin:0 0 10px}
.faq-a p:last-child{margin-bottom:0}
.faq-a code{background:var(--bg);border:1px solid var(--line);border-radius:5px;padding:1px 5px;font-size:12px}

/* Contact Support */
.sup-label{display:block;font-size:12.5px;font-weight:600;margin:12px 0 5px}
.sup-label:first-of-type{margin-top:0}
#sup-subject,#sup-category,#sup-priority,#sup-message{width:100%;border:1px solid var(--line);border-radius:9px;
  background:var(--card);color:var(--text);font:inherit;font-size:13.5px;padding:9px 12px}
#sup-subject:focus,#sup-category:focus,#sup-priority:focus,#sup-message:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
#sup-message{resize:vertical;min-height:120px}
.sup-error{margin:0 0 12px;padding:9px 12px;border-radius:9px;font-size:13px;
  background:rgba(239,68,68,.09);border:1px solid rgba(239,68,68,.3);color:var(--red)}
.sup-sent{margin:0 0 12px;padding:9px 12px;border-radius:9px;font-size:13px;
  background:rgba(25,178,107,.1);border:1px solid rgba(25,178,107,.3);color:var(--green)}
.sup-ticket{padding:12px 0;border-bottom:1px solid var(--line)}
.sup-ticket:first-child{padding-top:0}
.sup-ticket:last-child{border-bottom:none}
.sup-ticket.is-closed{opacity:.65}
.sup-ticket-head{display:flex;justify-content:space-between;gap:10px;align-items:baseline;margin-bottom:2px}
.sup-ticket-msg{margin-top:6px;font-size:13px;line-height:1.5;white-space:pre-wrap;
  display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.sup-badge{flex:0 0 auto;font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;
  padding:2px 8px;border-radius:999px;border:1px solid transparent}
.sup-open{background:rgba(25,178,107,.12);color:var(--green);border-color:rgba(25,178,107,.3)}
.sup-closed{background:var(--bg);color:var(--muted);border-color:var(--line)}
.sup-badges{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}
/* Ticket priority (opener picks; normal shows no badge) — tinted like the
   appointment chips, colors from the theme's --ap-* triads. */
.sup-pri-low{background:var(--ap-slate-bg);color:var(--ap-slate-fg);border-color:var(--ap-slate-bd)}
.sup-pri-normal{background:var(--ap-sky-bg);color:var(--ap-sky-fg);border-color:var(--ap-sky-bd)}
.sup-pri-high{background:var(--ap-amber-bg);color:var(--ap-amber-fg);border-color:var(--ap-amber-bd)}
.sup-pri-urgent{background:var(--ap-rose-bg);color:var(--ap-rose-fg);border-color:var(--ap-rose-bd)}
/* Triage flag (support sets it; tenants see friendly wording like "Waiting on you"). */
.sup-flag-in_progress{background:var(--ap-indigo-bg);color:var(--ap-indigo-fg);border-color:var(--ap-indigo-bd)}
.sup-flag-waiting_customer{background:var(--ap-amber-bg);color:var(--ap-amber-fg);border-color:var(--ap-amber-bd)}
.sup-flag-fix_scheduled{background:var(--ap-violet-bg);color:var(--ap-violet-fg);border-color:var(--ap-violet-bd)}
.sup-flag-follow_up{background:var(--ap-teal-bg);color:var(--ap-teal-fg);border-color:var(--ap-teal-bd)}
/* Platform console: the per-ticket triage-flag picker (bare selects have no global style). */
.sup-flag-sel{height:32px;border:1px solid var(--line);border-radius:8px;background:#fff;padding:0 8px;font-size:12.5px;color:var(--text)}
/* Ticket list rows open the thread view. */
.sup-ticket.sup-click{cursor:pointer;margin:0 -10px;padding-left:10px;padding-right:10px;border-radius:9px}
.sup-ticket.sup-click:hover{background:var(--bg)}
/* Small metadata chips (tagged locations, members) on rows + the detail view. */
.sup-chip{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:600;
  padding:2px 8px;border-radius:999px;background:var(--bg);border:1px solid var(--line);color:var(--muted)}
.sup-chip .sup-chip-x{cursor:pointer;font-weight:700;color:var(--muted);padding:0 1px}
.sup-chip .sup-chip-x:hover{color:var(--red)}
.sup-chips{display:flex;gap:5px;flex-wrap:wrap;margin-top:7px}
/* Thread view: opener message + replies. Quantum Connect (support-team) replies are tinted. */
.sup-msg{padding:10px 12px;border:1px solid var(--line);border-radius:10px;margin-top:10px;background:var(--card)}
.sup-msg.is-platform{background:var(--ap-indigo-bg);border-color:var(--ap-indigo-bd)}
.sup-msg-head{display:flex;justify-content:space-between;gap:10px;font-size:12px;margin-bottom:4px}
.sup-msg-head strong{font-size:12.5px}
.sup-msg-body{font-size:13px;line-height:1.55;white-space:pre-wrap;overflow-wrap:anywhere}
#sup-reply{width:100%;border:1px solid var(--line);border-radius:9px;background:var(--card);color:var(--text);
  font:inherit;font-size:13.5px;padding:9px 12px;resize:vertical;min-height:70px}
#sup-reply:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(37,99,235,.15)}
/* Location scope picker (form + detail retag): radio rows + checkbox list. */
.sup-scope-opt{display:flex;align-items:center;gap:8px;font-size:13px;margin:4px 0;cursor:pointer}
.sup-scope-locs{margin:6px 0 0 24px;display:none}
.sup-scope-locs.open{display:block}
.sup-scope-locs label{display:flex;align-items:center;gap:8px;font-size:13px;margin:3px 0;cursor:pointer}
@media (max-width:760px){
  .help-hero{padding:24px 18px 20px}
}

/* --- Custom Variables (Reports › Custom Variables — js/pages/formulas.js) --- */
.fx-head{align-items:flex-start;gap:16px}
.fx-head h2{margin:0 0 4px}
.fx-head .right-note{margin:0;max-width:760px}
.fx-hint{font-size:12px;color:var(--muted);margin:0}
.fx-ro{margin:0 0 12px}
.fx-flash{margin:0 0 12px;padding:9px 12px;border-radius:9px;font-size:13px;font-weight:600;color:var(--green);background:color-mix(in srgb,var(--green) 9%,var(--card));border:1px solid color-mix(in srgb,var(--green) 30%,var(--line))}
.fx-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:12px}
.fx-card{border:1px solid var(--line);border-radius:12px;padding:14px;background:var(--card);display:flex;flex-direction:column;gap:8px;min-width:0}
.fx-card.is-broken{border-color:color-mix(in srgb,var(--red) 45%,var(--line))}
.fx-card-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.fx-card-name{font-weight:700;font-size:15px;color:var(--text);overflow-wrap:anywhere}
.fx-card-actions{margin-left:auto;display:flex;gap:6px}
.fx-card-desc{font-size:13px;color:var(--muted)}
.fx-card-err{font-size:12px;font-weight:600;color:var(--red)}
.fx-card-meta{font-size:11px;color:var(--muted);margin-top:auto}
.fx-type{--c:var(--muted);display:inline-flex;align-items:center;height:20px;padding:0 8px;border-radius:999px;font-size:11px;font-weight:700;white-space:nowrap;color:var(--c);background:color-mix(in srgb,var(--c) 10%,var(--card));border:1px solid color-mix(in srgb,var(--c) 32%,var(--card));text-transform:none;letter-spacing:0}
.fx-type-bool{--c:var(--purple)}
.fx-type-number{--c:var(--blue)}
.fx-type-money{--c:var(--green)}
.fx-type-date{--c:var(--orange)}
.fx-type-text{--c:var(--navy)}

/* Typeset formula: fractions stack, exponents rise, square roots get a stretching radical. */
.fx-math{font-family:"Cambria Math","STIX Two Math","Latin Modern Math","Times New Roman",serif;font-size:17px;line-height:1.3;color:var(--text);display:flex;flex-wrap:wrap;align-items:center;gap:2px;padding:10px 12px;min-height:44px;border:1px solid var(--line);border-radius:10px;background:color-mix(in srgb,var(--purple) 3%,var(--card));overflow-x:auto}
.fx-math-sm{font-size:15px;padding:8px 10px;min-height:0}
.fx-math span{display:inline-flex;align-items:center}
.fx-math .fx-grp{flex-wrap:wrap;gap:0 1px}
.fx-math .fx-var{font-style:italic;font-weight:600;color:var(--purple);padding:0 2px}
.fx-math .fx-var-ref{color:var(--blue)}
.fx-math .fx-n{font-variant-numeric:tabular-nums}
.fx-math .fx-e{font-style:italic}
.fx-math .fx-s{color:var(--green)}
.fx-math .fx-kw,.fx-math .fx-conj{font-family:system-ui,-apple-system,"Segoe UI",sans-serif;font-size:.72em;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--muted);padding:0 5px}
.fx-math .fx-conj{color:var(--purple)}
.fx-math .fx-op{padding:0 .3em}
.fx-math .fx-comma{padding-right:.25em}
.fx-math .fx-bar{padding:0 1px}
.fx-math .fx-fn{padding-right:1px}
.fx-math .fx-fn-word{font-family:system-ui,-apple-system,"Segoe UI",sans-serif;font-size:.8em;font-weight:600;color:var(--orange)}
.fx-math .fx-hole{font-family:system-ui,sans-serif;font-size:.75em;font-weight:700;color:var(--red);padding:0 5px;border:1px dashed color-mix(in srgb,var(--red) 55%,var(--card));border-radius:4px}
.fx-math .fx-frac{flex-direction:column;align-items:stretch;margin:0 .2em;font-size:.94em}
.fx-math .fx-frac-num,.fx-math .fx-frac-den{justify-content:center;padding:0 .25em}
.fx-math .fx-frac-num{border-bottom:1.5px solid currentColor;padding-bottom:2px}
.fx-math .fx-frac-den{padding-top:2px}
.fx-math .fx-pow{align-items:flex-start}
.fx-math .fx-sup{display:inline-flex;align-items:center;font-size:.66em;line-height:1;margin:-.3em 0 0 .06em}
.fx-math .fx-sup .fx-sup{font-size:.85em}
.fx-math .fx-sqrt{align-items:stretch;margin:0 .1em}
.fx-math .fx-rad{width:.75em;flex:0 0 auto;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 20' preserveAspectRatio='none'%3E%3Cpath d='M0.5 12.5 L2.6 11.2 L5.2 19.2 L9.3 0.8 L10 0.8' fill='none' stroke='black' stroke-width='1.6' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E") no-repeat center/100% 100%;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 20' preserveAspectRatio='none'%3E%3Cpath d='M0.5 12.5 L2.6 11.2 L5.2 19.2 L9.3 0.8 L10 0.8' fill='none' stroke='black' stroke-width='1.6' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E") no-repeat center/100% 100%}
.fx-math .fx-radicand{border-top:1.5px solid currentColor;padding:3px .25em 0 .12em}
.fx-math .fx-pw{align-items:stretch;gap:6px}
.fx-math .fx-pw-brace{width:8px;flex:0 0 auto;border:1.5px solid currentColor;border-right:0;border-radius:8px 0 0 8px;margin:3px 0}
.fx-math .fx-pw-rows{display:grid;grid-template-columns:auto auto;column-gap:14px;row-gap:4px;align-items:center}
.fx-math .fx-pw-row{display:contents}
.fx-math .fx-pw-cond{flex-wrap:wrap}

/* Editor */
.fx-editor h2{margin:0}
.fx-ed-top{display:flex;align-items:center;gap:12px;margin-bottom:14px}
.fx-error{margin:0 0 12px}
.fx-ed-grid{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:18px;align-items:start}
.fx-ed-main{display:flex;flex-direction:column;gap:12px;min-width:0}
.fx-lbl{display:flex;flex-direction:column;gap:5px;font-size:12px;font-weight:700;color:var(--text)}
.fx-lbl input,.fx-lbl textarea{border:1px solid var(--line);border-radius:9px;padding:9px 12px;font:inherit;font-size:14px;font-weight:500;color:var(--text);background:var(--card)}
.fx-lbl textarea{resize:vertical}
.fx-lbl input:focus,.fx-lbl textarea:focus,.fx-in:focus,.fx-sel:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px color-mix(in srgb,var(--blue) 18%,transparent)}
.fx-opt{font-weight:500;color:var(--muted)}
.fx-lbl-row{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.fx-lbl-t{font-size:12px;font-weight:700;color:var(--text)}
.fx-builder{border:1px solid var(--line);border-radius:12px;padding:12px;background:var(--bg);overflow-x:auto}
.fx-shadow{display:none}
.fx-ed-side{display:flex;flex-direction:column;gap:12px;position:sticky;top:12px;min-width:0}
.fx-side-card{border:1px solid var(--line);border-radius:12px;padding:12px;background:var(--card);display:flex;flex-direction:column;gap:8px;min-width:0}
.fx-side-t{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
.fx-ed-foot{display:flex;align-items:center;gap:10px;margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.fx-foot-push{margin-left:auto}
@media (max-width:1100px){
  .fx-ed-grid{grid-template-columns:minmax(0,1fr)}
  .fx-ed-side{position:static}
}

/* Rule rows: every part is a slot with a ⋯ menu. */
.fx-slot{display:inline-flex;align-items:center;flex-wrap:wrap;gap:6px;position:relative;vertical-align:middle;max-width:100%;box-sizing:border-box}
.fx-slot-math,.fx-slot-fn,.fx-slot-cmp,.fx-slot-not{padding:4px 5px 4px 6px;border:1px solid var(--line);border-radius:10px;background:var(--card)}
.fx-slot-math{border-color:color-mix(in srgb,var(--blue) 32%,var(--line))}
.fx-slot-fn{border-color:color-mix(in srgb,var(--orange) 38%,var(--line))}
.fx-slot-block{display:flex;flex-direction:column;align-items:stretch;gap:8px;width:100%;padding:10px 42px 10px 10px;border:1px solid color-mix(in srgb,var(--purple) 28%,var(--line));border-radius:12px;background:color-mix(in srgb,var(--purple) 4%,var(--card))}
.fx-slot-block>.fx-more{position:absolute;top:8px;right:8px}
.fx-block-head,.fx-block-foot{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.fx-block-foot{gap:4px}
.fx-conds,.fx-if-rows{display:flex;flex-direction:column;gap:8px}
.fx-cond{display:flex;align-items:center;gap:6px;min-width:0}
.fx-cond>.fx-slot-block{flex:1 1 auto}
.fx-if-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.fx-if-kw{min-width:92px}
.fx-word{font-size:13px;font-weight:600;color:var(--muted)}
.fx-in{height:32px;box-sizing:border-box;border:1px solid var(--line);border-radius:8px;padding:0 8px;font:inherit;font-size:13px;color:var(--text);background:var(--card)}
.fx-in-num{width:100px;font-variant-numeric:tabular-nums}
.fx-in-text{width:150px}
.fx-in-list{width:230px}
.fx-in-money{display:inline-flex;align-items:center;gap:3px;font-size:13px;font-weight:700;color:var(--muted)}
.fx-sel{height:32px;border:1px solid var(--line);border-radius:8px;padding:0 6px;font:inherit;font-size:13px;color:var(--text);background:var(--card);max-width:260px}
.fx-sel-op{font-weight:700;color:var(--purple)}
.fx-chip{display:inline-flex;align-items:center;height:28px;padding:0 10px;border-radius:999px;font-size:12px;font-weight:700;color:var(--orange);background:color-mix(in srgb,var(--orange) 10%,var(--card))}
.fx-list{display:inline-flex;flex-wrap:wrap;gap:4px 12px;padding:4px 6px}
.fx-list-opt{display:inline-flex;align-items:center;gap:5px;font-size:13px;color:var(--text);cursor:pointer}
.fx-args,.fx-arg{display:inline-flex;align-items:center;flex-wrap:wrap;gap:6px}
.fx-arg{gap:4px}
.fx-more,.fx-x{width:26px;height:26px;padding:0;flex:0 0 auto;border:1px solid var(--line);border-radius:7px;background:var(--card);color:var(--muted);font-size:12px;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
.fx-more:hover,.fx-more[aria-expanded]{color:var(--purple);border-color:color-mix(in srgb,var(--purple) 45%,var(--line))}
.fx-x:hover{color:var(--red);border-color:color-mix(in srgb,var(--red) 45%,var(--line))}
.fx-choose{height:30px;padding:0 12px;border:1px dashed color-mix(in srgb,var(--purple) 45%,var(--line));border-radius:8px;background:transparent;color:var(--purple);font-size:13px;font-weight:600;cursor:pointer}
.fx-choose:hover,.fx-choose[aria-expanded]{background:color-mix(in srgb,var(--purple) 7%,var(--card))}
.fx-add{height:28px;padding:0 10px;border:1px solid transparent;border-radius:7px;background:transparent;color:var(--purple);font-size:12px;font-weight:700;cursor:pointer}
.fx-add:hover{background:color-mix(in srgb,var(--purple) 8%,var(--card))}
.fx-menu{position:fixed;z-index:300;min-width:260px;max-width:340px;max-height:70vh;overflow-y:auto;box-sizing:border-box;padding:6px;background:var(--card);border:1px solid var(--line);border-radius:12px;box-shadow:0 16px 40px rgba(16,24,40,.2)}
.fx-menu-g{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--text);padding:10px 8px 4px}
.fx-menu-g:first-child{padding-top:6px}
.fx-menu-item{display:block;width:100%;text-align:left;border:0;border-radius:7px;background:transparent;padding:7px 9px;font:inherit;font-size:13px;color:var(--text);cursor:pointer;white-space:pre}
.fx-menu-item:hover,.fx-menu-item:focus{outline:none;background:color-mix(in srgb,var(--purple) 9%,var(--card))}
.fx-menu-item[disabled]{opacity:.45;cursor:default;background:transparent}
.fx-menu-sep{height:1px;margin:5px 4px;background:var(--line)}
.fx-tpl-t{font-size:13px;font-weight:700;color:var(--text);margin:0 0 8px}
.fx-tpls{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:10px}
.fx-tpl{display:flex;flex-direction:column;align-items:flex-start;gap:4px;text-align:left;padding:12px;border:1px solid var(--line);border-radius:12px;background:var(--card);font:inherit;color:var(--text);cursor:pointer}
.fx-tpl:hover,.fx-tpl:focus-visible{outline:none;border-color:color-mix(in srgb,var(--purple) 45%,var(--line));box-shadow:0 0 0 3px color-mix(in srgb,var(--purple) 12%,transparent)}
.fx-tpl-i{font-size:20px;line-height:1;color:var(--purple)}
.fx-tpl b{font-size:14px}
.fx-tpl span:not(.fx-tpl-i){font-size:12px;color:var(--muted)}

/* Preview (aggregates only) */
.fx-preview{min-height:60px;transition:opacity .15s}
.fx-preview.is-busy{opacity:.55}
.fx-preview .fx-hint{margin-top:8px}
.fx-pv-head{font-size:13px;font-weight:600;color:var(--text);margin-bottom:8px}
.fx-pv-note{font-size:13px;color:var(--muted)}
.fx-pv-err{font-size:13px;font-weight:600;color:var(--red);padding:8px 10px;border-radius:8px;background:color-mix(in srgb,var(--red) 8%,var(--card))}
.fx-pv-bar{height:8px;margin-bottom:8px;border-radius:999px;overflow:hidden;background:color-mix(in srgb,var(--muted) 18%,var(--card))}
.fx-pv-bar span{display:block;height:100%;border-radius:999px;background:var(--purple)}
.fx-pv-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(92px,1fr));gap:8px}
.fx-pv-grid div{display:flex;flex-direction:column;gap:1px;padding:7px 9px;border:1px solid var(--line);border-radius:9px;min-width:0}
.fx-pv-grid b{font-size:15px;color:var(--text);font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.fx-pv-grid span{font-size:11px;color:var(--muted)}

/* Patients list: custom variable columns picker + Yes/No cell */
.pt-fx-modal{max-width:460px}
.pt-fx-hint{margin:0 0 10px}
.pt-fx-list{display:flex;flex-direction:column;gap:2px;max-height:min(50vh,360px);overflow-y:auto}
.pt-fx-item{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:8px;font-size:14px;color:var(--text);cursor:pointer}
.pt-fx-item:hover{background:color-mix(in srgb,var(--purple) 6%,var(--card))}
.pt-fx-warn{margin-left:auto;font-size:11px;font-weight:700;color:var(--red)}
.fx-yn{display:inline-flex;align-items:center;height:20px;padding:0 8px;border-radius:999px;font-size:11px;font-weight:700;border:1px solid var(--line)}
.fx-yn.yes{color:var(--green);background:color-mix(in srgb,var(--green) 10%,var(--card));border-color:color-mix(in srgb,var(--green) 30%,var(--card))}
.fx-yn.no{color:var(--muted);background:color-mix(in srgb,var(--muted) 8%,var(--card))}
