:root {
  --sidebar-bg: #12141c;
  --sidebar-text: #9a9fb0;
  --sidebar-active-bg: #3d2c1a;
  --sidebar-active-text: #e0a458;
  --content-bg: #f5f3ee;
  --card-bg: #ffffff;
  --card-border: #e7e3d9;
  --text: #1b1c22;
  --text-muted: #767b88;
  --accent: #d9822b;
  --accent-dark: #b8691c;
  --dark-btn: #1b1c22;
  --green-bg: #dff0e2;
  --green-text: #2c6b3f;
  --amber-bg: #fbe9d2;
  --amber-text: #9a5c14;
  --red-bg: #fbe1e1;
  --red-text: #b23b3b;
  --blue-bg: #e1ebfb;
  --blue-text: #2a56a8;
  --violet-bg: #ece1fb;
  --violet-text: #6d3fb0;
  --mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
}

* { box-sizing: border-box; }

/* The app is a viewport-locked three-column layout: the page itself never
   scrolls. Each column owns its own scrolling (sidebar nav, .content for
   ordinary pages, and inside Live Chat the conversation list and message list
   separately). Locking it here rather than per-page is what stops a tall panel
   from dragging the whole document with it. */
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--content-bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 14px;
  overflow: hidden;
}

.shell { display: flex; height: 100vh; overflow: hidden; }

/* ---------------------------------------------------------------- Sidebar */
.sidebar {
  width: 232px;
  flex-shrink: 0;
  background: var(--sidebar-bg);
  color: var(--sidebar-text);
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  /* Full height of the locked shell and independently scrollable, so a long
     nav scrolls itself instead of the page. `sticky` is no longer needed now
     that .shell is viewport-height rather than min-height. */
  height: 100%;
  min-height: 0;
  overflow-y: auto;
}
.sidebar-brand { padding: 6px 10px 14px; }
.brand-suite { color: #fff; font-weight: 700; font-size: 17px; letter-spacing: -0.01em; }

.app-switcher {
  width: 100%; display: flex; align-items: center; gap: 9px;
  background: #1a1e29; border: 1px solid #2b2f3c; color: #e4e6ec;
  padding: 10px 12px; border-radius: 10px; margin-bottom: 6px;
  font-size: 13.5px; font-weight: 600; cursor: pointer; text-align: left;
}
.app-switcher:hover { border-color: #3a3f50; }
.app-switcher-icon { font-size: 15px; flex-shrink: 0; }
.app-switcher-name { flex: 1; }
.app-switcher-chevron { flex-shrink: 0; color: var(--sidebar-text); transition: transform .18s ease; }
.app-switcher.collapsed .app-switcher-chevron { transform: rotate(-90deg); }

.sidenav { display: flex; flex-direction: column; gap: 2px; }
.sidenav a {
  display: flex; align-items: center; gap: 10px;
  color: var(--sidebar-text); text-decoration: none;
  padding: 10px 12px; border-radius: 8px; font-size: 13.5px; font-weight: 500;
  position: relative;
}
.sidenav a:hover { background: #1c1f2a; color: #fff; }
.sidenav a.active { background: var(--sidebar-active-bg); color: var(--sidebar-active-text); }
.sidenav .idx { font-family: var(--mono); font-size: 11px; color: inherit; opacity: .65; width: 18px; }
.nav-badge {
  margin-left: auto; background: var(--accent); color: #1b1c22; font-size: 10.5px; font-weight: 700;
  border-radius: 999px; padding: 1px 7px; font-family: var(--mono);
}

.sidebar-footer { border-top: 1px solid #262a37; padding-top: 14px; margin-top: auto; }
.connection-switcher { position: relative; margin-bottom: 10px; }
.connection-switcher-btn {
  width: 100%; display: flex; align-items: center; gap: 8px; background: none; border: 1px solid transparent;
  padding: 6px 10px; border-radius: 8px; cursor: pointer; text-align: left;
}
.connection-switcher-btn:hover { background: #1a1e29; border-color: #2b2f3c; }
.connection-switcher-btn .dot { width: 7px; height: 7px; border-radius: 50%; background: #3ecf8e; flex-shrink: 0; }
.connection-switcher-btn .dot.dot-off { background: #6b7280; }
.connection-switcher-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.connection-switcher-btn .chevron { color: var(--sidebar-text); flex-shrink: 0; }
.sending-label { font-size: 10.5px; color: var(--sidebar-text); text-transform: uppercase; letter-spacing: .04em; }
.sending-value { font-size: 12.5px; color: #d7d9e0; word-break: break-word; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.connection-dropdown {
  position: absolute; bottom: calc(100% + 6px); left: 0; right: 0;
  background: #1a1e29; border: 1px solid #2b2f3c; border-radius: 10px;
  padding: 5px; box-shadow: 0 8px 24px rgba(0,0,0,.35); z-index: 40;
}
.connection-option {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  background: none; border: none; color: #d7d9e0; text-align: left;
  padding: 8px 10px; border-radius: 7px; font-size: 12.5px; cursor: pointer;
}
.connection-option:hover { background: #232838; }
.connection-option.active { color: var(--accent); }
.connection-option .check { color: var(--accent); }
.connection-dropdown-divider { height: 1px; background: #2b2f3c; margin: 4px 6px; }
.logout-btn {
  width: 100%; background: transparent; border: 1px solid #2b2f3c; color: var(--sidebar-text);
  padding: 9px; border-radius: 8px; font-size: 12.5px; cursor: pointer;
}
.logout-btn:hover { border-color: #4a4f60; color: #fff; }

/* ----------------------------------------------------------------- Content */
/* The scroll container for ordinary pages (Dashboard, Contacts, Templates,
   Campaigns, Settings). Live Chat overrides this to hidden and hands scrolling
   to its own inner columns - see the Live Chat layout block below. */
.content { flex: 1; padding: 34px 40px; min-width: 0; min-height: 0; overflow-y: auto; }
.page-title { font-size: 26px; font-weight: 700; margin: 0 0 22px; letter-spacing: -0.01em; }

.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 20px; }
@media (max-width: 1100px) { .grid-4 { grid-template-columns: repeat(2, 1fr); } }

.card {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 14px;
  padding: 22px;
  margin-bottom: 18px;
}
.card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; gap: 10px; flex-wrap: wrap; }
.card-head h2 { line-height: 1.3; }
/* Collapsible cards: the gap between header and body must live on the body
   (margin-top), not the header (margin-bottom) - a hidden body's margin
   collapses away too, keeping the header vertically centered when collapsed.
   A visible header's own margin-bottom would otherwise persist and visually
   push the heading toward the top of the card. */
.card-head.collapse-head { margin-bottom: 0; }
.collapse-body { margin-top: 10px; }
.card h2 { font-size: 15px; font-weight: 700; margin: 0; }
.hint { color: var(--text-muted); font-size: 12.5px; margin: 4px 0 14px; line-height: 1.5; }

.stat-card { }
.stat-label { color: var(--text-muted); font-size: 12.5px; margin-bottom: 8px; }
.stat-value { font-size: 30px; font-weight: 700; }

/* ------------------------------------------------------------------- Forms */
label { display: block; font-size: 12.5px; color: var(--text-muted); margin-bottom: 14px; font-weight: 500; }
.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.row-inline { display: flex; align-items: center; gap: 10px; }
.field-note { display: block; color: var(--text-muted); font-weight: 400; font-size: 11px; margin-top: 3px; }
.optional { font-weight: 400; font-style: italic; }

input[type=text], input[type=number], input[type=file], input[type=password], input[type=email], select, textarea {
  width: 100%; background: #fbfaf7; border: 1px solid var(--card-border); color: var(--text);
  border-radius: 8px; padding: 9px 11px; font-size: 13.5px; margin-top: 6px; font-family: inherit;
}
textarea { resize: vertical; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
code { font-family: var(--mono); background: #f0ede4; padding: 1px 5px; border-radius: 4px; font-size: 12px; }

/* ----------------------------------------------------------------- Buttons */
button { font-family: inherit; cursor: pointer; }
.btn-dark, .btn-outline, .btn-danger-outline, .btn-accent {
  border-radius: 8px; padding: 10px 16px; font-size: 13px; font-weight: 600; border: 1px solid transparent;
  display: inline-flex; align-items: center; gap: 6px; text-decoration: none;
}
.btn-dark { background: var(--dark-btn); color: #fff; }
.btn-dark:hover { background: #000; }
.btn-accent { background: var(--accent); color: #201404; }
.btn-accent:hover { background: var(--accent-dark); color: #fff; }
.btn-outline { background: #fff; color: var(--text); border-color: var(--card-border); }
.btn-outline:hover { border-color: #b9b4a4; }
.btn-danger-outline { background: #fff; color: var(--red-text); border-color: #e3b6b6; }
.btn-danger-outline:hover { background: var(--red-bg); }
button:disabled { opacity: .45; cursor: not-allowed; }
.btn-sm { padding: 6px 11px; font-size: 12px; }

.form-msg { margin-top: 12px; font-size: 12.5px; }
.form-msg.error { color: var(--red-text); }
.form-msg.success { color: var(--green-text); }

/* --------------------------------------------------------- Auth (login/setup) */
.auth-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px; background: var(--content-bg);
}
.auth-card { width: 100%; max-width: 380px; }
.auth-card .page-title { margin-bottom: 6px; }
.auth-card form button[type=submit] { width: 100%; justify-content: center; margin-top: 6px; }
.current-user-label {
  font-size: 11.5px; color: var(--text-muted); padding: 0 2px 8px; line-height: 1.4;
  overflow-wrap: anywhere;
}

/* ------------------------------------------------------------------- Table */
.table { width: 100%; border-collapse: collapse; margin-top: 4px; font-size: 13px; }
.table th { text-align: left; color: var(--text-muted); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; padding: 9px 10px; border-bottom: 1px solid var(--card-border); }
.table td { padding: 11px 10px; border-bottom: 1px solid var(--card-border); font-size: 13px; vertical-align: middle; }
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: #fbfaf6; }
.empty { color: var(--text-muted); font-size: 12.5px; padding: 16px 4px; }

.badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 11px; font-weight: 700; text-transform: lowercase; }
.badge-active, .badge-APPROVED, .badge-completed, .badge-sent, .badge-delivered, .badge-read { background: var(--green-bg); color: var(--green-text); }
.badge-PENDING, .badge-queued, .badge-running { background: var(--amber-bg); color: var(--amber-text); }
.badge-SUBMITTING { background: var(--blue-bg); color: var(--blue-text); }
.badge-REJECTED, .badge-failed, .badge-stopped { background: var(--red-bg); color: var(--red-text); }
.badge-blocked { background: #e3e1da; color: #4a4a45; }
.badge-paused { background: var(--violet-bg); color: var(--violet-text); }
.badge-info { background: var(--blue-bg); color: var(--blue-text); }

/* --------------------------------------------------------------------- Tabs */
.pill-tabs { display: flex; gap: 26px; border-bottom: 1px solid var(--card-border); margin-bottom: 22px; }
.pill-tabs button {
  background: transparent; border: none; padding: 8px 4px 12px; font-size: 13.5px; font-weight: 600;
  color: var(--text-muted); border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.pill-tabs button.active { color: var(--text); border-bottom-color: var(--accent); }

/* Templates page header: tabs on the left, Refresh + New template on the right,
   same line. The sync-status hint drops to its own smaller line below. On narrow
   widths the action group wraps under the tabs (flex-wrap, no media query). */
.templates-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px 20px; flex-wrap: wrap; }
.templates-toolbar .pill-tabs { margin-bottom: 0; flex: 1 1 auto; }
.templates-toolbar .row-inline { flex: 0 0 auto; }
.templates-hint { margin: 10px 0 0; font-size: 11.5px; }

.subtabs { display: flex; gap: 6px; margin-bottom: 14px; }
.subtab { background: #fbfaf7; border: 1px solid var(--card-border); color: var(--text-muted); padding: 7px 14px; border-radius: 7px; font-size: 12.5px; }
.subtab.active { color: var(--text); border-color: var(--accent); background: #fff; }
.source-panel { display: none; }
.source-panel.active { display: block; }

/* --------------------------------------------------------------- Progress */
/* Stats row (TOTAL/SENT/DELIVERED/READ/NOT RECEIVED/STATUS): a grid, not
   flex-wrap, so every box in a row is forced to the same width - flex-basis
   with wrapping can leave uneven leftover space between boxes depending on
   how many fit per row. auto-fit + minmax keeps boxes from getting either
   too cramped or stretched absurdly wide at any viewport size. */
.progress-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 12px;
  margin-bottom: 18px;
  width: 100%;
  box-sizing: border-box;
}
.progress-stats > div {
  box-sizing: border-box;
  border: 1px solid var(--card-border);
  border-radius: 10px;
  padding: 16px 14px;
  background: #fbfaf7;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 76px;
  text-align: center;
}
.progress-stats b { font-size: 22px; line-height: 1; }
.progress-stats span { color: var(--text-muted); font-size: 11px; text-transform: uppercase; letter-spacing: .05em; }
@media (max-width: 640px) {
  .progress-stats { grid-template-columns: repeat(2, 1fr); }
}
.progress-bar { height: 8px; background: #eeece4; border-radius: 999px; overflow: hidden; margin-bottom: 20px; }
.progress-bar-fill { height: 100%; background: var(--accent); width: 0%; transition: width .3s ease; }
.progress-actions { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }

/* Contact results table (Name/Number/Status/Detail): fixed column widths so
   Name/Number get consistent room, Status stays centered under its header
   regardless of badge text length, and Detail (often a full Meta error
   message) gets the majority of the remaining width and wraps instead of
   overflowing or forcing the table wider than the modal. */
#progress-table, #modal-progress-table { table-layout: fixed; }
#progress-table th:nth-child(1), #progress-table td:nth-child(1),
#modal-progress-table th:nth-child(1), #modal-progress-table td:nth-child(1) { width: 22%; }
#progress-table th:nth-child(2), #progress-table td:nth-child(2),
#modal-progress-table th:nth-child(2), #modal-progress-table td:nth-child(2) { width: 18%; }
#progress-table th:nth-child(3), #progress-table td:nth-child(3),
#modal-progress-table th:nth-child(3), #modal-progress-table td:nth-child(3) { width: 14%; text-align: center; }
#progress-table th:nth-child(4), #progress-table td:nth-child(4),
#modal-progress-table th:nth-child(4), #modal-progress-table td:nth-child(4) { width: 46%; }
#progress-table td:nth-child(1), #progress-table td:nth-child(2),
#modal-progress-table td:nth-child(1), #modal-progress-table td:nth-child(2) {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#progress-table td:nth-child(4), #modal-progress-table td:nth-child(4) {
  white-space: normal; word-break: break-word; color: var(--text-muted); font-size: 12.5px; line-height: 1.4;
}

/* ------------------------------------------------------------------ Template preview */
.template-preview-slot { margin-top: 14px; }
.template-preview-slot:empty { margin-top: 0; }

.button-row { display: grid; grid-template-columns: 130px 1fr 1fr 32px; gap: 8px; align-items: center; margin-bottom: 8px; }
.button-row select, .button-row input { margin-top: 0; }
.remove-btn { background: none; border: none; color: var(--red-text); font-size: 16px; cursor: pointer; }

/* ------------------------------------------------------------------- Chat */
/* Live Chat is styled to match WhatsApp Web. Everything in this block is
   scoped to the chat page's own classes (or nested under .chat-* containers),
   so Dashboard / Contacts / Templates / Campaigns / Settings are untouched. */
:root {
  --wa-green: #00a884;          /* WhatsApp Web's primary accent */
  --wa-badge: #25d366;          /* unread badge / send */
  --wa-panel: #f0f2f5;          /* header + composer bars */
  --wa-divider: #e9edef;
  --wa-text: #111b21;
  --wa-muted: #667781;
  --wa-icon: #54656f;
  --wa-out: #d9fdd3;            /* outgoing bubble */
  --wa-hover: #f5f6f6;
  --wa-active: #f0f2f5;
}

/* ---------------------------------------------------------------------------
   Live Chat layout chain. Every level below is deliberate; removing any one of
   them reintroduces the "whole pane scrolls together" bug:

   .content (flex column, overflow hidden)
     └ #page-root (flex column, flex:1, min-height:0)
         └ .chat-shell (grid, flex:1, min-height:0, overflow hidden)
             ├ .chat-list-col (flex column, min-height:0)  -> its own scroller
             └ .chat-pane     (flex column, min-height:0)
                 ├ header / banners / composer  -> flex: 0 0 auto (never scroll)
                 └ .chat-messages               -> flex: 1, min-height: 0 (the
                                                   ONLY scrolling element)

   `min-height: 0` on each flex/grid child is the load-bearing part: a flex item
   defaults to min-height:auto and so refuses to shrink below its content, which
   pushes the pane past the viewport and drags the header and composer with it.
   The chain also replaces a hardcoded `height: calc(100vh - 104px)`, which had
   to be kept in sync by hand with the page padding and heading height and broke
   the moment either changed.
   --------------------------------------------------------------------------- */
.content:has(.chat-shell) { display: flex; flex-direction: column; overflow: hidden; }
.content:has(.chat-shell) > #page-root { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }

.chat-shell {
  display: grid; grid-template-columns: minmax(260px, 30%) 1fr; gap: 0;
  flex: 1 1 auto; min-height: 0; background: #fff;
  border: 1px solid var(--wa-divider); border-radius: 10px; overflow: hidden;
}
/* Compact heading row above the shell - chat only, other pages keep theirs. */
.chat-page-head { margin-bottom: 10px; }
.chat-page-head .page-title { font-size: 19px; }
.chat-list { overflow-y: auto; background: #fff; }
.chat-list-item {
  display: flex; align-items: center; gap: 11px; padding: 8px 12px;
  text-decoration: none; color: inherit; cursor: pointer; position: relative;
}
/* Divider starts after the avatar, the way WhatsApp Web draws it. */
.chat-list-item::after {
  content: ''; position: absolute; left: 72px; right: 0; bottom: 0; height: 1px; background: var(--wa-divider);
}
.chat-list-item:last-child::after { display: none; }
.chat-list-avatar { flex-shrink: 0; }
.chat-list-body { min-width: 0; flex: 1; }
.chat-list-item:hover { background: var(--wa-hover); }
.chat-list-item.active { background: var(--wa-active); }
.chat-list-name {
  font-weight: 500; font-size: 15px; color: var(--wa-text); line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-list-name span { overflow: hidden; text-overflow: ellipsis; }
.chat-list-preview {
  color: var(--wa-muted); font-size: 13px; margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.35;
}
/* Right-hand column: timestamp on top, unread badge underneath. */
.chat-list-meta {
  display: flex; flex-direction: column; align-items: flex-end; justify-content: center;
  gap: 5px; flex-shrink: 0; min-height: 38px; align-self: stretch; padding: 4px 0;
}
.chat-list-time { color: var(--wa-muted); font-size: 11.5px; font-family: inherit; line-height: 1; }
.chat-list-item.active .chat-list-time { color: var(--wa-muted); }
.unread-dot {
  background: var(--wa-badge); color: #fff; font-size: 11.5px; font-weight: 600;
  border-radius: 999px; min-width: 20px; height: 20px; padding: 0 6px; font-family: inherit;
  display: inline-flex; align-items: center; justify-content: center; line-height: 1;
}

/* Grid child of .chat-shell: needs min-height:0 for the same reason its own
   children do, or its content floor pushes the pane past the shell. */
.chat-pane { display: flex; flex-direction: column; height: 100%; min-height: 0; background: #fff; overflow: hidden; }
/* Everything in the pane except the message list is fixed furniture. Listed
   together so a newly added banner can't accidentally become scrollable. */
.chat-pane-header,
.chat-search-bar,
.chat-window-banner,
.chat-reply-context,
#attachment-preview,
.chat-input-row { flex: 0 0 auto; }
.chat-pane-header {
  padding: 8px 16px; border-bottom: 1px solid var(--wa-divider); background: var(--wa-panel);
  display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 56px;
}
.chat-profile-btn {
  display: flex; align-items: center; gap: 12px; background: none; border: none; cursor: pointer;
  padding: 4px 6px; border-radius: 8px; text-align: left; min-width: 0;
}
.chat-profile-btn:hover { background: rgba(0,0,0,.04); }
.chat-profile-btn .sub { display: block; font-weight: 400; color: var(--wa-muted); font-size: 12.5px; font-family: inherit; }
.chat-pane-name { font-weight: 500; font-size: 15.5px; display: block; color: var(--wa-text); }
.chat-avatar {
  width: 40px; height: 40px; border-radius: 50%; background: #dfe5e7; color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 500; font-size: 16px; flex-shrink: 0;
}
.chat-list-avatar { width: 49px; height: 49px; font-size: 19px; }
/* Muted WhatsApp-ish avatar tint rather than the app's amber accent. */
.chat-avatar { background: linear-gradient(180deg, #b9c3c8, #a3b0b6); }
.chat-avatar-lg { width: 52px; height: 52px; font-size: 20px; }
.profile-avatar-row { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
.profile-name { font-weight: 700; font-size: 16px; }
.profile-phone { color: var(--text-muted); font-size: 12.5px; font-family: var(--mono); }
.profile-table td { font-size: 13px; }
.profile-table td:first-child { color: var(--text-muted); width: 40%; }
.chat-pane-header .sub { font-weight: 400; color: var(--text-muted); font-size: 12px; font-family: var(--mono); }
/* --- WhatsApp-style message area (Phase 3). Scoped to the bubble area only:
   the app shell, sidebar, header and conversation-list panel are untouched. */
/* The one and only scrolling element in the conversation pane.
   min-height: 0 is what actually lets it shrink and scroll instead of growing
   the pane. The clamped side padding keeps bubbles off the panel walls at every
   width (never below 16px, never a runaway gutter on a wide screen). */
.chat-messages {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  padding: 10px clamp(16px, 4%, 40px) 12px;
  display: flex; flex-direction: column; gap: 0;
  background-color: #efeae2;
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='60'%20height='60'%20viewBox='0%200%2060%2060'%3E%3Cg%20fill='none'%20stroke='%23000000'%20stroke-opacity='0.035'%20stroke-width='1.4'%3E%3Cpath%20d='M9%2013c2-3%205-3%207%200s-1%206-3%206-6-3-4-6z'/%3E%3Cpath%20d='M42%208h7v5h-4l-3%203z'/%3E%3Ccircle%20cx='31'%20cy='31'%20r='4'/%3E%3Cpath%20d='M13%2044c3-4%206-2%206%201s-3%205-6%203'/%3E%3Cpath%20d='M46%2040l4%204-4%204-4-4z'/%3E%3Cpath%20d='M22%2022l3-4%203%204'/%3E%3C/g%3E%3C/svg%3E");
}
.chat-bubble {
  position: relative; max-width: 65%; padding: 6px 7px 8px 9px; border-radius: 7.5px;
  font-size: 14.2px; line-height: 1.35; color: var(--wa-text);
  box-shadow: 0 1px 0.5px rgba(11,20,26,.13); margin-top: 12px; word-wrap: break-word;
}
.chat-bubble.in  { align-self: flex-start; background: #ffffff; border-top-left-radius: 0; }
.chat-bubble.out { align-self: flex-end;   background: var(--wa-out); border-top-right-radius: 0; }
/* Tail on the first bubble of each run, exactly as WhatsApp Web draws it. */
.chat-bubble.in::before, .chat-bubble.out::before {
  content: ''; position: absolute; top: 0; width: 8px; height: 13px;
}
.chat-bubble.in::before  { left: -8px;  background: #ffffff; clip-path: polygon(100% 0, 0 0, 100% 100%); }
.chat-bubble.out::before { right: -8px; background: var(--wa-out); clip-path: polygon(0 0, 100% 0, 0 100%); }
/* Consecutive messages from the same side hug together and drop the tail;
   a change of sender keeps the bigger 12px gap set above. */
.chat-bubble.in + .chat-bubble.in,
.chat-bubble.out + .chat-bubble.out { margin-top: 2px; }
.chat-bubble.in + .chat-bubble.in { border-top-left-radius: 7.5px; }
.chat-bubble.out + .chat-bubble.out { border-top-right-radius: 7.5px; }
.chat-bubble.in + .chat-bubble.in::before,
.chat-bubble.out + .chat-bubble.out::before { display: none; }
.chat-bubble.failed { background: #fdecea; }
.chat-bubble.failed::before { background: #fdecea; }
.chat-bubble .msg-text { white-space: pre-wrap; }
.chat-bubble a { color: #027eb5; text-decoration: underline; word-break: break-all; }
/* Timestamp + ticks in the bubble's bottom-right corner. Kept as a block row
   (not a float) so a very short message can never overlap the timestamp. */
.chat-bubble .meta {
  display: flex; justify-content: flex-end; align-items: center; gap: 3px;
  margin-top: 4px; font-size: 11px; color: var(--wa-muted);
  line-height: 15px; user-select: none; white-space: nowrap;
}
.chat-bubble.out .meta { color: rgba(17,27,33,.5); }
.tick { display: inline-flex; align-items: center; margin-left: 1px; color: #8696a0; letter-spacing: normal; font-size: 11px; }
.tick-ic { width: 15px; height: 14px; display: block; }
.tick-ic-double { width: 17px; }
.chat-bubble.out .tick { color: #8696a0; }
.tick-read { color: #53bdeb; }
.tick-failed { color: var(--red-text); letter-spacing: 0; font-weight: 700; }
.msg-template-tag {
  display: inline-block; font-size: 9.5px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: #027eb5; margin-bottom: 3px;
}

/* quoted reply shown inside a bubble */
.bubble-quote {
  display: block; border-left: 3px solid #06cf9c; background: rgba(0,0,0,.04);
  border-radius: 4px; padding: 4px 7px; margin-bottom: 4px; font-size: 12.5px;
}
.chat-bubble.out .bubble-quote { border-left-color: #4a7c59; background: rgba(0,0,0,.05); }
.bubble-quote-label { display: block; font-weight: 600; color: #06897a; font-size: 11.5px; }
.chat-bubble.out .bubble-quote-label { color: #3d6b4c; }
.bubble-quote span:last-child { color: #4b5a63; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* reaction chip sitting on the bubble's lower edge */
.bubble-reaction {
  position: absolute; bottom: -12px; right: 6px; background: #fff; border-radius: 999px;
  padding: 1px 5px; font-size: 12px; box-shadow: 0 1px 3px rgba(11,20,26,.2); line-height: 1.4;
}
.chat-bubble.in .bubble-reaction { right: auto; left: 6px; }

/* per-message hover toolbar + quick reaction bar */
.msg-actions {
  position: absolute; top: 2px; right: 4px; display: none; gap: 1px;
  background: rgba(255,255,255,.92); border-radius: 6px; box-shadow: 0 1px 4px rgba(11,20,26,.18);
}
.chat-bubble.out .msg-actions { background: rgba(217,253,211,.95); }
.chat-bubble:hover .msg-actions { display: flex; }
.msg-act { background: none; border: none; cursor: pointer; font-size: 12px; padding: 3px 5px; border-radius: 5px; }
.msg-act:hover { background: rgba(0,0,0,.07); }
.reaction-bar {
  position: absolute; bottom: calc(100% - 4px); right: 0; z-index: 5;
  background: #fff; border-radius: 999px; box-shadow: 0 2px 10px rgba(11,20,26,.25);
  padding: 3px 6px; display: flex; gap: 2px;
}
/* Same [hidden] fix - otherwise every bubble showed its reaction bar at all
   times instead of only after clicking the react action. */
.reaction-bar[hidden] { display: none; }
.chat-bubble.in .reaction-bar { right: auto; left: 0; }
.reaction-pick { background: none; border: none; cursor: pointer; font-size: 17px; padding: 2px 4px; border-radius: 50%; line-height: 1; }
.reaction-pick:hover { background: rgba(0,0,0,.08); transform: scale(1.15); }

/* day separator - centred rounded pill, WhatsApp style */
.chat-day-sep { align-self: center; margin: 14px 0 6px; }
.chat-day-sep span {
  display: inline-block; background: #ffffff; color: #54656f; font-size: 12.5px; font-weight: 500;
  text-transform: uppercase; letter-spacing: .02em; padding: 5px 12px; border-radius: 7.5px;
  box-shadow: 0 1px 0.5px rgba(11,20,26,.13);
}
.chat-load-older { align-self: center; margin: 6px 0 8px; }
.chat-load-older button {
  background: #fff; border: none; color: #027eb5; font-size: 12.5px; font-weight: 500;
  padding: 6px 14px; border-radius: 7.5px; cursor: pointer; box-shadow: 0 1px 0.5px rgba(11,20,26,.13);
}
.chat-bubble.flash { animation: bubbleFlash 1.6s ease; }
@keyframes bubbleFlash { 0%, 100% { box-shadow: 0 1px 0.5px rgba(11,20,26,.13); } 30% { box-shadow: 0 0 0 3px rgba(37,211,102,.55); } }

.chat-empty { display: flex; align-items: center; justify-content: center; height: 100%; color: var(--text-muted); font-size: 13px; }

/* header actions + search bar */
.chat-header-actions { display: flex; align-items: center; gap: 2px; }
/* Plain, minimal round icon buttons (magnifier / three-dot), WhatsApp style. */
.icon-btn {
  background: none; border: none; cursor: pointer; color: var(--wa-icon);
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center; padding: 0;
}
.icon-btn:hover { background: rgba(0,0,0,.05); }
.icon-btn .ic, .attach-btn .ic { width: 22px; height: 22px; display: block; }
.chat-pane-header .conv-status-chip { margin-right: 4px; }
.chat-pane-header .btn-outline.btn-sm {
  border-color: #d1d7db; color: var(--wa-icon); background: #fff;
  border-radius: 16px; font-size: 12px; padding: 5px 12px; font-weight: 500;
}
.chat-pane-header .btn-outline.btn-sm:hover { background: var(--wa-hover); border-color: #c5ccd0; }
.chat-search-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 7px 14px; border-bottom: 1px solid var(--wa-divider); background: var(--wa-panel); position: relative;
}
/* Same author-`display` vs UA-`[hidden]` conflict as .emoji-popover: without
   this the bar ignored its `hidden` attribute and sat under the header
   permanently. It is now revealed only via ⋮ -> "Search messages". */
.chat-search-bar[hidden] { display: none; }
.chat-search-bar input { margin: 0; flex: 1; min-width: 160px; }
.chat-search-results { flex-basis: 100%; max-height: 200px; overflow-y: auto; }
.chat-search-hit {
  display: flex; flex-direction: column; gap: 2px; width: 100%; text-align: left;
  background: #fff; border: 1px solid var(--card-border); border-radius: 7px;
  padding: 6px 10px; margin-top: 6px; cursor: pointer; font-size: 12.5px;
}
.chat-search-hit:hover { background: #fbf2e6; }
.hit-when { color: var(--text-muted); font-size: 10.5px; font-family: var(--mono); }
.hit-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 24h-window notice: calm, muted - part of the interface, not an alert box. */
.chat-window-banner:not([hidden]) {
  padding: 9px 16px; background: #f7f8fa; color: var(--wa-muted); font-size: 12.5px;
  line-height: 1.45; border-bottom: 1px solid var(--wa-divider); text-align: center;
}
.chat-warn { padding: 8px 16px; background: #f7f8fa; color: var(--wa-muted); font-size: 11.5px; }

/* reply-in-progress bar above composer */
.chat-reply-context:not([hidden]) {
  display: flex; align-items: center; gap: 8px; padding: 8px 14px;
  background: var(--wa-panel); border-top: 1px solid var(--wa-divider);
}
.reply-quote { flex: 1; border-left: 4px solid var(--wa-green); padding: 2px 8px; min-width: 0; background: rgba(0,0,0,.03); border-radius: 4px; }
.reply-quote-label { display: block; font-weight: 500; font-size: 12px; color: var(--wa-green); }
.reply-quote-text { display: block; font-size: 12.5px; color: var(--wa-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* composer bar */
/* Pinned to the bottom of the pane, never part of the scrolling area. The
   border plus a soft upward shadow keep it visually separate from the last
   message instead of blending into it. */
.chat-input-row {
  display: flex; gap: 6px; padding: 8px 12px; border-top: 1px solid var(--wa-divider);
  background: var(--wa-panel); align-items: center; position: relative;
  box-shadow: 0 -1px 3px rgba(11,20,26,.05);
}
.chat-input-row input[type="text"] {
  margin-top: 0; flex: 1; border-radius: 8px; border: none; background: #fff;
  padding: 10px 14px; font-size: 14.5px; color: var(--wa-text); box-shadow: none; min-width: 0;
}
.chat-input-row input[type="text"]:focus { outline: none; box-shadow: none; }
.chat-input-row input[type="text"]::placeholder { color: #8696a0; }
/* Send stays a text button: doSend() rewrites its label to "Sending…", which
   would wipe an icon. Styled as WhatsApp's green action instead. */
.chat-input-row .btn-accent {
  background: var(--wa-badge); color: #fff; border: none; border-radius: 20px;
  padding: 9px 20px; font-size: 13.5px; font-weight: 500; flex-shrink: 0; box-shadow: none;
}
.chat-input-row .btn-accent:hover:not(:disabled) { background: #1eb955; }
.chat-input-row .btn-accent:disabled { opacity: .6; }
.chat-input-row.template-only { justify-content: center; padding: 12px 16px; }
.chat-input-row.template-only .btn-accent {
  background: #fff; color: var(--wa-green); border: 1px solid #d1d7db;
  border-radius: 20px; font-weight: 500; padding: 10px 18px;
}
.chat-input-row.template-only .btn-accent:hover:not(:disabled) { background: var(--wa-hover); }

.emoji-popover {
  position: absolute; bottom: calc(100% + 6px); left: 8px; z-index: 20;
  width: 288px; max-height: 220px; overflow-y: auto; padding: 8px;
  background: #fff; border: 1px solid var(--card-border); border-radius: 12px;
  box-shadow: 0 6px 24px rgba(11,20,26,.22);
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px;
}
/* `display: grid` above is an author rule and beats the UA's
   `[hidden] { display: none }`, so the picker stayed painted no matter what
   the JS set .hidden to. Re-assert it here (higher specificity) so the
   existing hidden-toggling code actually takes effect. */
.emoji-popover[hidden] { display: none; }
.emoji-cell { background: none; border: none; font-size: 19px; padding: 4px; border-radius: 6px; cursor: pointer; line-height: 1; }
.emoji-cell:hover { background: #f0ede4; }

.attach-btn {
  background: none; border: none; cursor: pointer; color: var(--wa-icon); padding: 0;
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.attach-btn:hover { background: rgba(0,0,0,.05); }
#attachment-preview:not(:empty) { padding: 8px 16px 0; }
.attach-chip { display: inline-flex; align-items: center; gap: 8px; background: #f0ede4; border-radius: 10px; padding: 6px 10px; font-size: 12.5px; }
.attach-chip img { width: 32px; height: 32px; object-fit: cover; border-radius: 6px; }
.attach-chip button { background: none; border: none; cursor: pointer; color: var(--text-muted); font-size: 13px; }

.chat-media-img { max-width: 260px; border-radius: 8px; display: block; margin: 2px 0 3px; }
.chat-doc-link { color: #027eb5; text-decoration: none; font-weight: 600; }
.chat-bubble audio { max-width: 240px; }
.tpl-preview { margin: 10px 0; }

/* interactive (button/list) message bubbles - static render of what was sent,
   or of the tapped reply, not a live interactive widget on the agent's side */
.msg-interactive-opts { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.msg-interactive-opt {
  background: rgba(0,0,0,.04); border: 1px solid rgba(0,0,0,.08); border-radius: 8px;
  padding: 6px 10px; font-size: 13px; color: #027eb5; font-weight: 500; text-align: center;
}
.msg-interactive-opt-desc { display: block; color: var(--wa-muted); font-weight: 400; font-size: 12px; margin-top: 2px; }
.msg-interactive-cta { font-size: 11.5px; color: var(--wa-muted); text-transform: uppercase; letter-spacing: .03em; margin-top: 4px; }
.msg-tapped-tag {
  display: inline-block; font-size: 9.5px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: #06897a; margin-right: 4px;
}

/* "Automated" chip on a bubble whose sent_by === 'automation' (Stage 1
   groundwork only - nothing sets this yet, but the render path must exist). */
.msg-automated-chip {
  display: inline-block; font-size: 9.5px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: #7a5cff; background: rgba(122,92,255,.12);
  border-radius: 4px; padding: 1px 6px; margin-bottom: 3px;
}

/* button/list composer modal */
.interactive-mode-tabs { display: flex; gap: 8px; margin-bottom: 14px; }
.interactive-mode-tabs .btn-sm.active { background: var(--wa-green); color: #fff; border-color: var(--wa-green); }
.int-list-row { display: flex; gap: 8px; margin-bottom: 6px; }
.int-list-row input { margin-top: 0; flex: 1; }


/* transient toast */
#toast-host { position: fixed; left: 50%; bottom: 32px; transform: translateX(-50%); z-index: 4000; display: flex; flex-direction: column; gap: 8px; align-items: center; }
.toast { background: #1b1c22; color: #fff; font-size: 12.5px; padding: 8px 16px; border-radius: 20px; box-shadow: 0 4px 16px rgba(0,0,0,.25); opacity: 1; transition: opacity .3s; }
.toast.leaving { opacity: 0; }

.contacts-summary { margin-top: 12px; font-size: 12.5px; color: var(--text-muted); }
.contacts-summary strong { color: var(--text); }
.checkbox-list { max-height: 320px; overflow-y: auto; border: 1px solid var(--card-border); border-radius: 8px; padding: 4px 8px; }
.checkbox-list-2col { max-height: 320px; }
.contact-picker-toolbar { display: flex; align-items: center; justify-content: flex-start; gap: 8px; margin: 12px 0 6px; flex-wrap: wrap; }
.contact-picker-toolbar button { min-width: 128px; height: 38px; text-align: center; flex: 0 0 auto; box-sizing: border-box; }

/* WhatsApp-style live preview */
.wa-preview-card { position: sticky; top: 20px; }
.wa-preview-bg {
  background: #e9ddc8; border-radius: 12px; padding: 18px 14px;
  background-image: radial-gradient(circle at 1px 1px, #ded1b5 1px, transparent 0);
  background-size: 16px 16px;
}
.wa-preview-bubble {
  background: #fff; border-radius: 8px; padding: 8px 8px 6px; max-width: 280px;
  box-shadow: 0 1px 2px rgba(0,0,0,.12); font-size: 13.5px; color: #111b21;
}
.wa-preview-img { width: 100%; border-radius: 6px; display: block; margin-bottom: 6px; max-height: 180px; object-fit: cover; }
/* Video header preview: show the whole frame (letterboxed) instead of cropping
   to a fixed landscape ratio, so portrait clips aren't zoomed. Must come after
   .wa-preview-img (equal specificity) to win the object-fit tie. Applied only
   to the <video> in whatsAppPreviewHtml - never to <img> or carousel cards. */
.wa-preview-video { object-fit: contain; background: #000; }
.wa-preview-img-placeholder {
  width: 100%; height: 120px; border-radius: 6px; margin-bottom: 6px; background: #f0ede4;
  display: flex; align-items: center; justify-content: center; color: var(--text-muted); font-size: 12.5px;
}
.wa-preview-header-text { font-weight: 700; margin-bottom: 4px; }
.wa-preview-body-text { white-space: pre-wrap; line-height: 1.4; }
.wa-preview-footer-text { color: #667781; font-size: 12px; margin-top: 4px; }
.wa-preview-meta { text-align: right; color: #667781; font-size: 10.5px; margin-top: 4px; }
.wa-check { color: #53bdeb; }
.wa-preview-buttons { background: #fff; border-radius: 8px; margin-top: 2px; max-width: 280px; box-shadow: 0 1px 2px rgba(0,0,0,.12); overflow: hidden; }
.wa-preview-button {
  padding: 9px 8px; text-align: center; color: #00a5f4; font-size: 13px; font-weight: 600;
  border-top: 1px solid #f0ede4;
}
.wa-preview-button:first-child { border-top: none; }
@media (max-width: 860px) { .wa-preview-card { position: static; } }

/* Carousel: horizontally scrollable strip of mini card-bubbles under the main body */
.wa-carousel-scroll {
  display: flex; gap: 10px; overflow-x: auto; margin-top: 8px; padding: 4px 2px 10px;
  scrollbar-width: thin; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
}
.wa-carousel-scroll::-webkit-scrollbar { height: 6px; }
.wa-carousel-scroll::-webkit-scrollbar-thumb { background: #c4b99a; border-radius: 4px; }
.wa-carousel-card {
  flex: 0 0 160px; width: 160px; background: #fff; border-radius: 10px; padding: 0 0 6px;
  box-shadow: 0 1px 3px rgba(0,0,0,.12); font-size: 12px; color: #111b21; overflow: hidden; scroll-snap-align: start;
}
.wa-carousel-card .wa-preview-img,
.wa-carousel-card .wa-preview-img-placeholder { max-height: 110px; height: 110px; width: 100%; object-fit: cover; margin-bottom: 4px; border-radius: 0; }
.wa-carousel-card-body { font-size: 12px; max-height: 72px; overflow: hidden; padding: 0 8px; }
.wa-carousel-card .wa-preview-buttons { max-width: 100%; margin-top: 4px; }
.wa-carousel-card .wa-preview-button { padding: 7px 6px; font-size: 12px; }

/* Carousel card editor (Create Template tab) */
.carousel-card-editor { border: 1px solid var(--card-border); box-shadow: none; padding: 14px 16px; }
.carousel-card-editor .card-head h2 { color: var(--text-muted); }

.eyebrow { font-size: 11px; font-weight: 700; color: var(--accent-dark); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 4px; }

.tag-pill { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 700; }

/* Collapsible card sections */
.collapse-head { cursor: default; }
.collapse-toggle {
  width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--card-border);
  background: #fff; color: var(--text-muted); display: flex; align-items: center; justify-content: center;
  cursor: pointer; flex-shrink: 0; padding: 0;
}
.collapse-toggle:hover { border-color: var(--accent); color: var(--text); }
.collapse-toggle .chevron { display: block; transition: transform .18s ease; flex-shrink: 0; }
.collapse-toggle.collapsed .chevron { transform: rotate(-90deg); }

/* Pagination */
.pagination-bar {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--card-border); font-size: 12.5px; color: var(--text-muted);
}
.page-size-select { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 12.5px; }
.page-size-select select { width: auto; margin: 0; padding: 5px 8px; font-size: 12.5px; }
.page-info { flex: 1; text-align: center; }
.page-controls { display: flex; align-items: center; gap: 6px; }
.page-btn {
  width: 26px; height: 26px; border-radius: 6px; border: 1px solid var(--card-border); background: #fff;
  color: var(--text); cursor: pointer; font-size: 13px; display: inline-flex; align-items: center; justify-content: center;
}
.page-btn:hover:not(:disabled) { border-color: var(--accent); }
.page-btn:disabled { opacity: .35; cursor: not-allowed; }
.page-of { padding: 0 4px; }

/* Modal */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(20,18,14,.45); display: flex;
  align-items: center; justify-content: center; z-index: 100; padding: 20px;
}
.modal-box { background: #fff; border-radius: 14px; width: 100%; max-width: 440px; box-shadow: 0 20px 50px rgba(0,0,0,.25); }
.modal-box-wide { max-width: 75vw; min-width: 700px; }
.modal-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--card-border); }
.modal-head h3 { margin: 0; font-size: 15px; }
.modal-close { background: none; border: none; font-size: 15px; color: var(--text-muted); cursor: pointer; }
.modal-close:hover { color: var(--text); }
.modal-body { padding: 20px; max-height: 80vh; overflow-y: auto; }
.modal-actions { display: flex; gap: 10px; margin-top: 16px; justify-content: flex-end; }

/* Template builder 2-column layout: form left, preview right */
.modal-box-wide .modal-body { overflow: hidden; padding: 0; }

/* ---------------------------------------------------------------------------
   Campaign detail modal (Campaigns -> History -> View).
   Everything is scoped to .campaign-detail because .progress-stats,
   .progress-bar and .table are shared with the Compose tab's live progress
   panel and every other table in the app.
   The wide-modal rule above zeroes .modal-body padding and hides overflow for
   the template builder's edge-to-edge grid; this modal is ordinary flow
   content, so it restores its own padding and its own scroll container.
   --------------------------------------------------------------------------- */
.campaign-detail { padding: 16px 20px 18px; max-height: 78vh; overflow-y: auto; }

/* Stat strip: compact cells joined into one connected row instead of six
   isolated boxes with wide gutters. */
.campaign-detail .progress-stats {
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 0; margin-bottom: 22px;
  border: 1px solid var(--card-border); border-radius: 10px; overflow: hidden;
  background: #fbfaf7;
}
.campaign-detail .progress-stats > div {
  border: none; border-right: 1px solid var(--card-border); border-radius: 0;
  padding: 10px 8px; gap: 3px; min-height: 0; background: transparent;
}
.campaign-detail .progress-stats > div:last-child { border-right: none; }
.campaign-detail .progress-stats b { font-size: 19px; }
.campaign-detail .progress-stats span { font-size: 10px; letter-spacing: .04em; }
@media (max-width: 860px) {
  /* Wrapping into rows needs the horizontal rules back so the strip still reads
     as a grid rather than a run-on block. */
  .campaign-detail .progress-stats > div { border-bottom: 1px solid var(--card-border); }
}

/* Send progress: a real indicator (percent of recipients processed), kept but
   made quiet - it was reading as a stray loading bar at full width. */
.campaign-detail .progress-bar { height: 3px; background: #ece9e1; margin-bottom: 18px; }
.campaign-detail .progress-bar-fill { background: #c6b7a2; }

.campaign-detail .progress-actions { margin-bottom: 16px; }

/* Results table: roomier rows and cell padding, matching the Live Chat list. */
.campaign-detail .table { margin-top: 0; }
.campaign-detail .table th { padding: 9px 14px; }
.campaign-detail .table td { padding: 12px 14px; }
.campaign-detail .table .badge { padding: 4px 10px; }
/* Detail is usually empty (it only carries a Meta error), so give the columns
   that always have content more room and stop the empty cell dominating. */
.campaign-detail #modal-progress-table th:nth-child(1),
.campaign-detail #modal-progress-table td:nth-child(1) { width: 26%; }
.campaign-detail #modal-progress-table th:nth-child(2),
.campaign-detail #modal-progress-table td:nth-child(2) { width: 20%; }
.campaign-detail #modal-progress-table th:nth-child(3),
.campaign-detail #modal-progress-table td:nth-child(3) { width: 16%; }
.campaign-detail #modal-progress-table th:nth-child(4),
.campaign-detail #modal-progress-table td:nth-child(4) { width: 38%; }
.campaign-detail #modal-progress-pagination:not(:empty) { margin-top: 12px; }
/* Balance the space above/below the header rule with the body's top padding.
   :has() scopes this to the campaign modal only - the template builder and
   every other modal keep the shared .modal-head padding. */
.modal-box-wide:has(.campaign-detail) .modal-head { padding: 14px 20px; }
.template-builder-grid {
  display: grid; grid-template-columns: 1fr 1fr; height: 75vh; max-height: 75vh;
}
.template-builder-form {
  padding: 20px; overflow-y: auto; border-right: 1px solid var(--card-border,#e8e4da);
}
.template-builder-preview {
  padding: 20px; overflow-y: auto; display: flex; flex-direction: column;
}
.template-builder-preview .wa-preview-card { position: static; flex: 1; }
@media (max-width: 860px) {
  .template-builder-grid { grid-template-columns: 1fr; height: auto; max-height: 80vh; }
  .template-builder-form { border-right: none; border-bottom: 1px solid var(--card-border,#e8e4da); max-height: 50vh; }
  .template-builder-preview { max-height: 40vh; }
}

/* ---------------------------------------------------------- Template cards */
.template-cards-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; margin-top: 18px;
}
.template-card {
  background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 14px; overflow: hidden;
  display: flex; flex-direction: column; transition: box-shadow .15s ease, border-color .15s ease;
}
.template-card-clickable { cursor: pointer; display: flex; flex-direction: column; }
.template-card-clickable:hover { background: #fbfaf6; }
.template-card:has(.template-card-clickable:hover) { border-color: var(--accent); box-shadow: 0 2px 10px rgba(0,0,0,.06); }
.template-card-thumb {
  height: 160px; overflow: hidden; background: #ece7d8; padding: 10px; position: relative; pointer-events: none;
}
.template-card-thumb .wa-preview { transform: scale(0.82); transform-origin: top left; width: 122%; }
.template-card-body { padding: 12px 14px 4px; }
.template-card-title { font-weight: 700; font-size: 14px; margin-bottom: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.template-card-sub { color: var(--text-muted); font-size: 12px; margin-bottom: 8px; text-transform: capitalize; }
.template-card-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.template-card-date { color: var(--text-muted); font-size: 11px; }
.template-card-rejection { color: var(--red-text); font-size: 11.5px; margin-top: 8px; line-height: 1.4; }
/* flex (not a fixed-column grid) so the row stays a single clean line whether
   it holds 2 buttons (DRAFT/SUBMITTING cards: retry/submitting + delete) or 3
   (use/edit/delete) - a fixed column count leaves a dangling empty cell on
   whichever count doesn't divide evenly. nowrap + flex:1 + min-width:0 keeps all
   three on one row at any card width; min-height keeps them tap-friendly. */
.template-card-actions { display: flex; gap: 6px; padding: 10px 12px 12px; margin-top: auto; }
.template-card-actions button {
  flex: 1; min-width: 0; justify-content: center; white-space: nowrap;
  padding: 5px 8px; font-size: 11px; min-height: 32px;
}

.checkbox-row {
  display: grid; grid-template-columns: 26px minmax(0, 1.3fr) minmax(0, 1fr) 32px;
  align-items: center; gap: 10px; padding: 8px 6px; font-size: 13px; border-bottom: 1px solid #f0ede4;
}
.checkbox-row:last-child { border-bottom: none; }
.checkbox-row-head {
  color: var(--text-muted); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  padding-top: 4px; padding-bottom: 8px; border-bottom: 1px solid var(--card-border); position: sticky; top: 0; background: #fff;
}
.cb-label-wrap { display: flex; align-items: center; justify-content: center; cursor: pointer; height: 100%; }
.cb-label-wrap input[type="checkbox"] { width: 15px; height: 15px; margin: 0; flex-shrink: 0; }
.cb-col-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.cb-col-phone { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-muted); font-family: var(--mono); font-size: 12.5px; }

.kebab-wrap { position: relative; }
.kebab-btn { font-weight: 700; line-height: 1; padding: 6px 11px; }
.kebab-btn-mini { background: none; border: none; cursor: pointer; font-size: 15px; color: var(--text-muted); padding: 2px 8px; border-radius: 6px; flex-shrink: 0; }
.kebab-btn-mini:hover { background: #eeece4; color: var(--text); }
.kebab-menu {
  position: absolute; right: 0; top: calc(100% + 4px); background: #fff;
  border: 1px solid var(--card-border); border-radius: 10px;
  box-shadow: 0 8px 20px rgba(20,20,20,.10); z-index: 30; min-width: 168px; padding: 5px;
}
.kebab-menu button {
  display: block; width: 100%; text-align: left; background: none; border: none;
  padding: 8px 10px; font-size: 12.5px; border-radius: 6px; cursor: pointer; color: var(--text);
}
.kebab-menu button:hover { background: #f5f3ee; }
.kebab-menu button.danger { color: var(--red-text); }

/* --- Template card states --- */
.template-card-inactive { opacity: 0.6; }
.template-card-inactive .template-card-thumb { filter: grayscale(0.4); }
.badge-inactive { background: #e0ddd5; color: #6b6555; font-size: 10px; padding: 2px 8px; border-radius: 6px; }
.badge-active { background: #d1fae5; color: #065f46; font-size: 10px; padding: 2px 8px; border-radius: 6px; }
.badge-DRAFT, .badge-draft { background: #fef3c7; color: #92400e; font-size: 10px; padding: 2px 8px; border-radius: 6px; }

/* --- URL + image/video header warning --- */
.form-msg.warning { background: #fef3c7; color: #92400e; border: 1px solid #f59e0b; border-radius: 8px; padding: 10px 14px; font-size: 12.5px; line-height: 1.5; margin-bottom: 10px; }
.form-msg.info { background: #ecfdf5; color: #065f46; border: 1px solid #34d399; border-radius: 8px; padding: 10px 14px; font-size: 12.5px; line-height: 1.5; margin-bottom: 10px; }

/* --- Modal actions row --- */
.modal-actions { display: flex; gap: 10px; margin-top: 16px; justify-content: flex-end; }

/* --- Live Chat: search/filter, conversation status, quick replies (Stage 3) --- */
.chat-list-col { display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--wa-divider); overflow: hidden; background: #fff; }
.chat-list-col .chat-list { flex: 1; min-height: 0; border-right: none; }
.chat-list-filters { flex-shrink: 0; padding: 6px 10px; background: #fff; display: flex; flex-direction: column; gap: 5px; }
/* Rounded search field with the magnifier sitting inside it - no emoji. */
.cl-search-wrap { position: relative; display: flex; align-items: center; }
.cl-search-ic {
  position: absolute; left: 12px; display: inline-flex; align-items: center;
  color: #8696a0; pointer-events: none;
}
.cl-search-ic .ic { width: 18px; height: 18px; display: block; }
.cl-search {
  width: 100%; font-size: 13.5px; padding: 8px 12px 8px 38px; border: none;
  border-radius: 8px; background: var(--wa-panel); color: var(--wa-text); margin: 0;
}
.cl-search:focus { outline: none; background: #fff; box-shadow: 0 0 0 1px #d1d7db inset; }
.cl-search::placeholder { color: #8696a0; }
.cl-select {
  width: 100%; font-size: 12.5px; padding: 5px 8px; border: 1px solid var(--wa-divider);
  border-radius: 14px; background: #fff; color: var(--wa-icon); margin: 0;
}
.cl-select:focus { outline: none; border-color: #c5ccd0; }
.cl-filter-row { display: flex; gap: 6px; }
.cl-filter-row .cl-select { flex: 1; min-width: 0; }

.conv-status-chip {
  display: inline-block; background: #e7f3ef; color: #027a63; font-size: 10.5px;
  font-weight: 600; padding: 1px 7px; border-radius: 10px; vertical-align: middle;
}
.chat-list-item.resolved .chat-list-name { color: var(--wa-muted); }

.qr-popover {
  position: absolute; bottom: calc(100% + 6px); left: 8px; z-index: 20;
  width: 320px; max-height: 300px; overflow-y: auto; padding: 8px;
  background: #fff; border: 1px solid var(--card-border); border-radius: 12px;
  box-shadow: 0 6px 24px rgba(11,20,26,.22);
}
/* Belt-and-braces: keep [hidden] authoritative if a display rule is ever
   added here too (see the .emoji-popover note above). */
.qr-popover[hidden] { display: none; }
#qr-filter { width: 100%; font-size: 12.5px; padding: 6px 8px; border: 1px solid var(--card-border); border-radius: 8px; margin-bottom: 6px; }
.qr-list { display: flex; flex-direction: column; gap: 2px; }
.qr-item { text-align: left; background: none; border: none; padding: 7px 8px; border-radius: 8px; cursor: pointer; display: flex; flex-direction: column; gap: 2px; width: 100%; }
.qr-item:hover { background: #f0ede4; }
.qr-item-title { font-weight: 600; font-size: 12.5px; color: var(--text); }
.qr-item-body { font-size: 11.5px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qr-cell-body { max-width: 380px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-muted); font-size: 12px; }

/* Automation (Stage 2) - Flows/Activity tabs. Reuses .card, .pill-tabs,
   .table, .badge from elsewhere rather than inventing a parallel set. */
/* Any wide table scrolls INSIDE this wrapper, so a table that outgrows the
   viewport never widens the page itself. */
.table-wrap { width: 100%; max-width: 100%; overflow-x: auto; }

/* The Flows list is a .table like Contacts and Campaign history, so the three
   list views in the app read the same way. Numeric columns are right-aligned
   and tabular so Steps/In Progress/Completed line up down the column. */
.automation-table { table-layout: auto; }
.automation-table .col-num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; width: 1%; }
.automation-table .col-actions { text-align: right; white-space: nowrap; width: 1%; }
.automation-table td { vertical-align: top; }
.automation-table .badge { white-space: nowrap; }
/* Tighter than the shared .table so all six columns plus four action buttons
   fit at 1280px without the row wrapping - per the brief, trim padding before
   ever letting the buttons wrap. */
.automation-table th, .automation-table td { padding-left: 8px; padding-right: 8px; }
.automation-table th { font-size: 10.5px; }
.automation-table td { font-size: 12.5px; }

/* The four row actions sit on ONE line, always. flex-wrap:nowrap is the whole
   point: they used to wrap onto a second line inside the cell. */
.flow-actions {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  align-items: center;
  justify-content: flex-end;
}
.flow-actions .btn-sm {
  flex: 0 0 auto;      /* never shrink to illegibility */
  white-space: nowrap;
  padding: 4px 9px;
  font-size: 11.5px;
}

/* The flow name is the primary way into the editor, so it reads as a link
   rather than a button - but stays a real <button> for keyboard/screen-reader
   semantics, since it performs an action rather than navigating. */
.flow-name-btn {
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; font-weight: 600; color: var(--accent, #1e7b34);
  cursor: pointer; text-align: left;
}
.flow-name-btn:hover { text-decoration: underline; }
.flow-name-btn:focus-visible { outline: 2px solid var(--accent, #1e7b34); outline-offset: 2px; border-radius: 2px; }
.flow-lastfired { margin-top: 3px; font-size: 11px; }

/* Multi-step editor: each step is a bordered block so the boundary between
   one step's fields and the next is unmistakable in a long form. */
.flow-step {
  border: 1px solid var(--card-border);
  border-radius: 8px;
  padding: 10px 12px;
  margin-top: 10px;
  background: #fbfaf6;
}
.flow-step-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.flow-choice { display: flex; gap: 6px; align-items: center; margin-top: 6px; }
.flow-choice .form-input { margin: 0; }
.flow-choice .step-choice-title { flex: 1 1 40%; min-width: 0; }
.flow-choice .step-choice-to { flex: 1 1 45%; min-width: 0; }

/* --- The automation builder, as a full page --------------------------------
   Was a modal; now a route (#/automation/<id>). The page fills the viewport
   the same way Live Chat does - see the .content:has(.chat-shell) rules above,
   which this deliberately mirrors rather than inventing a second mechanism. */
.content:has(.ab-shell) { display: flex; flex-direction: column; overflow: hidden; }
.content:has(.ab-shell) > #page-root { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.ab-shell { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }

.ab-topbar { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; flex: 0 0 auto; }
.ab-topbar-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.ab-name {
  font-size: 19px; font-weight: 700; color: var(--text);
  border: 1px solid transparent; border-radius: 8px;
  padding: 5px 9px; background: transparent; min-width: 220px; max-width: 420px; flex: 0 1 auto;
}
.ab-name:hover:not([readonly]) { border-color: var(--card-border); background: #fff; }
.ab-name:focus { outline: none; border-color: var(--accent); background: #fff; }
.ab-tabs { flex: 0 0 auto; margin-bottom: 14px; }

.ab-trigger {
  flex: 0 0 auto; display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 10px 14px; margin-bottom: 12px;
  border: 1px solid var(--card-border); border-radius: 10px; background: #fbfaf6;
}
.ab-trigger-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-muted); margin: 0;
}
.ab-trigger .form-input { margin: 0; }
.ab-trigger-select { flex: 0 0 auto; width: auto; min-width: 170px; }
/* display:contents so the keyword input and the match dropdown are direct
   participants in the trigger row's flex line. As a nested flex container it
   was its own line box, which is what pushed "Contains / Exact match" onto a
   second row at ordinary desktop widths. */
.ab-trigger-kw { display: contents; }
/* An author display rule again beats the UA [hidden] rule - so hiding the
   keyword fields for a non-keyword trigger needs this to actually work. */
.ab-trigger-kw[hidden] { display: none; }
.ab-trigger #ab-keywords { flex: 1 1 220px; min-width: 160px; }
.ab-trigger #ab-match { flex: 0 0 auto; width: auto; min-width: 128px; }
.ab-trigger-help { flex: 1 1 100%; margin: 0; font-size: 12px; }
.ab-trigger-help.warn { color: #a6631a; font-weight: 600; }

/* Flow tab: palette beside the canvas, both filling the remaining height. */
.ab-body { display: flex; flex: 1 1 auto; min-height: 0; border: 1px solid var(--card-border); border-radius: 10px; overflow: hidden; background: #fff; }
/* Contacts tab: ordinary scrolling content, not a canvas. */
.ab-body-plain { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

.fc-palette {
  width: 190px; flex: 0 0 auto; padding: 14px;
  border-right: 1px solid var(--card-border); background: #fbfaf6;
  overflow-y: auto;
}
.fc-palette-label {
  margin: 0 0 8px; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-muted);
}
.fc-palette-btn {
  display: block; width: 100%; text-align: left; background: #fff;
  border: 1px solid var(--card-border); border-radius: 8px;
  padding: 7px 10px; font-size: 12.5px; font-weight: 600; color: inherit;
  cursor: pointer; margin-bottom: 6px;
}
.fc-palette-btn:hover { border-color: var(--accent); }
.fc-hint { margin-top: 12px; font-size: 11px; line-height: 1.5; }

.fc-canvas-wrap { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

/* The viewport CLIPS - it never scrolls. Navigating a large flow is done by
   dragging the canvas and using the zoom controls, so the graph is never
   bracketed by a horizontal and a vertical native scrollbar. */
.fc-viewport {
  position: relative; flex: 1 1 auto; min-height: 0; min-width: 0;
  overflow: hidden; background: #f7f6f1; cursor: grab;
}
.fc-viewport.fc-panning { cursor: grabbing; }
.fc-canvas {
  position: absolute; top: 0; left: 0;
  /* Fixed, not min-, size: absolutely-positioned children never grow a
     relatively-positioned parent, and an <svg> clips at its own box, so a
     min-size would cut connectors off once a node is dragged past it. */
  width: 2600px; height: 1600px;
  transform-origin: 0 0;
}
.fc-canvas.fc-connecting { cursor: crosshair; }
/* Lives in the viewport, not the transformed canvas, so pan/zoom cannot drag
   it around or slide it underneath a node. */
.fc-empty {
  position: absolute; top: 16px; left: 16px; right: 200px; max-width: 460px;
  font-size: 13px; color: var(--text-muted); line-height: 1.6; z-index: 2;
}
/* Belt-and-braces for the author-display vs UA-[hidden] conflict that already
   bit .emoji-popover, .reaction-bar, .chat-search-bar and .qr-popover. The
   builder no longer renders the inactive tab at all, but if either pane ever
   grows a display rule again, [hidden] must still win. */
.ab-body[hidden], .ab-body-plain[hidden], .ab-trigger[hidden] { display: none; }
/* Something the author needs to fix before Save will succeed. */
.fc-empty-warn {
  color: #8a5514; background: #fdf3e2; border: 1px solid #f0d9b0;
  border-radius: 10px; padding: 12px 14px;
}

/* Which step the trigger runs first - derived from the graph, not ticked on a
   step, so it cannot be set on two steps or on none. */
.fc-start-badge {
  position: absolute; top: -10px; left: 10px; z-index: 1;
  background: var(--accent); color: #1b1c22;
  font-size: 9.5px; font-weight: 800; letter-spacing: .08em;
  padding: 2px 7px; border-radius: 999px;
  box-shadow: 0 1px 3px rgba(0,0,0,.15);
}

/* A step nothing leads to. Shown ON the step rather than as a canvas-wide
   banner, so adding a step from the palette no longer raises an alarm next to
   the START badge before you have had a chance to connect it. */
.fc-node.fc-orphan { border-style: dashed; border-color: #b48a3a; }
.fc-orphan-badge {
  position: absolute; top: -10px; right: 10px; z-index: 1;
  background: #f7e6c4; color: #7a5312; border: 1px solid #e0c48a;
  font-size: 9px; font-weight: 800; letter-spacing: .06em;
  padding: 2px 7px; border-radius: 999px; white-space: nowrap;
}

/* An active automation that another active one always beats to the same
   trigger. It never runs, which is otherwise completely invisible. */
.ab-clash {
  flex: 0 0 auto; margin: 0 0 12px; padding: 10px 14px;
  border: 1px solid #e8b4aa; background: #f8e6e2; border-radius: 10px;
  color: #8c3323; font-size: 12.5px; line-height: 1.55;
}
.flow-shadowed {
  margin-top: 4px; font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: #a03a2b; white-space: nowrap; cursor: help;
}

/* Enrolled contacts */
.ab-runs-table .ab-run-row { cursor: pointer; }
.ab-runs-table .ab-run-row:hover { background: #fbfaf6; }
.ab-runs-table .ab-run-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ab-runs-table .ab-run-phone { font-variant-numeric: tabular-nums; font-weight: 600; }
.ab-run-live {
  margin-left: 6px; font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: #1e7b34;
}

/* Zoom controls float over the top-right corner of the canvas. */
.fc-zoom {
  position: absolute; top: 10px; right: 12px; z-index: 2;
  display: flex; align-items: center; gap: 6px; font-size: 12px;
  background: #fff; border: 1px solid var(--card-border); border-radius: 8px;
  padding: 4px 6px; box-shadow: 0 1px 4px rgba(0,0,0,.06);
}
.fc-zoom button {
  border: 1px solid var(--card-border); background: #fff; border-radius: 6px;
  width: 26px; height: 26px; cursor: pointer; font-size: 14px; line-height: 1;
}
.fc-zoom button:hover { border-color: var(--accent); }
.fc-zoom #fc-zoom-reset { width: auto; padding: 0 8px; font-size: 11px; }
.fc-zoom span { min-width: 40px; text-align: center; font-variant-numeric: tabular-nums; }
#fc-edges { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }

.fc-node {
  position: absolute; width: 210px; background: #fff;
  border: 1.5px solid var(--card-border); border-radius: 8px;
  box-shadow: 0 1px 4px rgba(0,0,0,.06); cursor: grab; user-select: none;
}
.fc-node:active { cursor: grabbing; }
.fc-node.fc-entry { border-color: var(--accent); }
.fc-node.fc-send_buttons, .fc-node.fc-send_list, .fc-node.fc-wait_for_reply { border-color: #2f5d88; }
.fc-node.fc-condition { border-color: #2f6b45; }
.fc-node.fc-handoff, .fc-node.fc-end { border-color: #b4432f; }
.fc-node-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 10px; border-bottom: 1px solid var(--card-border);
}
.fc-node-type {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-muted);
}
.fc-node-del { border: 0; background: none; cursor: pointer; color: var(--text-muted); font-size: 12px; line-height: 1; padding: 2px 4px; }
.fc-node-del:hover { color: #b4432f; }
.fc-node-body { padding: 8px 10px; font-size: 12px; min-height: 20px; word-break: break-word; }

.fc-port {
  position: absolute; width: 12px; height: 12px; border-radius: 50%;
  background: #fff; border: 2px solid var(--text-muted); cursor: crosshair;
}
.fc-port.fc-in { left: -7px; top: 20px; }
.fc-port.fc-out { right: -7px; }
.fc-port.fc-yes { border-color: #2f6b45; }
.fc-port.fc-no { border-color: #b4432f; }
.fc-port.fc-choice { border-color: #2f5d88; }
.fc-port-label {
  position: absolute; right: -8px; transform: translateX(100%);
  font-size: 10px; font-weight: 600; color: var(--text-muted); white-space: nowrap;
}
/* --- Step config modal ------------------------------------------------------
   Sized to sit comfortably over the builder canvas rather than the narrow
   440px default. max-width + a viewport fallback, so it never overflows a
   laptop screen or a narrow window. */
.modal-box-config { max-width: min(960px, 94vw); }
.modal-box-config .modal-body { padding: 22px 26px 24px; max-height: 78vh; overflow-y: auto; }

/* Field groups get real separation - these forms used to read as one stack.
   One rhythm throughout: 22px between groups, 6px label-to-control, 6px
   control-to-help, so the modal reads as a single form. */
.ncfg-group { margin-bottom: 22px; }
.ncfg-group:last-of-type { margin-bottom: 0; }
.ncfg .form-label { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.ncfg .form-input { margin: 0; }
.ncfg-help { margin: 6px 0 0; font-size: 12px; line-height: 1.5; color: var(--text-muted); }
.ncfg-textarea { min-height: 150px; resize: vertical; line-height: 1.55; }

/* Inputs: a little more breathing room inside. Focus is deliberately NOT
   restyled here - these fields fall through to the app-wide
   `input:focus { outline: 2px solid var(--accent) }` so they behave exactly
   like every other form input in the product. An earlier version gave them an
   accent border plus a glow; that was a second focus convention for one modal,
   and it is gone. Nothing here may reintroduce `outline: none` - keyboard
   users need to see where they are. */
.ncfg .form-input {
  border-radius: 9px;
  padding: 10px 12px;
  background: #fff;
  transition: border-color .12s ease;
}
.ncfg .form-input:hover:not(:focus) { border-color: #ccc4b4; }
.ncfg select.form-input { padding-right: 30px; }

/* Live character counter - deliberately secondary to the field's content. */
.ncfg-count {
  margin-left: auto; font-size: 10.5px; font-weight: 600;
  color: var(--text-muted); opacity: .75; font-variant-numeric: tabular-nums;
  text-transform: none; letter-spacing: 0;
}
.ncfg-count.is-near, .ncfg-count.is-full { opacity: 1; }
.ncfg-count.is-near { color: #a6631a; }
.ncfg-count.is-full { color: #b4432f; }

/* The choices block reads as one unit rather than loose rows. */
.ncfg-choices {
  border: 1px solid var(--card-border); border-radius: 10px;
  background: #fbfaf6; padding: 12px; display: flex; flex-direction: column; gap: 10px;
}
.ncfg-choices:empty { display: none; }
.ncfg-choice { display: flex; align-items: flex-start; gap: 10px; }
.ncfg-choice-n {
  flex: 0 0 auto; width: 22px; height: 22px; margin-top: 7px;
  border-radius: 50%; background: #fff; border: 1px solid var(--card-border);
  font-size: 11px; font-weight: 700; color: var(--text-muted);
  display: flex; align-items: center; justify-content: center;
}
.ncfg-choice-field { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ncfg-choice-meta { display: flex; align-items: baseline; gap: 10px; }
.ncfg-choice-meta .ncfg-count { margin-left: auto; }
.ncfg-choice-warn { font-size: 11px; font-weight: 600; color: #a6631a; }
.ncfg-choice .btn-sm { flex: 0 0 auto; margin-top: 4px; }
/* Kept clearly off the last choice row. */
.ncfg-choice-add { display: flex; align-items: center; gap: 12px; margin-top: 12px; flex-wrap: wrap; }
.ncfg-choice-add .hint { font-size: 12px; }

/* Send template: picker, variable mapping and the reused preview. */
.ncfg-tpl-preview {
  border: 1px solid var(--card-border); border-radius: 10px;
  background: #fbfaf6; padding: 12px; max-height: 320px; overflow-y: auto;
}
.ncfg-tpl-preview .tpl-preview,
.ncfg-tpl-preview .wa-preview { margin: 0; }
.ncfg-param { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.ncfg-param:last-child { margin-bottom: 0; }
.ncfg-param-n {
  flex: 0 0 auto; min-width: 42px; font-family: var(--mono); font-size: 11.5px;
  font-weight: 700; color: var(--text-muted);
}
.ncfg-param .fc-cfg-param-src { flex: 0 0 auto; width: auto; min-width: 150px; }
.ncfg-param .fc-cfg-param-val { flex: 1 1 auto; min-width: 0; }

.ncfg-terminal {
  margin: 0; padding: 12px 14px; font-size: 13px; line-height: 1.55;
  border: 1px solid var(--card-border); border-radius: 10px; background: #fbfaf6;
  color: var(--text-muted);
}

/* "This is the first step" reads as a decision, not a stray checkbox. */
/* Says where the start is; it is not settable here any more. */
.ncfg-entry { padding-top: 18px; border-top: 1px solid var(--card-border); }
.ncfg-entry-is {
  margin: 0; font-size: 13px; line-height: 1.5;
  padding: 10px 12px; border-radius: 8px;
  background: #fdf3e2; border: 1px solid #f0d9b0; color: #8a5514;
}

@media (max-width: 720px) {
  .modal-box-config .modal-body { padding: 16px; }
  .ncfg-choice { flex-wrap: wrap; }
  .ncfg-choice-field { flex-basis: 100%; }
}

.badge.status-active { background: #e3f3e6; color: #1e7b34; }
.badge.status-draft { background: #eee; color: #666; }
.badge.status-paused { background: #fdefd9; color: #a6631a; }
.badge.status-running, .badge.status-waiting { background: #e3f3e6; color: #1e7b34; }
.badge.status-completed { background: #eee; color: #555; }
.badge.status-failed { background: #fbe4e4; color: #b3261e; }
.badge.status-cancelled, .badge.status-handed_off { background: #fdefd9; color: #a6631a; }
.automation-takeover-btn { border-color: var(--accent, #d9822b); color: var(--accent, #d9822b); }

/* --- Trigger qualifiers ("only when…") ----------------------------------- */
/* Sits directly under the trigger row and reuses its shell, so a qualified
   trigger reads as one setting rather than two unrelated blocks. */
.ab-qualifier { align-items: flex-start; }
.ab-qual-body { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.ab-qual-toggle { display: flex; align-items: center; gap: 8px; font-size: 13px; flex-wrap: wrap; }
.ab-qual-num { width: 72px; padding: 6px 8px; }
.ab-qual-hours { display: flex; flex-direction: column; gap: 8px; padding-left: 24px; }
.ab-qual-days { display: flex; gap: 10px; flex-wrap: wrap; }
.ab-qual-day { display: flex; align-items: center; gap: 4px; font-size: 12.5px; text-transform: capitalize; }
.ab-qual-range { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ab-qual-range .form-input { width: auto; }
.ab-qual-tz { min-width: 170px; }
/* Author-supplied display rule, so it beats the UA [hidden] { display: none }
   the same way .ab-body and .ab-trigger-kw already have to. */
.ab-qualifier[hidden], .ab-qual-hours[hidden] { display: none; }

/* --- Number-health banner ------------------------------------------------ */
/* Operator alert about YOUR WhatsApp number (quality/restriction), distinct
   from anything customer-facing. Sits above the page content and survives a
   route change, so a paused number cannot be navigated away from. */
.health-banner {
  margin: 0 0 14px; padding: 11px 14px; border-radius: 9px;
  font-size: 13px; line-height: 1.5; border: 1px solid transparent;
}
.health-banner .hint { display: inline-block; margin-left: 10px; font-size: 12px; opacity: 0.8; }
.health-banner-critical { background: #fdecea; border-color: #f3b7b0; color: #7d241a; }
.health-banner-warn { background: #fef7e6; border-color: #f0d9a3; color: #7a5a12; }
/* Author-supplied display rule, so it beats the UA [hidden] { display: none }
   the same way .ab-body and .ab-qualifier already have to. */
.health-banner[hidden] { display: none; }
