/* DealDesk — dark-first UI */
:root {
  --bg: #0e1116;
  --bg-raise: #161b23;
  --bg-card: #1c232e;
  --line: #2a3342;
  --text: #e8ecf2;
  --muted: #96a1b3;
  --accent: #d9a441;        /* brass */
  --accent-ink: #171006;
  --green: #4fc98c;
  --red: #e2685f;
  --blue: #6ba5e7;
  --radius: 10px;
  font-size: 15px;
}

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

body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Instrument Sans', system-ui, -apple-system, sans-serif;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* ---------- top bar ---------- */
/* Wraps rather than scrolls: on a phone the brand keeps the first line and the
   chips drop to a second one, so the page itself never gains a sideways
   scrollbar just because a signed-in email is long. */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 6px 14px;
  padding: 14px 22px; border-bottom: 1px solid var(--line);
  background: var(--bg-raise);
  position: sticky; top: 0; z-index: 10;
}
.brand { display: flex; align-items: center; gap: 12px; min-width: 0; }
.brand-logo { height: 28px; display: block; }
.brand-mark {
  font-weight: 700; font-size: 1.35rem;
  color: var(--accent); letter-spacing: 0.01em;
}
.brand-for {
  color: var(--muted); font-size: 0.9rem;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.topbar-right { display: flex; align-items: center; gap: 14px; min-width: 0; }
.tagline { color: var(--muted); font-style: italic; font-size: 0.85rem; }
.agent-chip {
  background: var(--bg-card); border: 1px solid var(--line); border-radius: 999px;
  padding: 4px 12px; font-size: 0.8rem; color: var(--muted);
  /* Long addresses truncate instead of pushing the header wider than the
     viewport. The local part — the identifying half — stays readable. */
  min-width: 0; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Phone: the tagline is decorative, and it is the piece that leaves the
   brand and the chips fighting over one line. */
@media (max-width: 720px) {
  .topbar { padding: 12px 14px; }
  .tagline { display: none; }
}

main { flex: 1; padding: 20px 22px; max-width: 1500px; width: 100%; margin: 0 auto; }
.hidden { display: none !important; }

/* ---------- buttons / forms ---------- */
.btn {
  border: 1px solid var(--line); background: var(--bg-card); color: var(--text);
  border-radius: 8px; padding: 8px 14px; font: inherit; font-weight: 600;
  cursor: pointer; font-size: 0.88rem;
}
.btn:hover { border-color: var(--accent); }
.btn.primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.btn.primary:hover { filter: brightness(1.1); }
.btn.ghost { background: transparent; }
.btn.small { padding: 4px 10px; font-size: 0.8rem; }
.btn.danger { color: var(--red); }

label { display: flex; flex-direction: column; gap: 4px; font-size: 0.8rem; color: var(--muted); font-weight: 600; }
input, select, textarea {
  background: var(--bg); border: 1px solid var(--line); border-radius: 7px;
  color: var(--text); padding: 8px 10px; font: inherit; font-size: 0.9rem;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); }
textarea { resize: vertical; min-height: 70px; }

.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.row3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }
.row4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }

/* ---------- board ---------- */
.board-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
/* Wraps rather than widening the page: this row grew an operator Users button
   and already ran past a phone's width on brokerage accounts. */
.board-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-left: auto; }
.board-actions #board-search { width: 240px; }

.digest-panel {
  background: color-mix(in srgb, var(--accent) 10%, var(--bg-raise));
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line));
  border-radius: var(--radius); padding: 12px 16px; font-size: 0.85rem; flex: 1;
}
.digest-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
.digest-head strong { color: var(--accent); font-size: 0.95rem; }
.digest-head > span { display: flex; align-items: center; gap: 8px; }
.digest-item {
  padding: 8px 0; border-top: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
  display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap;
}
.digest-item-actions { display: flex; gap: 6px; flex: none; }
.digest-item .digest-draft { flex-basis: 100%; }
.digest-item b { color: var(--text); cursor: pointer; }
.digest-item b:hover { color: var(--accent); }
.digest-reason { color: var(--muted); }
.digest-rec { color: var(--text); margin-top: 2px; font-size: 0.82rem; }
.digest-item .btn { margin-top: 6px; }
.digest-draft { margin-top: 8px; background: var(--bg-card); border: 1px solid var(--line); border-radius: 8px; padding: 10px; }
.digest-draft pre { white-space: pre-wrap; font-family: inherit; font-size: 0.82rem; line-height: 1.45; }

.badge.ai { color: var(--accent); border-color: var(--accent); }
.dlg-hint { color: var(--muted); font-size: 0.8rem; margin: -8px 0 6px; }
/* That pull-up is measured against dialog h2's 14px bottom margin, which
   leaves the hint 6px under its heading. An h3 has no bottom margin under the
   global reset, so the same pull-up would drag the hint onto the heading —
   state the 6px outright instead. */
dialog h3 + .dlg-hint { margin-top: 6px; }

.board {
  display: grid; grid-template-columns: repeat(6, minmax(200px, 1fr));
  gap: 12px; overflow-x: auto; align-items: start;
}
.col { background: var(--bg-raise); border: 1px solid var(--line); border-radius: var(--radius); min-height: 180px; }
.col-head {
  padding: 10px 12px; border-bottom: 1px solid var(--line);
  display: flex; justify-content: space-between; align-items: center;
}
.col-head h3 { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.col-head .count { background: var(--bg-card); border-radius: 999px; padding: 1px 9px; font-size: 0.75rem; color: var(--muted); }
.col-body { padding: 10px; display: flex; flex-direction: column; gap: 8px; }

.card {
  background: var(--bg-card); border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 12px; cursor: pointer; transition: border-color 0.15s;
}
.card:hover { border-color: var(--accent); }
.card.dragging { opacity: 0.45; }
.col.drag-over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 6%, transparent); }
.card .owner {
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.03em;
  color: var(--accent); margin-bottom: 3px;
}
.deal-head .owner {
  font-size: 0.82rem; font-weight: 600; letter-spacing: 0.03em;
  color: var(--accent); margin-bottom: 2px;
}
.card .addr {
  font-weight: 700; font-size: 0.92rem;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 6px;
}
/* Walkthrough-attached marker: a brass play glyph pinned to the right of the
   address row, so a wrapping address never orphans it onto its own line. */
.card .has-video {
  flex: none; margin-top: 1px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; border-radius: 999px;
  font-size: 0.55rem; line-height: 1; padding-left: 1px;
  color: var(--accent-ink); background: var(--accent);
}
.card .meta { color: var(--muted); font-size: 0.78rem; margin-top: 3px; }
.card .badges { margin-top: 6px; display: flex; gap: 6px; flex-wrap: wrap; }
.badge {
  font-size: 0.68rem; font-weight: 700; padding: 2px 7px; border-radius: 999px;
  background: var(--bg-raise); border: 1px solid var(--line); color: var(--muted);
}
.badge.demo { color: var(--blue); border-color: var(--blue); }
.badge.due { color: var(--accent); border-color: var(--accent); }
.badge.comps { color: var(--green); border-color: color-mix(in srgb, var(--green) 50%, var(--line)); }

/* ---------- deal detail ---------- */
.back { margin-bottom: 14px; }
.deal-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 14px; flex-wrap: wrap; margin-bottom: 4px; }
.deal-head h1 { font-size: 1.6rem; font-weight: 700; letter-spacing: -0.01em; }
.deal-head .sub { color: var(--muted); margin-top: 4px; font-size: 0.9rem; }
.deal-head-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
/* The person a buyer deal belongs to (cross-links §2.4). Sized like .sub so
   it reads as part of the header rather than as a control. */
.deal-head .deal-person { margin-top: 6px; font-size: 0.9rem; }
.deal-head .deal-person a { color: var(--accent); font-weight: 600; }

.stage-pills { display: flex; gap: 4px; margin: 16px 0; flex-wrap: wrap; }
.stage-pill {
  border: 1px solid var(--line); background: var(--bg-raise); color: var(--muted);
  padding: 6px 12px; border-radius: 999px; font-size: 0.78rem; font-weight: 700; cursor: pointer;
}
.stage-pill.done { color: var(--green); border-color: color-mix(in srgb, var(--green) 45%, var(--line)); }
.stage-pill.current { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin-bottom: 16px; flex-wrap: wrap; }
.tab {
  padding: 9px 16px; cursor: pointer; color: var(--muted); font-weight: 600; font-size: 0.88rem;
  border: none; background: none; border-bottom: 2px solid transparent; font-family: inherit;
}
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }

.panel { display: grid; gap: 14px; }
.card-block { background: var(--bg-raise); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px; }
.card-block h3 { font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); margin-bottom: 12px; }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; }
@media (max-width: 900px) { .split { grid-template-columns: 1fr; } .board { grid-template-columns: repeat(2, 1fr); } .row3, .row4 { grid-template-columns: 1fr 1fr; } }

table.data { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
table.data th { text-align: left; color: var(--muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em; padding: 6px 8px; border-bottom: 1px solid var(--line); }
table.data td { padding: 8px; border-bottom: 1px solid color-mix(in srgb, var(--line) 50%, transparent); }
table.data tr:last-child td { border-bottom: none; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 10px; }
.stat { background: var(--bg-card); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; }
.stat .k { color: var(--muted); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; }
.stat .v { font-size: 1.15rem; font-weight: 800; margin-top: 3px; }
.stat .v.good { color: var(--green); }
.stat .v.bad { color: var(--red); }
.stat .v.accent { color: var(--accent); }

.est-note { color: var(--muted); font-size: 0.75rem; font-style: italic; margin-top: 8px; }

/* score */
.score-wrap { display: flex; gap: 20px; align-items: center; }
.score-ring {
  width: 110px; height: 110px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; position: relative;
}
.score-ring .inner {
  width: 86px; height: 86px; border-radius: 50%; background: var(--bg-raise);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.score-ring .num { font-size: 1.7rem; font-weight: 800; }
.score-ring .lbl { font-size: 0.6rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }
.reasons { list-style: none; display: grid; gap: 5px; font-size: 0.83rem; }
.reasons li { color: var(--muted); }
.reasons li b { color: var(--text); }

/* outreach drafts */
.draft { background: var(--bg-card); border: 1px solid var(--line); border-radius: 8px; padding: 12px; }
.draft-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.draft-head .ch { font-weight: 800; text-transform: uppercase; font-size: 0.72rem; letter-spacing: 0.08em; color: var(--accent); }
.draft pre { white-space: pre-wrap; font-family: inherit; font-size: 0.85rem; color: var(--text); line-height: 1.45; }
.drafts { display: grid; gap: 10px; }

/* follow-ups */
.fu-item { border-left: 1px solid color-mix(in srgb, var(--line) 70%, transparent); padding: 6px 12px; margin-bottom: 10px; }
.fu-item .when { color: var(--muted); font-size: 0.72rem; }
.fu-item .status { font-weight: 700; font-size: 0.8rem; }
.fu-item .status.replied, .fu-item .status.booked_call, .fu-item .status.deal_active { color: var(--green); }
.fu-item .status.no_reply { color: var(--muted); }
.fu-item .next { color: var(--accent); font-size: 0.8rem; margin-top: 3px; }

.compliance-inline {
  background: color-mix(in srgb, var(--blue) 8%, var(--bg-raise));
  border: 1px solid color-mix(in srgb, var(--blue) 30%, var(--line));
  border-radius: 8px; padding: 10px 12px; font-size: 0.78rem; color: var(--muted);
}

/* dialog */
dialog {
  background: var(--bg-raise); color: var(--text); border: 1px solid var(--line);
  border-radius: 12px; padding: 22px; width: min(560px, 92vw); margin: auto;
}
dialog::backdrop { background: rgba(5, 8, 12, 0.7); }
dialog h2 { font-weight: 700; font-size: 1.15rem; margin-bottom: 14px; }
dialog form { display: grid; gap: 10px; }
.dlg-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 8px; }
/* A long dialog shouldn't make you scroll to the bottom just to leave: the
   title bar rides along and carries the same close as the footer. It supplies
   the dialog's own top padding (see #dlg-users) rather than being pulled above
   it — an element starting outside the scrollport gets scrolled into view when
   it takes focus, which nudged the first line of copy under the header. The
   side margins still span the padding so nothing scrolls out beside it. */
.dlg-head {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 0 -22px 14px; padding: 18px 22px 10px;
  background: var(--bg-raise); border-bottom: 1px solid var(--line);
}
.dlg-head h2 { margin-bottom: 0; }
/* A square icon target, not a shrunken text button — 38px stays comfortable
   under a thumb on the phone, where this dialog is longest. */
.dlg-x { flex: none; width: 38px; height: 38px; padding: 0; display: grid; place-items: center; line-height: 1; }
#btn-logout { margin-right: auto; }

/* footer */
.disclaimer {
  border-top: 1px solid var(--line); background: var(--bg-raise);
  color: var(--muted); font-size: 0.72rem; padding: 12px 22px; line-height: 1.5;
}

.empty { color: var(--muted); font-size: 0.85rem; padding: 8px 0; }

/* listing media */
.media-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: 14px; }
.media-item video { width: 100%; border-radius: 8px; border: 1px solid var(--line); background: #000; display: block; }
.media-meta { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; font-size: 0.85rem; }
input[type="file"] { border-style: dashed; padding: 14px; width: 100%; }
.toast {
  position: fixed; bottom: 20px; right: 20px; background: var(--bg-card);
  border: 1px solid var(--accent); border-radius: 8px; padding: 10px 16px;
  font-size: 0.85rem; z-index: 100;
}

/* Listing Media orders */
.order-pitch { color: var(--muted); font-size: 0.88rem; line-height: 1.5; max-width: 60ch; }
#lightbox {
  position: fixed; inset: 0; z-index: 100;
  display: none; align-items: center; justify-content: center; gap: 14px;
  background: rgba(4, 8, 14, 0.88); padding: 28px;
}
#lightbox.open { display: flex; }
#lightbox figure { margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 10px; align-items: center; }
#lightbox img {
  max-width: min(1400px, 84vw); max-height: 84vh; object-fit: contain;
  border-radius: 10px; border: 1px solid var(--line); background: var(--bg-card);
}
#lightbox figcaption { color: var(--muted); font-size: 0.85rem; text-align: center; }
.lb-nav, .lb-close {
  flex: none; width: 42px; height: 42px; border-radius: 999px; cursor: pointer;
  background: var(--bg-card); border: 1px solid var(--line); color: var(--text); font-size: 0.95rem;
}
.lb-nav:hover, .lb-close:hover { border-color: var(--accent); color: var(--accent); }
.lb-close { position: absolute; top: 18px; right: 18px; }
.thumb img { cursor: zoom-in; }

.tour-zone { margin-top: 10px; border: 1px dashed var(--line); border-radius: 10px; padding: 10px; }
.tour-zone.drag-over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 6%, transparent); }
.tour-zone .thumb-grid { margin-top: 0; }
.tour-zone .thumb { cursor: grab; }
.tour-zone .thumb.drag-target { outline: 2px solid var(--accent); outline-offset: 2px; }
.drop-hint { color: var(--muted); font-size: 0.85rem; text-align: center; padding: 26px 12px; }
.lib-add { position: absolute; top: 6px; right: 6px; padding: 2px 9px; }
#lib-grid .thumb { position: relative; }

.past-order { margin-top: 10px; border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px; }
.past-order summary { cursor: pointer; font-size: 0.85rem; color: var(--muted); }
.past-order[open] summary { color: var(--text); }

.thumb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin-top: 12px; }
.thumb { background: var(--bg-card); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.thumb img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; }
.thumb-cap { font-size: 0.72rem; color: var(--muted); padding: 6px 8px 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.thumb-actions { display: flex; gap: 4px; padding: 0 6px 6px; }
.thumb-actions .btn { padding: 2px 8px; }
.order-status { display: inline-block; font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--line); }
.order-status.submitted { color: var(--accent); border-color: var(--accent); }
.order-status.in_production { color: var(--blue); border-color: var(--blue); }
.order-status.delivered { color: var(--green); border-color: var(--green); }
.order-status.canceled { color: var(--muted); }
.queue-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; }
.queue-item { margin-bottom: 12px; }

/* credits */
.credit-chip {
  background: color-mix(in srgb, var(--accent) 12%, var(--bg-card));
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
  border-radius: 999px; padding: 4px 12px; font-size: 0.8rem;
  color: var(--accent); font-weight: 600; cursor: pointer; white-space: nowrap;
}
.credit-chip:hover { filter: brightness(1.15); }
#dlg-credits { width: min(640px, 92vw); }
.credit-balances { display: flex; gap: 24px; font-size: 1.05rem; }
.credit-balances b { font-size: 1.5rem; color: var(--accent); margin-right: 4px; }
#dlg-credits h3 { font-size: 0.95rem; font-weight: 600; margin-bottom: 8px; }
.pack-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 8px; }
.pack-btn { display: flex; flex-direction: column; gap: 2px; align-items: center; padding: 10px 8px; }
.pack-btn span { color: var(--muted); font-weight: 500; font-size: 0.82rem; }
/* User roster (operator dialog). Wider than the default dialog because the
   roster is a table: identity, activity, role, and actions on one line. */
#dlg-users { width: min(820px, 94vw); max-height: min(88vh, calc(100% - 2em)); overflow: auto; padding-top: 0; }
.user-list { display: flex; flex-direction: column; gap: 4px; }
/* Fixed track widths, not auto — every row is its own grid, so content-sized
   columns would make each row align differently and the list read as ragged. */
.user-row {
  display: grid;
  /* name · how they sign in · deals · role · actions */
  grid-template-columns: minmax(0, 1fr) 128px 64px 104px 250px;
  gap: 12px; align-items: center;
  min-height: 58px; /* pinned rows carry a badge, not a select — keep the rhythm */
  padding: 10px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--bg-card);
}
.user-row > div { min-width: 0; }
.user-row b { overflow-wrap: anywhere; }
.user-row .empty { padding: 0; font-size: 0.78rem; }
.user-row select { width: 100%; }
.user-off { opacity: 0.55; }

/* How someone signs in. Colour carries the same meaning as the words, never
   instead of them — the label is always readable on its own. */
.signin {
  display: inline-block; font-size: 0.72rem; font-weight: 600;
  padding: 2px 7px; border-radius: 999px; white-space: nowrap;
  border: 1px solid var(--line);
}
.signin-ok   { color: #7BC59A; border-color: #2E6B4F; background: rgba(46,107,79,.14); }
.signin-wait { color: var(--sand, #C98A4B); border-color: #7a5a30; background: rgba(201,138,75,.12); }
.signin-off  { color: var(--muted); }

/* Viewing-as banner. Sticky and undismissable — the whole point is that it
   cannot be lost behind a scroll while the operator reads someone else's data. */
.impersonating {
  position: sticky; top: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  gap: 14px; flex-wrap: wrap;
  padding: 9px 14px; font-size: 0.86rem;
  color: #1B1220; background: var(--sand, #C98A4B);
  border-bottom: 1px solid #8a5f2f;
}
.impersonating b { font-weight: 800; }
.impersonating .btn {
  background: #1B1220; color: #F3E4D2; border: 0;
  padding: 5px 11px; font-size: 0.8rem;
}
.impersonating .btn:hover { background: #2e2032; }
@media (max-width: 560px) { .impersonating { flex-direction: column; gap: 8px; text-align: center; } }

.invite-box {
  margin-top: 14px; padding: 12px; border-radius: 8px;
  border: 1px solid var(--sand, #C98A4B); background: rgba(201,138,75,.08);
}
.invite-row { display: flex; gap: 8px; margin: 8px 0 6px; }
.invite-row input {
  flex: 1 1 auto; min-width: 0; font-family: ui-monospace, Menlo, monospace;
  font-size: 0.8rem; padding: 7px 9px;
}
.user-row-actions { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; }
#dlg-users .grant-row { flex-wrap: wrap; }
#dlg-users .grant-row input { flex: 1 1 160px; min-width: 0; }
@media (max-width: 720px) {
  .user-row { grid-template-columns: 1fr; gap: 6px; }
  .user-row-actions { justify-content: flex-start; }
  .user-row select { width: auto; }
}

.grant-row { display: flex; gap: 8px; align-items: center; }
.grant-row input {
  background: var(--bg-card); border: 1px solid var(--line); border-radius: 8px;
  color: var(--text); font: inherit; padding: 8px 10px; flex: 1;
}
.credit-hist { display: grid; gap: 2px; max-height: 220px; overflow-y: auto; font-size: 0.82rem; }
.credit-hist-row { display: grid; grid-template-columns: 90px 36px 1fr auto; gap: 8px; padding: 4px 0; border-bottom: 1px solid var(--line); }
.credit-hist-row .pos { color: var(--green); font-weight: 600; }
.credit-hist-row .neg { color: var(--red); font-weight: 600; }
/* The property is the headline of a ledger line; the order number and city
   trail it as small print for whoever needs to match it to the queue. */
.credit-hist-row .hist-deal { color: var(--text); text-decoration: none; border-bottom: 1px solid var(--line); }
.credit-hist-row .hist-deal:hover { color: var(--accent); border-bottom-color: currentColor; }
.credit-hist-row .hist-detail { font-size: 0.92em; margin-left: 6px; white-space: nowrap; }

/* ---------- live render progress ---------- */
/* Shown while a Listing Media order is actually being built. The bar is fed
   by real clip state, so it is allowed to look precise. */
.render-progress {
  margin-top: 14px; padding: 14px 16px;
  background: var(--bg-raise); border: 1px solid var(--line);
  border-radius: var(--radius);
}
.render-progress.failed { border-color: color-mix(in srgb, var(--red) 55%, var(--line)); }

.render-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
}
.render-stage { font-weight: 600; font-size: 0.95rem; }
.render-pct { color: var(--accent); font-variant-numeric: tabular-nums; font-weight: 700; }
.render-progress.failed .render-stage { color: var(--red); }

.render-bar {
  margin-top: 9px; height: 6px; border-radius: 999px;
  background: var(--bg); overflow: hidden;
}
.render-bar-fill {
  height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 60%, var(--blue)), var(--accent));
  transition: width 0.6s ease;
}
.render-progress.failed .render-bar-fill { background: var(--red); }

/* The bar creeps forward on its own between polls so a long generation never
   reads as a frozen UI — the width jumps back to truth on the next tick. */
@media (prefers-reduced-motion: reduce) {
  .render-bar-fill { transition: none; }
}

.render-meta { margin-top: 7px; color: var(--muted); font-size: 0.82rem; }

.render-clips { list-style: none; margin-top: 11px; display: grid; gap: 3px; }
.render-clips .clip {
  display: flex; align-items: center; gap: 8px;
  font-size: 0.85rem; color: var(--muted);
}
.render-clips .clip-icon { width: 1em; text-align: center; }
.render-clips .clip.succeeded { color: var(--text); }
.render-clips .clip.succeeded .clip-icon { color: var(--green); }
.render-clips .clip.running .clip-icon,
.render-clips .clip.submitted .clip-icon { color: var(--accent); animation: clip-pulse 1.4s ease-in-out infinite; }
.render-clips .clip.failed, .render-clips .clip.dropped { opacity: 0.6; }
.clip-tag.muted { color: var(--muted); border-color: color-mix(in srgb, var(--muted) 30%, transparent); }
.clip-tag {
  font-size: 0.7rem; color: var(--accent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: 999px; padding: 0 6px;
}
@keyframes clip-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) {
  .render-clips .clip-icon { animation: none !important; }
}

.render-log {
  list-style: none; margin-top: 11px; padding-top: 9px;
  border-top: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
  display: grid; gap: 3px; font-size: 0.8rem; color: var(--muted);
}
.render-log .warn { color: var(--accent); }
.render-log .error { color: var(--red); }

/* ---------- viewing another agent's listing (broker read-only) ---------- */
/* The pane still shows everything; the controls are visibly inert so nobody
   types into a form that will be refused. */
.badge.view-only { background: var(--bg-raise); border: 1px solid var(--line); color: var(--muted); }
#deal-detail.view-only button:not(.tab),
#deal-detail.view-only input,
#deal-detail.view-only select,
#deal-detail.view-only textarea,
#deal-detail.view-only .stage-pill { opacity: 0.45; cursor: not-allowed; }
#deal-detail.view-only .tab { opacity: 1; cursor: pointer; }

/* ---------- brokerage mark in the top bar ---------- */
/* Sits beside the DealDesk mark once /api/config hands over its signed URL;
   the "for <name>" text is the fallback while it loads or if it never does. */
.brokerage-logo {
  height: 24px; max-width: 190px; display: block; object-fit: contain;
  padding-left: 12px; border-left: 1px solid var(--line);
}
@media (max-width: 720px) { .brokerage-logo { height: 20px; max-width: 140px; } }

/* ---------- open house ---------- */
.badge.oh { color: var(--green); border-color: color-mix(in srgb, var(--green) 60%, var(--line)); }
#tab-panel > .card-block { min-width: 0; } /* a guest table scrolls inside its block, never the page */
.oh-pulse {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-left: 6px;
  background: var(--green); vertical-align: middle; animation: clip-pulse 1.4s ease-in-out infinite;
}
.oh-live-grid { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 20px; align-items: start; }
.oh-qr canvas {
  width: 184px; height: 184px; display: block; border-radius: 8px;
  image-rendering: pixelated; background: #fff; border: 1px solid var(--line);
}
.oh-count { font-size: 1rem; }
.oh-count b { font-size: 1.9rem; color: var(--accent); font-variant-numeric: tabular-nums; margin-right: 2px; }
.oh-meta { color: var(--muted); font-size: 0.82rem; margin: 4px 0 12px; }
.oh-link-row { display: flex; gap: 8px; }
.oh-link-row input { flex: 1 1 auto; min-width: 0; font-family: ui-monospace, Menlo, monospace; font-size: 0.8rem; }
.oh-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 12px; }
.oh-tip-link { color: var(--muted); font-size: 0.82rem; margin-left: 4px; }
.oh-tip {
  margin-top: 12px; padding: 10px 12px; border-radius: 8px; font-size: 0.82rem; line-height: 1.5;
  background: color-mix(in srgb, var(--blue) 8%, var(--bg-raise));
  border: 1px solid color-mix(in srgb, var(--blue) 30%, var(--line)); color: var(--muted);
}
.oh-tip b { color: var(--text); }
.oh-tip .btn { margin-top: 8px; }
.oh-past-body { padding: 8px 0 4px; }
.oh-past-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 8px; }
.oh-guests { overflow-x: auto; max-width: 100%; }
.oh-table td { white-space: nowrap; }
.oh-table a { color: var(--text); text-decoration: none; border-bottom: 1px solid var(--line); }
.oh-table a:hover { color: var(--accent); border-bottom-color: currentColor; }
.oh-table .oh-when { color: var(--muted); }
.oh-table .oh-deal-link { color: var(--accent); }
/* Phone: the QR goes above the link and buttons, centred, so nothing shrinks. */
@media (max-width: 720px) {
  .oh-live-grid { grid-template-columns: 1fr; }
  .oh-qr canvas { margin: 0 auto; }
  .oh-start .row3 { grid-template-columns: 1fr; }
}

/* ---------- contacts ---------- */
/* People, not properties. A list rather than a table: an agent reads these on
   an iPad between showings, and a name with a phone under it survives a narrow
   screen where seven columns do not. */
.contacts-head { display: flex; align-items: baseline; gap: 12px; margin: 10px 0 14px; }
.contacts-head h1 { font-size: 1.6rem; font-weight: 700; letter-spacing: -0.01em; }
.contacts-filters { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; align-items: center; }
.contacts-filters #contacts-search { flex: 1 1 260px; min-width: 200px; }
/* flex-direction is explicit: the base `label` rule stacks its parts in a
   column, which would put the box above the words. */
.contacts-filters .check {
  display: flex; flex-direction: row; align-items: center; gap: 6px;
  color: var(--muted); font-size: 0.85rem; white-space: nowrap; font-weight: 400;
}
.contacts-filters .check input { width: auto; }
#contacts-list { display: flex; flex-direction: column; gap: 8px; }
.contact-row {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
  background: var(--bg-raise); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 12px 14px; cursor: pointer;
}
.contact-row:hover, .contact-row:focus-visible { border-color: var(--accent); outline: none; }
.contact-row .c-main { min-width: 0; }
.contact-row .c-name { font-weight: 700; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.contact-row .c-reach { font-size: 0.85rem; margin-top: 3px; }
.contact-row .c-reach a { color: var(--text); text-decoration: none; border-bottom: 1px solid var(--line); }
.contact-row .c-reach a:hover { color: var(--accent); border-bottom-color: currentColor; }
.contact-row .c-met { color: var(--muted); font-size: 0.78rem; margin-top: 4px; }
/* Decision 4's one line: a fact about a colleague, not a warning. */
.contact-row .c-shared { color: var(--blue); font-size: 0.78rem; margin-top: 3px; }
.badge.stop { color: var(--red); border-color: color-mix(in srgb, var(--red) 55%, var(--line)); }
.contact-row .c-next { text-align: right; flex: none; max-width: 42%; }
.contact-row .c-action { color: var(--text); font-size: 0.8rem; margin-top: 4px; }
.contact-row .c-when { color: var(--muted); font-size: 0.75rem; margin-top: 2px; }
@media (max-width: 720px) {
  .contact-row { flex-direction: column; gap: 8px; }
  .contact-row .c-next { text-align: left; max-width: 100%; }
}

/* ---------- contact card ---------- */
/* One person, one screen. The reading order is the order an agent needs it in:
   who they are and how to reach them, the one thing owed, what they said,
   anyone who might be them twice, the STOP controls, then the timeline. */
.card-head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
  margin: 10px 0 14px; flex-wrap: wrap;
}
.card-head h1 { font-size: 1.6rem; font-weight: 700; letter-spacing: -0.01em; }
.card-head .c-reach { font-size: 0.9rem; margin-top: 4px; }
.card-head .c-reach a { color: var(--text); text-decoration: none; border-bottom: 1px solid var(--line); }
.card-head .c-reach a:hover { color: var(--accent); border-bottom-color: currentColor; }
.card-head .c-shared { color: var(--blue); font-size: 0.82rem; margin-top: 5px; }
.card-badges { display: flex; gap: 6px; flex-wrap: wrap; }
.card-top { display: grid; grid-template-columns: minmax(200px, 1fr) 2fr; gap: 12px; margin-bottom: 14px; }
.card-next {
  background: var(--bg-raise); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px;
}
/* Owed is the one state worth a colour: it is the reason the screen is open. */
.card-next.owed { border-color: var(--accent); }
.card-next .k { color: var(--muted); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; }
.card-next .v { margin-top: 4px; font-weight: 600; }
.card-next a { display: inline-block; margin-top: 8px; font-size: 0.82rem; color: var(--accent); }
.card-wants { margin: 0; }
.card-block .check {
  display: flex; flex-direction: row; align-items: center; gap: 8px;
  font-weight: 400; margin-top: 8px;
}
.card-block .check input { width: auto; }
.danger-block { border-color: color-mix(in srgb, var(--red) 35%, var(--line)); }
.danger-block .btn { margin-right: 8px; margin-top: 6px; }

/* A suggestion is an offer, not an alert: it says what it thinks and leaves
   both answers the same size. */
.dupe {
  display: flex; justify-content: space-between; align-items: center; gap: 14px; flex-wrap: wrap;
  border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 12px; margin-top: 8px;
}
.dupe .c-name { font-weight: 700; }
.dupe .c-reach, .dupe .c-met { font-size: 0.8rem; color: var(--muted); margin-top: 2px; }
.dupe-act { display: flex; gap: 8px; flex-wrap: wrap; }

/* One timeline, newest first. The left rail is a time column, so a touch and
   the follow-up it produced read as one moment rather than two lists. */
.timeline { list-style: none; margin: 8px 0 0; padding: 0; }
.tl { display: flex; gap: 14px; padding: 10px 0; border-top: 1px solid var(--line); }
.tl:first-child { border-top: none; }
.tl-when { flex: none; width: 150px; color: var(--muted); font-size: 0.78rem; padding-top: 2px; }
.tl-body { min-width: 0; flex: 1; }
.tl-title { font-weight: 600; }
.tl.touch .tl-title a { color: var(--accent); }

/* "Where you've met them" (cross-links §2.3) — the same touches grouped by
   place. A row with no link is the same shape without the colour, so the two
   kinds sit in one list without one looking broken. */
.places { display: flex; flex-direction: column; gap: 10px; }
.place { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.place-where { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.place-where a { color: var(--accent); }
.place-when { color: var(--muted); font-size: 0.78rem; flex: none; }
@media (max-width: 640px) {
  .place { flex-direction: column; gap: 2px; }
}
.tl-said { font-size: 0.85rem; margin-top: 3px; }
.tl-note { color: var(--muted); font-size: 0.78rem; margin-top: 3px; }
.tl-draft {
  white-space: pre-wrap; background: var(--bg-raise); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 8px 10px; margin-top: 6px; font-size: 0.8rem;
}
.tl-body a { display: inline-block; margin-top: 6px; font-size: 0.8rem; color: var(--accent); }
.tl-body .btn.small { margin-top: 8px; }
.tl.touch .tl-title::before { content: '👤 '; }
.tl.followup .tl-title::before { content: '↩ '; }
.tl.draft .tl-title::before { content: '✎ '; }

@media (max-width: 720px) {
  .card-top { grid-template-columns: 1fr; }
  .tl { flex-direction: column; gap: 4px; }
  .tl-when { width: auto; }
}

/* ---- saved searches, seller form, analysis defaults (Oct 2026) ---- */
/* Wider than the default dialog: the match list carries a photo and a line of
   facts, and the defaults form is four rows of three. Top padding comes from
   the sticky .dlg-head, as in #dlg-users. */
dialog.dlg-wide { width: min(720px, 94vw); max-height: 88vh; overflow: auto; padding-top: 0; }
dialog.dlg-wide > .empty:only-child { padding-top: 22px; }
dialog.dlg-wide h3 { font-size: 0.85rem; margin: 6px 0 -2px; color: var(--muted); }
.search-list, .match-list { display: grid; gap: 8px; margin: 4px 0 6px; }
.search-row {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px;
}
.search-row .empty { margin-top: 2px; }
.search-actions { display: flex; gap: 6px; flex: none; }
.match-row {
  display: grid; grid-template-columns: 96px 1fr; gap: 12px; align-items: center;
  border: 1px solid var(--line); border-radius: 10px; padding: 8px; color: inherit; text-decoration: none;
}
.match-row:hover { border-color: var(--accent); }
.match-row img, .match-ph { width: 96px; height: 64px; object-fit: cover; border-radius: 6px; background: var(--line); }
.type-checks { display: flex; flex-wrap: wrap; gap: 6px 14px; }
dialog .check { flex-direction: row; align-items: center; gap: 6px; font-weight: 500; }
dialog .check input { width: auto; }
.sf-actions { display: flex; gap: 8px; margin: 8px 0 14px; }
.sf-grid { display: grid; grid-template-columns: auto 1fr; gap: 16px; align-items: start; }
#sf-embed { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.75rem; }
.an-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.an-head h3 { margin: 0; }
.badge.absentee { color: var(--blue); border-color: color-mix(in srgb, var(--blue) 55%, var(--line)); }
.absentee-note { font-size: 0.82rem; color: var(--text); background: var(--bg); border: 1px solid var(--line);
  border-radius: 8px; padding: 8px 10px; }
.absentee-note.muted { color: var(--muted); }
@media (max-width: 640px) {
  .sf-grid { grid-template-columns: 1fr; }
  .search-row { flex-direction: column; align-items: flex-start; }
}

/* Buyer deal: transaction status (src/disposition.js) */
.txn-block { margin: 12px 0; }
.txn-block .hint { color: var(--muted); font-size: 0.85rem; margin-top: 8px; }
.txn-block .row3 .hint { align-self: end; margin: 0 0 8px; }
