/* Wap Nest — interface styles.
   Brand colours come from CSS custom properties set in the layout, so the
   product name, logo and palette can be changed without touching this file. */

:root {
  --brand: #0B7D57;
  --brand-dark: #086747;
  --accent: #0F263E;
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #f9fafb;
  --border: #e3e6ea;
  --border-strong: #cbd2da;
  --text: #16202b;
  --muted: #64748b;
  --ok: #15803d;
  --ok-bg: #e8f5ee;
  --warn: #b45309;
  --warn-bg: #fdf4e3;
  --bad: #b91c1c;
  --bad-bg: #fdecec;
  --demo: #6d28d9;
  --demo-bg: #f3eefc;
  /* Ad attribution. 5.9:1 on its own background, so the chip is readable at
     11.5px — the size it is actually rendered at. */
  --ad: #1d4ed8;
  --ad-bg: #eaf1fd;
  --radius: 10px;
  --shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 1px 3px rgba(16, 24, 40, .06);
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans Bengali", sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
}

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------------------------------------------------------------- shell */

.app { display: flex; flex-direction: column; min-height: 100vh; }

.topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 16px;
  height: 56px;
  background: var(--accent);
  color: #fff;
  flex: 0 0 auto;
}
.topbar a { color: #fff; }
.topbar .logo {
  font-weight: 650;
  letter-spacing: -.01em;
  display: flex;
  align-items: center;
  gap: 8px;
}
.topbar .logo img { height: 26px; width: 26px; border-radius: 6px; display: block; }
.topbar nav { display: flex; gap: 4px; margin-left: 12px; }
.topbar nav a {
  padding: 6px 12px;
  border-radius: 7px;
  font-size: 14px;
  opacity: .82;
}
.topbar nav a:hover { background: rgba(255,255,255,.12); opacity: 1; text-decoration: none; }
.topbar nav a.active { background: rgba(255,255,255,.16); opacity: 1; }
.topbar .spacer { flex: 1; }
.topbar .who { font-size: 13px; opacity: .8; }
.topbar form { display: inline; }
.topbar .linkbtn {
  background: none; border: 0; color: #fff; opacity: .8;
  font: inherit; font-size: 13px; cursor: pointer; padding: 6px 8px;
}
.topbar .linkbtn:hover { opacity: 1; text-decoration: underline; }

/* min-width: 0 because .page is a flex ITEM of .app, and a flex item defaults
   to min-width:auto — it refuses to shrink below its content's minimum. With
   a wide horizontally-scrolling child like the pipeline board, that made the
   PAGE grow to the board's full width and every page on the site scrolled
   sideways with it. The board's own overflow-x could never help: nothing was
   ever narrower than the content. */
.page { flex: 1 1 auto; min-width: 0; padding: 20px 16px 48px; max-width: 1120px; width: 100%; margin: 0 auto; }

/* The page never scrolls sideways; a widget inside it may.
   `clip` rather than `hidden` on purpose: hidden turns the page into a scroll
   container, which breaks position:sticky for anything inside it — the
   inbox composer among them. clip stops the overflow without that side
   effect. Browsers without it fall back to the previous behaviour, which is
   a horizontal scrollbar rather than anything broken. */
.page:not(.wide) { overflow-x: clip; }
.page.wide { max-width: none; padding: 0; display: flex; min-height: 0; }

h1 { font-size: 22px; margin: 0 0 4px; letter-spacing: -.015em; }
h2 { font-size: 16px; margin: 28px 0 10px; letter-spacing: -.01em; }
h3 { font-size: 14px; margin: 0 0 8px; }
p.sub { color: var(--muted); margin: 0 0 20px; font-size: 14px; }

/* ---------------------------------------------------------------- cards */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px;
  margin-bottom: 16px;
}
.card > h2:first-child, .card > h3:first-child { margin-top: 0; }
.card-row { display: flex; gap: 16px; flex-wrap: wrap; }
.card-row > .card { flex: 1 1 260px; margin-bottom: 0; }

.stat { font-size: 26px; font-weight: 650; letter-spacing: -.02em; }
.stat-label { color: var(--muted); font-size: 13px; }

/* ---------------------------------------------------------------- forms */

label { display: block; font-size: 13px; font-weight: 600; margin: 0 0 5px; }
.hint { color: var(--muted); font-size: 12.5px; font-weight: 400; margin: 4px 0 0; }

input[type=text], input[type=email], input[type=password], input[type=search],
input[type=tel], input[type=color], select, textarea {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  font: inherit;
  font-size: 14px;
  background: #fff;
  color: var(--text);
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid color-mix(in srgb, var(--brand) 40%, transparent);
  outline-offset: 1px;
  border-color: var(--brand);
}
input[type=color] { padding: 3px; height: 38px; }
textarea { resize: vertical; min-height: 84px; }
.field { margin-bottom: 14px; }
.field-row { display: flex; gap: 12px; flex-wrap: wrap; }
.field-row > .field { flex: 1 1 200px; }

/* The HTML `hidden` attribute is only a browser default of display:none, so
   any author rule that sets display — .btn is inline-flex — silently beats it
   and the element stays on screen. Anything hidden from script relies on this.
   Found by driving a browser, not by reading the code. */
[hidden] { display: none !important; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px 15px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: var(--brand);
  color: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 550;
  cursor: pointer;
  text-decoration: none;
}
.btn:hover { background: var(--brand-dark); text-decoration: none; color: #fff; }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn.secondary { background: #fff; color: var(--text); border-color: var(--border-strong); }
.btn.secondary:hover { background: var(--surface-2); color: var(--text); }
.btn.danger { background: var(--bad); }
.btn.danger:hover { background: #991b1b; }
.btn.small { padding: 5px 10px; font-size: 13px; }
.btn-group { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* ---------------------------------------------------------------- alerts */

.alert {
  padding: 11px 14px;
  border-radius: 8px;
  margin-bottom: 14px;
  font-size: 14px;
  border: 1px solid;
}
.alert.success { background: var(--ok-bg); border-color: #bfe3ce; color: #14532d; }
.alert.error   { background: var(--bad-bg); border-color: #f5c6c6; color: #7f1d1d; }
.alert.info    { background: #eef3fb; border-color: #cfdcf1; color: #1e3a5f; }
.alert.warn    { background: var(--warn-bg); border-color: #f0dcb4; color: #78350f; }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11.5px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
  border: 1px solid var(--border);
  white-space: nowrap;
}
.badge.ok    { background: var(--ok-bg);   color: var(--ok);   border-color: #bfe3ce; }
.badge.warn  { background: var(--warn-bg); color: var(--warn); border-color: #f0dcb4; }
.badge.bad   { background: var(--bad-bg);  color: var(--bad);  border-color: #f5c6c6; }
.badge.demo  { background: var(--demo-bg); color: var(--demo); border-color: #ddd0f5; }
.badge.muted { background: var(--surface-2); color: var(--muted); }

/* An ad-sourced conversation. Deliberately not green, amber or red: those
   three already mean resolved, pending and failed in this inbox, and a fourth
   meaning on the same hues would make the row ambiguous at a glance. Blue is
   unused and reads as informational rather than as a state to act on. */
.badge.ad {
  background: var(--ad-bg);
  color: var(--ad);
  border-color: #c3d9f5;
  cursor: help;
}

/* The quick rename offered when WhatsApp gave us no usable name. */
.rename-inline { margin: 6px 0 10px; }
.rename-inline .rename-row { display: flex; gap: 6px; align-items: center; }
.rename-inline input[type="text"] { flex: 1 1 auto; min-width: 0; }
.rename-inline .btn { flex: 0 0 auto; }

.dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }

/* ---------------------------------------------------------------- tables */

table { width: 100%; border-collapse: collapse; font-size: 14px; }
th {
  text-align: left;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
}
td { padding: 10px; border-bottom: 1px solid var(--border); vertical-align: middle; }
tr:last-child td { border-bottom: 0; }
.table-wrap { overflow-x: auto; }

/* ---------------------------------------------------------------- inbox */

.inbox { display: flex; width: 100%; min-height: calc(100vh - 56px); }

.inbox-list {
  width: 340px;
  flex: 0 0 340px;
  border-right: 1px solid var(--border);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.inbox-filters { padding: 12px; border-bottom: 1px solid var(--border); }
.inbox-filters .field { margin-bottom: 8px; }
.inbox-filters .filter-row { display: flex; gap: 8px; }
.inbox-filters select { font-size: 13px; padding: 6px 8px; }
.chiprow { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.chip {
  font-size: 12.5px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: #fff;
  color: var(--muted);
  text-decoration: none;
}
.chip:hover { background: var(--surface-2); text-decoration: none; }
.chip.on { background: var(--brand); border-color: var(--brand); color: #fff; }

.conv-scroll { overflow-y: auto; flex: 1 1 auto; }
.conv {
  display: block;
  padding: 11px 13px;
  border-bottom: 1px solid var(--border);
  color: inherit;
  text-decoration: none;
  border-left: 3px solid transparent;
}
.conv:hover { background: var(--surface-2); text-decoration: none; }
.conv.active { background: #eef4f2; border-left-color: var(--brand); }
.conv-top { display: flex; align-items: baseline; gap: 8px; }
.conv-name { font-weight: 600; font-size: 14px; flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conv-time { font-size: 11.5px; color: var(--muted); flex: 0 0 auto; }
.conv-preview {
  font-size: 13px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 2px;
}
.conv-meta { display: flex; gap: 6px; align-items: center; margin-top: 6px; flex-wrap: wrap; }
.channel-tag {
  font-size: 11px;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: 4px;
  color: #fff;
}
.unread-pill {
  background: var(--brand);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  border-radius: 999px;
  padding: 1px 7px;
  min-width: 19px;
  text-align: center;
}

/* thread */

.thread { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; background: var(--bg); }
.thread-head {
  padding: 11px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.thread-head .who { font-weight: 650; font-size: 15px; }
.thread-head .num { color: var(--muted); font-size: 13px; }
.thread-head .spacer { flex: 1; }
.thread-head form { display: inline-flex; gap: 6px; align-items: center; }
.thread-head select { font-size: 13px; padding: 5px 8px; width: auto; }

.messages { flex: 1 1 auto; overflow-y: auto; padding: 18px 16px; display: flex; flex-direction: column; gap: 10px; }

.msg { max-width: min(620px, 78%); }
.msg.in  { align-self: flex-start; }
.msg.out { align-self: flex-end; }
.msg.note { align-self: center; max-width: min(680px, 92%); width: 100%; }

.bubble {
  padding: 9px 13px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  white-space: pre-wrap;
  word-wrap: break-word;
  overflow-wrap: anywhere;
  font-size: 14.5px;
}
.msg.out .bubble { background: #e3f2ec; border-color: #c9e5da; }
.msg.note .bubble {
  background: #fffbeb;
  border: 1px dashed #e5c877;
  color: #6b4e08;
  font-size: 14px;
}
.note-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: #92700d;
  margin-bottom: 3px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.msg-meta {
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 3px;
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
}
.msg.out .msg-meta { justify-content: flex-end; }
.msg-meta .st-ok   { color: var(--ok); }
.msg-meta .st-warn { color: var(--warn); font-weight: 600; }
.msg-meta .st-bad  { color: var(--bad); font-weight: 600; }

.attach {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-2);
  font-size: 13px;
}
.attach img { max-width: 100%; border-radius: 8px; display: block; }

/* composer */

.composer { border-top: 1px solid var(--border); background: var(--surface); padding: 12px 16px 14px; }
.composer-tabs { display: flex; gap: 4px; margin-bottom: 8px; }
.composer-tab {
  padding: 5px 12px;
  border-radius: 7px 7px 0 0;
  font-size: 13px;
  font-weight: 600;
  border: 1px solid transparent;
  background: none;
  cursor: pointer;
  color: var(--muted);
  font-family: inherit;
}
.composer-tab.on { background: var(--surface-2); border-color: var(--border); color: var(--text); }
.composer-tab.note-tab.on { background: #fffbeb; border-color: #e5c877; color: #92700d; }
.composer textarea { min-height: 66px; }
.composer .row { display: flex; gap: 8px; align-items: flex-end; margin-top: 8px; flex-wrap: wrap; }
.composer .row .spacer { flex: 1; }
.window-bar {
  font-size: 13px;
  padding: 8px 11px;
  border-radius: 8px;
  margin-bottom: 9px;
  border: 1px solid;
}
.window-bar.open   { background: var(--ok-bg);  border-color: #bfe3ce; color: #14532d; }
.window-bar.closed { background: var(--warn-bg); border-color: #f0dcb4; color: #78350f; }

/* Per-number quality, in Settings. */
.quality-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}

/* Quoted replies. The quote sits above its message, indented by a coloured
   rule, the way WhatsApp itself renders one — so it reads as context rather
   than as another message. */
.quoted {
  display: block;
  max-width: 78%;
  margin: 0 0 -2px;
  padding: 6px 10px;
  border-left: 3px solid var(--brand);
  border-radius: 8px 8px 0 0;
  background: rgba(15, 38, 62, .05);
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--muted);
  text-decoration: none;
}
.msg.out .quoted { margin-left: auto; }
a.quoted:hover { background: rgba(15, 38, 62, .09); }
.quoted.missing { border-left-color: var(--border-strong); font-style: italic; }
.quoted-who { display: block; font-weight: 600; color: var(--brand); font-size: 11.5px; }
.quoted.missing .quoted-who { color: var(--muted); }
.quoted-body { display: block; overflow-wrap: anywhere; }

.msg-reply-btn {
  border: 0;
  background: none;
  padding: 2px 4px;
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--muted);
  cursor: pointer;
  opacity: 0;
  transition: opacity .12s;
}
.msg:hover .msg-reply-btn,
.msg-reply-btn:focus-visible { opacity: 1; }
.msg.out .msg-reply-btn { align-self: flex-end; }
/* Touch screens have no hover, so the control must simply be there. */
@media (hover: none) { .msg-reply-btn { opacity: 1; } }

.replying-to {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 11px;
  margin-bottom: 8px;
  border-left: 3px solid var(--brand);
  border-radius: 8px;
  background: var(--panel-alt, #f7f9fb);
  font-size: 13px;
}
.replying-to > div:first-child { flex: 1 1 auto; min-width: 0; }
.replying-to #replying-preview { color: var(--muted); overflow-wrap: anywhere; }

/* Lead stages. Colour carries the progression: neutral at the start, warm in
   the middle, green when enrolled, muted when lost. */
.badge.stage-new       { background: #eef2f7; color: #334155; }
.badge.stage-contacted { background: #e0f2fe; color: #075985; }
.badge.stage-qualified { background: #ede9fe; color: #5925DC; }
.badge.stage-applied   { background: #fef3c7; color: #92400e; }
.badge.stage-enrolled  { background: #dcfce7; color: #14532d; }
.badge.stage-lost      { background: #f1f5f9; color: #64748b; }

/* Labels. The colour is per label and arrives as a custom property, so one
   rule serves every label without generating a stylesheet per workspace. */
.label-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.7;
  color: #fff;
  background: var(--label-colour, #4A5578);
  border: 1px solid transparent;
  white-space: nowrap;
}
.label-chip.small { font-size: 11px; padding: 1px 7px; }
.label-chip.removable { cursor: pointer; }
.label-chip.removable:hover { filter: brightness(1.12); }
.label-chip.removable span[aria-hidden] { opacity: .75; font-size: 13px; }

.thread-labels { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 6px; }
.thread-labels .label-form { display: inline-flex; gap: 6px; align-items: center; margin: 0; }
.thread-labels select { width: auto; max-width: 180px; font-size: 13px; padding: 4px 8px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Template picker — shown in place of the composer when the window is shut. */
.template-params {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 8px 12px;
  margin-top: 8px;
}
.template-param { display: flex; flex-direction: column; gap: 3px; }
.template-param > span {
  font-size: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--muted);
}
.template-preview {
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel-alt, #f7f9fb);
  font-size: 14px;
  white-space: pre-wrap;
  word-break: break-word;
}
.template-preview .k {
  display: block;
  font-size: 11px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 5px;
}

.file-label {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 12px; border: 1px solid var(--border-strong);
  border-radius: 8px; font-size: 13.5px; cursor: pointer; background: #fff;
}
.file-label:hover { background: var(--surface-2); }
.file-label input { display: none; }

.new-messages {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 190px;
  z-index: 5;
  background: var(--accent);
  color: #fff;
  border: 0;
  border-radius: 999px;
  padding: 7px 15px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(16, 24, 40, .22);
}
.new-messages:hover { opacity: .92; }

.thread { position: relative; }

.linkclear {
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}
.linkclear:hover { color: var(--bad); }

.empty {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 8px;
  color: var(--muted);
  text-align: center;
  padding: 40px 24px;
}
.empty h3 { font-size: 16px; color: var(--text); margin: 0; }
.empty p { margin: 0; max-width: 420px; font-size: 14px; }

/* contact panel */

.contact-panel {
  width: 280px;
  flex: 0 0 280px;
  border-left: 1px solid var(--border);
  background: var(--surface);
  padding: 16px;
  overflow-y: auto;
}
.contact-panel h3 { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin: 18px 0 7px; }
.contact-panel h3:first-child { margin-top: 0; }
.kv { font-size: 13.5px; margin-bottom: 6px; }
.kv .k { color: var(--muted); }

/* auth pages */

.auth-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; background: var(--bg); }
.auth-card { width: 100%; max-width: 400px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow); padding: 28px; }
.auth-card .logo { font-size: 19px; font-weight: 680; margin-bottom: 4px; letter-spacing: -.02em; }
.auth-card .tag { color: var(--muted); font-size: 13.5px; margin-bottom: 20px; }
.auth-card .btn { width: 100%; margin-top: 6px; }
.auth-foot { text-align: center; margin-top: 16px; font-size: 13px; color: var(--muted); }

/* platform */

.platform .topbar { background: #312e2b; }
.platform-tag {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  background: #b45309; color: #fff; padding: 2px 7px; border-radius: 4px;
}

.notice-strip {
  background: var(--warn-bg);
  border-bottom: 1px solid #f0dcb4;
  color: #78350f;
  font-size: 13.5px;
  padding: 8px 16px;
  text-align: center;
}
.notice-strip.demo { background: var(--demo-bg); border-color: #ddd0f5; color: var(--demo); }

/* ------------------------------------------------------------ responsive */

.only-mobile { display: none; }

@media (max-width: 900px) {
  .contact-panel { display: none; }
  .contact-panel.show { display: block; position: fixed; right: 0; top: 56px; bottom: 0; z-index: 30; box-shadow: -6px 0 20px rgba(0,0,0,.09); }
}

@media (max-width: 760px) {
  .only-mobile { display: inline-flex; }
  .inbox { display: block; min-height: 0; }
  .inbox-list { width: auto; flex: none; border-right: 0; min-height: calc(100vh - 56px); }
  .thread { min-height: calc(100vh - 56px); }
  /* On a phone the list and the thread are separate screens. */
  body.thread-open .inbox-list { display: none; }
  body:not(.thread-open) .thread { display: none; }
  .msg { max-width: 88%; }
  /* The top bar outgrew the phone once Pipeline, Reports and Follow-ups were
     added: five nowrap links plus the logo and Sign out came to roughly 560px,
     which widened the whole document and left every page scrolling sideways.
     The bar now clips at the viewport and the links scroll inside it, so the
     page itself never moves. */
  .topbar { gap: 8px; padding: 0 10px; overflow: hidden; }
  .topbar .logo { font-size: 14px; white-space: nowrap; flex: 0 0 auto; }
  .topbar nav {
    margin-left: 2px;
    flex: 1 1 auto;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .topbar nav::-webkit-scrollbar { display: none; }
  .topbar nav a { padding: 6px 9px; white-space: nowrap; }
  /* The nav takes the slack instead, so Sign out stays at the right edge. */
  .topbar .spacer { display: none; }
  .topbar form { flex: 0 0 auto; }
  .topbar .linkbtn { white-space: nowrap; padding: 6px 2px; }
  .topbar .who { display: none; }
  .thread-head { gap: 8px; padding: 10px 12px; }
  .thread-head form { flex: 1 1 140px; }
  .thread-head select { width: 100%; }
  .note-label { flex-wrap: wrap; }
  .page { padding: 16px 12px 40px; }
  .card { padding: 15px; }
}

/* Template creation form: example value rows. */
.example-row { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.example-row label { min-width: 7rem; margin: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .9rem; }
.example-row input { flex: 1; margin: 0; }
fieldset[data-template-examples] { border: 1px solid rgba(0,0,0,.12); border-radius: 10px; padding: 14px 16px; margin: 18px 0; }
fieldset[data-template-examples] legend { padding: 0 6px; font-weight: 600; font-size: .95rem; }
@media (max-width: 560px) {
  .example-row { flex-direction: column; align-items: stretch; gap: 4px; }
  .example-row label { min-width: 0; }
}

/* ===================================================== pipeline and reports
 *
 * Added in 0.4.0. The board is a horizontally scrolling row of stage columns,
 * because six stages will not fit side by side on a laptop at a readable card
 * width, and squeezing them makes every card useless. Scrolling sideways is
 * what a pipeline board does.
 */

.pipeline-filters { margin-bottom: 16px; }

/* The scroller is a SEPARATE element from the flex row.
   A flex container that is also its own scroller does not reliably stop its
   content widening the page — the row ends up sizing the ancestors before
   overflow ever gets a chance to clip. Splitting them is the pattern that
   actually holds: the wrapper is the width of the page and scrolls; the row
   inside is as wide as its columns need. */
.board-scroll {
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.board {
  display: flex;
  width: max-content;
  gap: 14px;
  align-items: flex-start;
  padding-bottom: 12px;

  /* NO max-width here. The row is deliberately as wide as its columns need —
     that is what gives .board-scroll something to scroll. An earlier attempt
     at this capped it with max-width:100%, which quietly undid width:max-content
     and left the columns spilling out of the scroller instead of inside it. */
}

/* Each column scrolls vertically, and the board does NOT grow taller than
   the window.

   This is the fix for a complaint that read as "the right side is fully
   cut". The board was scrolling correctly the whole time — but a column may
   hold up to COLUMN_LIMIT = 60 cards, which makes it some ten thousand
   pixels tall, and a scroll container's horizontal scrollbar sits at the
   BOTTOM of that container. The bar you need in order to reach the fourth
   stage was ten thousand pixels below the fold. Nobody will ever find it,
   so the columns past the page edge looked severed rather than scrollable.

   Capping the column's height keeps the whole board inside the window,
   which puts that horizontal scrollbar back on screen where it can be used.
   The header is sticky so you can still see which stage you are reading
   after scrolling down a long column. */
.board-col {
  flex: 0 0 290px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0 12px 12px;
  min-height: 120px;

  /* --board-max is set by app.js from the board's real distance down the
     page, because the filter card above it changes height with the number
     of filters and with the window width, and no fixed figure is right at
     every size. The fallback here is deliberately conservative: with
     JavaScript off the board is a little shorter than it could be, which
     costs a few rows of a column and still keeps the scrollbar on screen.
     Nothing here depends on JavaScript to WORK — only to fit well. */
  max-height: var(--board-max, calc(100vh - 320px));
  overflow-y: auto;
}

.board-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;

  /* Sticky INSIDE the column, which is the scroll container. The padding
     moved off .board-col and onto this element because a sticky box pins to
     the top of the scrollport, not below the container's padding — without
     that move the first card slid underneath the heading. */
  position: sticky;
  top: 0;
  z-index: 1;
  padding-top: 12px;
  background: var(--surface-2);
}
.board-head h2 {
  margin: 0;
  font-size: .82rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.board-count {
  margin-left: auto;
  font-size: .78rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 9px;
}

.board-empty, .board-more {
  font-size: .82rem;
  color: var(--muted);
  margin: 6px 2px 0;
}

.lead {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 11px 12px;
  margin-bottom: 9px;
  box-shadow: var(--shadow);
}
.lead-top { display: flex; align-items: baseline; gap: 8px; }
.lead-name { font-weight: 600; font-size: .93rem; text-decoration: none; color: var(--text); }
a.lead-name:hover { color: var(--brand); text-decoration: underline; }
.lead-when { margin-left: auto; font-size: .74rem; color: var(--muted); white-space: nowrap; }
.lead-meta { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.lead-who { margin: 8px 0 0; font-size: .78rem; color: var(--muted); }
.lead-who .muted-strong { color: var(--warn); font-weight: 600; }

/* Wraps, because a card that offers a stage AND a lost-reason cannot fit both
   plus a button on one line in a 290px column. Without flex-wrap the form
   simply grew, and since .board-col is a flex item with the default
   min-width:auto it grew with it — widening the board past its own scroller
   and taking the whole document sideways with it. */
.lead-move { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.lead-move select { flex: 1 1 120px; min-width: 0; font-size: .82rem; padding: 5px 7px; }
.lead-move .btn { flex: 0 0 auto; }

/* The same guard on the column itself: a card with an awkwardly long name or
   a wide control must never be able to stretch its column. */
.board-col { min-width: 0; }
.board-col > * { max-width: 100%; }

/* ------------------------------------------------- board controls, 0.12.0 */

.board-toggle { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 12px; }
.board-toggle .hint { margin: 0; }

/* One tap, and the only control that works on a phone. Hidden on a desktop,
   where the card can be dragged and the select is right there. */
.lead-next { display: none; margin-top: 10px; }
.btn.block { display: block; width: 100%; }

/* Dragging. The cursor is the whole affordance — there is no handle, because
   a handle on a 290px card costs more width than it earns. */
.lead.is-draggable { cursor: grab; }
.lead.is-draggable:active { cursor: grabbing; }
.lead.is-dragging { opacity: .45; }
.lead.is-saving { opacity: .6; }

/* Refused by the server and put back. Deliberately slow enough to notice:
   a card that silently returns to where it started reads as a gesture that
   did not register, which is a different thing from one that was refused. */
.lead.is-rejected { outline: 2px solid var(--bad); outline-offset: 2px; }

.board-col.is-over { background: #eef4f2; border-color: var(--brand); }

.board-error {
  font-size: .8rem;
  color: var(--bad);
  background: var(--surface);
  border: 1px solid currentColor;
  border-radius: 6px;
  padding: 6px 8px;
  margin: 0 0 8px;
}

@media (max-width: 700px) {
  /* The select plus a submit is three taps and a scroll inside a 290px
     column. On a phone the next stage is the move that is nearly always
     wanted, so it gets a button and the full control stays underneath. */
  .lead-next { display: block; }
}

/* Screen-reader-only. Each card's stage control needs a label, and repeating
 * the lead's name visually on every card would be noise. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 700px) {
  .board-col { flex: 0 0 84vw; }
}

/* ------------------------------------------------- follow-up reminders 0.5.0 */

/* The count beside "Follow-ups" in the navigation. Only rendered when it is
 * greater than zero — a badge showing 0 is a thing to ignore, and a navigation
 * full of zeros teaches people to ignore badges generally. */
.nav-count {
  display: inline-block;
  min-width: 18px;
  padding: 0 5px;
  margin-left: 4px;
  border-radius: 999px;
  background: var(--bad);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  vertical-align: 1px;
}

.badge.bad  { background: var(--bad-bg);  color: var(--bad); }
.badge.warn { background: var(--warn-bg); color: var(--warn); }

.contact-panel .btn-group { display: flex; gap: 6px; }

/* The signed-in address in the platform bar is now a link to the password
 * page. It keeps the muted weight of a label rather than shouting like a nav
 * item — it is a destination you want occasionally, not a section. */
a.who { color: inherit; text-decoration: none; }
a.who:hover { text-decoration: underline; }

/* A lead form's public address: forty hex characters with nothing to break on.
 * Left alone it widened the whole page on a phone, so it is told explicitly
 * that it may wrap mid-token. */
code.form-address {
  font-size: 12px;
  word-break: break-all;
  overflow-wrap: anywhere;
}

/* ------------------------------------------------------- numbers overview */
/* The inbox panel when no conversation is open: one stat tile per connected
 * number. It replaced a two-line "Select a conversation" that occupied the
 * largest area on the screen to say something people read once. */

.overview { padding: 22px 24px 32px; overflow-y: auto; height: 100%; }
.overview-head h3 { margin: 0 0 4px; font-size: 17px; }
.overview-head .hint { margin: 0 0 18px; max-width: 54ch; }
.overview-foot { margin-top: 18px; }

.overview-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(236px, 1fr));
  gap: 14px;
}

.num-card {
  display: block;
  padding: 15px 16px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  color: inherit;
}
.num-card:hover {
  text-decoration: none;
  border-color: var(--border-strong);
  box-shadow: 0 2px 4px rgba(16, 24, 40, .07), 0 4px 10px rgba(16, 24, 40, .07);
}

.num-head { display: flex; align-items: center; gap: 8px; }
/* The brand colour appears as a small dot rather than a filled bar: a card
 * tinted with a customer-chosen colour stops being readable the moment they
 * choose a dark one. */
.num-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.num-name {
  font-weight: 650;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.num-phone {
  margin: 2px 0 12px 18px;
  font-size: 13px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.num-figures { display: flex; gap: 18px; margin-bottom: 10px; }
.num-figure { display: flex; flex-direction: column; }
/* Stat-tile value, not a hero figure — there are several per screen, and a
 * view gets at most one hero. Proportional figures: tabular widths make a
 * standalone number look loose at this size. */
.num-value { font-size: 22px; font-weight: 650; line-height: 1.1; }
.num-value.is-unread { color: var(--brand); }
.num-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }

.spark { display: block; width: 100%; height: 34px; }
.num-week { margin: 6px 0 0; font-size: 12px; color: var(--muted); }
.num-week strong { color: var(--text); }
.num-quiet { margin: 10px 0 0; font-size: 12px; color: var(--muted); }

@media (max-width: 860px) {
  /* On a phone the thread pane is a separate screen and is hidden until a
     conversation is picked — which would have hidden this panel completely.
     So when nothing is open it moves ABOVE the conversation list as a short
     swipeable row: the same information, without pushing the conversations
     off the screen. */
  body:not(.thread-open) .inbox { display: flex; flex-direction: column; }
  body:not(.thread-open) .inbox .thread {
    display: block;
    order: -1;
    min-height: 0;
    border-bottom: 1px solid var(--border);
  }

  .overview { padding: 14px 12px 12px; height: auto; overflow: visible; }
  .overview-head h3 { font-size: 15px; }
  /* The explanatory lines are desktop affordances; on a phone they cost a
     screenful to say what the cards already show. */
  .overview-head .hint, .overview-foot { display: none; }

  .overview-grid {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    padding-bottom: 4px;
  }
  .num-card { flex: 0 0 208px; scroll-snap-align: start; }

  /* Three figures side by side need about 80px each for their labels, and a
     phone-width card has 46px. Side by side, "can reply free" wrapped onto
     four lines and doubled the height of every card. Stacked, each figure is
     one short line and the card gets shorter, not taller. */
  .num-figures { flex-direction: column; gap: 3px; margin-bottom: 8px; }
  .num-figure { flex-direction: row; align-items: baseline; gap: 6px; }
  .num-value { font-size: 17px; }
  .num-label { font-size: 12px; text-transform: none; letter-spacing: 0; }
}

/* -------------------------------------------------- one number, full width */
/* Opened from a card on the inbox overview. The narrow inbox column is built
 * for triage beside an open thread; this is the same conversations given the
 * whole page, because "show me everything on this number" is a different
 * question from "which one do I answer next". */

.number-page { max-width: 1100px; }
.number-head { margin-bottom: 14px; }
.number-title { display: flex; align-items: center; gap: 10px; }
.number-title h1 { margin: 0; font-size: 22px; }
.number-head .sub { margin: 4px 0 0; }

.number-filters { display: flex; gap: 8px; margin-bottom: 12px; }
.number-filters input[type="search"] { flex: 1 1 auto; min-width: 0; margin: 0; }

.tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.number-count { margin: 0 0 10px; }

.conv-cards { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }

.conv-card {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
/* Unread is carried by a left edge rather than a tinted row: a filled
 * background fights every badge sitting on it. */
.conv-card.is-unread { border-left: 3px solid var(--brand); }

.conv-card-main { flex: 1 1 auto; min-width: 0; }
.conv-card-name { font-weight: 650; font-size: 16px; color: var(--text); }
.conv-card-name:hover { color: var(--brand); }
.conv-card-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 5px 0 6px; }
.conv-card-meta .mono { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.conv-card-preview {
  margin: 0;
  color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.conv-card-side { flex: 0 0 auto; text-align: right; }
.conv-card-time { display: block; font-size: 12px; color: var(--muted); margin-bottom: 8px; }
.conv-card-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
.conv-card-actions form { display: flex; gap: 6px; margin: 0; }
.conv-card-actions select { margin: 0; padding: 4px 8px; font-size: 13px; max-width: 150px; }

.pager { display: flex; align-items: center; gap: 12px; margin-top: 16px; }

@media (max-width: 760px) {
  /* Stacked: the action row needs the full width once it wraps, and a
     right-aligned column 90px wide squeezes the preview into nothing. */
  .conv-card { flex-direction: column; gap: 10px; }
  .conv-card-side { text-align: left; width: 100%; }
  .conv-card-actions { justify-content: flex-start; }
  .conv-card-preview { white-space: normal; }
  .number-filters { flex-wrap: wrap; }
}

/* ------------------------------------------------------ per-number access */
/* The channel checkboxes on Settings → Staff. They sit inside the same form
 * as the role and status selectors, so one Apply saves all three — two forms
 * would let somebody change a role and believe the ticks went with it. */

.brand-access {
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
  margin-top: 8px;
}
.brand-access-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
}
.brand-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-weight: 400;
  white-space: nowrap;
}
.brand-check input { margin: 0; }

/* ------------------------------------------------- lead stage history */

/* A stage chip is coloured by its OUTCOME, never by its name: customers
   rename stages, and a class built from "Reg link sent" would be a class
   nobody styled. Three outcomes, three colours, any wording. */
.badge.stage-open { background: var(--surface-2); color: var(--ink);  border-color: var(--border); }
.badge.stage-won  { background: var(--ok-bg);    color: var(--ok);    border-color: #bfe3ce; }
.badge.stage-lost { background: var(--bad-bg);   color: var(--bad);   border-color: #f5c6c6; }

.stage-history { list-style: none; margin: 8px 0 0; padding: 0; }
.stage-history li {
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.stage-history li:last-child { border-bottom: 0; }
.stage-history .stage-move { display: block; }

/* A terminal column is dimmed, not hidden: 0.11.0 shows Won and Lost at the
   end of the board so the shape of the process is visible. 0.12.0 adds the
   toggle that collapses them by default. */
.board-col.is-terminal { opacity: .82; }
.lead-stale { margin: 4px 0 0; }

/* 0.13.0: the way into the new inbox, beside the account name. */
.topbar .try-new {
  font-size: 13px; font-weight: 600; color: #fff;
  border: 1px solid rgba(255,255,255,.35); border-radius: 999px;
  padding: 5px 12px; margin-right: 12px; white-space: nowrap;
}
.topbar .try-new:hover { background: rgba(255,255,255,.12); text-decoration: none; }
@media (max-width: 720px) { .topbar .try-new { padding: 4px 9px; margin-right: 6px; font-size: 12px; } }

/* Installable app (0.14.0). The button stays hidden until the browser says
   installing is possible; [hidden] must beat .btn / .linkbtn display rules. */
[data-pwa-install][hidden] { display: none !important; }
.topbar .install-app { white-space: nowrap; margin-right: 6px; }
/* Installed app: respect the phone's status bar and gesture area. */
@media (display-mode: standalone) {
  body { padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom); }
}

/* 0.15.0: Connect WhatsApp and the connection screen. */
.connect-routes { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; }
.connect-route { display: flex; flex-direction: column; gap: 10px; }
.connect-route .btn { align-self: flex-start; margin-top: auto; }
.checklist, .hint-list { margin: 8px 0 0; padding-left: 20px; }
.checklist li { margin: 6px 0; }
.hint-list li { margin: 4px 0; font-size: 13px; color: var(--muted, #5b6876); }
.facts { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 12px 0 0; }
.facts dt { color: var(--muted, #5b6876); }
.facts dd { margin: 0; font-weight: 500; }
form.inline { display: inline; }
.alert[hidden] { display: none; }

/* ===================================================== 0.15.1 inbox dashboard
   Colour carries meaning here, one hue per kind of work, used the same way
   in the summary tiles and on every number's card:
     amber   waiting for a reply      red     unread
     violet  open, nobody assigned    rose    reply window about to shut
     blue    messages in today        slate   open (neutral)
   Each pairs a dark text colour with a pale tint of itself, so the figure
   stays above 4.5:1 whatever the tile. A figure of zero drops to grey, so
   the colour on screen is always something to act on. */

:root {
  --t-wait: #92400e;       --t-wait-bg: #fef3c7;
  --t-unread: #b91c1c;     --t-unread-bg: #fee2e2;
  --t-unassigned: #6d28d9; --t-unassigned-bg: #ede9fe;
  --t-closing: #be123c;    --t-closing-bg: #ffe4e6;
  --t-today: #1d4ed8;      --t-today-bg: #dbeafe;
  --t-open: #334155;       --t-open-bg: #e2e8f0;
}

.overview { background: linear-gradient(180deg, #eef6f2 0, var(--bg) 220px); }
.overview-head h3 { font-size: 19px; }
.overview-head .hint { margin-bottom: 14px; }
.overview-sub { margin: 26px 0 12px; font-size: 15px; }

.glance {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}
.glance-tile {
  --tc: var(--t-open); --tb: var(--t-open-bg);
  display: flex; flex-direction: column; gap: 2px;
  padding: 14px 16px;
  border-radius: 12px;
  background: var(--tb);
  color: var(--tc);
  border: 1px solid color-mix(in srgb, var(--tc) 18%, transparent);
  box-shadow: var(--shadow);
  transition: transform .12s ease, box-shadow .12s ease;
}
a.glance-tile:hover { text-decoration: none; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(16, 24, 40, .10); }
.glance-value { font-size: 30px; font-weight: 750; line-height: 1.05; letter-spacing: -.02em; }
.glance-label { font-size: 13px; font-weight: 600; }
.glance-sub { font-size: 12px; opacity: .85; }
.t-wait       { --tc: var(--t-wait);       --tb: var(--t-wait-bg); }
.t-unread     { --tc: var(--t-unread);     --tb: var(--t-unread-bg); }
.t-unassigned { --tc: var(--t-unassigned); --tb: var(--t-unassigned-bg); }
.t-closing    { --tc: var(--t-closing);    --tb: var(--t-closing-bg); }
.t-today      { --tc: var(--t-today);      --tb: var(--t-today-bg); }
.glance-tile.is-zero { --tc: #64748b; --tb: #f1f5f9; box-shadow: none; }

/* A number's card: its own brand colour as a top bar and a faint wash, so
   four brands are told apart at a glance. The wash is 7% of the colour over
   white, light enough that body text stays readable on any brand colour. */
.num-card {
  --nc: #0F263E;
  display: flex; flex-direction: column;
  padding: 0 0 12px;
  overflow: hidden;
  border-top: 0;
}
.num-card::before {
  content: ""; display: block; height: 5px; background: var(--nc);
}
.num-card .num-head {
  padding: 12px 16px 0;
  background: linear-gradient(180deg, color-mix(in srgb, var(--nc) 7%, #fff), #fff);
}
.num-card .num-phone { margin: 2px 16px 12px 34px; }
.num-card .num-name { color: var(--text); font-size: 16px; }
.num-card .num-name:hover { color: var(--nc); }

.num-stats {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px;
  padding: 0 12px;
}
.num-stats .stat {
  --tc: var(--t-open); --tb: var(--t-open-bg);
  display: flex; flex-direction: column; align-items: center;
  padding: 7px 4px 6px;
  border-radius: 9px;
  background: var(--tb); color: var(--tc);
  min-width: 0;
}
.num-stats .stat:hover { text-decoration: none; filter: brightness(.97); }
.num-stats .stat b { font-size: 19px; line-height: 1.1; font-weight: 750; }
.num-stats .stat span { font-size: 10px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.num-stats .s-wait       { --tc: var(--t-wait);       --tb: var(--t-wait-bg); }
.num-stats .s-unread     { --tc: var(--t-unread);     --tb: var(--t-unread-bg); }
.num-stats .s-unassigned { --tc: var(--t-unassigned); --tb: var(--t-unassigned-bg); }
.num-stats .stat.is-zero { --tc: #64748b; --tb: #f1f5f9; }

.num-alert, .num-note, .num-card .num-quiet, .num-card .num-week { margin: 10px 16px 0; font-size: 12.5px; }
.num-alert {
  padding: 6px 9px; border-radius: 7px;
  background: var(--t-closing-bg); color: var(--t-closing); font-weight: 600;
}
.num-note { color: var(--t-wait); font-weight: 600; }
.num-card .spark { margin: 10px 16px 0; width: calc(100% - 32px); }
.num-foot {
  display: flex; justify-content: space-between; gap: 10px;
  margin: 12px 16px 0; padding-top: 10px;
  border-top: 1px solid var(--border);
  font-size: 13px; font-weight: 600;
}
.num-foot a { color: var(--nc); }
.num-foot a + a { color: var(--muted); font-weight: 500; }

@media (max-width: 860px) {
  .overview { background: var(--bg); }
  .glance { display: flex; overflow-x: auto; gap: 8px; padding-bottom: 4px; scroll-snap-type: x proximity; }
  .glance-tile { flex: 0 0 132px; padding: 10px 12px; scroll-snap-align: start; }
  .glance-value { font-size: 22px; }
  .glance-sub { display: none; }
  .overview-sub { margin: 14px 0 8px; }
  .num-card { flex: 0 0 248px; }
  .num-stats { grid-template-columns: repeat(2, 1fr); }
  .num-card .num-week { font-size: 12px; }
}

/* ======================================== 0.15.1 the reply box stays in view
   The inbox is exactly one screen tall on a laptop: the conversation list,
   the thread and the customer panel each scroll on their own, so the reply
   box is always at the bottom of the screen instead of the bottom of the
   page. Before, the page grew with the thread and the box was a long scroll
   away. */
@media (min-width: 761px) {
  .inbox {
    height: calc(100vh - 56px);
    height: calc(100dvh - 56px);
    min-height: 0;
  }
  .inbox-list, .thread, .contact-panel { min-height: 0; max-height: 100%; }
  .thread { overflow: hidden; }
  .messages { min-height: 0; }
  /* A long template form must not push the thread off the screen. */
  .composer { flex: 0 0 auto; max-height: 55%; overflow-y: auto; }
}
@media (max-width: 760px) {
  body.thread-open .thread {
    height: calc(100vh - 56px);
    height: calc(100dvh - 56px);
    min-height: 0;
    overflow: hidden;
  }
  body.thread-open .messages { min-height: 0; }
  body.thread-open .composer { flex: 0 0 auto; max-height: 60%; overflow-y: auto; }
}

/* ============================== 0.15.1 contact edit form, closed by default */
.panel-edit { margin-top: 18px; border-top: 1px solid var(--border); padding-top: 12px; }
.panel-edit > summary {
  cursor: pointer; list-style: none;
  font-size: 12px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--muted); font-weight: 650;
  display: flex; align-items: center; justify-content: space-between;
}
.panel-edit > summary::-webkit-details-marker { display: none; }
.panel-edit > summary::after { content: "Edit \25BE"; text-transform: none; letter-spacing: 0; color: var(--brand); font-size: 13px; }
.panel-edit[open] > summary::after { content: "Close \25B4"; }
.panel-edit > form { margin-top: 12px; }

/* ======================================================= 0.15.2 links and fit
   The number's name is the way into its page, so it looks like a link: the
   brand colour, an arrow, an underline on hover. */
.num-card .num-name { color: var(--nc); text-decoration: none; display: inline-flex; align-items: center; gap: 4px; }
.num-card .num-name:hover { text-decoration: underline; color: var(--nc); }
.num-go { font-size: 20px; line-height: 1; transition: transform .12s ease; }
.num-card .num-name:hover .num-go { transform: translateX(2px); }
.num-card.is-chosen { box-shadow: 0 0 0 2px var(--nc), var(--shadow); }
.num-stats .stat { cursor: pointer; transition: transform .12s ease; }
.num-stats .stat:hover { transform: translateY(-1px); }

.filter-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  margin: 0 0 14px; padding: 12px 14px;
  border-radius: 10px; background: #fff; border: 1px solid var(--border);
  border-left: 4px solid var(--brand); box-shadow: var(--shadow);
}
.filter-banner-hint { color: var(--muted); font-size: 13px; }

.chip-wait.on   { background: var(--t-wait-bg);   color: var(--t-wait);   border-color: currentColor; }
.chip-unread.on { background: var(--t-unread-bg); color: var(--t-unread); border-color: currentColor; }

/* Pipeline: the board uses the whole window width, and the columns share it,
   so five or six stages fit on a laptop without scrolling sideways. More
   stages than fit still scroll inside the board, never the page. */
.page:has(.board-scroll) { max-width: none; }
.board { min-width: 100%; }
.board-col { flex: 1 0 200px; max-width: 340px; }
@media (max-width: 700px) {
  .board-col { flex: 0 0 84vw; max-width: none; }
}

/* ===================================================== 0.15.3 brand colours
   Each number speaks in its own colour. --nb is the brand colour as chosen
   (the top bar, the dot); --nc is the same hue darkened only as far as text
   on white needs, so a lime brand reads lime-green rather than navy. */
.num-card::before { background: var(--nb, var(--nc)); }
.num-card .num-head { background: linear-gradient(180deg, color-mix(in srgb, var(--nb, var(--nc)) 12%, #fff), #fff); }

/* The name is a clear button: "this is <brand>; click to see its conversations". */
.num-card .num-name {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px 6px 10px; margin-left: -2px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--nb, var(--nc)) 14%, #fff);
  border: 1px solid color-mix(in srgb, var(--nb, var(--nc)) 35%, #fff);
  color: var(--nc); font-size: 16px; font-weight: 750; letter-spacing: -.01em;
  text-decoration: none;
  transition: background .12s ease, box-shadow .12s ease;
}
.num-card .num-name:hover {
  text-decoration: none; color: var(--nc);
  background: color-mix(in srgb, var(--nb, var(--nc)) 24%, #fff);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--nb, var(--nc)) 25%, transparent);
}
.num-card .num-name .num-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
.num-card .num-go { font-size: 20px; line-height: 1; }
.num-card .num-phone { margin: 6px 16px 12px 16px; }
.num-card .num-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 14px 14px 0; }

/* Pipeline: columns use the window's height, cards are compact, so more leads
   are visible at once. */
.board-col { max-height: max(var(--board-max, 0px), calc(100vh - 110px)); }
.lead { padding: 10px 12px; }
.lead-top { margin-bottom: 2px; }
.lead-who { margin: 4px 0 6px; font-size: 12.5px; }
.lead-move { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.lead-move select { flex: 1 1 110px; min-width: 0; font-size: 13px; padding: 5px 8px; }
.lead-move .btn { flex: 0 0 auto; }
.lead-move select[hidden] { display: none; }

/* ===================================================== 0.15.4 brand logos */
.num-card .num-name .num-logo {
  width: 34px; height: 34px; border-radius: 9px; object-fit: contain;
  background: #fff; border: 1px solid color-mix(in srgb, var(--nb, var(--nc)) 30%, #fff);
  margin: -4px 0 -4px -4px; flex: 0 0 auto;
}
.num-card .num-name { font-size: 17px; }
.number-title { display: flex; align-items: center; gap: 12px; }
.number-logo { width: 44px; height: 44px; border-radius: 11px; object-fit: contain; background: #fff; border: 1px solid var(--border); }
.logo-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.logo-preview { width: 64px; height: 64px; border-radius: 14px; object-fit: contain; background: #fff; border: 1px solid var(--border); }
.logo-empty { display: inline-flex; align-items: center; justify-content: center; font-size: 12px; color: var(--muted); }

/* ============================================= 0.15.4 the full logo as name
   When a number has a logo, the whole logo (mark plus lettering) stands in
   for the name, as large as the card allows: 64px tall, never wider than the
   card. A wide wordmark and a square badge both fit without distortion. */
.num-brand {
  display: flex; align-items: center; gap: 6px;
  min-height: 64px; max-width: 100%;
  padding: 4px 8px 4px 2px; border-radius: 12px;
  color: var(--nc); text-decoration: none;
  transition: background .12s ease;
}
.num-brand:hover { background: color-mix(in srgb, var(--nb, var(--nc)) 10%, transparent); text-decoration: none; }
.num-brand img { display: block; height: 64px; width: auto; max-width: calc(100% - 22px); object-fit: contain; }
.num-brand .num-go { font-size: 22px; }
.number-logo { width: auto; height: 72px; max-width: 320px; border: 0; background: transparent; border-radius: 12px; object-fit: contain; }

/* ===================================================== 0.15.5 bolder tiles
   Solid colour with white lettering: every pair is above 4.5:1, so the
   figures read sharply from across a room. No opacity on text (it blurs
   on some screens); hierarchy comes from size and weight instead. A tile
   with nothing to do turns plain white with grey text. */
.glance { gap: 14px; }
.glance-tile {
  --g1: #B45309; --g2: #92400E;
  background: linear-gradient(135deg, var(--g1), var(--g2));
  color: #fff;
  border: 0;
  border-radius: 14px;
  padding: 16px 18px 15px;
  min-height: 0;
  box-shadow: 0 6px 16px -6px color-mix(in srgb, var(--g2) 60%, transparent);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  position: relative;
  overflow: hidden;
}
.glance-tile::after {          /* a soft highlight, so the tile is not flat */
  content: ""; position: absolute; right: -30px; top: -30px;
  width: 110px; height: 110px; border-radius: 50%;
  background: rgba(255, 255, 255, .10); pointer-events: none;
}
.glance-value { font-size: 34px; font-weight: 800; letter-spacing: -.02em; color: #fff; text-shadow: 0 1px 1px rgba(0, 0, 0, .15); }
.glance-label { font-size: 14px; font-weight: 700; color: #fff; }
.glance-sub { font-size: 12.5px; font-weight: 600; color: #fff; opacity: 1; margin-top: 4px; }
a.glance-tile:hover { transform: translateY(-2px); box-shadow: 0 10px 22px -8px color-mix(in srgb, var(--g2) 70%, transparent); }
a.glance-tile:focus-visible { outline: 3px solid #111827; outline-offset: 2px; }

.t-wait       { --g1: #C2410C; --g2: #92400E; }   /* amber   */
.t-unread     { --g1: #DC2626; --g2: #B91C1C; }   /* red     */
.t-unassigned { --g1: #7C3AED; --g2: #5B21B6; }   /* violet  */
.t-closing    { --g1: #E11D48; --g2: #9F1239; }   /* rose    */
.t-today      { --g1: #2563EB; --g2: #1E40AF; }   /* blue    */

.glance-tile.is-zero {
  background: #fff; color: #475569;
  border: 1px solid var(--border); box-shadow: none;
}
.glance-tile.is-zero::after { display: none; }
.glance-tile.is-zero .glance-value { color: #64748B; text-shadow: none; }
.glance-tile.is-zero .glance-label { color: #334155; }
.glance-tile.is-zero .glance-sub { color: #475569; }

/* The small figures on each number card: darker text on the same tints. */
.num-stats .stat b { font-weight: 800; }
.num-stats .stat span { font-weight: 700; font-size: 10.5px; }
.num-stats .s-wait       { --tc: #92400E; }
.num-stats .s-unread     { --tc: #991B1B; }
.num-stats .s-unassigned { --tc: #5B21B6; }
.num-stats .stat.is-zero { --tc: #475569; }

@media (max-width: 860px) {
  .glance-value { font-size: 26px; }
}

/* =========================================== 0.15.6 colour across every page
   Each part of the product has its own colour (set by data-section on the
   body): the page title, the edge of each card heading and the active menu
   item take it, so you always know where you are.
     inbox green · pipeline violet · reports blue · follow-ups amber ·
     settings teal. All are dark enough for text (above 4.5:1 on white). */
body                          { --sec: #047857; --sec-bg: #ECFDF5; }
body[data-section="pipeline"] { --sec: #6D28D9; --sec-bg: #F5F3FF; }
body[data-section="reports"]  { --sec: #1D4ED8; --sec-bg: #EFF6FF; }
body[data-section="followups"]{ --sec: #B45309; --sec-bg: #FFFBEB; }
body[data-section="settings"] { --sec: #0F766E; --sec-bg: #F0FDFA; }

.page > h1:first-child, .page > h1 {
  display: flex; align-items: center; gap: 12px;
  color: #0F172A; font-weight: 800; letter-spacing: -.02em;
}
.page > h1::before {
  content: ""; width: 8px; height: 30px; border-radius: 4px;
  background: linear-gradient(180deg, var(--sec), color-mix(in srgb, var(--sec) 55%, #fff));
}
.page { background: linear-gradient(180deg, var(--sec-bg) 0, transparent 260px); }
.page.wide { background: none; }
.page > .sub { color: #475569; }
.card > h2:first-child, .card > h2 {
  border-left: 4px solid var(--sec); padding-left: 10px; margin-left: -2px;
}
.topbar nav a.active { box-shadow: inset 0 -3px 0 color-mix(in srgb, var(--sec) 70%, #fff); }

/* Figure tiles on Reports and Settings: coloured, sharp, never grey.
   They cycle through a palette so neighbouring figures are told apart. */
.card-row > .card:has(> .stat) {
  --c: #1D4ED8; --c-bg: #EFF6FF;
  background: linear-gradient(135deg, var(--c-bg), #fff 75%);
  border: 1px solid color-mix(in srgb, var(--c) 22%, #fff);
  border-top: 4px solid var(--c);
  padding: 16px 18px;
}
.card-row > .card:has(> .stat):nth-child(5n+2) { --c: #047857; --c-bg: #ECFDF5; }
.card-row > .card:has(> .stat):nth-child(5n+3) { --c: #6D28D9; --c-bg: #F5F3FF; }
.card-row > .card:has(> .stat):nth-child(5n+4) { --c: #B45309; --c-bg: #FFFBEB; }
.card-row > .card:has(> .stat):nth-child(5n+5) { --c: #BE123C; --c-bg: #FFF1F2; }
.card-row > .card > .stat {
  color: var(--c); font-size: 32px; font-weight: 800; letter-spacing: -.02em; line-height: 1.1;
  background: none; padding: 0; text-align: left;
  -webkit-font-smoothing: antialiased;
}
.card-row > .card > .stat-label { color: #1E293B; font-size: 14px; font-weight: 700; margin-top: 2px; }
.card-row > .card > .hint { color: #475569; margin: 4px 0 0; }
/* Four figures sit in one row on a laptop instead of three plus one stretched. */
.card-row > .card:has(> .stat) { flex: 1 1 200px; }

/* Pipeline: pick a number straight from the empty board. */
.pick-numbers { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 18px; }
.pick-number {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 64px; padding: 10px 18px; border-radius: 14px;
  background: #fff; color: var(--nc); font-weight: 750; font-size: 16px; text-decoration: none;
  border: 2px solid color-mix(in srgb, var(--nb) 35%, #fff);
  box-shadow: var(--shadow); transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
.pick-number:hover { text-decoration: none; transform: translateY(-2px); border-color: var(--nb); box-shadow: 0 8px 18px -8px color-mix(in srgb, var(--nb) 60%, transparent); }
.pick-number img { height: 44px; width: auto; max-width: 200px; object-fit: contain; }
.pick-number .num-dot { width: 12px; height: 12px; border-radius: 50%; }

/* Settings: each number's own colour or logo in the list. */
.brand-cell { display: inline-flex; align-items: center; gap: 10px; font-weight: 700; }
.brand-cell img { height: 40px; width: auto; max-width: 200px; object-fit: contain; }
.brand-cell .num-dot { width: 10px; height: 10px; border-radius: 50%; }

/* Follow-ups: each tab in the colour of what it holds. */
.fu-tab { --fc: #047857; }
.fu-overdue  { --fc: #B91C1C; }
.fu-today    { --fc: #B45309; }
.fu-upcoming { --fc: #1D4ED8; }
.fu-done     { --fc: #475569; }
.btn.fu-tab.secondary { color: var(--fc); border-color: color-mix(in srgb, var(--fc) 35%, #fff); background: #fff; }
.btn.fu-tab.on { background: var(--fc); border-color: var(--fc); color: #fff; }

/* =============================================== 0.15.8 number cards, calmer
   Wider cards (at most four to a row, three on a laptop beside the list),
   and the four figures as a 2 × 2 grid of rows — label left, figure right —
   so every word is written out in full and a four-digit figure fits. */
.overview-grid { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 18px; }
.num-card { padding: 0 0 16px; border-radius: 16px; }
.num-card .num-head { padding: 16px 18px 6px; }
.num-card .num-phone { margin: 0 18px 14px; font-size: 13px; color: #475569; letter-spacing: .01em; }

.num-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 0 18px; }
.num-stats .stat {
  flex-direction: row; align-items: center; justify-content: space-between;
  gap: 8px; padding: 10px 12px; border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--tc) 18%, transparent);
}
.num-stats .stat .stat-label { font-size: 13px; font-weight: 700; color: var(--tc); margin: 0; white-space: nowrap; }
.num-stats .stat b { font-size: 22px; font-weight: 800; line-height: 1; color: var(--tc); font-variant-numeric: tabular-nums; }
.num-stats .stat.is-zero { border-color: #E2E8F0; }
.num-stats .stat.is-zero .stat-label, .num-stats .stat.is-zero b { color: #64748B; }

.num-card .num-alert, .num-card .num-note, .num-card .num-quiet { margin: 14px 18px 0; font-size: 13px; }
.num-card .num-note { color: #92400E; font-weight: 600; }
.num-card .num-note strong { font-weight: 800; }
.num-card .num-quiet { color: #64748B; }
.num-card .spark { margin: 12px 18px 0; width: calc(100% - 36px); height: 38px; }
.num-card .num-week { display: flex; gap: 16px; margin: 6px 18px 0; font-size: 13px; color: #475569; }
.num-card .num-week strong { color: #0F172A; font-weight: 800; }

.num-brand img { height: 56px; }
@media (max-width: 860px) {
  .num-card { flex: 0 0 300px; }
  .num-stats { grid-template-columns: 1fr 1fr; }
}
.num-card .num-phone { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* ===================================================== 0.15.9 the list panel
   The filter panel gets the inbox's own green wash, a search box with a
   magnifier, and chips that carry the same colours as the dashboard tiles:
   All green, Waiting amber, Unread red, Open blue, Resolved slate. An
   inactive chip is white with coloured text and a coloured count; the
   chosen one is solid with white text. */
.inbox-filters {
  padding: 14px 14px 12px;
  background: linear-gradient(180deg, #E8F5EF 0%, #F4FAF7 100%);
  border-bottom: 1px solid #CFE6DA;
}
.inbox-filters input[type="search"] {
  padding: 10px 12px 10px 38px;
  border-radius: 12px; border: 1px solid #BFDCCD; background: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23047857' stroke-width='2.4' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: 12px 50%;
  font-size: 14px; box-shadow: 0 1px 2px rgba(4, 120, 87, .06);
}
.inbox-filters input[type="search"]:focus { border-color: #047857; box-shadow: 0 0 0 3px rgba(4, 120, 87, .15); outline: none; }
.inbox-filters select {
  border-radius: 10px; border: 1px solid #BFDCCD; background-color: #fff;
  font-weight: 600; color: #0F172A; padding: 8px 10px;
}
.inbox-filters select:focus { border-color: #047857; box-shadow: 0 0 0 3px rgba(4, 120, 87, .15); outline: none; }

.chiprow { gap: 7px; margin-top: 10px; }
.chiprow .chip {
  --cc: #047857; --cc-bg: #ECFDF5;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 6px 5px 11px; border-radius: 999px;
  background: #fff; color: var(--cc); font-weight: 700; font-size: 12.5px;
  border: 1px solid color-mix(in srgb, var(--cc) 30%, #fff);
}
.chiprow .chip span {
  min-width: 22px; padding: 1px 7px; border-radius: 999px; text-align: center;
  background: var(--cc-bg); color: var(--cc); font-weight: 800; font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.chiprow .chip:hover { background: var(--cc-bg); text-decoration: none; }
.chiprow .chip.on { background: var(--cc); border-color: var(--cc); color: #fff; box-shadow: 0 3px 8px -3px color-mix(in srgb, var(--cc) 70%, transparent); }
.chiprow .chip.on span { background: rgba(255, 255, 255, .22); color: #fff; }
.chiprow .chip-all      { --cc: #047857; --cc-bg: #ECFDF5; }
.chiprow .chip-wait     { --cc: #B45309; --cc-bg: #FEF3C7; }
.chiprow .chip-unread   { --cc: #B91C1C; --cc-bg: #FEE2E2; }
.chiprow .chip-open     { --cc: #1D4ED8; --cc-bg: #DBEAFE; }
.chiprow .chip-resolved { --cc: #475569; --cc-bg: #E2E8F0; }

/* ===================================================== 0.16.0 getting started
   A new workspace's first screen: a welcome and five steps that tick
   themselves. The next step to do is highlighted; done steps go quiet. */
.getting-started {
  background: #fff; border: 1px solid #CFE6DA; border-radius: 16px;
  box-shadow: var(--shadow); padding: 20px 22px; margin-bottom: 22px;
}
.getting-started.is-welcome {
  max-width: 760px; margin: 24px auto;
  background: linear-gradient(160deg, #ECFDF5 0%, #fff 55%);
  border-top: 5px solid #047857; padding: 28px 30px;
}
.gs-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-bottom: 14px; }
.gs-kicker { margin: 0 0 4px; font-size: 12px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: #047857; }
.getting-started h3 { margin: 0; font-size: 20px; font-weight: 800; color: #0F172A; }
.getting-started.is-welcome h3 { font-size: 26px; letter-spacing: -.02em; }
.gs-sub { margin: 4px 0 0; color: #475569; font-size: 14px; }
.gs-progress { flex: 0 0 180px; height: 10px; border-radius: 999px; background: #E2E8F0; overflow: hidden; }
.gs-progress span { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, #059669, #047857); }
.gs-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.gs-step {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 14px; border-radius: 12px; border: 1px solid #E2E8F0; background: #fff;
}
.gs-step.is-next { border-color: #047857; box-shadow: 0 0 0 3px rgba(4, 120, 87, .12); }
.gs-num {
  flex: 0 0 32px; height: 32px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 14px; color: #047857; background: #ECFDF5; border: 2px solid #A7F3D0;
}
.gs-step.is-next .gs-num { background: #047857; color: #fff; border-color: #047857; }
.gs-step.is-done .gs-num { background: #047857; color: #fff; border-color: #047857; }
.gs-body { flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.gs-body strong { color: #0F172A; font-size: 15px; }
.gs-body span { color: #475569; font-size: 13px; }
.gs-step.is-done { background: #F8FAFC; }
.gs-step.is-done .gs-body strong { color: #64748B; text-decoration: line-through; text-decoration-color: #94A3B8; }
.gs-tick { font-size: 12px; font-weight: 800; color: #047857; }
.gs-hide { margin-top: 10px; text-align: right; }
.gs-hide .linkbtn { background: none; border: 0; color: #64748B; font-size: 13px; cursor: pointer; text-decoration: underline; }
@media (max-width: 640px) {
  .gs-step { flex-wrap: wrap; }
  .gs-step .btn { margin-left: 46px; }
}

/* 0.16.1: one inbox. /inbox on its own is the dashboard, full width, with no
   conversation list beside it; the list is the inbox at /new. */
.inbox.dashboard-only > .thread { flex: 1 1 auto; width: 100%; background: linear-gradient(180deg, #eef6f2 0, var(--bg) 220px); }
.inbox.dashboard-only .overview { background: transparent; }
.inbox.dashboard-only .overview { max-width: 1280px; margin: 0 auto; width: 100%; }
@media (max-width: 900px) {
  .inbox.dashboard-only { display: block; }
  body:not(.thread-open) .inbox.dashboard-only .thread { display: block; border-bottom: 0; }
}

/* 0.16.2: four clearly different colours on the figures — amber waiting,
   blue unread, violet nobody assigned, green open — the same as the inbox. */
.t-unread     { --g1: #2563EB; --g2: #1E40AF; }
.t-today      { --g1: #16A34A; --g2: #166534; }
.num-stats .s-wait       { --tc: #92400E; --tb: #FEF3C7; }
.num-stats .s-unread     { --tc: #1E40AF; --tb: #DBEAFE; }
.num-stats .s-unassigned { --tc: #5B21B6; --tb: #EDE9FE; }
.num-stats .s-open       { --tc: #166534; --tb: #DCFCE7; }
.num-stats .stat:not(.is-zero) { background: var(--tb); border-color: color-mix(in srgb, var(--tc) 30%, transparent); }
.num-stats .stat { gap: 6px; padding: 10px; min-width: 0; }
.num-stats .stat .stat-label { font-size: 12.5px; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.num-stats .stat b { font-size: 19px; flex: none; }

/* 0.16.3: Waiting gold, Unread reddish orange (the same as the inbox). */
.t-wait       { --g1: #B8860B; --g2: #854D0E; }
.t-unread     { --g1: #EA4A1F; --g2: #B3300B; }
.num-stats .s-wait       { --tc: #854D0E; --tb: #FEF9C3; }
.num-stats .s-unread     { --tc: #B3300B; --tb: #FFE8DD; }

/* ============================================ 0.16.5 phones and tablets
   Below 900px the row of links in the top bar no longer fits (it clipped
   "Reports" and pushed Sign out under the links). Instead: the page name at
   the top, a Menu for everything, and a tab bar at the bottom with the same
   five places as the inbox. The dashboard's figures and number cards stack
   instead of scrolling sideways. */
.topbar-title, .topmenu, .tabbar { display: none; }
.topmenu summary { list-style: none; cursor: pointer; }
.topmenu summary::-webkit-details-marker { display: none; }

@media (max-width: 1180px) {
  .topbar .who { display: none; }
  .topbar nav a { padding: 6px 9px; }
}

@media (max-width: 900px) {
  .topbar { overflow: visible; gap: 10px; padding: 0 12px; padding-top: env(safe-area-inset-top); }
  .topbar .logo { font-size: 0; gap: 0; }               /* the mark only */
  .topbar .logo img { height: 30px; width: 30px; border-radius: 8px; }
  .topbar nav, .topbar .who, .topbar .signout-desk, .topbar > .install-app { display: none !important; }
  .topbar .spacer { display: block; flex: 1; }
  .topbar-title { display: block; color: #fff; font-size: 17px; font-weight: 750; letter-spacing: -.01em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }

  .topmenu { display: block; position: relative; }
  .topmenu summary {
    display: flex; align-items: center; gap: 6px; height: 40px; padding: 0 12px;
    border-radius: 10px; color: #fff; font-size: 14px; font-weight: 600;
    background: rgba(255,255,255,.12);
  }
  .topmenu[open] summary { background: rgba(255,255,255,.22); }
  .topmenu-panel {
    position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
    width: min(280px, calc(100vw - 24px));
    background: #fff; color: var(--text); border: 1px solid var(--border);
    border-radius: 14px; padding: 8px; box-shadow: 0 16px 40px -12px rgba(16,24,40,.35);
  }
  .topmenu-panel a, .topmenu-panel .linkbtn, .topmenu-signout {
    display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px; padding: 0 12px;
    border-radius: 10px; color: var(--text); font-size: 15px; font-weight: 600; text-decoration: none;
    background: none; border: 0; font-family: inherit; cursor: pointer; text-align: left; opacity: 1;
  }
  .topmenu-panel a:hover, .topmenu-panel .linkbtn:hover, .topmenu-signout:hover { background: #F1F5F9; text-decoration: none; }
  .topmenu-panel form { display: block; border-top: 1px solid var(--border); margin-top: 6px; padding-top: 6px; }
  .topmenu-signout { color: #B91C1C; }
  .topmenu-who { margin: 4px 12px 8px; font-size: 13px; color: #64748B; line-height: 1.4; }
  .topmenu-who strong { color: var(--text); font-size: 14px; }

  .tabbar {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
    background: #fff; border-top: 1px solid var(--border);
    padding: 4px 4px max(env(safe-area-inset-bottom), 8px);
    box-shadow: 0 -4px 16px -8px rgba(16,24,40,.12);
  }
  .tabbar a {
    position: relative; flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: 6px 2px 2px; color: #64748B; font-size: 11.5px; font-weight: 600; text-decoration: none; border-radius: 10px;
  }
  .tabbar a span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
  .tabbar a.on { color: var(--sec, #047857); }
  .tabbar a.on svg { stroke-width: 2.2; }
  .tabbar .tab-count {
    position: absolute; top: 2px; left: calc(50% + 6px); min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: 9px; background: #DC2626; color: #fff; font-size: 11px; line-height: 18px; text-align: center;
  }
  .app { padding-bottom: calc(64px + env(safe-area-inset-bottom)); }
  /* A conversation in the basic inbox keeps its reply box at the bottom. */
  body.thread-open .tabbar { display: none; }
  body.thread-open .app { padding-bottom: 0; }

  /* Dashboard: figures in a grid, number cards one under another. */
  .glance { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; overflow: visible; }
  .glance-tile { flex: none; min-width: 0; padding: 14px; }
  .glance-sub { display: block; }
  .overview-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; overflow: visible; padding-bottom: 0; }
  .num-card { flex: none; min-width: 0; }
  .overview-head .hint { display: block; }
  .page { padding: 16px 14px 28px; }

  /* Wide tables scroll inside their card; the numbers list stacks (below). */
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

@media (max-width: 600px) {
  .glance { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .glance-tile:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .glance-value { font-size: 28px; }
  .glance-label { font-size: 13px; }
  .overview-grid { grid-template-columns: 1fr; }
  .page h1 { font-size: 22px; }
  .btn-group { flex-wrap: wrap; }
  table.stack-sm, table.stack-sm tbody, table.stack-sm tr, table.stack-sm td { display: block; width: 100%; }
  table.stack-sm tr.head { display: none; }
  table.stack-sm tr { padding: 10px 0; border-bottom: 1px solid var(--border); }
  table.stack-sm td { border: 0; padding: 3px 0; }
}

/* 0.16.6: "Reply window shuts" in its own deep teal, coloured even at 0,
   so it never looks like an empty white box beside the others. */
.t-closing { --g1: #0E7490; --g2: #164E63; }

/* 0.16.8: keep me signed in */
.auth-card .remember { display: flex; align-items: center; gap: 9px; margin: 2px 0 14px; font-size: 14px; color: var(--text, inherit); cursor: pointer; }
.auth-card .remember input { width: 18px; height: 18px; margin: 0; accent-color: var(--brand); }
.num-card a.num-offboarded { display: block; text-decoration: none; font-weight: 700; line-height: 1.4; }

/* Connect Facebook and Instagram (0.18.0) */
.check-row { display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; cursor: pointer; }
.check-row input { margin-top: 3px; flex: none; }
.badge.kind-messenger { background: #E7F0FF; color: #0B4FC2; }
.badge.kind-instagram { background: #FCE7F3; color: #9D174D; }

/* ------------------------------------------- assignment you can't miss 0.19.0 */

/* Violet means "handed to you". Separate from the red unread and follow-up
 * counts so the two never read as one number. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.nav-count.nav-assign { background: #6D28D9; }
.tabbar .tab-count.tab-assign { background: #6D28D9; }

.assign-banner {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 10px 16px 0; padding: 10px 14px;
  border-radius: 12px;
  background: linear-gradient(135deg, #7C3AED, #5B21B6);
  color: #fff; font-size: 14px; line-height: 1.4;
  box-shadow: 0 6px 16px -8px rgba(91, 33, 182, .7);
}
.assign-banner-dot { width: 9px; height: 9px; border-radius: 50%; background: #fff; flex: none; box-shadow: 0 0 0 4px rgba(255, 255, 255, .25); }
.assign-banner-text { flex: 1 1 200px; min-width: 0; }
.assign-banner-open {
  flex: none; padding: 6px 14px; border-radius: 9px;
  background: #fff; color: #5B21B6; font-weight: 800; text-decoration: none;
}
.assign-banner-open:hover { text-decoration: none; background: #EDE9FE; }
.assign-banner-open:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }

.t-mine { --g1: #6D28D9; --g2: #3B0764; --tc: #4C1D95; --tb: #EDE9FE; }

.conv.mine { box-shadow: inset 4px 0 0 #6D28D9; }
.badge.mine { background: #EDE9FE; color: #5B21B6; font-weight: 700; }
.badge.assign-new { background: #6D28D9; color: #fff; font-weight: 800; letter-spacing: .04em; }

.task-strip {
  margin: 8px 16px 0; padding: 8px 12px; border-radius: 10px;
  background: #F5F3FF; border: 1px solid #DDD6FE; color: #4C1D95; font-size: 13.5px;
}
.task-strip.other { background: #F8FAFC; border-color: var(--border); color: #334155; }
.task-strip .not-seen { color: #B45309; font-weight: 700; }
.assign-task { margin: 6px 16px 0; font-size: 13px; }
.assign-task summary { cursor: pointer; color: #5B21B6; font-weight: 700; }
.assign-task-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: end; margin-top: 8px; }
.assign-task-form label { display: flex; flex-direction: column; gap: 2px; font-size: 12px; font-weight: 600; }
.assign-task-form input[type=text] { min-width: 200px; }

/* ------------------------------------------------ team view, notifications 0.20.0 */
.team-card { overflow-x: auto; }
.team-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.team-table th, .team-table td { padding: 10px 10px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; }
.team-table th { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted, #64748B); }
.team-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.team-table td.hot { color: #B45309; font-weight: 800; }
.team-table td.violet { color: #6D28D9; font-weight: 800; }
.team-table td.warn { color: #B91C1C; font-weight: 800; }
.team-table tr.team-unassigned td { background: #F5F3FF; }
.team-role { display: inline-block; margin-left: 6px; font-size: 12px; color: var(--muted, #64748B); }
.team-task { font-size: 12.5px; color: #4C1D95; margin-top: 2px; }
.team-move { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.team-move select { width: auto; min-width: 140px; max-width: 220px; }
.team-move .btn { flex: none; }
.check-row { display: flex; gap: 10px; align-items: flex-start; padding: 8px 0; font-size: 14.5px; line-height: 1.45; cursor: pointer; }
.check-row input { margin-top: 4px; flex: none; }
.hint.warn { color: #B45309; }
@media (max-width: 640px) {
  .team-table th, .team-table td { padding: 8px 6px; font-size: 13px; }
  .team-table .opt { display: none; }
  .team-table th { font-size: 10.5px; letter-spacing: .02em; white-space: normal; }
  .team-table .num { white-space: normal; }
  .team-role { display: block; margin-left: 0; }
}
