/* ==========================================================================
   Рассылки ЛС — a block-for-block port of the approved single-file mockup
   (gargona_mass_dm_singlefile_project_style.html): hero + Настройка/Активность
   tabs, a sticky 4-step workflow nav, four full-height step cards each with an
   accent bar, a corner "Шаг N из 4" label and a Назад/Продолжить footer, a
   sticky "Готовность к запуску" rail, and the Активность tab's stat tiles +
   log card.

   Structure, proportions and densities follow the mockup exactly; every colour,
   radius, shadow and font comes from this project's own tokens (--color-*,
   --radius-*, --shadow-*, --font-display) instead of the mockup's standalone
   palette, so the page follows the light/dark toggle like the rest of the app.

   Namespaced .dm-* and scoped under .mass-dm-page — nothing here can leak onto
   the other role pages, which still use the generic .card/.role-picker-* look.
   ========================================================================== */
.mass-dm-page { padding-bottom: 1.25rem; }

/* ---- hero ---- */
.dm-hero { display: flex; align-items: flex-start; justify-content: space-between; gap: 1.5rem; margin-bottom: 0.75rem; }
.dm-hero h2 { margin: 0; font-family: var(--font-display); font-size: 1.55rem; font-weight: 650; letter-spacing: -0.02em; }
.dm-hero p { margin: 0.45rem 0 0; color: var(--color-text-muted); max-width: 48rem; }
.dm-status-pill {
  display: inline-flex; align-items: center; gap: 0.45rem; white-space: nowrap; flex-shrink: 0;
  padding: 0.45rem 0.7rem; border: 1px solid var(--color-border); border-radius: 999px;
  background: var(--color-surface); box-shadow: var(--shadow-sm);
  color: var(--color-text-muted); font-weight: 650; font-size: 0.78rem;
}
.dm-status-dot { width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--color-text-faint); }
.dm-status-pill.is-running { color: var(--color-success-text); background: var(--color-success-bg); border-color: color-mix(in srgb, var(--color-accent) 25%, transparent); }
.dm-status-pill.is-running .dm-status-dot { background: var(--color-accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-accent) 18%, transparent); }

/* ---- Настройка / Активность tabs ---- */
/* max-width + overflow-x: the strip is `width: fit-content`, so once a page has
   enough tabs to exceed a phone's width it pushed the whole document sideways
   instead of scrolling itself -- measured on /analytics at 390px (4 tabs =
   396px wide inside a 390px viewport, 16px of body overflow). Scrolling inside
   its own box is the same convention the rest of the app already uses for wide
   content (.admin-table-wrap et al). Desktop is unaffected: fit-content still
   wins whenever the strip fits. */
.dm-view-tabs {
  display: flex; gap: 0.25rem; width: fit-content; padding: 0.25rem; margin-bottom: 1.15rem;
  border: 1px solid var(--color-border); border-radius: 14px; background: var(--color-surface-muted);
  max-width: 100%; overflow-x: auto; scrollbar-width: none;
}
.dm-view-tabs::-webkit-scrollbar { display: none; }
.dm-view-tab {
  border: 0; border-radius: 10px; background: transparent; color: var(--color-text-muted);
  padding: 0.5rem 0.9rem; font-weight: 700; font-size: 0.85rem; cursor: pointer;
  display: inline-flex; align-items: center; gap: 0.35rem;
  flex: 0 0 auto; white-space: nowrap;
  transition: background var(--transition-fast) var(--ease), color var(--transition-fast) var(--ease);
}
.dm-view-tab:hover { color: var(--color-text); }
.dm-view-tab.is-active {
  color: var(--color-on-primary);
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-grad-end));
  box-shadow: 0 6px 14px color-mix(in srgb, var(--color-primary) 22%, transparent);
}
.dm-view-tab.is-active .dm-badge { background: color-mix(in srgb, white 25%, transparent); color: inherit; }

/* ---- shared atoms ---- */
.dm-badge {
  display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.25rem 0.55rem;
  border-radius: 999px; font-size: 0.7rem; font-weight: 750;
  background: var(--color-surface-muted); color: var(--color-text-muted);
}
.dm-badge.is-ok { background: var(--color-success-bg); color: var(--color-success-text); }
.dm-badge.is-warn { background: var(--color-warning-bg); color: var(--color-warning-text); }
.dm-badge.is-error { background: var(--color-danger-bg); color: var(--color-danger-text); }

.dm-label { display: block; color: var(--color-text-muted); font-weight: 700; font-size: 0.72rem; }
.dm-hint { margin-top: 0.4rem; color: var(--color-text-faint); font-size: 0.72rem; }
.dm-link { color: var(--color-primary); text-decoration: underline; }
.dm-field { display: flex; flex-direction: column; gap: 0.4rem; }

/* initFancySelects replaces every select.input / select.dm-select with the app's own
   dropdown (trigger + list) and keeps the original classes on the wrapper for layout.
   On a wrapper, `.dm-select` must therefore contribute width and nothing else — the
   trigger inside it is already the visible field, so a second border/background here
   would draw a box behind a box. */
.fancy-select.dm-select {
  display: block; width: 100%; min-height: 0; padding: 0;
  border: 0; background: none; box-shadow: none;
}
.fancy-select.dm-select .fancy-select-trigger { width: 100%; }

.dm-input, .dm-textarea, .dm-select {
  width: 100%; min-height: 2.5rem; padding: 0.55rem 0.7rem;
  border: 1px solid var(--color-border); border-radius: 10px;
  background: var(--color-surface); color: var(--color-text); font: inherit; outline: none;
  transition: border-color var(--transition-fast) var(--ease), box-shadow var(--transition-fast) var(--ease);
}
.dm-textarea { min-height: 6rem; resize: vertical; }
.dm-input:hover, .dm-textarea:hover, .dm-select:hover { border-color: var(--color-text-faint); }
.dm-input:focus, .dm-textarea:focus, .dm-select:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 20%, transparent);
}
.dm-search-wrap { position: relative; }
.dm-search-wrap svg { position: absolute; left: 0.7rem; top: 50%; transform: translateY(-50%); width: 1rem; height: 1rem; color: var(--color-text-faint); pointer-events: none; }
.dm-search-wrap .dm-input { padding-left: 2.2rem; }

.dm-primary-btn, .dm-secondary-btn {
  min-height: 2.6rem; padding: 0 1.05rem; border: 1px solid transparent; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  font-weight: 700; font-size: 0.85rem; cursor: pointer;
  transition: transform var(--transition-fast) var(--ease), box-shadow var(--transition-fast) var(--ease), background var(--transition-fast) var(--ease);
}
.dm-primary-btn svg, .dm-secondary-btn svg { width: 1.05rem; height: 1.05rem; flex-shrink: 0; }
.dm-primary-btn {
  color: var(--color-on-primary);
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-grad-end));
  box-shadow: 0 10px 22px color-mix(in srgb, var(--color-primary) 25%, transparent);
}
.dm-primary-btn:hover:not(:disabled) { transform: translateY(-1px); }
.dm-primary-btn:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
.dm-secondary-btn { color: var(--color-text); background: var(--color-surface); border-color: var(--color-border); }
.dm-secondary-btn:hover { background: var(--color-surface-muted); border-color: var(--color-text-faint); }
.dm-primary-btn.is-full, .dm-secondary-btn.is-full { width: 100%; }

/* ---- sticky 4-step workflow nav ---- */
.dm-workflow-nav {
  position: sticky; top: 0; z-index: 30;
  /* The containing block for .dm-workflow-marker. */
  isolation: isolate;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.25rem;
  padding: 0.25rem; margin-bottom: 1.1rem;
  border: 1px solid var(--color-border); border-radius: 16px;
  /* More see-through than the surrounding cards on purpose — the blur below keeps it
     legible while the content scrolling underneath stays visible through it. */
  background: color-mix(in srgb, var(--color-surface) 72%, transparent);
  backdrop-filter: blur(16px); box-shadow: var(--shadow-md);
  /* Own compositing layer — a sticky + backdrop-filter element whose layer gets
     invalidated by an unrelated restyle below it can otherwise repaint blank. */
  transform: translateZ(0);
}
.dm-workflow-step {
  min-width: 0; min-height: 2.6rem; padding: 0.35rem 0.6rem;
  border: 0; border-radius: 12px; background: transparent; color: var(--color-text-muted);
  display: flex; align-items: center; gap: 0.5rem; text-align: left; cursor: pointer;
  transition: background var(--transition-fast) var(--ease), color var(--transition-fast) var(--ease);
}
.dm-workflow-step:hover { background: var(--color-surface-muted); color: var(--color-text); }
.dm-workflow-step.is-active {
  color: var(--color-on-primary);
  /* The fill lives on .dm-workflow-marker below, which slides between steps. Kept as a
     fallback for anything that never runs the script: without a marker the row would
     otherwise show no active step at all. */
  background: transparent;
}
.dm-workflow-nav:not(:has(.dm-workflow-marker)) .dm-workflow-step.is-active {
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-grad-end));
  box-shadow: 0 7px 18px color-mix(in srgb, var(--color-primary) 28%, transparent);
}

/* Sits behind the steps and is moved by initDmScrollspy. Width and height come from the
   step it covers, so the columns can keep sizing themselves. */
.dm-workflow-marker {
  position: absolute; top: 0; left: 0;
  border-radius: 12px; pointer-events: none; z-index: 0;
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-grad-end));
  box-shadow: 0 7px 18px color-mix(in srgb, var(--color-primary) 28%, transparent);
  transition: transform var(--tab-slide) var(--ease),
              width var(--tab-slide) var(--ease),
              height var(--tab-slide) var(--ease);
}
/* The first placement must not animate, or the pill flies in from the top-left corner
   on every page load. The class is added a frame later. */
.dm-workflow-marker:not(.is-ready) { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .dm-workflow-marker { transition: none; }
}
.dm-workflow-step { position: relative; z-index: 1; }
.dm-step-num {
  width: 1.3rem; height: 1.3rem; flex: 0 0 auto; border-radius: 999px;
  display: grid; place-items: center; font-size: 0.64rem; font-weight: 850;
  background: var(--color-surface-muted); color: var(--color-text-faint);
}
.dm-workflow-step.is-active .dm-step-num { background: color-mix(in srgb, white 25%, transparent); color: inherit; }
.dm-step-copy { min-width: 0; }
.dm-step-copy strong { display: block; font-size: 0.74rem; line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The sub-label is what made this bar two lines tall — kept, but no longer given its
   own margin, so a step reads as one compact block instead of a stacked pair. */
.dm-step-copy span { display: block; font-size: 0.62rem; line-height: 1.15; color: var(--color-text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dm-workflow-step.is-active .dm-step-copy span { color: color-mix(in srgb, currentColor 74%, transparent); }

/* ---- workspace: step column + sticky readiness rail ---- */
/* 278px, а не доля и не rem: ровно столько же занимает .accounts-aside на странице
   «Аккаунты» (.accounts-content-grid). Эту колонку используют десять страниц —
   модули, парсинг, аудитория, диалоги, — и раньше она была на 58px шире, чем на
   аккаунтах: при переходе между разделами правый край карточек заметно прыгал.
   Фиксированная величина, а не 21rem, потому что вторая сторона сравнения задана в
   пикселях, и в rem они совпадали бы только при шрифте ровно 16px. */
.dm-workspace { display: grid; grid-template-columns: minmax(0, 1fr) 278px; gap: 1rem; align-items: start; }
.dm-main-column { min-width: 0; }
.dm-aside { position: sticky; top: 4rem; display: flex; flex-direction: column; gap: 0.75rem; }

/* ---- step card ---- */
.dm-section-card {
  position: relative; overflow: hidden; display: flex; flex-direction: column;
  min-height: max(40rem, calc(100vh - 10rem));
  scroll-margin-top: 4.4rem;
  border: 1px solid var(--color-border); border-radius: 24px;
  background: var(--color-surface); box-shadow: var(--shadow-sm);
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
/* .story-section перечислена рядом, а не копирует это правило у себя: Теггер в историях
   рисует такие же карточки шагов, но не может взять .dm-section-card целиком — у того
   min-height в целый экран, рассчитанный на страницы с пятью шагами. Полоска и метка
   шага при этом должны быть теми же самыми, а не похожими, поэтому объявление одно.
   Три правила ниже — верхняя полоска, «ШАГ N ИЗ M» в углу и подсветка текущего шага —
   были у Теггера отдельными копиями, и полоски среди них просто не оказалось. */
.dm-section-card::before,
.story-section::before {
  content: ''; position: absolute; inset: 0 0 auto; height: 3px; z-index: 1;
  background: linear-gradient(90deg, var(--dm-accent, var(--color-primary)), color-mix(in srgb, var(--dm-accent, var(--color-primary)) 20%, transparent) 70%, transparent);
}
/* «ШАГ N ИЗ M» в углу карточки больше не рисуется. Номер шага и так стоит трижды:
   в навигации сверху, в подзаголовке блока и в его нижней панели перехода — четвёртое
   повторение только забивало угол, в котором теперь живёт значок справки.
   Атрибут data-step-label оставлен: на него смотрит скроллспай. */
.dm-section-card[data-step-label]::after,
.story-section[data-step-label]::after { content: none; }
.dm-section-card.is-current,
.story-page .story-section.is-current {
  border-color: color-mix(in srgb, var(--dm-accent, var(--color-primary)) 38%, var(--color-border));
  box-shadow: var(--shadow-md), 0 0 0 1px color-mix(in srgb, var(--dm-accent, var(--color-primary)) 10%, transparent);
}
.dm-section-card.is-problem-flash { box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-danger) 45%, transparent); }
#dm-section-accounts { --dm-accent: var(--color-primary); }
#dm-section-audience { --dm-accent: var(--color-warning); }
#dm-section-messages { --dm-accent: var(--color-accent); }
#dm-section-limits   { --dm-accent: var(--color-blue); }

/* Правый отступ был 7.5rem — под метку «ШАГ N ИЗ M», которой больше нет. Осталось
   место под значок справки в углу (components/block-help.css). */
.dm-section-head {
  min-height: 4.2rem; padding: 0.85rem 3rem 0.85rem 1rem;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  border-bottom: 1px solid var(--color-border);
  background: linear-gradient(180deg, color-mix(in srgb, var(--color-surface-muted) 78%, transparent), transparent);
}
.dm-section-title { display: flex; align-items: center; gap: 0.75rem; min-width: 0; }
.dm-section-icon {
  width: 2.45rem; height: 2.45rem; flex: 0 0 auto; border-radius: 13px;
  display: grid; place-items: center; background: var(--color-primary-bg); color: var(--color-primary);
}
.dm-section-icon svg { width: 1.2rem; height: 1.2rem; }
.dm-section-icon.is-amber { background: var(--color-warning-bg); color: var(--color-warning-text); }
.dm-section-icon.is-green { background: var(--color-success-bg); color: var(--color-accent); }
.dm-section-icon.is-blue { background: color-mix(in srgb, var(--color-blue) 16%, transparent); color: var(--color-blue); }
.dm-section-title h3 { margin: 0; font-family: var(--font-display); font-size: 1rem; font-weight: 650; }
.dm-section-title p { margin: 0.2rem 0 0; font-size: 0.75rem; color: var(--color-text-muted); }
.dm-section-body { flex: 1 1 auto; padding: 1rem; }

.dm-panel-nav {
  margin-top: auto; padding: 0.7rem 1rem; border-top: 1px solid var(--color-border);
  background: var(--color-surface-muted);
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap;
}
.dm-panel-nav-copy { min-width: 0; color: var(--color-text-muted); font-size: 0.72rem; }
.dm-panel-nav-copy strong { display: block; color: var(--color-text); font-size: 0.78rem; margin-bottom: 0.1rem; }
.dm-panel-nav-actions { display: flex; gap: 0.5rem; flex: 0 0 auto; }
.dm-panel-nav-actions > * { min-width: 7rem; }

/* ---- labeled divider between steps ---- */
.dm-workflow-divider {
  height: 4.4rem; display: grid; grid-template-columns: minmax(20px, 1fr) auto minmax(20px, 1fr);
  align-items: center; gap: 0.85rem;
  color: var(--color-text-faint); font-size: 0.62rem; font-weight: 850;
  letter-spacing: 0.1em; text-transform: uppercase;
}
.dm-workflow-divider::before { content: ''; height: 1px; background: linear-gradient(90deg, transparent, var(--color-border)); }
.dm-workflow-divider::after { content: ''; height: 1px; background: linear-gradient(90deg, var(--color-border), transparent); }
.dm-workflow-divider span {
  display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.7rem;
  border: 1px solid var(--color-border); border-radius: 999px;
  background: var(--color-surface); box-shadow: var(--shadow-sm);
}
.dm-workflow-divider i { width: 0.35rem; height: 0.35rem; border-radius: 50%; background: var(--color-primary); box-shadow: 0 0 0 3px var(--color-primary-bg); }

/* ---- step 1: flat executor picker ---- */
/* Search narrowed and capped: it used to take every spare pixel, which left the
   filters cramped. Now it has a fixed comfortable width and the three filter selects
   share the rest, so adding the role filter didn't squeeze anything. */
.dm-toolbar {
  display: grid; grid-template-columns: minmax(9rem, 16rem) repeat(3, minmax(7.5rem, 1fr));
  gap: 0.55rem; margin-bottom: 0.85rem;
}
.dm-account-overview {
  margin-bottom: 0.85rem; padding: 0.75rem 0.85rem;
  display: flex; align-items: center; justify-content: space-between; gap: 0.9rem;
  border: 1px solid color-mix(in srgb, var(--color-accent) 22%, var(--color-border)); border-radius: 14px;
  background: linear-gradient(135deg, var(--color-success-bg), transparent 75%);
}
.dm-account-overview strong { display: block; font-size: 0.8rem; }
.dm-account-overview span { display: block; margin-top: 0.1rem; color: var(--color-text-muted); font-size: 0.72rem; }
.dm-account-overview .dm-secondary-btn { min-height: 2.2rem; font-size: 0.78rem; flex-shrink: 0; }

.dm-account-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.55rem; }
.dm-account-card {
  position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: 0.6rem; min-height: 4.6rem; padding: 0.65rem;
  border: 1px solid var(--color-border); border-radius: 15px;
  background: var(--color-surface-muted); cursor: pointer;
  transition: border-color var(--transition-fast) var(--ease), background var(--transition-fast) var(--ease), transform var(--transition-fast) var(--ease);
}
.dm-account-card:hover { border-color: var(--color-primary); transform: translateY(-1px); }
.dm-account-card.is-selected {
  border-color: color-mix(in srgb, var(--color-primary) 62%, var(--color-border));
  background: var(--color-primary-bg);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-primary) 12%, transparent);
}
.dm-account-card.is-disabled { opacity: 0.55; cursor: not-allowed; }
.dm-account-card.is-disabled:hover { border-color: var(--color-border); transform: none; }
/* The whole card is the hit target (it's a <label>) — the real checkbox is only
   hidden visually, never removed, so form state and a11y stay intact. The radio is
   the same card in a one-of-many picker (Теггер в историях' executor, story_tagger/
   index.html): one story has one author, so there it is a radio and not a checkbox. */
.dm-account-card input[type="checkbox"],
.dm-account-card input[type="radio"] { position: absolute; opacity: 0; pointer-events: none; }
.dm-account-avatar {
  width: 2.35rem; height: 2.35rem; flex-shrink: 0; border-radius: 13px; overflow: hidden;
  display: grid; place-items: center; font-weight: 850; font-size: 0.9rem;
  background: var(--color-primary); color: var(--color-on-primary);
}
.dm-account-avatar img { width: 100%; height: 100%; object-fit: cover; }
.dm-account-card:nth-child(5n+2) .dm-account-avatar { background: var(--color-accent); }
.dm-account-card:nth-child(5n+3) .dm-account-avatar { background: var(--color-warning); }
.dm-account-card:nth-child(5n+4) .dm-account-avatar { background: var(--color-danger); }
.dm-account-card:nth-child(5n+5) .dm-account-avatar { background: var(--color-blue); }
.dm-account-copy { min-width: 0; }
.dm-account-copy strong { display: block; font-size: 0.85rem; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.dm-account-detail {
  display: flex; align-items: center; gap: 0.3rem; margin-top: 0.15rem;
  color: var(--color-text-muted); font-size: 0.7rem; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.dm-account-dot { width: 0.35rem; height: 0.35rem; flex: 0 0 auto; border-radius: 50%; background: var(--color-accent); box-shadow: 0 0 0 3px var(--color-success-bg); }
.dm-account-dot.is-error { background: var(--color-danger); box-shadow: 0 0 0 3px var(--color-danger-bg); }
.dm-account-state {
  width: 1.25rem; height: 1.25rem; flex-shrink: 0; border-radius: 7px;
  display: grid; place-items: center; border: 1px solid var(--color-text-faint); color: transparent;
}
.dm-account-state svg { width: 0.8rem; height: 0.8rem; }
.dm-account-card.is-selected .dm-account-state { background: var(--color-primary); border-color: var(--color-primary); color: var(--color-on-primary); }

.dm-inline-alert {
  display: flex; align-items: flex-start; gap: 0.55rem; margin-top: 0.85rem; padding: 0.65rem 0.75rem;
  border-radius: 12px; background: var(--color-warning-bg); color: var(--color-warning-text); font-size: 0.72rem;
}
.dm-inline-alert svg { width: 1rem; height: 1rem; flex: 0 0 auto; margin-top: 0.1rem; }
/* The same box reporting a settled state rather than a problem — the bot link on
   Smart-диалоги is amber while it is missing and quiet once it is done. */
.dm-inline-alert.is-ok { background: var(--color-success-bg); color: var(--color-success-text); }

/* Nothing open yet: the thread pane keeps its header (disabled, so the controls are
   visible before they are usable) and centres its message in the space that is left,
   rather than pinning it to the top edge of an otherwise blank column. */
.dialogue-thread-pane .is-idle { opacity: 0.55; pointer-events: none; }
.dialogue-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 2rem 1.5rem;
  text-align: center;
}
.dialogue-empty .icon {
  width: 2.4rem; height: 2.4rem;
  color: var(--color-text-faint); opacity: 0.5;
}
.dialogue-empty-title { font-weight: 650; font-size: 0.95rem; }
.dialogue-empty-desc {
  max-width: 32ch;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--color-text-muted);
}

/* Search + filters above that strip. Sized like the tab strip it sits under rather than
   stretched across the window: a search box the width of a monitor reads as the page's
   main input, which it is not. */
.dialogue-filter-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  width: fit-content;
  max-width: 100%;
}
.dialogue-filter-row .input { height: 2.4rem; font-size: 0.8rem; }
.dialogue-filter-row select.input { width: auto; }

/* The Входящие account strip. A ceiling and a scrollbar instead of unbounded wrapping:
   the point of the search above it is that the list can be long. */
.dialogue-accounts-strip {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  max-height: 13rem; overflow-y: auto; padding-right: 0.25rem;
}

/* ---- pairing the notification bot, inside step 4 ---- */
.dm-bot-link {
  display: flex; flex-direction: column; gap: 0.55rem;
  margin-top: 0.85rem; padding: 0.7rem 0.8rem;
  border-radius: 12px; font-size: 0.72rem;
  background: var(--color-warning-bg); color: var(--color-warning-text);
}
/* Linked is a settled state, not a warning — the block stops asking for attention. */
.dm-bot-link.is-ok { background: var(--color-success-bg); color: var(--color-success-text); }
.dm-bot-link-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
.dm-bot-link-head > span { display: flex; flex-direction: column; min-width: 0; }
.dm-bot-link .dm-hint { color: inherit; opacity: 0.85; }
/* Numbered because the three steps have to happen in order — the code is worthless
   before the bot is open, and the wait means nothing before the code is sent. */
.dm-bot-steps { display: flex; flex-direction: column; gap: 0.45rem; margin: 0; padding-left: 1.1rem; }
.dm-bot-steps li { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap; }
.dm-bot-code { display: inline-flex; align-items: center; gap: 0.4rem; }
.dm-bot-code code {
  padding: 0.25rem 0.5rem; border-radius: 8px;
  background: color-mix(in srgb, currentColor 12%, transparent);
  font-family: var(--font-data, monospace); font-size: 0.8rem; letter-spacing: 0.06em;
}
.dm-bot-waiting { display: inline-flex; align-items: center; gap: 0.4rem; opacity: 0.85; }
.dm-bot-waiting .btn-spinner { width: 0.8rem; height: 0.8rem; }

/* The block replaces itself in place (see swapBotBlock), so its arrival is the only
   signal that anything happened — the page around it deliberately does not move. */
.dm-bot-link.is-fresh { animation: ndBotIn 320ms var(--ease) both; }
@keyframes ndBotIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
/* The steps arrive one after another, in the order they are to be done. */
.dm-bot-link.is-fresh .dm-bot-steps li { animation: ndStepIn 300ms var(--ease) both; }
.dm-bot-link.is-fresh .dm-bot-steps li:nth-child(1) { animation-delay: 60ms; }
.dm-bot-link.is-fresh .dm-bot-steps li:nth-child(2) { animation-delay: 140ms; }
.dm-bot-link.is-fresh .dm-bot-steps li:nth-child(3) { animation-delay: 220ms; }
@keyframes ndStepIn {
  from { opacity: 0; transform: translateX(-6px); }
  to { opacity: 1; transform: none; }
}
/* While waiting, the step that is waiting breathes — the only moving thing in the block,
   so it reads as "this is what we are waiting on" rather than as decoration. */
.dm-bot-link[data-nd-bot-wait] .dm-bot-steps li:last-child { animation: ndBotPulse 2.4s ease-in-out infinite; }
@keyframes ndBotPulse {
  0%, 100% { opacity: 0.7; }
  50% { opacity: 1; }
}
.dm-bot-code code { transition: background 160ms var(--ease); }
.dm-bot-code code:hover { background: color-mix(in srgb, currentColor 20%, transparent); }
.dm-bot-link [data-nd-bot-action].is-busy { opacity: 0.6; cursor: progress; }
@media (prefers-reduced-motion: reduce) {
  .dm-bot-link.is-fresh,
  .dm-bot-link.is-fresh .dm-bot-steps li,
  .dm-bot-link[data-nd-bot-wait] .dm-bot-steps li:last-child { animation: none; }
}
/* With an action on the right the two sides are pushed apart, and the text column is
   allowed to wrap instead of squeezing the button off the row. */
.dm-inline-alert { justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
.dm-inline-alert > span { display: flex; flex-direction: column; min-width: 0; }
.dm-inline-alert .dm-hint { color: inherit; opacity: 0.85; }
.dm-inline-alert .dm-secondary-btn, .dm-inline-alert form { flex: 0 0 auto; }

/* ---- step 2: audience ---- */
.dm-segmented {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.3rem; padding: 0.25rem;
  border: 1px solid var(--color-border); border-radius: 13px; background: var(--color-surface-muted);
  margin-bottom: 0.9rem;
}
.dm-segment {
  min-height: 2.4rem; border-radius: 10px; display: flex; align-items: center; justify-content: center;
  gap: 0.5rem; color: var(--color-text-muted); font-weight: 750; font-size: 0.82rem; cursor: pointer;
  text-align: center; padding: 0 0.5rem;
  transition: background var(--transition-fast) var(--ease), color var(--transition-fast) var(--ease);
}
.dm-segment input { position: absolute; width: 1px; height: 1px; opacity: 0; }
/* :has() drives the selected look off the real radio, so it can never disagree
   with form state the way a server-rendered "active" class would after a click. */
.dm-segment:has(input:checked) { color: var(--color-text); background: var(--color-surface); box-shadow: var(--shadow-sm); }
.dm-segment.is-disabled { opacity: 0.5; cursor: not-allowed; }

.dm-audience-grid { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(11rem, 0.6fr); gap: 0.75rem; }
.dm-metric-box { padding: 0.85rem; border: 1px solid var(--color-border); border-radius: 16px; background: var(--color-surface-muted); }
.dm-metric-label { color: var(--color-text-muted); font-size: 0.72rem; font-weight: 700; }
.dm-metric-value { margin-top: 0.25rem; font-family: var(--font-display); font-size: 1.55rem; font-weight: 650; letter-spacing: -0.03em; }
.dm-metric-desc { margin-top: 0.15rem; color: var(--color-text-faint); font-size: 0.7rem; }

/* Чёрный список сценария — lives inside step 2 (audience), not the Активность
   tab: it scopes the current campaign's exclusions, so it belongs with the
   targeting it modifies. */
.dm-blacklist-panel {
  margin-top: 1rem; padding: 1rem;
  border: 1px solid color-mix(in srgb, var(--color-danger) 20%, var(--color-border)); border-radius: 18px;
  background: linear-gradient(135deg, var(--color-surface-muted), color-mix(in srgb, var(--color-danger-bg) 36%, var(--color-surface-muted)));
}
.dm-blacklist-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.9rem; margin-bottom: 0.8rem; }
.dm-blacklist-title { display: flex; align-items: flex-start; gap: 0.6rem; }
.dm-blacklist-icon {
  width: 2.1rem; height: 2.1rem; flex: 0 0 auto; border-radius: 12px; display: grid; place-items: center;
  background: var(--color-danger-bg); color: var(--color-danger);
}
.dm-blacklist-icon svg { width: 1.05rem; height: 1.05rem; }
.dm-blacklist-panel h4 { margin: 0 0 0.15rem; font-size: 0.85rem; }
.dm-blacklist-panel p { margin: 0; color: var(--color-text-muted); font-size: 0.72rem; line-height: 1.5; }
.dm-blacklist-add { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.5rem; }
.dm-blacklist-items { display: flex; flex-wrap: wrap; gap: 0.45rem; margin-top: 0.7rem; }
.dm-blacklist-chip {
  display: inline-flex; align-items: center; gap: 0.4rem; max-width: 100%; min-height: 2rem;
  padding: 0 0.3rem 0 0.65rem; border: 1px solid var(--color-border); border-radius: 10px;
  background: var(--color-surface); font-size: 0.72rem;
}
.dm-blacklist-chip > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 14rem; }
.dm-blacklist-chip button {
  width: 1.4rem; height: 1.4rem; flex-shrink: 0; border: 0; border-radius: 7px;
  display: grid; place-items: center; background: transparent; color: var(--color-text-faint); cursor: pointer;
}
.dm-blacklist-chip button svg { width: 0.8rem; height: 0.8rem; }
.dm-blacklist-chip button:hover { color: var(--color-danger); background: var(--color-danger-bg); }
.dm-blacklist-empty {
  margin-top: 0.7rem; padding: 0.75rem; border: 1px dashed var(--color-border); border-radius: 10px;
  color: var(--color-text-muted); font-size: 0.72rem; text-align: center;
}

/* ---- step 3: chain + phone preview ---- */
.dm-message-layout { display: grid; grid-template-columns: minmax(0, 1fr) 19rem; gap: 0.9rem; align-items: start; }
.dm-message-list { display: flex; flex-direction: column; gap: 0.55rem; }
.dm-message-item { padding: 0.7rem; border: 1px solid var(--color-border); border-radius: 15px; background: var(--color-surface-muted); }
.dm-message-item-head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; margin-bottom: 0.5rem; }
.dm-message-number { display: flex; align-items: center; gap: 0.45rem; font-weight: 750; font-size: 0.78rem; }
.dm-message-drag { color: var(--color-text-faint); cursor: grab; display: inline-flex; }
.dm-message-drag svg { width: 1rem; height: 1rem; }
.dm-message-actions { display: flex; align-items: center; gap: 0.25rem; }
.dm-mini-btn {
  width: 1.8rem; height: 1.8rem; border: 1px solid var(--color-border); border-radius: 9px;
  display: grid; place-items: center; background: var(--color-surface); color: var(--color-text-muted); cursor: pointer;
  transition: color var(--transition-fast) var(--ease), border-color var(--transition-fast) var(--ease);
}
.dm-mini-btn svg { width: 0.9rem; height: 0.9rem; }
.dm-mini-btn:hover { color: var(--color-text); border-color: var(--color-text-faint); }
.dm-mini-btn.is-danger:hover { color: var(--color-danger); border-color: color-mix(in srgb, var(--color-danger) 35%, transparent); }
.dm-message-delay { display: grid; grid-template-columns: 1fr 6rem; align-items: center; gap: 0.5rem; margin-top: 0.5rem; }
.dm-message-delay .dm-input { min-height: 2.1rem; }
.dm-message-item:first-child .dm-message-delay { display: none; }
.dm-add-btn {
  width: 100%; min-height: 2.6rem; margin-top: 0.55rem;
  border: 1px dashed var(--color-text-faint); border-radius: 13px; background: transparent;
  color: var(--color-text-muted); display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  font-weight: 700; font-size: 0.85rem; cursor: pointer;
  transition: color var(--transition-fast) var(--ease), border-color var(--transition-fast) var(--ease), background var(--transition-fast) var(--ease);
}
.dm-add-btn svg { width: 1rem; height: 1rem; }
.dm-add-btn:hover { color: var(--color-primary); border-color: var(--color-primary); background: var(--color-primary-bg); }
.dm-empty-state {
  padding: 1.25rem; border: 1px dashed var(--color-border); border-radius: 13px;
  text-align: center; color: var(--color-text-muted); font-size: 0.75rem;
}
.dm-empty-state svg { width: 1.6rem; height: 1.6rem; margin: 0 auto 0.5rem; display: block; color: var(--color-text-faint); }

/* Phone frame: same shape as the mockup, but surfaced with project tokens so it
   follows the light/dark toggle instead of being permanently dark. */
.dm-phone {
  position: sticky; top: 5rem; min-height: 18rem; padding: 0.6rem;
  border: 1px solid var(--color-border); border-radius: 20px;
  background: var(--color-surface-muted); box-shadow: inset 0 0 0 4px var(--color-surface);
}
.dm-phone-bar {
  height: 2.1rem; display: flex; align-items: center; gap: 0.5rem; padding: 0 0.25rem 0.55rem;
  border-bottom: 1px solid var(--color-border); color: var(--color-text-muted); font-size: 0.7rem;
}
.dm-phone-avatar { width: 1.5rem; height: 1.5rem; flex-shrink: 0; border-radius: 50%; background: var(--color-border); }
.dm-preview { padding: 0.8rem 0.25rem 0.4rem; display: flex; flex-direction: column; align-items: flex-end; gap: 0.5rem; }
.dm-bubble {
  max-width: 90%; padding: 0.55rem 0.7rem; border-radius: 13px 13px 4px 13px;
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-grad-end));
  color: var(--color-on-primary); font-size: 0.78rem; line-height: 1.42;
  white-space: pre-wrap; word-break: break-word;
}
.dm-bubble.is-empty {
  align-self: stretch; text-align: center; border-radius: 11px;
  background: var(--color-surface); border: 1px dashed var(--color-border); color: var(--color-text-faint);
}

/* ---- step 4: pacing ---- */
.dm-settings-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.65rem; }
.dm-split-inputs { display: grid; grid-template-columns: 1fr 1fr; gap: 0.45rem; }
.dm-details { border: 1px solid var(--color-border); border-radius: 15px; background: var(--color-surface-muted); overflow: hidden; }
.dm-details + .dm-details { margin-top: 0.55rem; }
.dm-details > summary {
  cursor: pointer; min-height: 3rem; padding: 0.75rem 0.85rem; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  font-weight: 750; font-size: 0.85rem;
}
.dm-details > summary::-webkit-details-marker { display: none; }
.dm-details > summary svg { width: 1.05rem; height: 1.05rem; flex-shrink: 0; color: var(--color-text-faint); transition: transform 0.2s var(--ease); }
.dm-details[open] > summary svg { transform: rotate(180deg); }
.dm-details-sub { margin-left: 0.4rem; color: var(--color-text-muted); font-weight: 500; font-size: 0.72rem; }
.dm-details-body { padding: 0.85rem; border-top: 1px solid var(--color-border); }

.dm-toggle-row {
  min-height: 3.2rem; display: flex; align-items: center; justify-content: space-between; gap: 0.9rem;
  padding: 0.55rem 0; border-bottom: 1px solid var(--color-border);
}
.dm-toggle-row:last-child { border-bottom: 0; }
.dm-toggle-row strong { display: block; font-size: 0.8rem; }
.dm-toggle-row span { display: block; margin-top: 0.1rem; color: var(--color-text-muted); font-size: 0.72rem; }
.dm-switch {
  position: relative; width: 2.4rem; height: 1.4rem; flex: 0 0 auto; border-radius: 999px;
  background: var(--color-surface); border: 1px solid var(--color-text-faint); cursor: pointer;
  transition: background var(--transition-fast) var(--ease), border-color var(--transition-fast) var(--ease);
}
.dm-switch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.dm-switch i {
  position: absolute; left: 2px; top: 2px; width: 1rem; height: 1rem; border-radius: 50%;
  background: var(--color-text-faint); transition: left var(--transition-fast) var(--ease), background var(--transition-fast) var(--ease);
}
.dm-switch input:checked + i { left: calc(100% - 1.15rem); background: var(--color-on-primary); }
.dm-switch:has(input:checked) { background: var(--color-primary); border-color: var(--color-primary); }

/* ---- sticky readiness rail ---- */
.dm-summary-card, .dm-quick-card {
  border: 1px solid var(--color-border); border-radius: var(--radius-2xl);
  background: var(--color-surface); box-shadow: var(--shadow-md); overflow: hidden;
}
.dm-summary-head { padding: 0.6rem 0.85rem; border-bottom: 1px solid var(--color-border); display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; }
.dm-summary-head strong { font-size: 0.85rem; }
.dm-summary-body { padding: 0.55rem 0.85rem; }
.dm-summary-row { min-height: 1.6rem; display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; border-bottom: 1px dashed var(--color-border); color: var(--color-text-muted); font-size: 0.74rem; }
.dm-summary-row:last-child { border-bottom: 0; }
.dm-summary-row b { color: var(--color-text); }
.dm-checklist { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.5rem; }
.dm-check { display: flex; align-items: center; gap: 0.5rem; color: var(--color-text-muted); font-size: 0.72rem; cursor: pointer; }
.dm-check-icon { width: 1.15rem; height: 1.15rem; flex-shrink: 0; border-radius: 6px; display: grid; place-items: center; background: var(--color-surface-muted); color: var(--color-text-faint); }
.dm-check-icon svg { width: 0.7rem; height: 0.7rem; }
.dm-check.is-ok { color: var(--color-success-text); }
.dm-check.is-ok .dm-check-icon { background: var(--color-success-bg); color: var(--color-success-text); }
/* The launch form keeps the .role-launch-fab class (that's what app.js's
   confirm-then-save-then-launch handler keys off), but inside the rail it is a
   normal block, not the floating action button other role pages get. */
.dm-summary-body .role-launch-fab { position: static; margin-top: 0.55rem; }
.dm-summary-body .role-launch-fab .dm-primary-btn { width: 100%; }
/* Полоса готовности над списком проверок. Живёт здесь, а не на странице Чат-рассылок,
   где появилась впервые: блок «Готовность к запуску» одинаковый на восьми страницах, и
   вторая копия правила — то, с чего они начинают расходиться. Ширину ведёт
   initDmReadinessProgress (dm-shared.js) из текста бейджа, поэтому разметка везде одна
   и та же и ей не нужна серверная переменная. */
.dm-progress {
  height: 6px; margin-bottom: 0.75rem; border-radius: 999px; overflow: hidden;
  background: var(--color-surface-muted);
}
.dm-progress i {
  display: block; height: 100%; width: 0; border-radius: inherit;
  background: linear-gradient(90deg, var(--color-primary), var(--color-primary-grad-end, var(--color-primary)));
  transition: width var(--transition-fast) var(--ease);
}
.dm-save-note { margin-top: 0.35rem; color: var(--color-text-faint); font-size: 0.62rem; text-align: center; }
.dm-quick-card { padding: 0.6rem 0.85rem; }
.dm-quick-card strong { display: block; font-size: 0.8rem; }
.dm-quick-card p { margin: 0.3rem 0 0.7rem; color: var(--color-text-muted); font-size: 0.72rem; }

/* ---- Активность tab ---- */
.dm-stats-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.65rem; margin-bottom: 0.9rem; }
.dm-stat-card {
  padding: 1rem; border: 1px solid var(--color-border); border-radius: var(--radius-2xl);
  background: var(--color-surface); box-shadow: var(--shadow-sm);
}
.dm-stat-card span { color: var(--color-text-muted); font-size: 0.72rem; }
.dm-stat-card strong { display: block; margin-top: 0.4rem; font-family: var(--font-display); font-size: 1.5rem; font-weight: 650; letter-spacing: -0.03em; }
.dm-log-card {
  border: 1px solid var(--color-border); border-radius: var(--radius-2xl);
  background: var(--color-surface); box-shadow: var(--shadow-sm); overflow: hidden;
}
.dm-log-toolbar { padding: 0.9rem 1rem; display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap; border-bottom: 1px solid var(--color-border); }
.dm-log-toolbar strong { font-size: 0.9rem; }
.dm-log-list { max-height: 35rem; overflow-y: auto; }
.dm-log-footer { padding: 0.75rem 1rem; border-top: 1px solid var(--color-border); color: var(--color-text-muted); font-size: 0.72rem; }

/* ---- Массовые реакции additions ----
   The 4-step shell, account picker, readiness rail, tabs and activity cards above are
   shared verbatim with Рассылки ЛС; only these component types are new to the
   reactions page (grouped sub-cards, the two-up choice cards, the probability slider,
   the target list, and the reaction-history table). */
.dm-subcard { padding: 0.9rem; border: 1px solid var(--color-border); border-radius: 15px; background: var(--color-surface-muted); }
.dm-subcard + .dm-subcard { margin-top: 0.7rem; }
.dm-subcard-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.75rem; }
.dm-subcard h4 { margin: 0; font-size: 0.85rem; }
.dm-subcard p { margin: 0.2rem 0 0; color: var(--color-text-muted); font-size: 0.72rem; }
.dm-two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; align-items: start; }

.dm-choice-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
.dm-choice-card {
  position: relative; padding: 0.8rem; border: 1px solid var(--color-border); border-radius: 12px;
  background: var(--color-surface); cursor: pointer;
  transition: border-color var(--transition-fast) var(--ease), background var(--transition-fast) var(--ease);
}
.dm-choice-card input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.dm-choice-card strong { display: block; font-size: 0.78rem; }
.dm-choice-title { display: flex; align-items: center; gap: 0.35rem; }
.dm-choice-title svg { width: 1rem; height: 1rem; flex: none; color: var(--color-primary); }
.dm-choice-card span { display: block; margin-top: 0.2rem; color: var(--color-text-muted); font-size: 0.72rem; }
.dm-choice-card:hover { border-color: var(--color-text-faint); }
.dm-choice-card:has(input:checked) {
  border-color: color-mix(in srgb, var(--color-primary) 55%, var(--color-border));
  background: var(--color-primary-bg);
}

.dm-range-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.6rem; align-items: center; }
.dm-range { width: 100%; accent-color: var(--color-primary); }

.dm-target-list { display: flex; flex-direction: column; gap: 0.4rem; }
.dm-target-row {
  display: grid; grid-template-columns: auto auto minmax(0, 1fr); align-items: center; gap: 0.6rem;
  min-height: 3.4rem; padding: 0.55rem 0.6rem;
  border: 1px solid var(--color-border); border-radius: 11px; background: var(--color-surface); cursor: pointer;
  transition: border-color var(--transition-fast) var(--ease), background var(--transition-fast) var(--ease);
}
.dm-target-row:hover { border-color: var(--color-text-faint); }
.dm-target-row:has(input:checked) {
  border-color: color-mix(in srgb, var(--color-primary) 55%, var(--color-border));
  background: var(--color-primary-bg);
}
.dm-target-icon {
  width: 2.1rem; height: 2.1rem; flex-shrink: 0; border-radius: 10px; display: grid; place-items: center;
  background: var(--color-warning-bg); color: var(--color-warning-text);
}
.dm-target-icon svg { width: 1.05rem; height: 1.05rem; }
.dm-target-copy { min-width: 0; }
.dm-target-copy strong { display: block; font-size: 0.78rem; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.dm-target-copy span { display: block; margin-top: 0.15rem; color: var(--color-text-muted); font-size: 0.72rem; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

.dm-history-table { width: 100%; border-collapse: collapse; font-size: 0.75rem; }
.dm-history-table th, .dm-history-table td { padding: 0.65rem 0.8rem; border-bottom: 1px solid var(--color-border); text-align: left; white-space: nowrap; }
.dm-history-table th { color: var(--color-text-muted); font-weight: 700; background: var(--color-surface-muted); }
.dm-history-table td:last-child, .dm-history-table th:last-child { white-space: normal; }
.dm-history-table tr:last-child td { border-bottom: 0; }

/* Обойма для таблицы результатов. Собранное измеряется тысячами строк, и без
   ограничения по высоте карточка вытягивалась на десятки экранов: всё, что на странице
   ниже — кнопки, экспорт, следующий шаг — уезжало за горизонт, а до конца списка никто
   всё равно не доходил. Высота в vh, а не в пикселях: на ноутбуке и на большом мониторе
   «примерно две трети экрана» — это разные числа, но одно и то же ощущение.
   Шапка липкая, иначе к сотой строке непонятно, что за столбцы. */
.dm-results-scroll {
  max-height: 62vh;
  overflow: auto;
}
.dm-results-scroll .dm-history-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
}

/* ---- Прогрев аккаунтов additions ----
   Its configurator is the same 5-step shell as the other redesigned module pages;
   only these component types are new to it (the manual/auto banner, the headline
   action cards, the fine-action checklist columns, the duration presets and the
   launch plan tiles). */
.dm-workflow-nav-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.dm-workflow-nav::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--color-text-faint) 22%, transparent) padding-box;
}
.dm-workflow-nav:hover::-webkit-scrollbar-thumb,
.dm-workflow-nav.is-scrolling::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--color-text-faint) 38%, transparent) padding-box;
}

.dm-mode-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  padding: 0.9rem 1rem; border: 1px solid var(--color-border); border-radius: 15px;
  background: linear-gradient(135deg, var(--color-primary-bg), transparent 72%);
}
.dm-mode-banner strong { display: block; font-size: 0.85rem; }
.dm-mode-banner span { display: block; margin-top: 0.2rem; color: var(--color-text-muted); font-size: 0.72rem; max-width: 40rem; }

.dm-action-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); gap: 0.6rem; }
.dm-action-card {
  position: relative; display: flex; flex-direction: column; gap: 0.25rem;
  padding: 0.85rem; border: 1px solid var(--color-border); border-radius: 15px;
  background: var(--color-surface-muted); cursor: pointer;
  transition: border-color var(--transition-fast) var(--ease), background var(--transition-fast) var(--ease);
}
.dm-action-card input[type="checkbox"] { position: absolute; top: 0.7rem; right: 0.7rem; margin: 0; }
.dm-action-card:hover { border-color: var(--color-text-faint); }
.dm-action-card:has(input:checked) {
  border-color: color-mix(in srgb, var(--color-primary) 55%, var(--color-border));
  background: var(--color-primary-bg);
}
/* Held at the size the emoji occupied, so the cards keep their rhythm. The tint
   is the accent rather than full-strength text: the icon labels the card, the
   heading under it is what should be read first. */
.dm-action-icon { font-size: 1.35rem; line-height: 1; color: var(--color-primary); }
.dm-action-icon svg { display: block; width: 1.35rem; height: 1.35rem; }
.dm-action-card:has(input:checked) .dm-action-icon { color: var(--color-primary-hover); }
.dm-action-card strong { font-size: 0.85rem; padding-right: 1.6rem; }
.dm-action-desc { color: var(--color-text-muted); font-size: 0.72rem; }
/* An action that cannot run yet: dimmed rather than hidden, because the reason is worth
   reading — hiding it would just raise the same question later. */
.dm-action-card.is-locked { opacity: 0.6; cursor: not-allowed; }
.dm-action-card.is-locked:hover { border-color: var(--color-border); }
.dm-action-card.is-locked input { pointer-events: none; }
.dm-action-lock {
  display: flex; align-items: flex-start; gap: 0.35rem; margin-top: 0.4rem;
  padding: 0.4rem 0.5rem; border-radius: 10px;
  background: var(--color-surface-muted); color: var(--color-text-muted);
  font-size: 0.68rem; line-height: 1.3;
}
.dm-action-lock .icon { flex: none; margin-top: 0.05rem; }
.dm-action-field { margin-top: 0.4rem; }

.dm-action-groups { display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: 0.6rem; margin-top: 0.5rem; }
.dm-action-group { padding: 0.7rem; border: 1px solid var(--color-border); border-radius: 12px; background: var(--color-surface); }
.dm-action-group-head {
  display: flex; align-items: center; gap: 0.35rem;
  font-size: 0.75rem; font-weight: 750; margin-bottom: 0.45rem;
}
.dm-action-group-head svg { width: 0.95rem; height: 0.95rem; flex: none; color: var(--color-primary); }
.dm-action-option {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  padding: 0.3rem 0; font-size: 0.72rem; color: var(--color-text-muted); cursor: pointer;
}
.dm-action-option:hover { color: var(--color-text); }

.dm-duration-grid { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.dm-duration-btn {
  min-height: 2.2rem; padding: 0 0.8rem; border: 1px solid var(--color-border); border-radius: 999px;
  background: var(--color-surface); color: var(--color-text-muted); font-size: 0.78rem; font-weight: 700; cursor: pointer;
  transition: border-color var(--transition-fast) var(--ease), color var(--transition-fast) var(--ease), background var(--transition-fast) var(--ease);
}
.dm-duration-btn:hover { color: var(--color-text); border-color: var(--color-text-faint); }
.dm-duration-btn.is-active {
  color: var(--color-on-primary); border-color: transparent;
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-grad-end));
}

.dm-plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 0.6rem; }
.dm-plan-card { padding: 0.85rem; border: 1px solid var(--color-border); border-radius: 14px; background: var(--color-surface-muted); }
.dm-plan-card span { display: block; color: var(--color-text-muted); font-size: 0.7rem; }
.dm-plan-card strong { display: block; margin-top: 0.3rem; font-family: var(--font-display); font-size: 1.2rem; font-weight: 650; }

.dm-section-icon.is-violet { background: color-mix(in srgb, #d887ff 14%, transparent); color: #b558e8; }

/* Smart-диалоги: multi-select goal chips. A checkbox styled as a pill — the real
   input stays in the DOM (only visually hidden) so the set posts as ordinary repeated
   form values and keyboard/screen-reader use is unaffected. */
.dm-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.dm-chip {
  display: inline-flex; align-items: center; min-height: 2.1rem; padding: 0 0.85rem;
  border: 1px solid var(--color-border); border-radius: 999px; background: var(--color-surface);
  color: var(--color-text-muted); font-size: 0.78rem; font-weight: 700; cursor: pointer;
  transition: border-color var(--transition-fast) var(--ease), color var(--transition-fast) var(--ease), background var(--transition-fast) var(--ease);
}
.dm-chip input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.dm-chip:hover { color: var(--color-text); border-color: var(--color-text-faint); }
.dm-chip:has(input:checked) {
  color: var(--color-on-primary); border-color: transparent;
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-grad-end));
}

/* ---- responsive ---- */
@media (max-width: 1180px) {
  .dm-workspace { grid-template-columns: 1fr; }
  .dm-aside { position: static; }
  .dm-summary-card { order: -1; }
  .dm-account-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dm-message-layout { grid-template-columns: minmax(0, 1fr) 15rem; }
  .dm-stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 960px) {
  .dm-message-layout, .dm-two-col { grid-template-columns: 1fr; }
  .dm-phone { position: static; }
  .dm-toolbar { grid-template-columns: 1fr 1fr; }
  .dm-toolbar .dm-search-wrap { grid-column: 1 / -1; }
  .dm-toolbar > .dm-select { grid-column: auto; }
}
@media (max-width: 680px) {
  .dm-hero { flex-direction: column; }
  /* .dm-workflow-nav-5 deliberately keeps the repeat(5) from its base rule here —
     only the 4-step nav narrows to 2 columns. */
  .dm-workflow-nav { grid-template-columns: 1fr 1fr; }
  .dm-workflow-nav, .dm-workflow-nav-5 { border-radius: 16px; }
  .dm-mode-banner { flex-direction: column; align-items: stretch; }
  .dm-step-copy span { display: none; }
  .dm-section-card { min-height: 0; border-radius: 20px; scroll-margin-top: 7rem; }
  .dm-section-card[data-step-label]::after { display: none; }
  .dm-section-head { padding: 0.8rem 0.85rem; }
  .dm-section-body { padding: 0.8rem; }
  .dm-toolbar, .dm-audience-grid, .dm-settings-grid, .dm-stats-grid, .dm-blacklist-add,
  .dm-two-col, .dm-choice-grid { grid-template-columns: 1fr; }
  .dm-toolbar .dm-search-wrap { grid-column: auto; }
  .dm-account-list { grid-template-columns: 1fr; }
  .dm-account-overview { flex-direction: column; align-items: flex-start; }
  .dm-panel-nav { flex-direction: column; align-items: stretch; }
  .dm-panel-nav-actions { width: 100%; }
  .dm-panel-nav-actions > * { flex: 1; min-width: 0; }
  .dm-workflow-divider { height: 3.4rem; }
}



/* --- Раздел, который ещё не настроен ---------------------------------------------
   Признак ставится из dm-shared.js по строкам проверки справа. Янтарный, а не красный:
   это «сюда ещё не дошли», а не «здесь ошибка», и на свежей странице таких разделов
   закономерно несколько — красная стена читалась бы как поломка. */
.dm-section-card.is-incomplete {
  border-color: color-mix(in srgb, var(--color-warning, #d97706) 45%, var(--color-border));
}
.dm-section-card.is-incomplete > .dm-section-head::before {
  content: ""; position: absolute; left: 0; top: 0.9rem; bottom: 0.9rem; width: 3px;
  border-radius: 0 3px 3px 0; background: var(--color-warning, #d97706);
}
.dm-section-card.is-incomplete > .dm-section-head { position: relative; }

/* В навигации — точка у номера шага. Кружок, а не цвет текста: шаг может быть
   одновременно активным (залит основным цветом), и цветом там уже не сказать ничего. */
.dm-workflow-step.is-incomplete .dm-step-num { position: relative; }
.dm-workflow-step.is-incomplete .dm-step-num::after {
  content: ""; position: absolute; right: -2px; top: -2px; width: 6px; height: 6px;
  border-radius: 50%; background: var(--color-warning, #d97706);
  box-shadow: 0 0 0 2px var(--color-surface);
}


/* Поле, из-за которого раздел считается ненастроенным. Тот же янтарный, что и у
   полосы раздела: это одна и та же мысль на двух масштабах — «сюда идти» и «вот это
   править». Рамка, а не заливка: значение в поле должно остаться читаемым. */
.dm-input.is-attention,
.dm-select.is-attention {
  border-color: var(--color-warning);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-warning) 18%, transparent);
}

/* Карточка аккаунтов, когда аккаунтов ещё ни одного. Страница модуля больше не
   подменяет себя целиком на «сначала добавьте аккаунт» — пустеет только этот блок,
   остальные секции остаются на месте и их видно до первого аккаунта. Пунктирная
   рамка, а не сплошная: это не настройка, а место, где настройка появится. */
.dm-account-empty {
  display: flex; align-items: center; gap: 0.8rem; padding: 1rem;
  color: var(--color-text-muted);
  background: var(--color-surface-muted);
  border: 1px dashed var(--color-border); border-radius: 16px;
}
.dm-account-empty > svg { width: 1.5rem; height: 1.5rem; flex: 0 0 auto; }
.dm-account-empty strong { display: block; color: var(--color-text); font-size: 0.82rem; }
.dm-account-empty p { margin: 0.2rem 0 0; font-size: 0.75rem; }
.dm-account-empty .dm-secondary-btn { margin-left: auto; flex: 0 0 auto; }


/* ==========================================================================
   Переходник — конструктор ботов
   ========================================================================== */
.bridge-layout { display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 1rem; align-items: start; }
@media (max-width: 980px) { .bridge-layout { grid-template-columns: 1fr; } }

.bridge-bot-list { display: flex; flex-direction: column; gap: .4rem; }
.bridge-bot {
  display: flex; align-items: center; gap: .6rem;
  padding: .55rem .7rem; border: 1px solid var(--color-border); border-radius: 12px;
  text-decoration: none; color: inherit; background: var(--color-surface-muted);
}
.bridge-bot:hover { border-color: color-mix(in srgb, var(--color-primary) 35%, var(--color-border)); }
.bridge-bot.is-active { border-color: var(--color-primary); background: var(--color-primary-bg); }
.bridge-bot-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-text-faint); flex: none; }
.bridge-bot-dot.is-on { background: var(--color-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 22%, transparent); }
.bridge-bot-dot.is-error { background: var(--color-danger); }
.bridge-bot-copy { min-width: 0; }
.bridge-bot-copy strong { display: block; font-size: .84rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bridge-bot-copy span { font-size: .72rem; color: var(--color-text-faint); }

.bridge-howto { margin: .8rem 0 0; padding-left: 1.1rem; font-size: .74rem; color: var(--color-text-muted); display: flex; flex-direction: column; gap: .25rem; }

.bridge-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem; }
.bridge-stats > div { background: var(--color-surface-muted); border: 1px solid var(--color-border); border-radius: 12px; padding: .55rem .7rem; }
.bridge-stats b { display: block; font-size: 1.25rem; font-weight: 700; letter-spacing: -.02em; }
.bridge-stats span { font-size: .7rem; color: var(--color-text-faint); }

.bridge-canvas { display: flex; flex-direction: column; gap: .6rem; margin-top: .9rem; }
.bridge-step {
  border: 1px solid var(--color-border); border-radius: 14px;
  background: var(--color-surface-muted); padding: .7rem;
  display: flex; flex-direction: column; gap: .5rem;
  position: relative;
}
/* Стрелка между шагами: видно, что это цепочка, без графа и перетаскиваний. */
.bridge-step + .bridge-step::before {
  content: '';
  position: absolute; top: -.55rem; left: 1.4rem;
  width: 1px; height: .5rem; background: var(--color-border);
}
.bridge-step-head { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.bridge-step-num {
  width: 1.5rem; height: 1.5rem; flex: none; border-radius: 8px;
  display: grid; place-items: center; font-size: .74rem; font-weight: 700;
  background: var(--color-primary-bg); color: var(--color-primary-hover);
}
.bridge-step-head .fancy-select, .bridge-step-head select { max-width: 15rem; }
.bridge-step-head [data-step-remove] { margin-left: auto; }
.bridge-buttons { display: flex; flex-direction: column; gap: .4rem; }
.bridge-button-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; gap: .4rem; align-items: center; }
@media (max-width: 720px) { .bridge-button-row { grid-template-columns: 1fr; } }

.bridge-actions { display: flex; align-items: center; justify-content: space-between; gap: .6rem; margin-top: .9rem; flex-wrap: wrap; }
.bridge-delete { margin: 0; }
