/* Dialer session — the screen an agent lives in while running a campaign.
 *
 * Opened from Campaigns › Calling when a campaign starts. It takes over the
 * window because that is what it is: for the length of a session this is the
 * only thing the agent is doing, and anything else on screen is a distraction
 * from the queue.
 *
 * Three dialer modes share this shell:
 *
 *   power       one contact at a time, agent-paced, cool-off between calls
 *   dynamic     same shape, but the queue is refilled as it drains
 *   predictive  several lines dialled per agent; the agent is joined to
 *               whichever one answers first
 *
 * Power and dynamic differ only in how the list is fed, so they share a
 * layout. Predictive is genuinely different — the agent does not choose who
 * is next — so its status column, its strip and its right rail all change.
 *
 * The layout is a fixed three-part stack: a session header that never moves,
 * a state strip that says what the session is doing right now and carries the
 * one control that matters, and the queue itself. The strip is the whole
 * design: an agent glancing up mid-call needs one line to know where they are.
 */

/* The session wears the app's own shell: the page sits on the same #F8F8F8
 * the sidebar uses, and the work area is a single white rounded card inset
 * from it — the same treatment .main gets on every primary nav page. */
/* The queue is a page in the work area, not an overlay over the window: it
   fills #mainBody so the side nav and topbar stay put. Its old fixed/inset
   took the whole app with it whenever a campaign started. */
.ds {
  flex: 1 1 auto; min-width: 0; min-height: 0;
  display: flex; flex-direction: column;
  background: #F8F8F8;
  font-family: 'Inter', -apple-system, sans-serif;
  opacity: 0;
  transition: opacity .14s ease;
}
.ds.show { opacity: 1; }

/* Docked so the call bar can sit under it, exactly as it does over the app. */
/* No `bottom` to push any more — the page is inside the work area, and the
   app's own dock padding already makes room for the strip. */

/* ---------- Session header ---------------------------------------------- */

/* Header carries the nav's background rather than the card's, so the card
 * below reads as the page and the header as chrome around it. */
.ds-top {
  flex: 0 0 auto; display: flex; align-items: center; gap: 16px;
  padding: 12px 20px 14px; background: #F8F8F8;
}

/* The session's vital signs. At the left edge, which is where a row of
 * figures is read from — it was centred when the campaign's name sat beside
 * it and the two shared the row. The name has gone (the breadcrumb above
 * carries it) and the row is now the only thing in the header besides the way
 * out, so it starts where reading starts.
 *
 * `auto` on the right rather than a fixed margin: predictive carries eight
 * cells against power's five, and the row should end where its own content
 * ends rather than being stretched to meet the controls. */
/* The groups. Predictive's running totals and its live engine figures are two
 * boxes side by side; every other mode has only the first and looks exactly as
 * it did. `auto` on the right rather than a fixed margin: the row should end
 * where its own content ends rather than being stretched to meet the
 * controls. */
.ds-statgroups {
  margin-right: auto; display: flex; align-items: stretch; min-width: 0; gap: 10px;
}
.ds-stats {
  display: flex; align-items: stretch;
  border: 1px solid #EAECF0; border-radius: 10px; overflow: hidden;
}
/* Eight cells will outgrow a narrow work area before four ever did. The row
   scrolls rather than wrapping, because a header that changes height moves
   the whole page under it. It scrolls as one row: the two boxes travel
   together, so the gap between them stays put and neither can slide out of
   step with the other. `flex: 0 0 auto` keeps each box at its natural width
   instead of letting the pair compress to fit. */
@media (max-width: 1400px) {
  .ds-statgroups { overflow-x: auto; scrollbar-width: none; }
  .ds-statgroups::-webkit-scrollbar { display: none; }
  .ds-stats { flex: 0 0 auto; }
}
.ds-stat { padding: 7px 18px; border-right: 1px solid #EAECF0; text-align: center; }
.ds-stat:last-child { border-right: 0; }
.ds-stat-k {
  font: 500 10.5px/1.4 'Inter', sans-serif; color: #98A2B3;
  letter-spacing: .06em; text-transform: uppercase;
}
.ds-stat-v { font: 600 17px/1.3 'Inter', sans-serif; color: #101828; font-variant-numeric: tabular-nums; }

.ds-top-acts { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }

/* ---------- Audio settings ----------------------------------------------
   The gear's panel. A light surface on the same recipe as .ds-menu — white,
   #EAECF0, 10px, one shadow — because it hangs off this header rather than
   off the call bar, whose own floating widgets are dark for that reason.
   Anchored right: the gear is the second-to-last control in the header, so a
   panel growing leftward stays on the page. */
.ds-as-wrap { position: relative; display: inline-flex; }
.ds-as {
  position: absolute; top: 100%; right: 0; margin-top: 8px; z-index: 30;
  width: 316px; text-align: left;
}
.ds-as-card {
  padding: 6px 14px 14px;
  background: #fff; border: 1px solid #EAECF0; border-radius: 12px;
  box-shadow: 0 14px 32px rgba(16, 24, 40, .16);
}
.ds-as-head { display: flex; align-items: center; gap: 8px; height: 38px; }
.ds-as-t { flex: 1 1 auto; font: 600 13.5px/1.4 'Inter', sans-serif; color: #101828; }
.ds-as-x {
  width: 26px; height: 26px; flex: 0 0 auto; padding: 0;
  display: inline-grid; place-items: center;
  border: 0; border-radius: 6px; background: transparent; color: #98A2B3; cursor: pointer;
}
.ds-as-x:hover { background: #F2F4F7; color: #475467; }
.ds-as-x svg { width: 15px; height: 15px; display: block; }

.ds-as-sec { padding-top: 4px; }
.ds-as-lbl {
  display: flex; align-items: center; gap: 7px; margin-bottom: 7px;
  font: 500 12px/1.4 'Inter', sans-serif; color: #475467;
}
.ds-as-lbl svg { width: 14px; height: 14px; flex: 0 0 auto; color: #98A2B3; }
.ds-as-lbl > span:first-of-type { flex: 1 1 auto; }
/* Which device the session will actually use, said on the label rather than
   only in the button's disabled state — a disabled button is a dead end to
   read, not an answer to "which one is it now". */
.ds-as-def {
  flex: 0 0 auto; padding: 1px 7px; border-radius: 20px;
  background: #ECFDF3; color: #027A48;
  font: 500 10.5px/1.6 'Inter', sans-serif; letter-spacing: .03em; text-transform: uppercase;
}
.ds-as-select {
  width: 100%; height: 36px; padding: 0 30px 0 11px;
  border: 1px solid #D0D5DD; border-radius: 8px; background: #fff; color: #101828;
  font: 400 13px/1 'Inter', sans-serif; font-family: 'Inter', sans-serif;
  cursor: pointer; appearance: none;
  /* The chevron is the background rather than a sibling element, so the
     select stays one hit area the whole width of the field. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='2' 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 9px center;
}
.ds-as-select:hover { border-color: #98A2B3; }
.ds-as-select:focus-visible { outline: none; border-color: #0B5CFF; box-shadow: 0 0 0 3px rgba(11, 92, 255, .16); }
.ds-as-select[disabled] { background-color: #F9FAFB; color: #98A2B3; cursor: default; }

.ds-as-acts { display: flex; gap: 8px; margin-top: 9px; }
/* The panel's own button size. Two controls on a 316px panel next to a 36px
   field: the header's 36px would leave them looking like the page's primary
   actions, which they are not. */
.ds-as .ds-btn.sm {
  height: 32px; padding: 0 11px; font-size: 12.5px; gap: 6px;
  flex: 1 1 0; justify-content: center;
}
.ds-as .ds-btn.sm svg { width: 14px; height: 14px; }
/* Testing is a state, not a press: the control says Stop while the meter is
   live, and looks held down to match. */
.ds-as .ds-btn.sm.on { background: #EFF4FF; border-color: #B2CCFF; color: #0B5CFF; }
.ds-as .ds-btn.sm.on svg { color: #0B5CFF; }

.ds-as-rule { height: 1px; margin: 14px 0 4px; background: #EAECF0; }

.ds-as-bar {
  height: 6px; margin-top: 10px; border-radius: 20px; background: #EAECF0; overflow: hidden;
}
.ds-as-bar-f {
  display: block; width: 0; height: 100%; border-radius: 20px; background: #D0D5DD;
  /* Short, because it is a meter: long enough to smooth the frame-to-frame
     jitter of an RMS reading, short enough that it still reads as following
     the voice rather than trailing it. */
  transition: width 80ms linear, background-color 160ms ease;
}
.ds-as-bar.live .ds-as-bar-f { background: #12B76A; }
.ds-as-hint { margin-top: 7px; font: 400 11.5px/1.5 'Inter', sans-serif; color: #98A2B3; }
.ds-as-err {
  margin: 2px 0 8px; padding: 8px 10px; border-radius: 8px;
  background: #FEF3F2; border: 1px solid #FEE4E2; color: #B42318;
  font: 400 11.5px/1.5 'Inter', sans-serif;
}
@media (prefers-reduced-motion: reduce) { .ds-as-bar-f { transition: none; } }
.ds-ib {
  width: 36px; height: 36px; border-radius: 8px; padding: 0;
  border: 0; background: transparent; color: #475467; cursor: pointer;
  display: grid; place-items: center; position: relative;
}
.ds-ib:hover { background: #F2F4F7; color: #101828; }
.ds-ib svg { width: 18px; height: 18px; }
.ds-ib .dot {
  position: absolute; top: 7px; right: 8px;
  width: 6px; height: 6px; border-radius: 999px; background: #F04438;
  border: 1.5px solid #fff;
}
.ds-btn {
  display: inline-flex; align-items: center; gap: 8px;
  height: 36px; padding: 0 14px; border-radius: 8px;
  border: 1px solid #D0D5DD; background: #fff; color: #344054; cursor: pointer;
  font: 500 13.5px/1 'Inter', sans-serif;
  /* The strip's middle column takes the slack, so a button never has to give
     up width: "Start Dialing" was breaking across two lines inside a control
     one line tall. */
  flex: 0 0 auto; white-space: nowrap;
}
.ds-btn:hover { background: #F9FAFB; }
.ds-btn svg { width: 16px; height: 16px; }
.ds-btn[disabled] { opacity: .45; cursor: default; }
.ds-btn.primary { background: #0B5CFF; border-color: #0B5CFF; color: #fff; }
.ds-btn.primary:hover { background: #0048CC; }
/* Blue stroke, no fill: for a control that is the lesser of two ways out of
   a state. Named `blue` rather than `secondary` on purpose —
   theme-customiser.css claims `button.secondary` for a theme-wide grey
   outline with !important, so a button of ours wearing that name loses its
   own colour in dark mode and there is no cascade left to win it back. */
.ds-btn.blue { border-color: #B2CCFF; color: #0B5CFF; }
.ds-btn.blue:hover { background: #EFF4FF; border-color: #0B5CFF; }
.ds-btn.danger { border-color: #FDA29B; color: #B42318; }
.ds-btn.danger:hover { background: #FEF3F2; }

/* ---------- Body ---------------------------------------------------------- */

/* Queue and contact share one container. They are two halves of the same
 * job — who is next, and who that is — so they get one card and an internal
 * divider rather than two panes with a seam between them.
 *
 * It is the third row of the page, not a card floating in it: page header,
 * campaign header, then this — full width, no inset. The margins it used to
 * carry cost ~20px of queue width on every side and drew a second border
 * inside the work area's own, which reads as a box within a box. The only
 * corners left are the bottom two, and they belong to the work area rather
 * than to this: 15px against the shell's 16px and its 1px border, so the two
 * curves are concentric instead of nearly-but-not-quite matching. */
.ds-main {
  flex: 1 1 auto; min-height: 0;
  display: grid; grid-template-columns: minmax(0, 1fr) 470px;
  background: #FFFFFF; border-top: 1px solid #E4E7EC;
  border-radius: 0 0 15px 15px;
  overflow: hidden;
}
/* Panel closed: the queue takes the width back. */
.ds-main.no-rail { grid-template-columns: minmax(0, 1fr); }

/* ---------- Queue beside the conversation -------------------------------- */

/* Picking a row opens the conversation with that contact rather than a panel
 * of their fields: the thread and the contact sheet, both the Conversations
 * page's own components. The tracks are set from JS (applyWidths) because the
 * three floors they answer to are a chain — the queue's 25%, the thread's 30%,
 * and a sheet that is dropped rather than squeezed past half — and grid can
 * express any one of them but not the order they give way in. */
.ds-main.ds-main-convo { grid-template-columns: 40% 14px minmax(0, 1fr); }

/* Connected: the queue is out of the layout and the thread has the work area
 * (see shellHTML). One track, and no left border on the pane — there is
 * nothing to its left to be divided from. JS sets the track too; this is the
 * value the first paint uses, before applyWidths has measured anything. */
.ds-main.ds-main-solo { grid-template-columns: minmax(0, 1fr); }
.ds-main.ds-main-solo .ds-pane { border-left: 0; }

/* One pane, one header, two columns under it — they are one contact, so they
   are titled once. The sheet is a column of the pane rather than of the page
   for that reason: a track of the outer grid would put it outside the header
   that names it. */
.ds-pane {
  min-width: 0; min-height: 0; display: flex; flex-direction: column;
  overflow: hidden; border-left: 1px solid #EAECF0; background: #FFFFFF;
}
.ds-pane-cols {
  flex: 1 1 auto; min-height: 0;
  display: grid; grid-template-columns: minmax(0, 1fr) 380px;
}
.ds-convo, .ds-sheet { min-width: 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
/* #FAFBFC is the thread scroller's own background (set inline in
   thread-view.jsx). The column matches it, and so does the strip the
   composer sits on — see --cmp-surface in messaging/composer.jsx — so the
   surface runs unbroken from the last message to the send button instead of
   changing to white for the bottom 200px. */
.ds-convo { background: #FAFBFC; --cmp-surface: #FAFBFC; }
.ds-sheet { border-left: 1px solid #EAECF0; background: #FFFFFF; overflow-y: auto; }
/* The components inside are the Conversations app's, and they expect to fill
   whatever they are given. */
.ds-convo > *, .ds-sheet > * { flex: 1 1 auto; min-height: 0; }

/* The pane's header. Sized and spaced like the thread header it replaces —
   it is standing in the same place, over both columns instead of one. */
.ds-ch {
  flex: 0 0 auto; display: flex; align-items: center; gap: 12px;
  padding: 12px 12px 12px 20px;
  border-bottom: 1px solid #E4E7EC; background: #FFFFFF;
}
.ds-ch-av {
  flex: 0 0 auto; width: 36px; height: 36px; border-radius: 999px;
  display: grid; place-items: center; background: #EEF2FF; color: #4453C7;
  font: 600 12.5px/1 'Inter', sans-serif;
}
.ds-ch-who { min-width: 0; flex: 1 1 auto; }
.ds-ch-n {
  display: block; font: 600 15px/1.3 'Inter', sans-serif; color: #101828;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ds-ch-p { display: block; margin-top: 1px; font: 400 11px/1.35 'Inter', sans-serif; color: #667085; }
.ds-ch-acts { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
.ds-ch-b {
  width: 32px; height: 32px; padding: 0; border-radius: 8px;
  border: 1px solid #E4E7EC; background: #fff; color: #667085;
  display: grid; place-items: center; cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.ds-ch-b svg { width: 15px; height: 15px; }
.ds-ch-b:hover { background: #F9FAFB; color: #344054; }
.ds-ch-b.on { background: #EFF4FF; border-color: #B2CCFF; color: #004CE6; }
@media (prefers-reduced-motion: reduce) { .ds-ch-b { transition: none; } }

/* The divider. Invisible until reached for — a line that is always drawn
   reads as a border between two panes, and this is a control. */
.ds-split {
  display: grid; place-items: center;
  cursor: col-resize; touch-action: none;
  background: transparent; border: 0; padding: 0;
}
.ds-split i {
  width: 3px; height: 48px; border-radius: 999px; background: transparent;
  transition: background 130ms ease, height 130ms ease;
}
.ds-split:hover i { background: #D0D5DD; }
.ds-split:focus-visible { outline: none; }
.ds-split:focus-visible i, .ds-split.on i { background: #0B5CFF; height: 76px; }
body.ds-dragging { cursor: col-resize; user-select: none; }
body.ds-dragging * { cursor: col-resize !important; }
@media (prefers-reduced-motion: reduce) { .ds-split i { transition: none; } }
.ds-work { min-width: 0; display: flex; flex-direction: column; }
.ds-rail { border-left: 1px solid #EAECF0; min-width: 0; display: flex; flex-direction: column; overflow-y: auto; }

/* The strip is the container's first row and the container's top edge is
   square now, so there is no rounded corner left to keep clear of. */

/* ---------- State strip --------------------------------------------------- */

/* One row, always in the same place, saying what the session is doing and
 * offering the single action that matters in that state. */
.ds-strip {
  flex: 0 0 auto; display: flex; align-items: center; gap: 14px;
  padding: 16px 22px; min-height: 74px;
}
.ds-strip-ic {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: 999px;
  display: grid; place-items: center; background: #F2F4F7; color: #475467;
}
.ds-strip-ic svg { width: 21px; height: 21px; }
.ds-strip-ic.warn { background: #FFFAEB; color: #DC6803; }
.ds-strip-ic.ok   { background: #ECFDF3; color: #067647; }
.ds-strip-ic.live { background: #EFF4FF; color: #004CE6; }
.ds-strip-t { display: block; font: 600 15.5px/1.35 'Inter', sans-serif; color: #101828; }
.ds-strip-s { display: block; margin-top: 2px; font: 400 13.5px/1.45 'Inter', sans-serif; color: #667085; }
.ds-strip > span:not([class]) { flex: 1 1 auto; min-width: 0; }
.ds-strip-acts { flex: 0 0 auto; margin-left: auto; display: flex; align-items: center; gap: 10px; }

/* Reasons a queue is stalled, shown inline so the agent can see whether it is
 * worth waiting or worth leaving. */
.ds-reasons { margin-left: auto; display: flex; align-items: center; gap: 22px; }
.ds-reason {
  display: inline-flex; align-items: center; gap: 8px;
  font: 400 14px/1.4 'Inter', sans-serif; color: #475467;
}
.ds-reason svg { width: 17px; height: 17px; color: #98A2B3; }

/* Cool-off ring. The countdown is the whole point, so it gets the ring. */
.ds-ring { flex: 0 0 auto; width: 44px; height: 44px; position: relative; }
.ds-ring svg { width: 44px; height: 44px; transform: rotate(-90deg); display: block; }
.ds-ring circle { fill: none; stroke-width: 4; }
.ds-ring .bg { stroke: #EAECF0; }
.ds-ring .fg { stroke: #0B5CFF; stroke-linecap: round; transition: stroke-dashoffset 1s linear; }
.ds-count {
  display: inline-flex; align-items: center; gap: 4px;
  font: 600 15.5px/1.35 'Inter', sans-serif; color: #101828;
}
.ds-count b {
  padding: 2px 9px; border-radius: 7px; background: #EFF4FF; color: #0B5CFF;
  font: 600 14px/1.4 'Inter', sans-serif; font-variant-numeric: tabular-nums;
}

/* Predictive's "lines are ringing" indicator. */
.ds-eq { flex: 0 0 auto; display: flex; align-items: flex-end; gap: 3px; width: 44px; height: 30px; }
.ds-eq i { flex: 1; border-radius: 2px; background: #0B5CFF; animation: dsEq 900ms ease-in-out infinite alternate; }
.ds-eq i:nth-child(2) { animation-delay: .2s; }
.ds-eq i:nth-child(3) { animation-delay: .4s; }
@keyframes dsEq { from { height: 28%; } to { height: 100%; } }
@media (prefers-reduced-motion: reduce) { .ds-eq i { animation: none; height: 62%; } }

/* ---------- Queue table --------------------------------------------------- */

/* The queue is its own node so a repaint of the list leaves the row above it
 * alone. */
.ds-queue { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* Inset to the same 22px gutter the strip uses, so the queue sits on the
   page's margin rather than running into its edges. */
.ds-table-wrap { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 0 22px 8px; }

/* The table itself is .ct-table — the one Contacts, Call Logs and the two
 * campaign lists use — so nothing here restates its type, its row height, its
 * cell padding or its sticky head. This queue used to carry all four and had
 * drifted from the rest of the app on every one of them.
 *
 * What is left is what the shared table has no opinion about: which row the
 * contact panel is describing, which rows cannot be acted on yet, and a row
 * on its way out of the queue. */

/* The contact the panel is describing, or the one being dialled. Louder than
   the shared hover, because it survives the pointer leaving the row. */
.ds-queue .ct-table tbody tr.on td { background: #F4F8FF; }
/* Rows the agent cannot act on right now read back a step. */
.ds-queue .ct-table tbody tr.dim td,
.ds-queue .ct-table tbody tr.dim .jc-name { color: #98A2B3; }
.ds-queue .ct-table tbody tr { cursor: pointer; }
/* .ct-row-in is worn for its hover — the blue one Contacts rows get — but not
   for its entrance. That 240ms fade suits a table that renders once and then
   on a filter change; this queue rebuilds its tbody on every turn of the
   session's state machine, so the whole list would replay the animation each
   time. Rows here are being repainted, not arriving. */
.ds-queue .ct-table tbody tr.ct-row-in { animation: none; }

.ds-more {
  display: flex; align-items: center; gap: 16px; padding: 20px 22px;
  font: 400 13.5px/1.4 'Inter', sans-serif; color: #98A2B3;
}
.ds-more::before, .ds-more::after { content: ''; flex: 1; height: 1px; background: #F2F4F7; }

.ds-empty { padding: 60px 22px; text-align: center; }
.ds-empty-t { font: 500 15px/1.4 'Inter', sans-serif; color: #344054; }
.ds-empty-s { margin-top: 4px; font: 400 13.5px/1.5 'Inter', sans-serif; color: #667085; }

/* Status, as a tag ---------------------------------------------------------
 *
 * The chip itself is .jc-tag — shape, height, border, type and every tint,
 * light and dark — so the Status column and the Tags column beside it are the
 * same object. All this adds is the icon, which a tag has never had to hold:
 * 13px rather than the 15px the old pill used, because the shared chip is
 * 22px tall against that pill's 28. */
/* A status never breaks across lines; .jc-tags-cell lets its contents wrap
   so that several tags can, and this cell holds one that must not. */
.ds-st { gap: 5px; white-space: nowrap; }
.ds-st svg { width: 13px; height: 13px; flex: 0 0 auto; }
.ds-st .dot { width: 5px; height: 5px; border-radius: 999px; background: currentColor; }
/* Ringing should look like it is doing something. */
.ds-st.ring svg { animation: dsShake 1.1s ease-in-out infinite; }
@keyframes dsShake { 0%, 100% { transform: rotate(-8deg); } 50% { transform: rotate(8deg); } }
@media (prefers-reduced-motion: reduce) { .ds-st.ring svg { animation: none; } }

/* ---------- Rail: contact (power / dynamic) ------------------------------- */

.ds-rail-head { flex: 0 0 auto; padding: 20px 24px 0; }
.ds-rail-x {
  margin-left: auto; flex: 0 0 auto; width: 28px; height: 28px; padding: 0;
  border: 0; border-radius: 7px; background: transparent; color: #98A2B3;
  display: grid; place-items: center; cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.ds-rail-x:hover { background: #F2F4F7; color: #344054; }
.ds-rail-x svg { width: 17px; height: 17px; }
.ds-rc { display: flex; align-items: center; gap: 14px; }
.ds-rc > span:last-child { min-width: 0; }
.ds-rc-av {
  flex: 0 0 auto; width: 46px; height: 46px; border-radius: 999px;
  display: grid; place-items: center; background: #EEF2FF; color: #4453C7;
  font: 600 15px/1 'Inter', sans-serif;
}
.ds-rc-n { display: block; font: 600 21px/1.25 'Inter', sans-serif; color: #101828; letter-spacing: -.01em; }
.ds-rc-p { display: block; margin-top: 1px; font: 400 14.5px/1.35 'Inter', sans-serif; color: #667085; }

/* Where this contact already lives. Real dialers put these here because the
 * first thing an agent does on a connect is open the CRM record. */
.ds-apps {
  display: inline-flex; align-items: center; gap: 12px; margin-top: 14px;
  padding: 8px 12px; border: 1px solid #EAECF0; border-radius: 10px;
}
.ds-app { width: 22px; height: 22px; display: grid; place-items: center; cursor: pointer; }
.ds-app svg { width: 22px; height: 22px; display: block; }
.ds-apps .chev { color: #667085; padding-left: 4px; border-left: 1px solid #EAECF0; }
.ds-apps .chev svg { width: 18px; height: 18px; }

.ds-tabs { display: flex; gap: 26px; margin-top: 18px; border-bottom: 1px solid #EAECF0; }
.ds-tab {
  position: relative; padding: 0 0 12px; border: 0; background: transparent;
  font: 500 15px/1.3 'Inter', sans-serif; color: #667085; cursor: pointer;
}
.ds-tab.on { color: #101828; }
.ds-tab.on::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; background: #0B5CFF; border-radius: 2px 2px 0 0;
}
.ds-tab .n {
  margin-left: 7px; padding: 1px 7px; border-radius: 6px;
  background: #F2F4F7; color: #475467; font: 500 12.5px/1.5 'Inter', sans-serif;
}
.ds-rail-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 8px 24px 28px; }

.ds-kv { display: grid; grid-template-columns: 1fr auto; gap: 14px; align-items: baseline; padding: 13px 0; }
.ds-kv-k { font: 400 14.5px/1.4 'Inter', sans-serif; color: #667085; }
.ds-kv-v { font: 400 14.5px/1.4 'Inter', sans-serif; color: #101828; text-align: right; word-break: break-word; }
.ds-kv-v a { color: #0B5CFF; text-decoration: none; }

/* Recent calls — collapsed to outcome and time, expanded to the detail that
 * changes how you open the next call. */
.ds-call { border: 1px solid #EAECF0; border-radius: 12px; margin-bottom: 12px; }
.ds-call-head {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 14px; border: 0; background: transparent; cursor: pointer; text-align: left;
}
.ds-call-ic { flex: 0 0 auto; width: 36px; height: 36px; border-radius: 999px; display: grid; place-items: center; }
.ds-call-ic svg { width: 18px; height: 18px; }
.ds-call-ic.ok   { background: #ECFDF3; color: #067647; }
.ds-call-ic.vm   { background: #F4F3FF; color: #7F56D9; }
.ds-call-ic.miss { background: #FEF3F2; color: #D92D20; }
.ds-call-t { display: block; font: 600 15px/1.3 'Inter', sans-serif; color: #101828; }
.ds-call-d { display: block; margin-top: 2px; font: 400 13.5px/1.3 'Inter', sans-serif; color: #667085; }
.ds-call-head > span:nth-child(2) { flex: 1 1 auto; min-width: 0; }
.ds-call-chev { margin-left: auto; color: #98A2B3; transition: transform 160ms ease; }
.ds-call-chev svg { width: 18px; height: 18px; display: block; }
.ds-call[aria-expanded="true"] .ds-call-head > span:nth-child(2) { flex: 1 1 auto; min-width: 0; }
.ds-call-chev { transform: rotate(180deg); }
.ds-call-body { display: none; padding: 0 14px 14px; border-top: 1px solid #F2F4F7; margin: 0 14px; padding-left: 0; padding-right: 0; }
.ds-call[aria-expanded="true"] .ds-call-body { display: block; }
.ds-call-row { display: flex; align-items: baseline; gap: 12px; padding: 9px 0; }
.ds-call-row .k { font: 400 14px/1.4 'Inter', sans-serif; color: #667085; }
.ds-call-row .v { margin-left: auto; font: 400 14px/1.4 'Inter', sans-serif; color: #101828; text-align: right; }

/* ---------- Narrow ------------------------------------------------------- */

@media (max-width: 1240px) {
  .ds-main { grid-template-columns: minmax(0, 1fr) 380px; }
}
@media (max-width: 1000px) {
  .ds-main { grid-template-columns: minmax(0, 1fr); }
  .ds-rail { display: none; }
}

/* ======================================================================== */
/* Agent working surface                                                     */
/* ======================================================================== */

/* The three additions that turn the queue from something you watch into
 * something you work: a brief on whoever is next, hands-free control, and
 * per-row actions that don't require opening anything. */

/* ---------- Row hover actions -------------------------------------------- */

/* Skip has a column of its own — it is in the header, so the space is held
 * whether or not anything is in it. It used to float over the right of the
 * row on a gradient, because the alternative then was reserving width for a
 * button nobody could see; a named column says what that width is for.
 * Hidden until the row is under the pointer or holds focus, and pinned open
 * while its menu is. */
.ds-queue td.ds-col-acts { text-align: right; }
.ds-row-acts {
  display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
  opacity: 0; pointer-events: none;
  transition: opacity 130ms ease;
}
.ds-queue tbody tr:hover .ds-row-acts,
.ds-queue tbody tr:focus-within .ds-row-acts,
.ds-row-acts.open { opacity: 1; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .ds-row-acts { transition: none; } }

.ds-ra {
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 10px; border-radius: 7px;
  border: 1px solid #EAECF0; background: #fff; color: #475467; cursor: pointer;
  font: 500 12.5px/1 'Inter', sans-serif; white-space: nowrap;
}
.ds-ra:hover { background: #F9FAFB; color: #101828; border-color: #D0D5DD; }
.ds-ra svg { width: 14px; height: 14px; }
.ds-ra.go { border-color: #B2CCFF; color: #0B5CFF; }
.ds-ra.go:hover { background: #EFF4FF; border-color: #0B5CFF; }
.ds-ra.icon { padding: 0; width: 30px; justify-content: center; }

.ds-ra-wrap { position: relative; display: inline-flex; }
.ds-menu {
  position: absolute; top: 100%; right: 0; margin-top: 6px; z-index: 20;
  min-width: 210px; padding: 6px;
  background: #fff; border: 1px solid #EAECF0; border-radius: 10px;
  box-shadow: 0 14px 32px rgba(16, 24, 40, .16);
  text-align: left;
}
.ds-menu[hidden] { display: none; }
.ds-menu-h {
  padding: 7px 10px 5px; font: 500 11.5px/1.4 'Inter', sans-serif;
  color: #98A2B3; letter-spacing: .05em; text-transform: uppercase;
}
.ds-menu button {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 9px 10px; border: 0; border-radius: 7px; background: transparent;
  font: 400 14px/1.3 'Inter', sans-serif; color: #101828; cursor: pointer; text-align: left;
}
.ds-menu button:hover { background: #F2F4F7; }
.ds-menu button svg { width: 15px; height: 15px; color: #98A2B3; flex: 0 0 auto; }
.ds-menu button.danger { color: #B42318; }
.ds-menu button.danger svg { color: #D92D20; }

/* ---------- Up-next label ------------------------------------------------ */

.ds-eyebrow {
  display: flex; align-items: center; gap: 9px; margin-bottom: 12px;
  font: 500 11.5px/1.4 'Inter', sans-serif; color: #667085;
  letter-spacing: .06em; text-transform: uppercase;
}
.ds-eyebrow .tag {
  padding: 2px 8px; border-radius: 999px; background: #EFF4FF; color: #0B5CFF;
  letter-spacing: .04em;
}
.ds-eyebrow .in {
  margin-left: auto; text-transform: none; letter-spacing: 0;
  font: 400 12.5px/1.4 'Inter', sans-serif; color: #98A2B3; font-variant-numeric: tabular-nums;
}

/* A row that has been snoozed or skipped from the queue fades out on its way
 * off the list, so the change is legible rather than a silent disappearance. */
.ds-queue tbody tr.leaving td { background: #FCFCFD; color: #C4CBD6; }
.ds-queue tbody tr.leaving { transition: opacity 200ms ease; opacity: 0; }

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

/* The session borrows the app shell, so it borrows the shell's dark surfaces
 * too: page on --surface, work card on --surface-alt, dividers on --border.
 * The status pills are restated rather than flipped — ringing blue and held
 * amber are the whole point of that column, and pale tints meant for a white
 * row glow on a dark one. */

body.theme-dark .ds { background: var(--surface); }
body.theme-dark .ds-top { background: var(--surface); }
body.theme-dark .ds-stats { border-color: var(--border); }
body.theme-dark .ds-stat { border-right-color: var(--border); }
body.theme-dark .ds-stat-k { color: var(--text-tertiary); }
body.theme-dark .ds-stat-v { color: var(--text-primary); }
body.theme-dark .ds-ib { color: var(--text-secondary); }
body.theme-dark .ds-ib:hover { background: var(--surface-panel); color: var(--text-primary); }
body.theme-dark .ds-ib .dot { border-color: var(--surface); }
body.theme-dark .ds-btn { background: var(--surface-alt); border-color: var(--border-strong); color: var(--text-primary); }
body.theme-dark .ds-btn:hover { background: var(--surface-panel); }
body.theme-dark .ds-btn.primary { background: var(--brand-blue); border-color: var(--brand-blue); color: #fff; }
body.theme-dark .ds-btn.blue { background: transparent; border-color: #2C3E63; color: #7FA9FF; }
body.theme-dark .ds-btn.blue:hover { background: var(--brand-blue-soft); border-color: var(--brand-blue); }
body.theme-dark .ds-btn.danger { border-color: #6B2B27; color: #FF8A80; }
body.theme-dark .ds-btn.danger:hover { background: #33191A; }

/* ---- work card ---- */
body.theme-dark .ds-main { background: var(--surface-alt); border-color: var(--border); }
body.theme-dark .ds-rail { border-left-color: var(--border); }
body.theme-dark .ds-pane { border-left-color: var(--border); background: var(--surface-alt); }
body.theme-dark .ds-convo { background: var(--surface); }
body.theme-dark .ds-sheet { border-left-color: var(--border); background: var(--surface-alt); }
body.theme-dark .ds-ch { background: var(--surface-alt); border-bottom-color: var(--border); }
body.theme-dark .ds-ch-av { background: var(--brand-blue-soft); color: #7FA9FF; }
body.theme-dark .ds-ch-n { color: var(--text-primary); }
body.theme-dark .ds-ch-p { color: var(--text-secondary); }
body.theme-dark .ds-ch-b { background: var(--surface-alt); border-color: var(--border-strong); color: var(--text-secondary); }
body.theme-dark .ds-ch-b:hover { background: var(--surface-panel); color: var(--text-primary); }
body.theme-dark .ds-ch-b.on { background: var(--brand-blue-soft); border-color: var(--brand-blue); color: #7FA9FF; }
body.theme-dark .ds-split:hover i { background: var(--border-strong); }
body.theme-dark .ds-rail-x { color: var(--text-tertiary); }
body.theme-dark .ds-rail-x:hover { background: var(--surface-panel); color: var(--text-primary); }

/* ---- state strip ---- */
body.theme-dark .ds-strip-ic { background: var(--surface-panel); color: var(--text-secondary); }
body.theme-dark .ds-strip-ic.warn { background: #2E2413; color: #E9A23B; }
body.theme-dark .ds-strip-ic.ok { background: #102A1C; color: #5EDDA0; }
body.theme-dark .ds-strip-ic.live { background: var(--brand-blue-soft); color: #7FA9FF; }
body.theme-dark .ds-strip-t { color: var(--text-primary); }
body.theme-dark .ds-strip-s { color: var(--text-secondary); }
body.theme-dark .ds-reason { color: var(--text-secondary); }
body.theme-dark .ds-reason svg { color: var(--text-tertiary); }
body.theme-dark .ds-ring .bg { stroke: var(--border); }
body.theme-dark .ds-ring .fg { stroke: var(--brand-blue); }
body.theme-dark .ds-count { color: var(--text-primary); }
body.theme-dark .ds-count b { background: var(--brand-blue-soft); color: #7FA9FF; }
body.theme-dark .ds-eq i { background: var(--brand-blue); }

/* ---- queue ---- */
/* The shared table brings its own dark mode (theme-customiser.css); only the
   two row states this queue adds need saying. */
body.theme-dark .ds-queue .ct-table tbody tr.on td { background: #1E2740 !important; }
body.theme-dark .ds-queue .ct-table tbody tr.dim td,
body.theme-dark .ds-queue .ct-table tbody tr.dim .jc-name { color: var(--text-tertiary); }
body.theme-dark .ds-more { color: var(--text-tertiary); }
body.theme-dark .ds-more::before, body.theme-dark .ds-more::after { background: var(--border); }
body.theme-dark .ds-empty-t { color: var(--text-primary); }
body.theme-dark .ds-empty-s { color: var(--text-secondary); }

/* ---- row actions ---- */
body.theme-dark .ds-ra { background: var(--surface-alt); border-color: var(--border-strong); color: var(--text-secondary); }
body.theme-dark .ds-ra:hover { background: var(--surface-panel); color: var(--text-primary); }
body.theme-dark .ds-ra.go { border-color: #2C3E63; color: #7FA9FF; }
body.theme-dark .ds-ra.go:hover { background: var(--brand-blue-soft); border-color: var(--brand-blue); }
/* Light by design (it hangs off this header, not the dark call bar), but the
   app has a dark theme and a white card in it would glare. */
body.theme-dark .ds-as-card { background: var(--surface-alt); border-color: var(--border); }
body.theme-dark .ds-as-t { color: var(--text-primary); }
body.theme-dark .ds-as-lbl { color: var(--text-secondary); }
body.theme-dark .ds-as-x:hover { background: var(--surface-panel); color: var(--text-primary); }
body.theme-dark .ds-as-select {
  background-color: var(--surface); border-color: var(--border); color: var(--text-primary);
}
body.theme-dark .ds-as-select[disabled] { background-color: var(--surface-panel); color: var(--text-tertiary); }
body.theme-dark .ds-as-rule { background: var(--border); }
body.theme-dark .ds-as-bar { background: var(--surface-panel); }
body.theme-dark .ds-as-hint { color: var(--text-tertiary); }

body.theme-dark .ds-menu { background: var(--surface-alt); border-color: var(--border); }
body.theme-dark .ds-menu-h { color: var(--text-tertiary); }
body.theme-dark .ds-menu button { color: var(--text-primary); }
body.theme-dark .ds-menu button:hover { background: var(--surface-panel); }
body.theme-dark .ds-menu button svg { color: var(--text-tertiary); }
body.theme-dark .ds-menu button.danger { color: #FF8A80; }
body.theme-dark .ds-menu button.danger svg { color: #F0645B; }

/* ---- rail ---- */
body.theme-dark .ds-eyebrow { color: var(--text-secondary); }
body.theme-dark .ds-eyebrow .tag { background: var(--brand-blue-soft); color: #7FA9FF; }
body.theme-dark .ds-eyebrow .in { color: var(--text-tertiary); }
body.theme-dark .ds-rc-av { background: var(--brand-blue-soft); color: #7FA9FF; }
body.theme-dark .ds-rc-n { color: var(--text-primary); }
body.theme-dark .ds-rc-p { color: var(--text-secondary); }
body.theme-dark .ds-apps { border-color: var(--border); }
body.theme-dark .ds-apps .chev { border-left-color: var(--border); color: var(--text-secondary); }
body.theme-dark .ds-tabs { border-bottom-color: var(--border); }
body.theme-dark .ds-tab { color: var(--text-secondary); }
body.theme-dark .ds-tab.on { color: var(--text-primary); }
body.theme-dark .ds-tab.on::after { background: var(--brand-blue); }
body.theme-dark .ds-tab .n { background: var(--surface-panel); color: var(--text-secondary); }
body.theme-dark .ds-kv-k { color: var(--text-secondary); }
body.theme-dark .ds-kv-v { color: var(--text-primary); }
body.theme-dark .ds-kv-v a { color: #7FA9FF; }

/* ---- recent calls ---- */
body.theme-dark .ds-call { border-color: var(--border); }
body.theme-dark .ds-call-ic.ok { background: #102A1C; color: #5EDDA0; }
body.theme-dark .ds-call-ic.vm { background: #241F3D; color: #B9A0FA; }
body.theme-dark .ds-call-ic.miss { background: #33191A; color: #FF8A80; }
body.theme-dark .ds-call-t { color: var(--text-primary); }
body.theme-dark .ds-call-d { color: var(--text-secondary); }
body.theme-dark .ds-call-chev { color: var(--text-tertiary); }
body.theme-dark .ds-call-body { border-top-color: var(--border); }
body.theme-dark .ds-call-row .k { color: var(--text-secondary); }
body.theme-dark .ds-call-row .v { color: var(--text-primary); }

/* ---- engine rail ---- */
