/* The calling experience — one call, three surfaces.
 *
 *   .cx-bar   a sticky bar pinned to the bottom of the app. It appears the
 *             moment a call starts and stays for the whole call, whether or
 *             not the full view is open. Ringing and connected are the same
 *             bar in two states, so nothing jumps when the call is answered.
 *   .cx-full  the expanded on-call workspace: script, live guidance, and one
 *             optional side panel (assist / notes / transcript).
 *   .cx-post  wrap-up, once the call has ended.
 *
 * The bar is the constant; the other two are things that open over the app
 * while it keeps running underneath.
 *
 * The dark chrome is deliberate. During a live call this is the only surface
 * that matters, and a dark bar reads as "in progress" against a product that
 * is otherwise white.
 */

:root {
  --cx-ink:        #0C1A2E;   /* call chrome */
  --cx-ink-2:      #16294a;
  --cx-on-dark:    #FFFFFF;
  --cx-on-dark-2:  #93A4BE;
  --cx-danger:     #E5342A;
  --cx-accent:     #004CE6;
  --cx-line:       #EAECF0;
  --cx-surface:    #FFFFFF;
  --cx-canvas:     #F5FAFB;
}

/* ====================================================================== */
/* Sticky call bar                                                         */
/* ====================================================================== */

/* Docking. The bar doesn't float over the page — the page gives up a strip
 * of its own height and the bar sits in it, separated from the work area by
 * the same 10px the work area already keeps from the window edge.
 *
 * .app is height:100vh and border-box, so padding-bottom shortens the work
 * area rather than pushing it off-screen. This is the same mechanism the AI
 * Assist panel already uses on padding-right — that declaration is repeated
 * here because this rule replaces it in the cascade.
 *
 * Left and right are measured from .main at render time rather than hard-coded,
 * so the strip stays clear of the side navigation whether it is expanded or
 * collapsed, and stays clear of the AI panel when that is docked too.
 *
 * The full-screen call layout is a fixed inset:0 overlay, so none of this
 * reaches it. */
.app {
  transition: padding-right .32s cubic-bezier(.22, 1, .36, 1),
              padding-bottom .34s cubic-bezier(.22, 1, .36, 1);
}
body.cx-docked .app { padding-bottom: var(--cx-dock, 74px); }

.cx-bar {
  position: fixed; left: 12px; right: 12px; bottom: 10px; z-index: 1400;
  display: flex; align-items: center; gap: 14px;
  padding: 12px 14px;
  background: var(--cx-ink); border-radius: 14px;
  box-shadow: 0 18px 40px rgba(12, 26, 46, 0.28), 0 2px 8px rgba(12, 26, 46, 0.18);
  color: var(--cx-on-dark);
  font-family: 'Inter', -apple-system, sans-serif;
  transform: translateY(140%);
  transition: transform .34s cubic-bezier(.2, .9, .25, 1), opacity .2s ease;
  opacity: 0;
}
.cx-bar.show { transform: translateY(0); opacity: 1; }

/* Ringing gets a soft halo so the bar reads as pending rather than live. */
.cx-bar.ringing { box-shadow: 0 0 0 1px rgba(0, 220, 160, .28), 0 18px 40px rgba(12, 26, 46, .28); }


/* Three dots that cycle while the far end rings. */
.cx-dots { display: inline-flex; gap: 3px; }
.cx-dots i {
  width: 3px; height: 3px; border-radius: 999px; background: #7FE7C4;
  animation: cxDot 1.25s ease-in-out infinite;
}
.cx-dots i:nth-child(2) { animation-delay: .18s; }
.cx-dots i:nth-child(3) { animation-delay: .36s; }
@keyframes cxDot { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }

/* ---- wrap-up: title, then facts ---- */
/* Hierarchy without a dark slab: the title is the largest thing on the page,
   the facts sit under a rule in muted labels, and the two work panels carry
   their own borders. */
/* Every band in the wrap-up hangs off one gutter. The header used to carry a
   2px page inset while the body carried 18px, which was invisible as a page —
   the shell *is* the page there — and plainly wrong as a modal: the title and
   the close control sat hard against the card's edges, 16px out of step with
   the panels below them. One variable, set per mode, keeps them in a column. */
.cx-post { --cx-gut: 2px; }

.cx-post-head {
  flex: 0 0 auto; display: flex; align-items: center; gap: 12px;
  padding: 0 var(--cx-gut) 14px;
}
.cx-post-h {
  margin: 0; font: 600 20px/1.25 'Inter', sans-serif; color: #101828; letter-spacing: -.01em;
}
/* Ghost, like every other close in the product. A bordered box here read as a
   control with something to do rather than a way out. */
.cx-post-x {
  margin-left: auto; width: 30px; height: 30px; border-radius: 7px; padding: 0;
  border: 0; background: transparent; color: #98A2B3;
  display: grid; place-items: center; cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.cx-post-x:hover { background: #F2F4F7; color: #344054; }
.cx-post-x svg { width: 17px; height: 17px; }

/* Full-bleed rule, inset content: the border is on the band, the padding is
   on its contents, so the line reaches the card's edges either side. */
.cx-post-facts {
  flex: 0 0 auto; display: flex; align-items: center; gap: 28px;
  padding: 0 var(--cx-gut) 16px; margin-bottom: 16px;
  border-bottom: 1px solid var(--cx-line);
}
.cx-fact-id { display: flex; align-items: center; gap: 11px; min-width: 0; }
.cx-fact-av {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 999px;
  display: grid; place-items: center; background: #EFF8FF; color: #175CD3;
  font: 600 13.5px/1 'Inter', sans-serif;
}
.cx-fact-who { min-width: 0; }
.cx-fact-name { display: block; font: 600 15px/1.3 'Inter', sans-serif; color: #101828; }
.cx-fact-sub { display: block; font: 400 12.5px/1.4 'Inter', sans-serif; color: #667085; }
.cx-fact { display: flex; flex-direction: column; gap: 3px; }
.cx-fact-k {
  font: 500 10.5px/1.5 'Inter', sans-serif; color: #98A2B3;
  letter-spacing: .06em; text-transform: uppercase;
}
/* Sized with the contact's name, not above it. At 18px the clock was the
   loudest thing in the row, and how long the call ran is the third thing the
   agent needs to know here, not the first. */
.cx-fact-v { font: 600 15px/1.3 'Inter', sans-serif; color: #101828; font-variant-numeric: tabular-nums; }
.cx-fact-audio { margin-left: auto; }
/* One two-value choice, so one control: the product's segmented track rather
   than two loose bordered chips with a gap down the middle. */
.cx-fact-qs {
  display: inline-flex; align-items: center; gap: 0;
  padding: 3px; border-radius: 9px; background: #F4F4F5;
}

/* The value came from the suggestion, not from the agent — say so, quietly. */
.cx-outcome-sugg {
  margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 6px; background: #F4F3FF; color: #6941C6;
  font: 500 11px/1.5 'Inter', sans-serif; flex: 0 0 auto;
}
.cx-outcome-sugg svg { width: 12px; height: 12px; }

/* ---- identity: one block, both bars ---- */
/* Values are image 1's: the translucent avatar, the 15.5px name, and the
   recording dot beside a long clock. The phone number sits to the right of the
   name in the dark theme's secondary ink — it identifies the person, so it
   belongs on their line, not wedged against the timer. */
.cx-id { flex: 0 0 auto; display: flex; align-items: center; gap: 11px; min-width: 0; }
.cx-id-av {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 999px;
  display: grid; place-items: center; overflow: hidden;
  background: rgba(255, 255, 255, .12); color: #fff;
  font: 600 13.5px/1 'Inter', sans-serif;
}
.cx-id-av.ico svg { width: 18px; height: 18px; }
.cx-id-who { min-width: 0; }
.cx-id-top { display: flex; align-items: baseline; gap: 9px; min-width: 0; }
.cx-id-name {
  font: 600 15.5px/1.3 'Inter', sans-serif; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px;
}
.cx-id-num {
  flex: 0 0 auto; font: 400 13px/1.3 'Inter', sans-serif;
  color: var(--cx-on-dark-2); white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* Dialing puts the dots in the heading, where they read as the sentence's
   trailing punctuation rather than as a separate indicator — so they sit on
   the text's baseline, and closer to it than the 9px the name and number
   want between them. The heading also gets more room while ringing: it is
   carrying "Dialing " in front of the name, and the bar has nothing in it
   but End call at that point. */
.cx-id-top .cx-dots { align-self: baseline; margin-left: -3px; }
.cx-bar.ringing .cx-id-name { max-width: 380px; }

.cx-id-meta {
  display: flex; align-items: center; gap: 7px; margin-top: 1px;
  font: 400 12.5px/1.4 'Inter', sans-serif; color: var(--cx-on-dark-2);
  font-variant-numeric: tabular-nums;
}
/* Health bars read as part of the meta line, so they sit on its baseline. */
.cx-id-meta .cx-signal { margin-left: 2px; }

.cx-bar-spacer { flex: 1 1 auto; }

/* Live audio, faked. Bars are seeded per-index in JS so the shape doesn't
 * pulse in lockstep, which is the tell that it isn't real. */
.cx-wave { display: flex; align-items: center; gap: 2px; height: 18px; }
.cx-wave i {
  width: 2px; border-radius: 2px; background: #6EE7C0;
  animation: cxWave 900ms ease-in-out infinite alternate;
}
.cx-wave.lg { height: 34px; gap: 2.5px; }
.cx-wave.lg i { width: 2.5px; background: #C7D6EC; }
@keyframes cxWave { from { height: 12%; } to { height: 100%; } }
@media (prefers-reduced-motion: reduce) {
  .cx-wave i, .cx-dots i { animation: none; }
  .cx-wave i { height: 55%; }
}

.cx-bar-tools { display: flex; align-items: center; gap: 6px; }

.cx-ib {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 999px;
  display: grid; place-items: center; padding: 0;
  border: 0; background: rgba(255, 255, 255, .08); color: #D5E0F0;
  cursor: pointer; transition: background 130ms ease, color 130ms ease;
}
.cx-ib:hover { background: rgba(255, 255, 255, .18); color: #fff; }
.cx-ib.on { background: #fff; color: var(--cx-ink); }
.cx-ib svg { width: 16px; height: 16px; display: block; }

/* ---------------------------------------------------------------------- */
/* Who is on the call                                                      */
/* ---------------------------------------------------------------------- */

/* Hanging off the Add participant button, above it, in both docks. The panel
 * is a step lighter than the bar (--cx-ink-2) rather than the white the app's
 * other menus use: it belongs to the dock it grows out of, and a white card
 * on a dark bar reads as a dialog that has to be dismissed.
 *
 * The wrapper is only as big as the button; the panel's own bottom padding
 * covers the 10px between them, so the pointer never crosses a gap that
 * would close it. Anchored on the button's right edge because the button sits
 * in the right-hand tool cluster — centred, the panel would hang off the end
 * of the bar on a narrow window. */
.cx-people { position: relative; display: inline-flex; flex: 0 0 auto; }

.cx-pop {
  position: absolute; bottom: 100%; right: -6px; z-index: 5;
  /* Enough to clear the dock: the panel is anchored to the button, and the
     button sits 12–14px inside the bar, so a 10px gap would put the card's
     border across the bar's own top edge. 22px lands it 8–10px clear in both
     docks, and it is padding rather than margin so the pointer still crosses
     from the button into the panel without leaving the hover target. */
  padding-bottom: 22px; width: 272px;
  opacity: 0; pointer-events: none; transform: translateY(4px);
  transition: opacity 130ms ease, transform 130ms ease;
}
.cx-people:hover .cx-pop,
.cx-people:focus-within .cx-pop { opacity: 1; pointer-events: auto; transform: none; }
@media (prefers-reduced-motion: reduce) { .cx-pop { transition: none; } }

.cx-pop-card {
  position: relative; display: block; padding: 6px;
  background: var(--cx-ink-2); border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 12px; box-shadow: 0 16px 34px rgba(6, 14, 26, .42);
  color: var(--cx-on-dark);
}
/* The pointer down at the button, drawn as a corner of the card itself. */
.cx-pop-card::after {
  content: ''; position: absolute; right: 22px; bottom: -5px;
  width: 10px; height: 10px; background: var(--cx-ink-2);
  border-right: 1px solid rgba(255, 255, 255, .14);
  border-bottom: 1px solid rgba(255, 255, 255, .14);
  transform: rotate(45deg);
}

.cx-pop-h {
  display: flex; align-items: center; gap: 8px; padding: 7px 10px 8px;
  font: 500 11.5px/1.4 'Inter', sans-serif; color: var(--cx-on-dark-2);
  letter-spacing: .06em; text-transform: uppercase;
}
.cx-pop-h b {
  margin-left: auto; padding: 1px 7px; border-radius: 999px;
  background: rgba(255, 255, 255, .12); color: #fff;
  font: 500 11.5px/1.5 'Inter', sans-serif; letter-spacing: 0;
}

.cx-person { display: flex; align-items: center; gap: 10px; padding: 7px 10px; }
.cx-person-av {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 999px;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .12); color: #fff;
  font: 600 11px/1 'Inter', sans-serif;
}
/* The agent's own row, marked the way the transcript marks their turns. */
.cx-person-av.me { background: var(--cx-accent); }
.cx-person-tx { min-width: 0; flex: 1 1 auto; }
.cx-person-n {
  display: block; font: 500 13.5px/1.35 'Inter', sans-serif; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cx-person-s {
  display: block; font: 400 12px/1.35 'Inter', sans-serif; color: var(--cx-on-dark-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cx-person-st {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px;
  font: 400 11.5px/1.4 'Inter', sans-serif; color: var(--cx-on-dark-2);
}
.cx-person-st::before {
  content: ''; width: 6px; height: 6px; border-radius: 999px; background: currentColor;
}
.cx-person-st.live { color: #5EDDA0; }
.cx-person-st.muted { color: #F0A868; }
.cx-person-st.held { color: #E9A23B; }

/* What the button does, said in the panel the button opens — and where the
   answer lands until the picker exists. */
.cx-pop-add {
  display: flex; align-items: center; gap: 8px;
  margin-top: 4px; padding: 9px 10px;
  border-top: 1px solid rgba(255, 255, 255, .1);
  font: 500 13px/1.35 'Inter', sans-serif; color: #fff;
}
.cx-pop-add svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--cx-on-dark-2); }
.cx-pop-add.pending { color: var(--cx-on-dark-2); font-weight: 400; }

.cx-end {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px;
  height: 36px; padding: 0 16px; border: 0; border-radius: 999px;
  background: var(--cx-danger); color: #fff; cursor: pointer;
  font: 500 13.5px/1 'Inter', sans-serif;
  transition: background 130ms ease;
}
.cx-end:hover { background: #C42920; }
.cx-end svg { width: 15px; height: 15px; }


/* ====================================================================== */
/* Full-screen call workspace                                              */
/* ====================================================================== */

/* The maxi view is a page in the work area, not an overlay over the window:
   it fills #mainBody so the side nav and topbar stay where they are. Its old
   fixed/inset/z-index made the whole app disappear behind it. */
.cx-full {
  flex: 1 1 auto; min-width: 0; min-height: 0;
  background: var(--cx-canvas);
  display: flex; flex-direction: column;
  padding: 16px 20px 18px;
  font-family: 'Inter', -apple-system, sans-serif;
  opacity: 0;
  transition: opacity .14s ease;
}
.cx-full.show { opacity: 1; }

/* While the maxi view is up, the mini bar is redundant — it is the same call,
   collapsed. The dock it reserves is not: the maxi view's own controls take
   that slot, so the padding stays and the work area still ends above them. */
body.cx-maxi .cx-bar { display: none; }

/* No top margin now — the topbar above it is the page's header. */
.cx-shell { width: 100%; max-width: 1560px; margin: 0 auto; display: flex; flex-direction: column; min-height: 0; flex: 1; }

/* ---------- Dimensions the workspace's state controller switches ---------- */

/* One class each on .cx-full, stamped from app/call-layout.js. Every one of
   these has to be a pure restyle of identical markup — that is the test the
   flow switch applies to its own dimensions, and the reason this view can
   change shape without being re-rendered under the agent.
   Content width: the columns stop at 1560 by default, which on a very wide
   screen leaves the dock spanning further than the content it belongs to.
   End to end gives the whole work area to the columns. */
.cx-full.cx-w-w1 .cx-shell { max-width: none; }

/* ---- dark header ---- */
.cx-head {
  flex: 0 0 auto; display: flex; align-items: center; gap: 18px;
  padding: 14px 18px; border-radius: 14px;
  background: var(--cx-ink); color: #fff;
}
/* In the workspace it is not a header at all — it is the same dock the mini
   strip uses, in the same position, so the call's controls hold still while
   the page above them changes. Left and right are measured against the work
   area in layout(); bottom and the shadow match .cx-bar exactly. */
.cx-full .cx-head {
  position: fixed; left: 12px; right: 12px; bottom: 10px; z-index: 1400;
  box-shadow: 0 18px 40px rgba(12, 26, 46, .28), 0 2px 8px rgba(12, 26, 46, .18);
}
.cx-head-who { flex: 0 0 auto; min-width: 0; }
.cx-head-name { display: block; font: 600 16px/1.3 'Inter', sans-serif; }
.cx-head-time { display: block; font: 400 13px/1.4 'Inter', sans-serif; color: var(--cx-on-dark-2); font-variant-numeric: tabular-nums; }

.cx-rec {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px;
  height: 26px; padding: 0 12px; border-radius: 999px;
  background: #fff; color: #B42318;
  font: 500 12.5px/1 'Inter', sans-serif;
}
.cx-rec .dot { width: 7px; height: 7px; border-radius: 999px; background: #E5342A; animation: cxPulse 1.6s ease-in-out infinite; }
@keyframes cxPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* Whole pixels, or the bars come out different widths. Dividing a 12px box
   between four bars gave each 2.25px, which lands on half a device pixel and
   rounds one bar wider than its neighbour — the meter looked hand-drawn. The
   bars are 2px each with 2px gaps and the box is whatever that adds up to
   (14), which is worth the two extra pixels for four bars that match. */
.cx-signal { display: flex; align-items: flex-end; gap: 2px; height: 12px; }
.cx-signal i { width: 2px; border-radius: 1px; background: #12B76A; }
/* An unfilled bar: still there, holding the meter's shape. */
.cx-signal i.off { background: rgba(255, 255, 255, .24); }
.cx-signal i:nth-child(1) { height: 35%; }
.cx-signal i:nth-child(2) { height: 60%; }
.cx-signal i:nth-child(3) { height: 85%; }
.cx-signal i:nth-child(4) { height: 100%; }

.cx-head-tools { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
.cx-head-sep { width: 1px; height: 26px; background: rgba(255, 255, 255, .16); margin: 0 4px; }
/* The Live Assist / Notes / Transcript bay, with its own leading separator so
   the group and that separator disappear together on narrow screens. */
.cx-head-bay { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
.cx-head .cx-ib { width: 38px; height: 38px; }
.cx-head .cx-ib svg { width: 17px; height: 17px; }

/* ---- panel grid ---- */
.cx-body {
  flex: 1 1 auto; min-height: 0;
  display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: 16px;
}
/* The bar moved under the columns, so the gap that used to sit below it now
   sits above it. Scoped to the full view — the wrap-up's header is still the
   first thing in its own shell. */
/* The maxi bar matches the mini bar: same padding, so same height. Both were
   already --cx-ink, so the ink needed no change. Scoped to .cx-full because the
   wrap-up shares .cx-head. */
.cx-full .cx-head { margin-top: 16px; padding: 12px 14px; }
.cx-body.with-side { grid-template-columns: 300px minmax(0, 1fr) 340px; }

.cx-panel {
  background: var(--cx-surface); border: 1px solid var(--cx-line); border-radius: 14px;
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
}
.cx-panel-head {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  padding: 14px 16px; border-bottom: 1px solid var(--cx-line);
}
.cx-panel-title {
  display: inline-flex; align-items: center; gap: 8px;
  font: 600 14.5px/1.3 'Inter', sans-serif; color: #101828;
}
.cx-panel-title svg { width: 16px; height: 16px; color: #475467; }
.cx-panel-title .spark { color: #7F56D9; }
.cx-panel-new { font: 400 13px/1.3 'Inter', sans-serif; color: #667085; }
.cx-panel-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 12px 16px 18px; }

.cx-panel-x {
  margin-left: auto; width: 26px; height: 26px; border-radius: 6px; padding: 0;
  border: 0; background: transparent; color: #98A2B3; cursor: pointer;
  display: grid; place-items: center;
}
.cx-panel-x:hover { background: #F2F4F7; color: #475467; }
.cx-panel-x svg { width: 15px; height: 15px; }

/* ---- script ---- */
.cx-script-wrap { margin-left: auto; position: relative; display: inline-flex; }
.cx-script-pick {
  display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 8px 0 10px; border: 0; border-radius: 8px;
  background: transparent; color: #344054; cursor: pointer;
  font: 400 13.5px/1 'Inter', sans-serif;
}
.cx-script-pick:hover { background: #F2F4F7; }
.cx-script-pick svg { width: 15px; height: 15px; color: #667085; transition: transform 160ms ease; }
.cx-script-pick[aria-expanded="true"] svg { transform: rotate(180deg); }

.cx-menu {
  position: absolute; top: 100%; right: 0; margin-top: 6px; z-index: 5;
  min-width: 210px; padding: 6px;
  background: #fff; border: 1px solid var(--cx-line); border-radius: 10px;
  box-shadow: 0 12px 28px rgba(16, 24, 40, .14);
}
.cx-menu[hidden] { display: none; }
.cx-menu button {
  display: block; width: 100%; text-align: left;
  padding: 9px 12px; border: 0; border-radius: 7px; background: transparent;
  font: 400 14px/1.3 'Inter', sans-serif; color: #101828; cursor: pointer;
}
.cx-menu button:hover { background: #F2F4F7; }
.cx-menu button.on { background: #EFF4FF; color: #004CE6; }

.cx-step { display: grid; grid-template-columns: 20px 1fr; gap: 10px; padding: 10px 0; }
.cx-step-mark { margin-top: 1px; width: 17px; height: 17px; }
.cx-step-mark svg { width: 17px; height: 17px; display: block; }
.cx-step-t { display: block; font: 500 14px/1.4 'Inter', sans-serif; color: #101828; }
.cx-step-q { display: block; margin-top: 3px; font: 400 13.5px/1.5 'Inter', sans-serif; color: #98A2B3; }
.cx-step.done .cx-step-t { color: #101828; }
.cx-step.done .cx-step-q { color: #C4CBD6; }

/* ---- guidance ---- */
.cx-listening {
  display: flex; align-items: center; gap: 10px; padding: 10px 2px;
  font: 400 14px/1.4 'Inter', sans-serif; color: #667085;
}
.cx-listening .cx-wave i { background: #7F56D9; }

.cx-card {
  border: 1px solid #D6E0FA; border-radius: 12px; overflow: hidden;
  margin-bottom: 12px; background: #fff;
  animation: cxCardIn .3s cubic-bezier(.2, .8, .2, 1);
}
@keyframes cxCardIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .cx-card { animation: none; } }

.cx-card-head {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 12px 14px; border: 0; background: #EEF4FF; cursor: pointer;
  font: 500 14px/1.3 'Inter', sans-serif; color: #004CE6; text-align: left;
}
.cx-card-head svg.lead { width: 16px; height: 16px; flex: 0 0 auto; }
.cx-card-chev { margin-left: auto; width: 16px; height: 16px; color: #6C8FD6; transition: transform 160ms ease; }
.cx-card[aria-expanded="false"] .cx-card-chev { transform: rotate(180deg); }
.cx-card-body { padding: 14px; }
.cx-card[aria-expanded="false"] .cx-card-body,
.cx-card[aria-expanded="false"] .cx-card-foot { display: none; }

.cx-eyebrow {
  font: 500 11.5px/1.4 'Inter', sans-serif; color: #667085;
  letter-spacing: .05em; text-transform: uppercase; margin-bottom: 8px;
}
.cx-quote { font: 600 15px/1.55 'Inter', sans-serif; color: #101828; margin-bottom: 16px; }
.cx-card-body p { font: 400 14px/1.55 'Inter', sans-serif; color: #344054; margin: 0 0 10px; }
.cx-bullets { list-style: none; margin: 0 0 14px; padding: 0; }
.cx-bullets li {
  display: flex; align-items: flex-start; gap: 9px; padding: 5px 0;
  font: 400 14px/1.5 'Inter', sans-serif; color: #101828;
}
.cx-bullets li svg { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 2px; color: #004CE6; }
.cx-bullets.plain li { list-style: none; }
.cx-bullets.plain li::before {
  content: ''; flex: 0 0 auto; width: 4px; height: 4px; margin: 9px 6px 0 4px;
  border-radius: 999px; background: #98A2B3;
}
.cx-kb-link {
  display: inline-flex; align-items: center; gap: 6px;
  font: 400 14px/1.4 'Inter', sans-serif; color: #004CE6; cursor: pointer;
}
.cx-kb-link svg { width: 13px; height: 13px; }

.cx-battle { width: 100%; border-collapse: collapse; border: 1px solid var(--cx-line); border-radius: 8px; overflow: hidden; }
.cx-battle th, .cx-battle td {
  padding: 9px 12px; text-align: left;
  font: 400 13.5px/1.4 'Inter', sans-serif; border-bottom: 1px solid var(--cx-line);
}
.cx-battle thead th { background: #F9FAFB; color: #344054; font-weight: 500; }
.cx-battle thead th.us { background: #004CE6; color: #fff; text-align: center; }
.cx-battle thead th.them { background: #fff; color: #344054; text-align: center; }
.cx-battle td.v { text-align: center; }
.cx-battle td.yes { color: #067647; }
.cx-battle td.no { color: #B42318; }
.cx-battle td.part { color: #344054; }
.cx-battle tr:last-child td { border-bottom: 0; }

.cx-card-foot { display: flex; gap: 4px; padding: 8px 14px; border-top: 1px solid #F2F4F7; }
.cx-vote {
  width: 28px; height: 28px; border-radius: 6px; padding: 0;
  border: 0; background: transparent; color: #98A2B3; cursor: pointer;
  display: grid; place-items: center;
}
.cx-vote:hover { background: #F2F4F7; color: #475467; }
.cx-vote.on { color: #004CE6; }
.cx-vote svg { width: 15px; height: 15px; }

/* Coaching nudges — quieter than a guidance card, and dismissed not expanded. */
.cx-nudge {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px; margin-bottom: 12px;
  border: 1px solid #E9E6FE; border-left: 3px solid #7F56D9; border-radius: 10px;
  background: #FBFAFF;
  animation: cxCardIn .3s cubic-bezier(.2, .8, .2, 1);
}
.cx-nudge.warn { border-color: #FEDF89; border-left-color: #F79009; background: #FFFCF5; }
.cx-nudge > span { flex: 1 1 auto; min-width: 0; }
.cx-nudge svg { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 1px; color: #7F56D9; }
.cx-nudge.warn svg { color: #DC6803; }
.cx-nudge-t { display: block; font: 500 14px/1.4 'Inter', sans-serif; color: #101828; }
.cx-nudge-s { display: block; margin-top: 2px; font: 400 13.5px/1.45 'Inter', sans-serif; color: #667085; }
.cx-nudge-got {
  margin-left: auto; align-self: center; border: 0; background: transparent;
  font: 500 13.5px/1 'Inter', sans-serif; color: #7F56D9; cursor: pointer; padding: 4px 2px;
}
.cx-nudge.warn .cx-nudge-got { color: #B54708; }

/* Actions the assistant is offering to take. White, not blue: these are
 * things that will happen in another system, not things to say. */
.cx-act {
  border: 1px solid var(--cx-line); border-radius: 12px; padding: 14px;
  margin-bottom: 12px; background: #fff;
  animation: cxCardIn .3s cubic-bezier(.2, .8, .2, 1);
}
.cx-act-head { display: flex; align-items: center; gap: 9px; }
.cx-act-head svg { width: 16px; height: 16px; color: #004CE6; }
.cx-act-t { font: 500 14.5px/1.3 'Inter', sans-serif; color: #101828; }
.cx-act-link { margin-left: auto; font: 400 13.5px/1 'Inter', sans-serif; color: #004CE6; cursor: pointer; }
.cx-act-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; }
.cx-act-k { font: 400 13px/1.4 'Inter', sans-serif; color: #667085; }
.cx-act-v { margin-top: 2px; font: 400 14px/1.4 'Inter', sans-serif; color: #101828; }
.cx-act-mail { margin-top: 12px; font: 400 13.5px/1.6 'Inter', sans-serif; color: #344054; }
.cx-file {
  display: flex; align-items: center; gap: 10px; margin-top: 12px;
  padding: 10px 12px; border: 1px solid var(--cx-line); border-radius: 10px;
}
.cx-file svg { width: 18px; height: 18px; color: #667085; }
.cx-file-n { display: block; font: 500 13.5px/1.3 'Inter', sans-serif; color: #101828; }
.cx-file-m { display: block; font: 400 12.5px/1.3 'Inter', sans-serif; color: #667085; margin-top: 1px; }
.cx-file-v { margin-left: auto; font: 400 13.5px/1 'Inter', sans-serif; color: #004CE6; cursor: pointer; }

/* ---- live assist ---- */
.cx-side-label { font: 400 13px/1.4 'Inter', sans-serif; color: #667085; margin-bottom: 6px; }
.cx-sup {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 9px 11px; border: 1px solid #D0D5DD; border-radius: 9px;
  background: #fff; cursor: pointer; text-align: left;
}
.cx-sup-av {
  width: 26px; height: 26px; border-radius: 999px; flex: 0 0 auto;
  display: grid; place-items: center; background: #FFF1E6; color: #B54708;
  font: 600 10.5px/1 'Inter', sans-serif;
}
.cx-sup-n { font: 400 14px/1.3 'Inter', sans-serif; color: #101828; }
.cx-sup-n .st { color: #667085; }
.cx-sup svg { margin-left: auto; width: 16px; height: 16px; color: #667085; }
.cx-side-note { margin-top: 14px; font: 400 13.5px/1.55 'Inter', sans-serif; color: #667085; }

.cx-ask { flex: 0 0 auto; display: flex; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--cx-line); }
.cx-ask input {
  flex: 1 1 auto; min-width: 0; height: 40px; padding: 0 12px;
  border: 1px solid #004CE6; border-radius: 9px; background: #fff;
  font: 400 14px/1 'Inter', sans-serif; color: #101828;
}
.cx-ask input::placeholder { color: #98A2B3; }
.cx-ask input:focus { outline: none; box-shadow: 0 0 0 3px rgba(0, 76, 230, .12); }
.cx-send {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 9px; padding: 0;
  border: 1px solid var(--cx-line); background: #F9FAFB; color: #98A2B3; cursor: pointer;
  display: grid; place-items: center;
}
.cx-send.ready { background: #004CE6; border-color: #004CE6; color: #fff; }
.cx-send svg { width: 17px; height: 17px; }

.cx-msg { margin-bottom: 12px; }
.cx-msg-who { display: block; font: 500 11.5px/1.4 'Inter', sans-serif; color: #667085; letter-spacing: .04em; text-transform: uppercase; }
.cx-msg-b {
  margin-top: 4px; padding: 10px 12px; border-radius: 10px;
  font: 400 14px/1.5 'Inter', sans-serif;
  background: #F2F4F7; color: #101828;
}
.cx-msg.me .cx-msg-b { background: #EFF4FF; color: #17306B; }

/* .cx-count is shared with the wrap-up's own notes field. The textarea that
   used to be styled here belonged to the side panel's Notes tab; notes are a
   floating widget on the dock now, and the whole definition lives with it —
   see .cx-fw-notes. Left here, this rule's min-height:240px was quietly
   overriding that widget's height:168px. */
.cx-count { margin-top: 8px; text-align: right; font: 400 12.5px/1 'Inter', sans-serif; color: #98A2B3; }

/* ---- live transcript ---- */
.cx-tr { margin-bottom: 14px; animation: cxCardIn .26s ease; }
.cx-tr-who {
  display: flex; align-items: center; gap: 7px; margin-bottom: 4px;
  font: 500 11.5px/1.4 'Inter', sans-serif; color: #667085;
  letter-spacing: .04em; text-transform: uppercase;
}
.cx-tr-av {
  width: 20px; height: 20px; border-radius: 999px; flex: 0 0 auto;
  display: grid; place-items: center; background: #EFF4FF; color: #004CE6;
  font: 600 9px/1 'Inter', sans-serif; letter-spacing: 0;
}
.cx-tr-t { font: 400 14px/1.55 'Inter', sans-serif; color: #101828; }
.cx-tr.me .cx-tr-t { color: #667085; }
.cx-tr.partial .cx-tr-t { color: #98A2B3; }

/* ====================================================================== */
/* Post-call wrap-up                                                       */
/* ====================================================================== */

.cx-post {
  position: fixed; inset: 0; z-index: 1500;
  background: var(--cx-canvas);
  display: flex; flex-direction: column;
  padding: 28px 28px 20px;
  font-family: 'Inter', -apple-system, sans-serif;
  opacity: 0; pointer-events: none;
  transition: opacity .12s ease;
}
.cx-post.show { opacity: 1; pointer-events: auto; }

/* Segments on a tinted track: unselected is quiet, selected lifts to white.
   Matches the segmented control the rest of the product uses. */
.cx-q {
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 11px; border: 0; border-radius: 6px;
  background: transparent; color: #667085; cursor: pointer;
  font: 500 12.5px/1 'Inter', sans-serif;
  transition: background .14s ease, color .14s ease, box-shadow .14s ease;
}
.cx-q:hover { color: #344054; }
.cx-q.on { background: #fff; color: #101828; box-shadow: 0 1px 2px rgba(16, 24, 40, .1); }
.cx-q svg { width: 14px; height: 14px; }

.cx-post-body {
  flex: 1 1 auto; min-height: 0; margin-top: 16px;
  display: grid; grid-template-columns: minmax(0, 1fr) 400px; gap: 16px;
}

.cx-sum-head { display: flex; align-items: center; margin-bottom: 10px; }
/* Under the panel's own title, not level with it: these were 15px against the
   panel header's 14.5px, so each section shouted slightly louder than the
   panel containing it. Weight carries them against 14.5px body copy. */
.cx-sum-h { font: 600 14px/1.3 'Inter', sans-serif; color: #101828; }
.cx-copy {
  margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
  border: 0; background: transparent; cursor: pointer; padding: 4px 6px; border-radius: 6px;
  font: 400 13.5px/1 'Inter', sans-serif; color: #667085;
}
.cx-copy:hover { background: #F2F4F7; color: #101828; }
.cx-copy svg { width: 15px; height: 15px; }
/* Measure, not column width: the recap panel is wide enough to run past 90
   characters a line, which is where the eye starts losing its place between
   rows of a five-line paragraph. */
.cx-sum-t { max-width: 68ch; font: 400 14.5px/1.65 'Inter', sans-serif; color: #101828; }
/* Caret while the recap is still being written. */
.cx-sum-t.typing::after {
  content: ''; display: inline-block; width: 2px; height: 1em;
  margin-left: 2px; vertical-align: -2px; background: #004CE6;
  animation: cxCaret 1s step-end infinite;
}
@keyframes cxCaret { 50% { opacity: 0; } }

.cx-ai-h { margin: 26px 0 10px; font: 600 14px/1.3 'Inter', sans-serif; color: #101828; }
.cx-ai {
  display: flex; align-items: center; gap: 12px; padding: 13px 14px;
  border: 1px solid var(--cx-line); border-radius: 10px; margin-bottom: 10px;
  animation: cxCardIn .28s ease;
}
.cx-ai-cb { flex: 0 0 auto; width: 20px; height: 20px; cursor: pointer; }
.cx-ai-cb svg { width: 20px; height: 20px; display: block; }
.cx-ai-t { font: 400 14.5px/1.45 'Inter', sans-serif; color: #101828; }
.cx-ai.done .cx-ai-t { color: #475467; }
.cx-ai-link { margin-left: auto; flex: 0 0 auto; font: 400 13.5px/1 'Inter', sans-serif; color: #004CE6; cursor: pointer; }

.cx-wrap-f { margin-bottom: 18px; }
.cx-wrap-l { display: block; margin-bottom: 7px; font: 500 14px/1.3 'Inter', sans-serif; color: #101828; }
.cx-wrap-l .req { color: #E5342A; }
.cx-outcome {
  position: relative; display: flex; align-items: center; gap: 9px;
  width: 100%; height: 46px; padding: 0 12px;
  border: 1px solid #D0D5DD; border-radius: 9px; background: #fff; cursor: pointer;
  font: 400 14.5px/1 'Inter', sans-serif; color: #101828; text-align: left;
}
.cx-outcome .dot { width: 8px; height: 8px; border-radius: 999px; background: #12B76A; flex: 0 0 auto; }
.cx-outcome .sp { margin-left: auto; display: inline-flex; color: #7F56D9; }
.cx-outcome svg { width: 16px; height: 16px; }
.cx-outcome .chev { color: #667085; margin-left: auto; }
/* Nothing chosen yet: placeholder ink, and no green dot — the dot is what
   says an outcome has been recorded. */
.cx-outcome.empty { color: #98A2B3; }

/* The suggestion the control used to arrive pre-filled with. Sits under the
   field as an offer, not an answer. */
.cx-sugg {
  display: flex; align-items: center; gap: 8px;
  width: 100%; margin-top: 8px; padding: 8px 10px;
  border: 1px solid #E9D7FE; border-radius: 8px; background: #FCFAFF; cursor: pointer;
  font: 400 13px/1.3 'Inter', sans-serif; color: #475467; text-align: left;
}
.cx-sugg:hover { border-color: #D6BBFB; background: #F9F5FF; }
.cx-sugg[hidden] { display: none; }
.cx-sugg .sp { display: inline-flex; color: #7F56D9; flex: 0 0 auto; }
.cx-sugg svg { width: 15px; height: 15px; }
.cx-sugg-go { margin-left: auto; flex: 0 0 auto; font-weight: 500; color: #6941C6; }
/* Grows into the column instead of leaving a hole under it. With the save
   button pinned to the bottom of this panel there were 83 empty pixels
   between the character count and the button — on the one field in the
   dialog that wants all the room it can get. */
.cx-post-ta {
  width: 100%; flex: 1 1 auto; min-height: 150px; resize: vertical;
  padding: 12px 14px; border: 1px solid #D0D5DD; border-radius: 9px;
  font: 400 14px/1.55 'Inter', sans-serif; color: #101828; background: #fff;
}
.cx-post-ta:focus { outline: none; border-color: #004CE6; box-shadow: 0 0 0 3px rgba(0, 76, 230, .12); }
.cx-post-ta::placeholder { color: #98A2B3; }

/* The primary action belongs to the dialog, not to the right-hand column, so
   it sits in a footer band with the other bands' gutter. */
.cx-post-foot {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: flex-end; gap: 12px;
  padding: 14px var(--cx-gut) 0; border-top: 1px solid var(--cx-line);
}
.cx-post-hint { margin-right: auto; font: 400 13px/1.4 'Inter', sans-serif; color: #667085; }

.cx-save {
  flex: 0 0 auto; height: 38px; padding: 0 18px;
  border: 0; border-radius: 8px; background: #0B5CFF; color: #fff; cursor: pointer;
  font: 500 13.5px/1 'Inter', sans-serif;
  transition: background 130ms ease;
}
.cx-save:hover { background: #0048CC; }
/* Call outcome is required, so Save waits for one. */
.cx-save[disabled] { background: #E4E7EC; color: #98A2B3; cursor: not-allowed; }
.cx-save[disabled]:hover { background: #E4E7EC; }

/* ====================================================================== */
/* Narrow screens — the left column goes before the side panel does.       */
/* ====================================================================== */

/* This used to drop the side panel first, which meant the three controls that
   open it had to be hidden too — and they vanished soonest on the campaign
   layout, the one carrying an extra column and so the first to get narrow.
   A panel the agent explicitly asked for should not be the thing that yields;
   the script and the campaign facts can wait a moment. */
@media (max-width: 1180px) {
  .cx-body, .cx-body.with-side { grid-template-columns: 280px minmax(0, 1fr); }
  .cx-post-body { grid-template-columns: minmax(0, 1fr) 340px; }
}
@media (max-width: 900px) {
  .cx-full, .cx-post { padding: 16px; }
  .cx-body, .cx-body.with-side, .cx-post-body { grid-template-columns: minmax(0, 1fr); }
  .cx-body .cx-script { display: none; }
  .cx-id-name { max-width: 160px; }
  .cx-bar .cx-hide-sm { display: none; }
}

/* ---------- Campaign context --------------------------------------------- */

/* On a campaign call the agent needs two extra facts the call itself doesn't
 * carry: which queue this came from, and how far through it they are. */
.cx-camp {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px;
  margin-left: 4px; padding: 5px 10px 5px 12px;
  border: 1px solid rgba(255, 255, 255, .14); border-radius: 999px;
  font: 400 12.5px/1.3 'Inter', sans-serif; color: #C3D0E4; white-space: nowrap;
}
.cx-camp b {
  padding: 1px 8px; border-radius: 999px;
  background: rgba(255, 255, 255, .12); color: #fff;
  font: 500 12px/1.5 'Inter', sans-serif; font-variant-numeric: tabular-nums;
}
/* The chip is a control: it goes back to the queue this call came from,
   which is parked whenever the agent is working on another page. */
.cx-camp { background: none; cursor: pointer; transition: background .14s, border-color .14s, color .14s; }
.cx-camp:hover { background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .26); color: #EAF0F9; }
.cx-camp:active { background: rgba(255, 255, 255, .12); }

.cx-head-camp { flex: 0 0 auto; padding-left: 18px; border-left: 1px solid rgba(255, 255, 255, .16); }
.cx-head-camp-n { display: block; font: 500 13.5px/1.35 'Inter', sans-serif; color: #fff; }
.cx-head-camp-m { display: block; margin-top: 1px; font: 400 12.5px/1.35 'Inter', sans-serif; color: var(--cx-on-dark-2); }

/* ---------- Wrap-up as a modal ------------------------------------------- */

/* Over a dialer session the wrap-up is a modal, not a page. The queue behind
 * it is the context the agent is dispositioning against, and the same scrim
 * the rest of the product uses keeps it readable underneath. */
.cx-post.modal {
  padding: 0; display: grid; place-items: center;
  background: rgba(16, 24, 40, .32);
}
/* Height, not max-height. The recap types itself in and the action items
   land after it, so a card sized to its content grew twice while the agent
   was reading it — and the disposition control beside it, the one thing they
   are there to use, moved both times. It opens at the size it will keep, and
   anything past that scrolls inside the panel it belongs to (.cx-panel-body
   is the scroller; the head, the facts and the footer hold still). */
.cx-post.modal .cx-shell {
  width: min(1020px, calc(100vw - 64px));
  height: min(720px, calc(100vh - 80px));
  margin: 0; flex: 0 0 auto;
  background: #fff; border-radius: 16px; overflow: hidden;
  box-shadow: 0 24px 64px rgba(16, 24, 40, .28);
}
.cx-post.modal { --cx-gut: 24px; }
/* A card needs its own top margin; as a page the window supplied one. */
.cx-post.modal .cx-post-head { padding-top: 20px; }
.cx-post.modal .cx-head { border-radius: 0; padding: 16px 20px; }
.cx-post.modal .cx-post-body {
  margin: 0; padding: 0 var(--cx-gut) 20px; gap: 18px;
  grid-template-columns: minmax(0, 1fr) 340px;
}
.cx-post.modal .cx-panel { border-radius: 12px; }
.cx-post.modal .cx-post-foot { padding-bottom: 14px; background: #FBFBFC; }
/* The close control sits on the card's own header rather than the window. */

@media (max-width: 900px) {
  .cx-post.modal .cx-post-body { grid-template-columns: minmax(0, 1fr); }
}

/* Close lives on the wrap-up's own header — it belongs to the card, not the
 * window, and the floating one has nothing to anchor to once this is a modal. */

/* ======================================================================== */
/* Full view, second pass                                                    */
/* ======================================================================== */

/* The header was carrying identity, timer, campaign, mode, queue position,
 * attempt, local time, a recording pill, a signal meter, a full-width
 * waveform and eight buttons. It now carries three things — who, how the call
 * is going, and what you can do about it. Everything else moved to where it
 * is actually used: campaign facts beside the script, panel toggles onto the
 * panel they open. */

.cx-head { gap: 14px; padding: 10px 14px; }

.cx-head-name {
  display: block; font: 600 15.5px/1.3 'Inter', sans-serif; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px;
}
/* Recording is a state, not an announcement — a dot next to the timer says it
 * as well as a pill did, in a tenth of the room. */
.cx-rec-dot {
  width: 7px; height: 7px; border-radius: 999px; background: #FF5A4E;
  flex: 0 0 auto; animation: cxPulse 1.6s ease-in-out infinite;
}


.cx-head-spacer { flex: 1 1 auto; }
.cx-head .cx-ib { width: 36px; height: 36px; }
.cx-head .cx-ib svg { width: 16px; height: 16px; }
.cx-head .cx-end { height: 36px; }

/* ---------- Left column ------------------------------------------------- */

.cx-col-left { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 14px; }
.cx-col-left .cx-script { flex: 1 1 auto; min-height: 0; }

/* ---------- Two columns -------------------------------------------------- */

/* The other layout the state controller offers: guidance in a column of its
 * own, script over transcript in the other, and a divider the agent can move.
 *
 * Guidance is on the left and gets the wider default because it is the one
 * panel that changes while nobody is watching it — a card lands on its own.
 * The script and the transcript are both read deliberately, and neither needs
 * full height to be read, so they share a column as rows.
 *
 * The divider is a real 16px track rather than a bar floating in the gap, so
 * it is a grab target at any pointer size and the gap it occupies is the same
 * gap the three-column layout leaves between panels. Grid gap is 0 here for
 * that reason: the track is the gap. */
.cx-body.cx-body-2 {
  grid-template-columns: minmax(0, var(--cx-split, 54%)) 16px minmax(0, 1fr);
  gap: 0;
}
.cx-col-right {
  min-width: 0; min-height: 0;
  display: grid; grid-template-rows: minmax(0, 1fr) minmax(0, 1fr); gap: 16px;
}

/* Invisible until wanted. A divider that is always drawn reads as a border
   between two things; this one is a control, and controls that do nothing
   until you reach for them should not be on screen the rest of the time. */
.cx-split {
  display: grid; place-items: center;
  cursor: col-resize; touch-action: none;
  background: transparent; border: 0; padding: 0;
}
.cx-split i {
  width: 3px; height: 48px; border-radius: 999px;
  background: transparent;
  transition: background 130ms ease, height 130ms ease;
}
.cx-split:hover i { background: #D0D5DD; }
.cx-split:focus-visible { outline: none; }
.cx-split:focus-visible i, .cx-split.on i { background: var(--cx-accent); height: 72px; }
/* While dragging, the whole window is the drag surface: without this the
   pointer picks up text selection in whichever panel it crosses. */
body.cx-dragging { cursor: col-resize; user-select: none; }
body.cx-dragging * { cursor: col-resize !important; }
@media (prefers-reduced-motion: reduce) { .cx-split i { transition: none; } }

/* ---------- Floating widgets: keypad and notes --------------------------- */

/* Click-toggled, unlike the participants list next to them, because these are
 * things you type into: a panel that closes when the pointer wanders is no
 * good for a phone extension or a sentence. They reuse .cx-pop's placement
 * and card, so all three panels off this row of buttons are the same object
 * in the same place. */
.cx-fw { position: relative; display: inline-flex; flex: 0 0 auto; }
.cx-pop-fw { opacity: 0; pointer-events: none; }
.cx-pop-fw.open { opacity: 1; pointer-events: auto; transform: none; }
.cx-pop-keypad { width: 268px; }
.cx-pop-notes { width: 340px; }

.cx-fw-head {
  display: flex; align-items: center; gap: 8px; padding: 6px 6px 10px 10px;
}
.cx-fw-t { font: 500 13.5px/1.4 'Inter', sans-serif; color: #fff; }
.cx-fw-x {
  margin-left: auto; flex: 0 0 auto; width: 26px; height: 26px; padding: 0;
  border: 0; border-radius: 7px; background: transparent; color: var(--cx-on-dark-2);
  display: grid; place-items: center; cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.cx-fw-x:hover { background: rgba(255, 255, 255, .12); color: #fff; }
.cx-fw-x svg { width: 15px; height: 15px; display: block; }

/* ---- keypad ---- */
.cx-kp { display: block; padding: 0 6px 4px; }
/* The readout keeps its line whether or not anything has been keyed, so the
   pad does not jump the first time it is used. */
.cx-kp-out {
  display: block; min-height: 30px; margin: 0 4px 10px; padding-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, .18);
  font: 500 19px/30px 'Inter', sans-serif; color: #fff;
  font-variant-numeric: tabular-nums; letter-spacing: .06em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl;
}
.cx-kp-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; }
.cx-kp-k {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; height: 46px; padding: 0; border: 0; border-radius: 10px;
  background: transparent; color: #fff; cursor: pointer;
  transition: background 110ms ease;
}
.cx-kp-k:hover { background: rgba(255, 255, 255, .1); }
.cx-kp-k:active { background: rgba(255, 255, 255, .18); }
.cx-kp-k b { font: 400 20px/1 'Inter', sans-serif; font-variant-numeric: tabular-nums; }
.cx-kp-k i {
  font: 500 8.5px/1 'Inter', sans-serif; font-style: normal;
  letter-spacing: .1em; color: var(--cx-on-dark-2);
}

/* ---- notes ---- */
.cx-fw-notes { display: block; padding: 0 10px 10px; }
.cx-fw-notes .cx-notes-ta {
  display: block; width: 100%; height: 168px; min-height: 0; resize: none;
  padding: 10px 12px; border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, .18);
  background: rgba(255, 255, 255, .06); color: #fff;
  font: 400 13.5px/1.55 'Inter', sans-serif;
}
.cx-fw-notes .cx-notes-ta::placeholder { color: var(--cx-on-dark-2); }
.cx-fw-notes .cx-notes-ta:focus {
  outline: none; border-color: var(--cx-accent);
  box-shadow: 0 0 0 3px rgba(0, 76, 230, .25);
}
.cx-fw-notes .cx-count {
  display: block; margin-top: 6px; text-align: right;
  font: 400 11.5px/1.4 'Inter', sans-serif; color: var(--cx-on-dark-2);
}

/* ---------- Growing out of the dock -------------------------------------- */

/* The dock does not move between the two views — the mini bar and this
 * view's header are the same strip in the same place — so expanding is the
 * work arriving from it and collapsing is the work returning to it. Four
 * regions travel: the banner and the three columns, each rising its last
 * 22px with a touch of scale, staggered top-down so it reads as one thing
 * unfolding. The dock is a sibling of these, not a descendant, so nothing
 * here touches it: it holds still while the page grows above it, which is
 * what makes the two views feel like one.
 *
 * .cx-grow is only on during the animation. It carries transforms, and a
 * transform makes its box the containing block for any fixed descendant —
 * left on permanently it would quietly re-anchor anything of that kind that
 * lands in a column later. */
.cx-full.cx-grow .cx-col-left,
.cx-full.cx-grow .cx-col-right,
.cx-full.cx-grow .cx-guide,
.cx-full.cx-grow .cx-side {
  transform-origin: 50% 100%;
  opacity: 0; transform: translateY(22px) scale(.985);
  transition: opacity 200ms ease, transform 260ms cubic-bezier(.2, .9, .28, 1);
  will-change: transform, opacity;
}
.cx-full.cx-grow.show .cx-col-left,
.cx-full.cx-grow.show .cx-col-right,
.cx-full.cx-grow.show .cx-guide,
.cx-full.cx-grow.show .cx-side { opacity: 1; transform: none; }
/* Left to right in either layout: in three columns that is script, guidance,
   panel; in two it is guidance then the script-over-transcript column. The
   first one starts immediately — it held 40ms while the campaign banner had
   the opening slot, and with that gone the entry began on a dead beat. */
.cx-full.cx-grow.show .cx-guide     { transition-delay: 40ms; }
.cx-full.cx-grow.show .cx-side      { transition-delay: 80ms; }
.cx-full.cx-l-c2.cx-grow.show .cx-guide     { transition-delay: 0ms; }
.cx-full.cx-l-c2.cx-grow.show .cx-col-right { transition-delay: 40ms; }

/* Collapsing goes down together rather than staggered — in reverse a stagger
   reads as the page coming apart rather than folding away — and the shell's
   own fade is slowed to the travel so it is still there to be seen landing. */
.cx-full.cx-shrinking { transition: opacity 260ms ease; }
.cx-full.cx-shrinking .cx-col-left,
.cx-full.cx-shrinking .cx-col-right,
.cx-full.cx-shrinking .cx-guide,
.cx-full.cx-shrinking .cx-side { transition-delay: 0ms; }

/* The controls only the workspace has ------------------------------------- */

/* The dock is the same strip in both views; what differs is that the
 * workspace adds a bay — Live Assist, Notes, Transcript — and the separators
 * around it. Appearing and vanishing between two otherwise identical bars is
 * the one moment the illusion breaks, so the bay opens like a drawer instead:
 * its width runs 0 → natural with the three buttons scaling up inside it, and
 * the controls either side slide over to make room rather than jumping.
 *
 * max-width rather than width, because the natural width is the layout's to
 * decide (141px today, and a fourth panel would change it). 160 is a ceiling
 * above that: the visible growth finishes when the used width reaches its
 * natural value, at about 88% of the stated duration.
 *
 * It rides .cx-grow, so it is on for exactly the entry and the exit and gone
 * after — nothing here constrains the bay once it has arrived. */
.cx-full.cx-grow .cx-head-bay {
  overflow: hidden; max-width: 160px;
  transition: max-width 220ms cubic-bezier(.2, .9, .28, 1), opacity 150ms ease;
}
.cx-full.cx-grow:not(.show) .cx-head-bay { max-width: 0; opacity: 0; }

.cx-full.cx-grow .cx-head-bay .cx-ib {
  transition: transform 200ms cubic-bezier(.2, .9, .28, 1), opacity 160ms ease;
}
.cx-full.cx-grow:not(.show) .cx-head-bay .cx-ib { opacity: 0; transform: scale(.55); }
/* Left to right as the drawer opens, so the three read as arriving in order
   rather than all at once. nth-of-type counts the buttons only — the bay's
   leading separator is a span. */
.cx-full.cx-grow.show .cx-head-bay .cx-ib:nth-of-type(2) { transition-delay: 45ms; }
.cx-full.cx-grow.show .cx-head-bay .cx-ib:nth-of-type(3) { transition-delay: 90ms; }

/* The separator between the bay and Minimise is the workspace's too. */
.cx-full.cx-grow .cx-head-tools > .cx-head-sep {
  transition: width 200ms ease, margin 200ms ease, opacity 150ms ease;
}
.cx-full.cx-grow:not(.show) .cx-head-tools > .cx-head-sep {
  width: 0; margin-left: 0; margin-right: 0; opacity: 0;
}

/* Closing goes at once and quickly: the drawer has to be shut before the
   node is taken away 280ms later, and a staggered exit on three buttons
   reads as them falling off the bar one at a time. */
.cx-full.cx-shrinking .cx-head-bay { transition-duration: 170ms, 130ms; }
.cx-full.cx-shrinking .cx-head-bay .cx-ib { transition-delay: 0ms; transition-duration: 150ms, 120ms; }

@media (prefers-reduced-motion: reduce) {
  .cx-full.cx-grow .cx-head-bay,
  .cx-full.cx-grow .cx-head-bay .cx-ib,
  .cx-full.cx-grow .cx-head-tools > .cx-head-sep { transition: none; }
}

/* ---------- Skeletons, on the way in only -------------------------------- */

/* Laid over each panel's own box, with the real content beneath it at
 * opacity 0: the panel is already the height it will be, so the hand-over is
 * a cross-fade in place and not a reflow. .sk-shimmer is the shared
 * primitive from components.html — sized inline, as it documents. */
.cx-full.cx-skel-on .cx-panel-body,
.cx-full.cx-skel-off .cx-panel-body { position: relative; }
/* The panel body is a scroller, and an overlay inside one is positioned
   against the content rather than the port — scrolled down, the skeleton
   sits somewhere above the visible box. Nothing should scroll while it is
   up anyway: there is nothing yet to scroll to. */
.cx-full.cx-skel-on .cx-panel-body { overflow: hidden; }

.cx-full.cx-skel-on .cx-panel-body > :not(.cx-skel),
.cx-full.cx-skel-off .cx-panel-body > :not(.cx-skel) { transition: opacity 140ms ease; }
.cx-full.cx-skel-on .cx-panel-body > :not(.cx-skel) { opacity: 0; }

.cx-skel {
  position: absolute; inset: 12px 16px 18px; z-index: 1;
  display: flex; flex-direction: column; gap: 14px;
  pointer-events: none; transition: opacity 140ms ease;
}
.cx-full.cx-skel-off .cx-skel { opacity: 0; }
.cx-skel-b { display: flex; flex-direction: column; gap: 7px; }
/* Shaped like a guidance card, because that is what lands here. */
.cx-skel-card {
  display: flex; flex-direction: column; gap: 8px; padding: 14px;
  border: 1px solid var(--cx-line); border-radius: 12px;
}

/* Expand and collapse are locked while either runs. */
.cx-ib[disabled] { opacity: .45; cursor: default; }
.cx-ib[disabled]:hover { background: rgba(255, 255, 255, .08); color: #D5E0F0; }

/* ---------- Right column: its own tabs ----------------------------------- */

.cx-side-head {
  flex: 0 0 auto; display: flex; align-items: center; gap: 4px;
  padding: 8px 10px 0 14px; border-bottom: 1px solid var(--cx-line);
}
.cx-side-tab {
  position: relative; padding: 8px 4px 11px; margin-right: 14px;
  border: 0; background: transparent; cursor: pointer;
  font: 500 13.5px/1.3 'Inter', sans-serif; color: #667085;
}
.cx-side-tab:hover { color: #344054; }
.cx-side-tab.on { color: #101828; }
.cx-side-tab.on::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; background: var(--cx-accent); border-radius: 2px 2px 0 0;
}
.cx-side-head .cx-panel-x { margin-left: auto; margin-bottom: 3px; }

/* Columns rebalanced: the left column now holds two things, and the right is
 * a panel rather than an occasional guest. */
.cx-body { grid-template-columns: 320px minmax(0, 1fr); }
.cx-body.with-side { grid-template-columns: 320px minmax(0, 1fr) 360px; }

@media (max-width: 1180px) {
  .cx-body { grid-template-columns: 300px minmax(0, 1fr); }
  /* Panel open: spend the left column on it rather than not opening at all. */
  .cx-body.with-side { grid-template-columns: minmax(0, 1fr) 340px; }
  .cx-body.with-side .cx-col-left { display: none; }
}
@media (max-width: 900px) {
  .cx-body, .cx-body.with-side { grid-template-columns: minmax(0, 1fr); }
  .cx-body .cx-col-left { display: none; }
  /* One column left, so the panel is the column while it is open. */
  .cx-body.with-side .cx-guide { display: none; }
}

/* A call button that quietly does nothing is worse than one that shows it
 * can't. While a call is up, every "start a call" control reads as closed. */
body.cx-on-call [data-jc-call] {
  opacity: .4; cursor: not-allowed; pointer-events: none;
}

/* ======================================================================== */
/* Dark mode                                                                 */
/* ======================================================================== */

/* Most of this file is already dark — the call chrome is --cx-ink by design,
 * and it needs no help. The work is on the light surfaces the call opens over:
 * the workspace canvas, its panels, and the pale tints that carry meaning
 * (guidance blue, nudge violet, metric green) which go luminous on a dark row
 * if left alone. */

body.theme-dark {
  --cx-on-dark-2: #9BA1AC;
  --cx-line:      #2A2D33;
  --cx-surface:   #23262C;
  --cx-canvas:    #191A1C;
}

/* ---- workspace shell ---- */
body.theme-dark .cx-panel-head { border-bottom-color: var(--border); }
body.theme-dark .cx-panel-title { color: var(--text-primary); }
body.theme-dark .cx-panel-title svg { color: var(--text-secondary); }
body.theme-dark .cx-panel-new,
body.theme-dark .cx-listening { color: var(--text-secondary); }
body.theme-dark .cx-panel-x:hover { background: var(--surface-panel); color: var(--text-primary); }

/* ---- script ---- */
body.theme-dark .cx-step-t { color: var(--text-primary); }
body.theme-dark .cx-step-q { color: var(--text-tertiary); }
body.theme-dark .cx-step.done .cx-step-q { color: #5A5F68; }
body.theme-dark .cx-script-pick { color: var(--text-primary); }
body.theme-dark .cx-script-pick:hover { background: var(--surface-panel); }
body.theme-dark .cx-menu { background: var(--surface-alt); border-color: var(--border); }
body.theme-dark .cx-menu button { color: var(--text-primary); }
body.theme-dark .cx-menu button:hover { background: var(--surface-panel); }
body.theme-dark .cx-menu button.on { background: var(--brand-blue-soft); color: #7FA9FF; }

/* ---- guidance ---- */
body.theme-dark .cx-card { background: var(--surface-alt); border-color: #29344A; }
body.theme-dark .cx-card-head { background: #17233A; color: #7FA9FF; }
body.theme-dark .cx-card-chev { color: #5C7BB5; }
body.theme-dark .cx-card-body p,
body.theme-dark .cx-bullets li { color: var(--text-primary); }
body.theme-dark .cx-quote { color: var(--text-primary); }
/* The wrap-up's header and facts row are light surfaces now, so they need dark
   values like the panels beside them. */
body.theme-dark .cx-post-h { color: var(--text-primary); }
body.theme-dark .cx-post-x { color: var(--text-secondary); }
body.theme-dark .cx-post-x:hover { background: var(--surface-panel); color: var(--text-primary); }
body.theme-dark .cx-post-facts { border-bottom-color: var(--border); }
body.theme-dark .cx-fact-name, body.theme-dark .cx-fact-v { color: var(--text-primary); }
body.theme-dark .cx-fact-sub { color: var(--text-secondary); }
/* The initials disc was the one thing in here that stayed a near-white chip
   in dark mode, and a global text rule had already turned its letters
   near-white — so it read as an empty white circle. */
body.theme-dark .cx-fact-av { background: var(--brand-blue-soft); color: #7FA9FF; }
/* The segmented track inverts: the rail sinks, the chosen segment lifts. */
body.theme-dark .cx-fact-qs { background: var(--surface-alt); }
body.theme-dark .cx-q { color: var(--text-secondary); }
body.theme-dark .cx-q:hover { color: var(--text-primary); }
body.theme-dark .cx-q.on { background: var(--surface-panel); color: var(--text-primary); box-shadow: none; }
body.theme-dark .cx-post-foot { border-top-color: var(--border); }
body.theme-dark .cx-post.modal .cx-post-foot { background: var(--surface-alt); }
body.theme-dark .cx-post-hint { color: var(--text-tertiary); }
body.theme-dark .cx-outcome-sugg { background: rgba(105, 65, 198, .18); color: #B692F6; }
body.theme-dark .cx-eyebrow { color: var(--text-secondary); }
body.theme-dark .cx-bullets li svg { color: #7FA9FF; }
body.theme-dark .cx-kb-link { color: #7FA9FF; }
body.theme-dark .cx-card-foot { border-top-color: var(--border); }
body.theme-dark .cx-vote:hover { background: var(--surface-panel); color: var(--text-primary); }

body.theme-dark .cx-battle { border-color: var(--border); }
body.theme-dark .cx-battle th, body.theme-dark .cx-battle td { border-bottom-color: var(--border); }
body.theme-dark .cx-battle thead th { background: var(--surface-panel); color: var(--text-primary); }
body.theme-dark .cx-battle thead th.them { background: var(--surface-alt); color: var(--text-primary); }
body.theme-dark .cx-battle td.yes { color: #5EDDA0; }
body.theme-dark .cx-battle td.no { color: #FF8A80; }
body.theme-dark .cx-battle td.part { color: var(--text-secondary); }

body.theme-dark .cx-nudge { background: #221E33; border-color: #37306B; border-left-color: #9B7CF6; }
body.theme-dark .cx-nudge.warn { background: #2A2213; border-color: #5C4415; border-left-color: #E9A23B; }
body.theme-dark .cx-nudge svg { color: #B9A0FA; }
body.theme-dark .cx-nudge.warn svg { color: #E9A23B; }
body.theme-dark .cx-nudge-t { color: var(--text-primary); }
body.theme-dark .cx-nudge-s { color: var(--text-secondary); }
body.theme-dark .cx-nudge-got { color: #B9A0FA; }
body.theme-dark .cx-nudge.warn .cx-nudge-got { color: #E9A23B; }

body.theme-dark .cx-act { background: var(--surface-alt); border-color: var(--border); }
body.theme-dark .cx-act-head svg, body.theme-dark .cx-act-link, body.theme-dark .cx-file-v { color: #7FA9FF; }
body.theme-dark .cx-act-t, body.theme-dark .cx-act-v, body.theme-dark .cx-file-n { color: var(--text-primary); }
body.theme-dark .cx-act-k, body.theme-dark .cx-act-mail, body.theme-dark .cx-file-m { color: var(--text-secondary); }
body.theme-dark .cx-file { border-color: var(--border); }
body.theme-dark .cx-file svg { color: var(--text-secondary); }

/* ---- side panel ---- */
body.theme-dark .cx-side-tab { color: var(--text-secondary); }
body.theme-dark .cx-side-tab.on { color: var(--text-primary); }
body.theme-dark .cx-side-tab.on::after { background: var(--brand-blue); }
body.theme-dark .cx-side-head { border-bottom-color: var(--border); }
body.theme-dark .cx-side-label, body.theme-dark .cx-side-note { color: var(--text-secondary); }
body.theme-dark .cx-sup { background: var(--surface-alt); border-color: var(--border-strong); }
body.theme-dark .cx-sup-n { color: var(--text-primary); }
body.theme-dark .cx-sup-n .st, body.theme-dark .cx-sup svg { color: var(--text-secondary); }
body.theme-dark .cx-sup-av { background: #3A2A14; color: #E9A23B; }
body.theme-dark .cx-ask { border-top-color: var(--border); }
body.theme-dark .cx-ask input { background: var(--surface-alt); border-color: var(--brand-blue); color: var(--text-primary); }
body.theme-dark .cx-send { background: var(--surface-panel); border-color: var(--border); color: var(--text-tertiary); }
body.theme-dark .cx-send.ready { background: var(--brand-blue); border-color: var(--brand-blue); color: #fff; }
body.theme-dark .cx-msg-who { color: var(--text-secondary); }
body.theme-dark .cx-msg-b { background: var(--surface-panel); color: var(--text-primary); }
body.theme-dark .cx-msg.me .cx-msg-b { background: var(--brand-blue-soft); color: #C7D9FF; }
body.theme-dark .cx-count { color: var(--text-tertiary); }
body.theme-dark .cx-tr-t { color: var(--text-primary); }
body.theme-dark .cx-tr.me .cx-tr-t { color: var(--text-secondary); }
body.theme-dark .cx-tr-who { color: var(--text-secondary); }
body.theme-dark .cx-tr-av { background: var(--brand-blue-soft); color: #7FA9FF; }

/* ---- campaign context ---- */
body.theme-dark .cx-split:hover i { background: var(--border-strong); }
body.theme-dark .cx-skel-card { border-color: var(--border); }

/* ---- wrap-up ---- */
body.theme-dark .cx-post.modal .cx-shell { background: var(--surface); }
body.theme-dark .cx-sum-h, body.theme-dark .cx-sum-t, body.theme-dark .cx-ai-h, body.theme-dark .cx-ai-t { color: var(--text-primary); }
body.theme-dark .cx-ai { border-color: var(--border); }
body.theme-dark .cx-ai.done .cx-ai-t { color: var(--text-secondary); }
body.theme-dark .cx-ai-link { color: #7FA9FF; }
body.theme-dark .cx-copy:hover { background: var(--surface-panel); color: var(--text-primary); }
body.theme-dark .cx-wrap-l { color: var(--text-primary); }
body.theme-dark .cx-outcome { background: var(--surface-alt); border-color: var(--border-strong); color: var(--text-primary); }
body.theme-dark .cx-outcome.empty { color: var(--text-tertiary); }
body.theme-dark .cx-post-ta { background: var(--surface-alt); border-color: var(--border-strong); color: var(--text-primary); }
body.theme-dark .cx-save { background: var(--brand-blue); }
/* The disabled Save and the suggestion carry meaning, so they get dark values
   rather than staying light blocks on a dark panel. */
body.theme-dark .cx-save[disabled] { background: var(--surface-panel); color: var(--text-tertiary); }
body.theme-dark .cx-save[disabled]:hover { background: var(--surface-panel); }
body.theme-dark .cx-sugg { background: var(--surface-alt); border-color: var(--border-strong); color: var(--text-secondary); }
body.theme-dark .cx-sugg:hover { background: var(--surface-panel); }
body.theme-dark .cx-sugg .sp, body.theme-dark .cx-sugg-go { color: #B692F6; }

/* ---- metric pills: meaning, not surface ---- */
body.theme-dark .cx-metric.good { background: #102A1C; color: #5EDDA0; }
body.theme-dark .cx-metric.warn { background: #2E2413; color: #E9A23B; }
body.theme-dark .cx-metric.bad  { background: #33191A; color: #FF8A80; }
body.theme-dark .cx-notes { background: var(--surface-alt); border-color: var(--border); }
body.theme-dark .cx-notes textarea { background: #2A2517; color: var(--text-primary); }
body.theme-dark .cx-notes-foot { background: var(--surface-alt); border-top-color: var(--border); }
body.theme-dark .cx-note { color: var(--text-secondary); }
body.theme-dark .cx-select { background: var(--surface-alt); border-color: var(--border-strong); color: var(--text-primary); }
body.theme-dark .cx-field { border-bottom-color: var(--border); }
body.theme-dark .cx-empty-t { color: var(--text-primary); }
body.theme-dark .cx-empty-s { color: var(--text-secondary); }

/* ---------- Making room for the docked strip ----------------------------- */

/* Two other things live at the bottom of the content area, both position:fixed
 * and both unaware of each other: the call-recording player and the bulk
 * action bar. Docking the call strip puts it straight through them — the
 * player sits above it on z-index and covers End call, and the bulk bar
 * disappears underneath it.
 *
 * Neither can be fixed by z-index, because the answer is not "which one wins"
 * but "both, stacked". They lift by exactly the height the strip took, so the
 * three read as one column of bars rather than a pile.
 *
 * A dragged player sets inline top/left, which outranks this — someone who has
 * moved it has said where they want it. */
body.cx-docked .cl-player,
body.cx-docked .bulk-bar {
  bottom: calc(var(--cx-dock, 74px) + 14px);
}
