* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

:root {
  --bg: #FAF8F5;
  --card: #ffffff;
  --border: #EBE6DE;
  --text: #2D2645;
  --text-secondary: #6B6478;
  --text-muted: #8B82A0;
  --accent: #9D8ED8;
  --accent-hover: #8B7BC6;
  --danger: #dc2626;
  --success: #16a34a;
  --warning: #d97706;
  --radius: 10px;
}

html.dark {
  color-scheme: dark;
  --bg: #111111;
  --card: #1A1A1A;
  --border: #2A2A2A;
  --text: #E8E8E8;
  --text-secondary: #B0B0B0;
  --text-muted: #808080;
  --accent: #9D8ED8;
  --accent-hover: #B0A3E0;
  --danger: #ef4444;
  --success: #22c55e;
  --warning: #f59e0b;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
  /* On iOS, 100vh is the LARGE viewport, the height with the URL bar hidden, so
     it makes the body taller than what you can actually see and leaves a strip
     of scroll slack on a page whose content already fits. Nudge that and the top
     bar slides up under the browser chrome and reads as clipped. dvh is the
     visible height. The vh line stays as the fallback for anything older. */
  min-height: 100vh;
  min-height: 100dvh;
}

/* Login */
.login-screen {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.login-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 40px 32px;
  width: 100%;
  max-width: 360px;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
  text-align: center;
}

.login-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 16px;
  color: var(--accent);
}

.login-card h1 {
  font-size: 20px;
  font-weight: 600;
  margin-bottom: 4px;
}

.login-subtitle {
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 24px;
}

.login-card form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.login-card input {
  width: 100%;
  padding: 10px 14px;
  border: 2px solid var(--border);
  border-radius: 8px;
  font-size: 14px;
  color: var(--text);
  background: var(--card);
  outline: none;
  transition: border-color 0.2s;
}

.login-card input:focus {
  border-color: var(--accent);
}

.login-card button[type="submit"] {
  padding: 10px;
  border-radius: 8px;
  background: var(--accent);
  color: white;
  font-weight: 600;
  font-size: 14px;
  border: none;
  cursor: pointer;
  transition: background 0.2s;
}

.login-card button[type="submit"]:hover {
  background: var(--accent-hover);
}

.login-card button[type="submit"]:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.error-text {
  color: var(--danger);
  font-size: 13px;
  text-align: left;
}

/* Top bar */
.top-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 24px;
  background: var(--card);
  border-bottom: 1px solid var(--border);
}

.top-bar h1 {
  font-size: 18px;
  font-weight: 700;
}

.top-bar-right {
  display: flex;
  align-items: center;
  gap: 10px;
}

.theme-toggle {
  padding: 5px 8px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text-secondary);
  font-size: 12px;
  cursor: pointer;
}

.btn-logout {
  padding: 6px 14px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text-secondary);
  font-size: 13px;
  cursor: pointer;
  transition: all 0.2s;
}

.btn-logout:hover {
  background: var(--bg);
  color: var(--text);
}

/* Tab bar */
.tab-bar {
  display: flex;
  justify-content: center;
  gap: 0;
  padding: 0 24px;
  background: var(--card);
  border-bottom: 1px solid var(--border);
}

.tab {
  padding: 12px 20px;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-muted);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  transition: all 0.2s;
}

.tab:hover {
  color: var(--text);
}

.tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* Content */
.content {
  padding: 24px;
  max-width: 1200px;
  margin: 0 auto;
}

/* The directory table carries contact and login columns, so it gets more room. */
.content:has(#tab-directory.active) {
  max-width: 1600px;
}

.tab-content {
  display: none;
}

.tab-content.active {
  display: block;
}

/* Stats grid */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 16px;
  margin-bottom: 32px;
}

.stat-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
}

.stat-label {
  font-size: 12px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 6px;
}

.stat-value {
  font-size: 28px;
  font-weight: 700;
  color: var(--text);
}

/* Section headers */
.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}

.section-header h2 {
  font-size: 16px;
  font-weight: 600;
}

.header-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

/* Novie status multi-select checkboxes (replaces the old single-select dropdown) */
.novie-status-filters {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 12px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
}
.novie-status-filters label {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
}
.novie-status-filters input[type="checkbox"] {
  cursor: pointer;
  margin: 0;
}
/* Divider between funnel groups in the filter row. */
.novie-filter-divider {
  width: 1px;
  align-self: stretch;
  background: var(--border);
  margin: 2px 0;
}

/* Tables */
.table-wrap {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow-x: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

th {
  text-align: left;
  padding: 12px 16px;
  background: var(--bg);
  color: var(--text-muted);
  font-weight: 500;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  border-bottom: 1px solid var(--border);
}

/* A sortable header: looks like the other headers, underlined on hover. */
.th-sort {
  all: unset;
  cursor: pointer;
  white-space: nowrap;
  font: inherit;
  color: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
}
.th-sort:hover,
.th-sort:focus-visible {
  color: var(--text);
  text-decoration: underline;
}

td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
}

tr:last-child td {
  border-bottom: none;
}

tr:hover td {
  background: var(--bg);
}

/* Buttons */
.btn-secondary {
  padding: 6px 14px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text-secondary);
  font-size: 13px;
  cursor: pointer;
  transition: all 0.2s;
}

.btn-secondary:hover {
  background: var(--bg);
}

/* Purple "Have Novie join" button: same size/shape as .btn-secondary. */
.btn-novie {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.btn-novie:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

/* Inline call-button states (replace the old popups). */
.btn-secondary.is-connecting {
  background: #fef3c7; border-color: #fcd34d; color: #92400e; cursor: default;
}
/* Stays green for the whole call and carries a running timer. tabular-nums keeps
   the button from twitching wider as the digits change. The disabled overrides
   are for the live-call button, which is green but not clickable. */
.btn-secondary.is-connected {
  background: #dcfce7; border-color: #86efac; color: #166534; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.btn-secondary.is-connected:hover { background: #dcfce7; }
.btn-secondary.is-connected[disabled] {
  opacity: 1; cursor: default; background: #dcfce7; color: #166534;
}
.btn-secondary.is-failed {
  background: #fee2e2; border-color: #fca5a5; color: #991b1b;
}

.btn-danger {
  padding: 8px 16px;
  border-radius: 6px;
  border: none;
  background: var(--danger);
  color: white;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.2s;
}

.btn-danger:hover {
  background: #b91c1c;
}

.btn-approve {
  padding: 5px 12px;
  border-radius: 6px;
  border: none;
  background: #dcfce7;
  color: var(--success);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.2s;
}

.btn-approve:hover {
  background: #bbf7d0;
}

.btn-deny {
  padding: 5px 12px;
  border-radius: 6px;
  border: none;
  background: #fee2e2;
  color: var(--danger);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.2s;
}

.btn-deny:hover {
  background: #fecaca;
}

/* Select */
select {
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid var(--border);
  font-size: 13px;
  color: var(--text);
  background: var(--card);
  cursor: pointer;
}

/* Identity review cards */
.review-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 12px;
}

.review-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-bottom: 16px;
}

.review-field-label {
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.3px;
  margin-bottom: 4px;
}

.review-field-value {
  font-size: 14px;
  font-weight: 500;
}

.review-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.review-meta {
  font-size: 12px;
  color: var(--text-muted);
}

.review-buttons {
  display: flex;
  gap: 8px;
}

/* Status badges */
.badge {
  display: inline-block;
  padding: 3px 8px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 500;
  text-transform: capitalize;
}

.badge-running { background: #dbeafe; color: #1d4ed8; }
/* Who a workflow step emails (Workflow Runs page). */
.badge-aud { text-transform: none; }
.badge-aud-prospect { background: #dff3f5; color: #1f6f78; }
.badge-aud-practitioner { background: #ece8f8; color: #5b4aa8; }
.badge-completed { background: #dcfce7; color: #166534; }
.badge-failed { background: #fee2e2; color: #991b1b; }
.badge-cancelled { background: #f3f4f6; color: #6b7280; }
.badge-sleeping { background: #fef3c7; color: #92400e; }
.badge-pending { background: #fef3c7; color: #92400e; }
.badge-approved { background: #dcfce7; color: #166534; }
.badge-denied { background: #fee2e2; color: #991b1b; }
.badge-no_site { background: #fee2e2; color: #991b1b; }
.badge-not_a_fit { background: #f3f4f6; color: #6b7280; }
/* Novie prospect funnel */
.badge-called { background: #dbeafe; color: #1d4ed8; }
.badge-interested { background: #dcfce7; color: #166534; }
.badge-not_interested { background: #f3f4f6; color: #6b7280; }
.badge-left_message { background: #fef3c7; color: #92400e; }
.badge-not_called { background: #f1f5f9; color: #475569; }
.badge-call_back { background: #e0e7ff; color: #3730a3; }
.badge-viewed { background: #e0e7ff; color: #4338ca; }
.badge-converted { background: #ccfbf1; color: #0f766e; }

html.dark .badge-running { background: #1e3a5f; color: #93c5fd; }
html.dark .badge-aud-prospect { background: #12383c; color: #8fd9e2; }
html.dark .badge-aud-practitioner { background: #2b2547; color: #c4b8f0; }
html.dark .badge-completed { background: #14532d; color: #86efac; }
html.dark .badge-failed { background: #450a0a; color: #fca5a5; }
html.dark .badge-cancelled { background: #2a2a2a; color: #9ca3af; }
html.dark .badge-sleeping { background: #451a03; color: #fcd34d; }
html.dark .badge-pending { background: #451a03; color: #fcd34d; }
html.dark .badge-approved { background: #14532d; color: #86efac; }
html.dark .badge-denied { background: #450a0a; color: #fca5a5; }
html.dark .badge-no_site { background: #450a0a; color: #fca5a5; }
html.dark .badge-not_a_fit { background: #2a2a2a; color: #9ca3af; }
html.dark .badge-called { background: #1e3a5f; color: #93c5fd; }
html.dark .badge-interested { background: #14532d; color: #86efac; }
html.dark .badge-not_interested { background: #2a2a2a; color: #9ca3af; }
html.dark .badge-left_message { background: #451a03; color: #fcd34d; }
html.dark .badge-not_called { background: #1e293b; color: #cbd5e1; }
html.dark .badge-call_back { background: #1e1b4b; color: #a5b4fc; }
html.dark .badge-viewed { background: #312e81; color: #a5b4fc; }
html.dark .badge-converted { background: #134e4a; color: #5eead4; }
html.dark .btn-approve { background: #14532d; color: #86efac; }
html.dark .btn-approve:hover { background: #166534; }
html.dark .btn-deny { background: #450a0a; color: #fca5a5; }
html.dark .btn-deny:hover { background: #991b1b; }
html.dark .btn-danger { background: #b91c1c; }
html.dark .btn-danger:hover { background: #991b1b; }
html.dark .modal-backdrop { background: rgba(0, 0, 0, 0.6); }

/* Empty state */
.empty-state {
  text-align: center;
  padding: 48px 20px;
  color: var(--text-muted);
  font-size: 14px;
}

/* Texting tab */
.texting-note {
  margin: 0 0 16px;
  max-width: 820px;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.6;
}
.texting-sub {
  color: var(--text-muted);
  font-size: 12px;
}

/* Deletions tab */
.deletions-note {
  margin: 0 0 16px;
  max-width: 820px;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.6;
}
.deletions-scope-note {
  display: block;
  margin-top: 4px;
  max-width: 340px;
  color: var(--text-muted);
  font-size: 12px;
  line-height: 1.4;
}
/* The 30 day deadline, so an open request that is running out of time is the
   thing the eye lands on first. Only open requests are ever marked. */
.deletions-due-soon {
  color: var(--warning);
  font-weight: 500;
  white-space: nowrap;
}
.deletions-due-late {
  color: var(--danger);
  font-weight: 600;
  white-space: nowrap;
}

/* Modal */
.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
}

.modal-card {
  position: relative;
  background: var(--card);
  border-radius: 12px;
  padding: 24px;
  width: 100%;
  max-width: 400px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
}

.modal-card h3 {
  font-size: 16px;
  margin-bottom: 12px;
}

.modal-card textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 13px;
  resize: none;
  margin-bottom: 16px;
  font-family: inherit;
  outline: none;
}

.modal-card textarea:focus {
  border-color: var(--accent);
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* Loading spinner */
.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* Chat Inbox */
.chat-inbox-layout {
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  height: calc(100vh - 220px);
  min-height: 400px;
  overflow: hidden;
}

.chat-session-list {
  border-right: 1px solid var(--border);
  overflow-y: auto;
}

.chat-session-item {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.15s;
}

.chat-session-item:hover {
  background: var(--bg);
}

.chat-session-item.active {
  background: var(--bg);
  border-left: 3px solid var(--accent);
}

.chat-session-item .chat-session-preview {
  font-size: 13px;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 4px;
}

.chat-session-item .chat-session-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 4px;
}

.chat-session-item .chat-session-source {
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
}

/* Only ever the shared-front-desk warning. The number and the city both moved
   to the conversation header, so most rows do not draw this line at all. */
.chat-session-item .chat-session-sub {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
}

.chat-session-status {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 4px;
}

.chat-session-status.active { background: var(--success); }
.chat-session-status.ended { background: var(--text-muted); }

.chat-conversation {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.chat-conv-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--text-muted);
  font-size: 14px;
}

.chat-conv-header {
  padding: 14px 20px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  color: var(--text-secondary);
  background: var(--bg);
}

.chat-conv-header strong {
  color: var(--text);
  font-size: 14px;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.chat-msg {
  max-width: 75%;
  padding: 10px 14px;
  border-radius: 12px;
  font-size: 13px;
  line-height: 1.5;
  word-wrap: break-word;
}

.chat-msg.visitor {
  align-self: flex-start;
  background: var(--bg);
  color: var(--text);
  border-bottom-left-radius: 4px;
}

.chat-msg.ai {
  align-self: flex-end;
  background: var(--accent);
  color: white;
  border-bottom-right-radius: 4px;
}

.chat-msg.system {
  align-self: center;
  background: transparent;
  color: var(--text-muted);
  font-size: 12px;
  font-style: italic;
  padding: 4px 0;
}

.chat-msg.practitioner {
  align-self: flex-end;
  background: #9D8ED8;
  color: white;
  border-bottom-right-radius: 4px;
}

.chat-msg-time {
  font-size: 10px;
  color: var(--text-muted);
  margin-top: 4px;
}

.chat-msg.ai .chat-msg-time,
.chat-msg.practitioner .chat-msg-time {
  color: rgba(255, 255, 255, 0.7);
}

/* Sales texts (reuses the chat inbox two-pane layout) */
.cs-unread {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  margin-left: 6px;
}

.cs-optout {
  color: var(--danger);
  font-weight: 500;
}

/* Two groups: who this is on the left, the one action on the right. */
.conv-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.conv-id {
  flex: 1 1 auto;
  min-width: 0;
}

.conv-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
}

.conv-title strong {
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* One quiet line under the name holding everything you might glance at before
   the phone rings: the number, the city, the demo page. All the same weight and
   the same muted colour on purpose, because none of them is the thing you came
   here to do. */
.conv-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--text-muted);
}

.conv-dot {
  color: var(--text-muted);
  opacity: 0.5;
}

.conv-phone {
  font-variant-numeric: tabular-nums;
}

/* What time it is where the prospect is. Muted like the rest of the line until
   the hour is one nobody wants to be called at, and then it is the one warm
   thing in the header, so it registers before it is read. */
.conv-time {
  font-variant-numeric: tabular-nums;
}

.conv-time-odd {
  color: var(--warning);
  font-weight: 600;
}

.conv-demo {
  color: var(--accent);
  text-decoration: none;
}

.conv-demo:hover {
  text-decoration: underline;
}

/* Dials the thread through the operator's own phone, and it is the only filled
   control in this header because dialling is the whole reason the header is
   read. It keeps .btn-secondary so it still picks up the shared
   connecting/connected/failed states, which are two-class rules and so override
   this fill on their own. */
.conv-call {
  padding: 8px 20px;
  min-height: 38px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  flex: none;
  background: var(--accent);
  border-color: var(--accent);
  color: white;
}

.conv-call:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: white;
}

/* Renaming is housekeeping, so it is a text link tucked beside the name rather
   than a bordered button competing with Call. Still labelled rather than a bare
   pencil, so it reads without a tooltip. */
.conv-rename {
  border: none;
  background: none;
  padding: 0;
  color: var(--text-muted);
  font: inherit;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  flex: none;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 2px;
  transition: color 0.15s, text-decoration-color 0.15s;
}

.conv-rename:hover,
.conv-rename:focus-visible {
  color: var(--accent);
  text-decoration-color: currentColor;
}

.conv-rename-form {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  width: 100%;
}

.conv-rename-input {
  flex: 1 1 180px;
  min-width: 0;
  min-height: 36px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: 14px;
}

.conv-rename-input:focus {
  outline: none;
  border-color: var(--accent);
}

.conv-rename-btn {
  min-height: 36px;
  flex: none;
}

.conv-rename-hint {
  color: var(--text-muted);
  font-size: 12px;
  flex: 1 1 100%;
}

.conv-blocked {
  padding: 12px 20px;
  border-top: 1px solid var(--border);
  color: var(--danger);
  font-size: 13px;
}

.chat-conv-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 20px;
}

.msg {
  margin: 8px 0;
  max-width: 78%;
}

.msg-inbound { margin-right: auto; }
.msg-outbound { margin-left: auto; text-align: right; }

.msg-body {
  display: inline-block;
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--bg);
  color: var(--text);
  font-size: 13px;
  line-height: 1.5;
  text-align: left;
  word-wrap: break-word;
}

.msg-outbound .msg-body {
  background: var(--accent);
  color: #fff;
}

.msg-meta {
  font-size: 10px;
  color: var(--text-muted);
  margin-top: 4px;
}

/* The composer stacks: a row of one-click messages, then the textarea and Send.
   Only the Texts tab uses this class. */
.chat-composer {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  padding: 12px 20px;
  border-top: 1px solid var(--border);
  background: var(--bg);
}

.composer-row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

.composer-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* "Send demo link" is the whole reason this row exists, so it carries the
   accent. Both keep a 32px tap target; this console gets used one-handed. */
.composer-action,
.composer-action-quiet {
  border-radius: 6px;
  padding: 4px 12px;
  min-height: 32px;
  font: inherit;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  flex: none;
  transition: all 0.2s;
}

.composer-action {
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
}

.composer-action:hover {
  filter: brightness(1.08);
}

/* Quieter on purpose. The opt-in prompt is the fallback for a prospect who
   texted without ever opening the demo page, so it is rarely the right click. */
.composer-action-quiet {
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text-secondary);
}

.composer-action-quiet:hover {
  background: var(--bg);
  color: var(--text);
  border-color: var(--accent);
}

/* The overflow menu and the icon-only send button are phone-only; a desktop keeps
   the two canned-message buttons in the open and a Send button that says Send. */
.composer-more { display: none; }
.composer-send-icon { display: none; }
/* The box grows, so the buttons sit on its last line rather than floating in the
   middle of a three-line box. */
.composer-row { align-items: flex-end; }

/* One line to start, growing with what is typed and scrolling past three. The
   ceiling lives here rather than in JS so it stays a styling decision; app.js
   only sets height from scrollHeight and lets max-height clamp it.
   line-height is pinned because the maths below depends on it. */
.chat-composer textarea {
  flex: 1;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  line-height: 1.4;
  resize: none;
  overflow-y: auto;
  /* 3 lines of text plus the 8px padding top and bottom and the 1px borders. */
  max-height: calc((13px * 1.4 * 3) + 18px);
}

.badge-active { background: #dcfce7; color: #166534; }
.badge-ended { background: #f3f4f6; color: #6b7280; }
.badge-support { background: #fef3c7; color: #92400e; }
.badge-inquiry { background: #dbeafe; color: #1d4ed8; }
.badge-free { background: #f3f4f6; color: #6b7280; }
.badge-preferred { background: #ede9fe; color: #5b21b6; }
.badge-platform { background: #fce7f3; color: #9d174d; }

.notes-cell {
  font-size: 12px;
  color: var(--text-secondary);
  max-width: 320px;
  line-height: 1.6;
}

html.dark .badge-active { background: #14532d; color: #86efac; }
html.dark .badge-ended { background: #2a2a2a; color: #9ca3af; }
html.dark .badge-support { background: #451a03; color: #fcd34d; }
html.dark .badge-inquiry { background: #1e3a5f; color: #93c5fd; }
html.dark .badge-free { background: #2a2a2a; color: #9ca3af; }
html.dark .badge-preferred { background: #2e1065; color: #c4b5fd; }
html.dark .badge-platform { background: #831843; color: #f9a8d4; }

/* Health grid */
.health-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin-bottom: 32px;
}

.health-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.health-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--text-muted);
}

.health-card.healthy .health-dot { background: #84cc16; box-shadow: 0 0 6px 2px #84cc16, 0 0 12px 4px rgba(132, 204, 22, 0.35); }
.health-card.degraded .health-dot { background: var(--warning); box-shadow: 0 0 6px 2px var(--warning), 0 0 12px 4px rgba(217, 119, 6, 0.3); }
.health-card.down .health-dot { background: var(--danger); box-shadow: 0 0 6px 2px var(--danger), 0 0 12px 4px rgba(220, 38, 38, 0.3); }
.health-card.loading .health-dot { background: var(--text-muted); animation: pulse 1.5s infinite; }

@keyframes pulse {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 1; }
}

.health-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.health-detail {
  font-size: 11px;
  color: var(--text-muted);
  margin-left: auto;
}

/* GSC chart */
.gsc-chart-wrap {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 32px;
}

.gsc-chart-wrap canvas {
  min-height: 360px;
}

/* Interval buttons */
.interval-bar {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.interval-btn {
  padding: 6px 16px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  background: var(--card);
  border: none;
  border-right: 1px solid var(--border);
  cursor: pointer;
  transition: all 0.15s;
}

.interval-btn:last-child {
  border-right: none;
}

.interval-btn:hover {
  background: var(--bg);
}

.interval-btn.active {
  background: var(--accent);
  color: white;
}

.section-subtitle {
  font-size: 12px;
  font-weight: 400;
  color: var(--text-muted);
}

/* Stat delta (trend indicator) */
.stat-delta {
  font-size: 12px;
  margin-top: 4px;
}

.stat-delta.up { color: var(--success); }
.stat-delta.down { color: var(--danger); }
.stat-delta.neutral { color: var(--text-muted); }
.stat-delta.up-bad { color: var(--danger); }
.stat-delta.down-good { color: var(--success); }

/* Responsive */
@media (max-width: 600px) {
  .content { padding: 16px; }
  .stats-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .stat-card { padding: 14px; }
  .stat-value { font-size: 22px; }
  .tab { padding: 10px 14px; font-size: 13px; }
  .top-bar { padding: 12px 16px; }
  .review-grid { grid-template-columns: 1fr; }
  .chat-inbox-layout { grid-template-columns: 1fr; height: auto; }
  .chat-session-list { max-height: 300px; border-right: none; border-bottom: 1px solid var(--border); }
  .msg { max-width: 90%; }
  .health-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ---- Novie detail page ---- */
.novie-list-table tbody tr.novie-row { cursor: pointer; }
.novie-list-table tbody tr.novie-row:hover { background: var(--bg); }

/* The count sits in the top-right corner, above the filter controls. */
.novie-section-header { align-items: flex-start; }
.novie-header-right { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.novie-header-right .header-actions { justify-content: flex-end; }

.novie-listbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.novie-listbar-actions { display: flex; align-items: center; gap: 10px; }
.novie-count { color: var(--text-muted); font-size: 14px; white-space: nowrap; }
.novie-export-status { color: var(--text-muted); font-size: 13px; }
#novie-export-csv[disabled] { opacity: 0.45; cursor: not-allowed; }

.novie-detail-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.novie-nav { display: flex; gap: 8px; align-items: center; }
.novie-nav button[disabled] { opacity: 0.45; cursor: not-allowed; }
.novie-nav-pos { color: var(--text-muted); font-size: 13px; margin-left: 4px; }
#novie-call-actions { display: flex; gap: 8px; }

.novie-detail-head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 20px; }
.novie-detail-head h2 { margin: 0; }
.novie-sub { color: var(--text-muted); font-size: 13px; margin: 4px 0 0; }
.novie-status-edit { font-size: 13px; color: var(--text-secondary); display: flex; flex-direction: column; gap: 4px; }

.novie-detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px; }
.novie-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; margin-bottom: 16px; }
.novie-card h3 { margin: 0 0 12px; font-size: 15px; }

.novie-field { display: block; font-size: 13px; color: var(--text-secondary); margin-bottom: 10px; }
.novie-field input, .novie-textarea { width: 100%; margin-top: 4px; padding: 8px; border: 1px solid var(--border); border-radius: 8px; font: inherit; box-sizing: border-box; }
.novie-notes-card { display: flex; flex-direction: column; }
.novie-notes-card .novie-textarea { flex: 1; resize: none; }
.novie-help { color: var(--text-muted); font-size: 12px; margin: 0 0 8px; line-height: 1.4; }
.novie-row-2 { display: grid; grid-template-columns: 2fr 1fr; gap: 10px; }
.novie-check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; margin-right: 16px; }

.novie-hours-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.novie-day-label { width: 38px; font-size: 13px; color: var(--text-secondary); }
.novie-hours-row input[type="time"] { padding: 5px; border: 1px solid var(--border); border-radius: 6px; }
.novie-hours-row input[type="time"]:disabled { color: var(--text-muted); background: var(--bg); }

.novie-svc-head, .novie-svc-row { display: grid; grid-template-columns: 2fr 0.8fr 1fr 1fr 28px; gap: 8px; align-items: center; }
.novie-svc-head { font-size: 12px; color: var(--text-muted); margin-bottom: 6px; }
.novie-svc-row { margin-bottom: 6px; }
.novie-svc-row input, .novie-faq-row input { padding: 7px; border: 1px solid var(--border); border-radius: 6px; font: inherit; }
.novie-faq-row { display: grid; grid-template-columns: 1fr 1fr 28px; gap: 8px; margin-bottom: 6px; align-items: center; }
#nd-add-service, #nd-add-faq { margin-top: 8px; }

.novie-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.novie-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--bg); border: 1px solid var(--border); border-radius: 999px; padding: 4px 10px; font-size: 13px; }
.novie-chip-add { display: flex; gap: 8px; }
.novie-chip-add input { flex: 1; padding: 7px; border: 1px solid var(--border); border-radius: 6px; font: inherit; }

.novie-x { background: none; border: none; color: var(--text-muted); cursor: pointer; font-size: 14px; line-height: 1; padding: 2px; }
.novie-x:hover { color: var(--danger); }
.mod-chip-main { border-color: var(--accent); font-weight: 600; }
.mod-chip-name { background: none; border: none; padding: 0; font: inherit; color: inherit; cursor: pointer; }
.mod-chip-name:hover { color: var(--accent); }
.mod-suggest-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.mod-suggest { background: none; border: 1px dashed var(--border); border-radius: 999px; padding: 3px 10px; font: inherit; font-size: 12px; color: var(--text-secondary); cursor: pointer; }
.mod-suggest:hover { border-color: var(--accent); color: var(--accent); }
.dir-offers { padding: 8px 4px; max-width: 900px; }
.dir-offers-bio { font-size: 13px; line-height: 1.5; color: var(--text-secondary); margin: 0 0 10px; white-space: pre-wrap; }
.dir-offers-actions { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.dir-offers-actions .novie-help { margin: 0; }

.novie-autosave-pill {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 50;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 8px 16px;
  font-size: 13px;
  color: var(--text-muted);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
  transition: color 0.2s;
}
.novie-autosave-pill.is-saved { color: var(--success); }

/* Prospect search. Grows to fill the header row on desktop, goes full width and
   sits first on a phone (see the mobile block below). */
.novie-search {
  /* Fixed-ish on desktop so it does not balloon and push the status filters
     onto their own line; the mobile block below gives it the full width. */
  flex: 0 1 240px;
  min-width: 160px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--text);
  font: inherit;
  font-size: 13px;
}
.novie-search::placeholder { color: var(--text-muted); }

@media (max-width: 720px) {
  .novie-detail-grid { grid-template-columns: 1fr; }
}

/* ---- Phone layout ----
   Rick works this page one-handed while a prospect is on the line: search for the
   practice, open it, hit Call prospect, then Have Novie join. So the search box
   and those three buttons are what get the room, and the columns and editing
   grids that only matter at a desk collapse out of the way. */
@media (max-width: 700px) {
  .content { padding: 12px; }

  /* Eight tabs never fit across a phone. Scroll them instead of wrapping them
     into a stack that pushes the page content below the fold. */
  .tab-bar {
    justify-content: flex-start;
    padding: 0 12px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .tab-bar::-webkit-scrollbar { display: none; }
  .tab { white-space: nowrap; }

  .section-header { flex-direction: column; align-items: stretch; gap: 12px; }
  .header-actions { gap: 10px; }
  /* Search first and full width: it is the only control that matters mid-call. */
  .novie-search { order: -1; flex-basis: 100%; width: 100%; font-size: 16px; }
  .novie-status-filters { width: 100%; box-sizing: border-box; }
  #novie-tz-filter, #novie-refresh { flex: 1 1 auto; }

  /* Location, time zone and the view/call counters are desk-time columns. Drop
     them so practitioner, practice and status get the full width. */
  .novie-list-table th:nth-child(3), .novie-list-table td:nth-child(3),
  .novie-list-table th:nth-child(4), .novie-list-table td:nth-child(4),
  .novie-list-table th:nth-child(6), .novie-list-table td:nth-child(6),
  .novie-list-table th:nth-child(7), .novie-list-table td:nth-child(7) { display: none; }
  .novie-list-table th, .novie-list-table td { padding: 10px 10px; }
  /* Taller rows so a thumb lands on the right prospect. */
  .novie-list-table tbody tr.novie-row td { padding-top: 14px; padding-bottom: 14px; }

  /* Call actions above the prev/next nav, full width, thumb sized. */
  .novie-detail-top { flex-direction: column; align-items: stretch; gap: 12px; }
  .novie-nav { order: 2; flex-wrap: wrap; }
  #novie-call-actions { order: 1; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  #novie-call-actions button { padding: 14px 10px; font-size: 15px; }
  /* Have Novie join is the point of the page, so it spans the row under the
     other two whether or not Call prospect and Text are both rendered. */
  #novie-call-actions #nd-call-me { grid-column: 1 / -1; }

  .novie-detail-head { flex-direction: column; gap: 12px; }
  .novie-status-edit { flex-direction: row; align-items: center; gap: 8px; }
  .novie-row-2 { grid-template-columns: 1fr; }

  /* 16px stops mobile Safari zooming the whole page in on focus. */
  .novie-field input, .novie-textarea, .novie-svc-row input, .novie-faq-row input,
  .novie-chip-add input { font-size: 16px; }

  /* The service/FAQ column headers have no room; every input already carries a
     placeholder saying the same thing, so stack the rows and drop the header. */
  .novie-svc-head { display: none; }
  .novie-svc-row { grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 14px; }
  .novie-svc-row .nd-svc-name { grid-column: 1 / -1; }
  .novie-faq-row { grid-template-columns: 1fr; gap: 6px; margin-bottom: 14px; }
  .novie-svc-row .novie-x, .novie-faq-row .novie-x { justify-self: end; }

  .novie-hours-row { flex-wrap: wrap; }
  /* The autosave pill sits over the bottom of the form on a short screen. */
  .novie-autosave-pill { bottom: 10px; right: 10px; padding: 6px 12px; font-size: 12px; }
}

/* ---- Texts console on a phone ----
   Two panes side by side does not survive a 390px screen. The old rule stacked
   them and set height:auto, which broke the flex chain the message list hangs
   off: .chat-conv-body is flex:1 of nothing, so it collapsed to a sliver and the
   conversation appeared as a strip under a list you had to scroll past. This
   shows exactly ONE pane, the list until you tap a contact and the conversation
   after, with a back bar to return. #texts-layout is an id so this cannot reach
   the Chat Inbox tab, which shares the class and has no back control. */
/* Back and the conversation header share one row, so back costs no vertical
   space at all. On a desktop back is hidden and the row is just the header. */
.conv-top {
  display: flex;
  align-items: stretch;
}

.conv-top .chat-conv-header {
  flex: 1;
  min-width: 0;
}

.conv-back {
  display: none;
  flex: none;
  align-items: center;
  padding: 0 14px;
  border: none;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  color: var(--accent);
  font: inherit;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

@media (max-width: 700px) {
  /* Reading a conversation is a full-screen job. Everything here is list-level or
     app-level chrome that does nothing while you are in a thread: the heading and
     the New text / Refresh buttons belong to the LIST, and the FAH Admin bar and
     the tab strip belong to the app. Together they are about 165px of a screen
     that also has to hold a keyboard and Safari's form accessory bar. The back
     bar is the way out and brings all of them back, so nothing is stranded.
     The heading is scoped to #tab-texts so this cannot reach another tab's. */
  .texts-thread-open .top-bar,
  .texts-thread-open .tab-bar,
  .texts-thread-open #tab-texts .section-header { display: none; }

  #texts-layout {
    grid-template-columns: 1fr;
    /* A real height, so .chat-conv-body's flex:1 has something to be 1 of.
       dvh rather than vh because mobile browser chrome moves. The subtraction is
       the top bar, the tab bar and the content padding, plus the section header
       in the list state, which is gone in the thread state. */
    height: calc(100dvh - 210px);
    min-height: 360px;
  }
  /* Pinned to the VISUAL viewport, not the layout one, so the on-screen keyboard
     cannot push the header off or detach the composer. --app-height and --app-top
     are set from window.visualViewport in app.js (weldTextsToVisualViewport):
     height tracks visualViewport.height so the pane shrinks to the band above the
     keyboard, and top tracks visualViewport.offsetTop so the pane follows when
     iOS pans to reveal the composer. Without JS, or without visualViewport, it
     falls back to a full-screen fixed pane, which is what it already was.
     min-height MUST be 0: any floor here would defeat the shrink and put the
     composer back under the keyboard, which is the bug this fixes. */
  #texts-layout.has-thread {
    position: fixed;
    top: var(--app-top, 0px);
    left: 0;
    right: 0;
    height: var(--app-height, 100dvh);
    min-height: 0;
    z-index: 20;
    border-radius: 0;
    border-left: none;
    border-right: none;
  }
  #texts-layout .chat-session-list {
    max-height: none;
    height: 100%;
    border-right: none;
    border-bottom: none;
  }
  #texts-layout .chat-conversation { display: none; }
  #texts-layout.has-thread .chat-session-list { display: none; }
  #texts-layout.has-thread .chat-conversation { display: flex; }

  .conv-back { display: flex; }

  /* Bigger rows: this list is worked with a thumb while a prospect is on hold. */
  .chat-session-item { padding: 14px 16px 16px; }
  .chat-session-item .chat-session-source { font-size: 15px; }
  .chat-session-item .chat-session-preview { font-size: 13px; }

  /* Name and meta on their own lines with Call beside them, rather than the
     three-way wrap the desktop row degrades into. */
  /* The header is a fixed cost on every screenful of a conversation, so it is
     trimmed rather than restyled: same three facts, less air around them. */
  .chat-conv-header { padding: 10px 14px; }
  .conv-head { gap: 10px; }
  .conv-meta { font-size: 11px; gap: 5px; }
  .conv-call { flex: none; }

  .chat-conv-body { padding: 14px 12px; }
  .msg { max-width: 88%; }

  /* One row: menu, box, send. The two canned messages move behind the menu, which
     is a whole row of vertical space back and leaves the composer reading like a
     phone messaging app rather than a form. */
  .chat-composer { padding: 10px 12px; position: relative; }
  /* 16px stops mobile Safari zooming the page when the composer takes focus, and
     the three-line ceiling has to be restated because it is derived from it. */
  .chat-composer textarea {
    font-size: 16px;
    max-height: calc((16px * 1.4 * 3) + 20px);
    padding: 9px 12px;
  }
  /* flex-end, so the two 40px buttons stay level with the box's last line as it
     grows, which is where a thumb expects them. */
  .composer-row { align-items: flex-end; gap: 8px; }

  .composer-more {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--card);
    color: var(--text-secondary);
    font: inherit;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
  }
  .composer-more[aria-expanded="true"] {
    border-color: var(--accent);
    color: var(--accent);
  }

  /* Square, so it reads as an icon button and not a truncated word. */
  .composer-send {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 12px;
    /* overflow visible: the 34px glyph is meant to nearly fill the 44px button. */
    overflow: visible;
  }
  .composer-send-label { display: none; }
  /* Visibility only. The SIZE lives on the svg elements in app.js, next to the
     shape it applies to, so an icon cannot end up depending on which stylesheet
     the browser is holding. */
  .composer-send-icon { display: block; }
  .composer-more-icon { display: block; }

  /* A sheet above the box rather than a row above it, so it costs nothing until
     it is asked for. Anchored to .chat-composer, which is the relative parent. */
  .chat-composer .composer-actions { display: none; }
  .chat-composer.actions-open .composer-actions {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    position: absolute;
    bottom: calc(100% + 6px);
    left: 12px;
    right: 12px;
    z-index: 30;
    padding: 10px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  }
  .chat-composer.actions-open .composer-action,
  .chat-composer.actions-open .composer-action-quiet {
    min-height: 40px;
    font-size: 14px;
  }
}

.btn-primary { background: var(--accent); color: #fff; border: none; border-radius: 8px; padding: 8px 16px; font: inherit; cursor: pointer; }
.btn-primary:hover { background: var(--accent-hover); }

a.btn-secondary { text-decoration: none; display: inline-flex; align-items: center; }

/* Possible duplicates (a view inside the Directory tab). Each pair is a block
   with its two listings side by side; on a phone they stack, full width, with
   no card around them. */
.dup-note { margin: 0 0 16px; max-width: 820px; color: var(--text-muted); font-size: 13px; line-height: 1.6; }
.dup-confident-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 8px 0; }
.dup-confident-head h3, .dup-other-heading { font-size: 15px; margin: 0; }
.dup-other-heading { margin: 28px 0 8px; }
.dup-batch-result { margin: 8px 0 16px; font-size: 13px; line-height: 1.5; }
.dup-batch-result ul { margin: 4px 0 0 18px; }
.dup-pair { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; margin-bottom: 14px; }
.dup-why { font-size: 12px; color: var(--text-muted); margin-bottom: 10px; }
.dup-sides { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.dup-side { border: 1px solid var(--border); border-radius: 8px; padding: 12px; min-width: 0; }
.dup-side.is-keep { border-color: var(--accent); }
.dup-head { display: flex; gap: 10px; align-items: flex-start; margin-bottom: 8px; }
.dup-photo { width: 48px; height: 48px; border-radius: 50%; object-fit: cover; flex: none; background: var(--bg); }
.dup-name { font-weight: 600; }
.dup-practice { font-size: 13px; color: var(--text-secondary); }
.dup-badges { margin-top: 2px; }
.dup-fields { display: grid; grid-template-columns: max-content 1fr; gap: 2px 10px; font-size: 13px; margin: 0 0 8px; }
.dup-fields dt { color: var(--text-muted); }
.dup-fields dd { margin: 0; overflow-wrap: anywhere; }
.dup-match { background: rgba(157, 142, 216, 0.2); border-radius: 4px; padding: 0 3px; }
.dup-bio { font-size: 13px; color: var(--text-secondary); margin: 0 0 6px; }
.dup-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 12px; }
.dup-actions .novie-help { margin: 0; }

@media (max-width: 700px) {
  .dup-confident-head { flex-direction: column; align-items: stretch; }
  .dup-pair { background: none; border: none; border-radius: 0; border-top: 1px solid var(--border); padding: 14px 0; margin: 0; }
  .dup-sides { grid-template-columns: 1fr; }
  .dup-side { border: none; border-left: 3px solid var(--border); border-radius: 0; padding: 2px 0 2px 10px; }
  .dup-side.is-keep { border-left-color: var(--accent); }
}

/* Workflow Runs */
.badge-paused { background: #fef3c7; color: #92400e; }
html.dark .badge-paused { background: #451a03; color: #fcd34d; }
.runs-note { margin: 0 0 12px; font-size: 12px; color: var(--text-muted); }
.runs-chip { margin: 0 0 12px; font-size: 13px; color: var(--text-secondary); }
.runs-link {
  all: unset;
  cursor: pointer;
  color: var(--text);
  text-decoration: underline;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
}
.runs-chip .runs-link { font-family: inherit; font-size: inherit; }
.runs-link:hover, .runs-link:focus-visible { color: var(--text-secondary); }
.runs-caret-col { width: 28px; padding-right: 0; }
.run-caret {
  all: unset;
  cursor: pointer;
  width: 20px;
  text-align: center;
  color: var(--text-muted);
}
.run-caret:hover, .run-caret:focus-visible { color: var(--text); }
.run-caret:focus-visible, .runs-link:focus-visible { outline: 2px solid var(--primary, currentColor); outline-offset: 2px; }
.run-next-when { color: var(--text-muted); }
.run-action { text-align: right; white-space: nowrap; }
tr.run-steps > td { background: var(--bg); padding: 4px 16px 12px 44px; }
.run-step-list { list-style: none; margin: 0; padding: 0; }
.run-step {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  padding: 6px 0;
  font-size: 13px;
  border-bottom: 1px solid var(--border);
}
.run-step:last-child { border-bottom: none; }
.run-step-icon { width: 16px; text-align: center; color: var(--text-muted); }
.run-step-label { color: var(--text); }
.run-step-to { color: var(--text-muted); font-size: 12px; }
.run-step-when { margin-left: auto; color: var(--text-secondary); font-size: 12px; text-align: right; }
.run-step-sent .run-step-icon, .run-step-reached .run-step-icon { color: var(--success, #2e7d32); }
.run-step-next .run-step-icon, .run-step-due .run-step-icon { color: var(--text); }
.run-step-ended .run-step-icon { color: var(--danger, #c62828); }
@media (max-width: 600px) {
  tr.run-steps > td { padding-left: 16px; }
  .run-step-when { margin-left: 28px; flex-basis: 100%; text-align: left; }
}

/* Novie 2.0: status with its call-back date beside it, and the Call now toggle. */
.novie-status-edit-wrap { display: flex; gap: 14px; align-items: flex-end; flex-wrap: wrap; }
.novie-status-edit[hidden] { display: none; }
.novie-callnow {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--border); font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.novie-callnow[hidden] { display: none; }
.novie-callnow:has(input:checked) { background: var(--accent, #6B4E9E); border-color: var(--accent, #6B4E9E); color: #fff; }

/* Novie 2.0 funnel summary above the list. */
.novie-funnel { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 0 0 16px; padding: 10px 14px;
  border: 1px solid var(--border); border-radius: 10px; font-size: 13px; color: var(--text-secondary); }
.novie-funnel[hidden] { display: none; }
.novie-funnel-label { font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; font-size: 11px; margin-right: 4px; }
.novie-funnel-step strong { color: var(--text); font-size: 15px; margin-right: 3px; }
.novie-funnel-arrow { color: var(--text-muted); }

/* Novie 2.0: a city estimated from the phone number, and the city filter. */
.novie-est { font-size: 11px; color: var(--text-muted); border: 1px solid var(--border); border-radius: 999px; padding: 0 6px; margin-left: 4px; }
#novie-city-filter[hidden] { display: none; }
