/* Contacts as a table.
 *
 * Scoped to body[data-crm-contacts], which contacts-inbox.js already sets on
 * this route. Every selector below is a plain Tailwind combination that exists
 * on other screens too, and none of this should reach them.
 *
 * WHY A TABLE. The shipped screen is a stack of cards, and a card lays its
 * fields out left to right as they come: a long email pushed the phone right
 * and a longer one pushed it further. Measured on three consecutive rows the
 * phone began at 520, 548 and 584, and "View details" ranged over 347px - 366
 * on a group with no email, 713 on a contact with a long one. Nothing in a
 * column could be read down the page, because there were no columns.
 */

/* ---------- the header ---------- */

.crm-ct-head {
  position: sticky;
  top: 0;
  z-index: 15;
  display: grid;
  align-items: center;
  column-gap: 16px;
  padding: 9px 18px;
  font-size: 13px;
  font-weight: 600;
  color: rgb(var(--slate-12, 40 46 52));
  background-color: #fff;
  background-color: rgb(var(--surface-1));
  border-bottom: 1px solid rgba(130, 140, 155, .22);
}

/* One definition of the columns, shared by the header and every row, so they
   cannot drift apart. */
.crm-ct-head,
body[data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 {
  grid-template-columns: 72px minmax(150px, 1.4fr) minmax(150px, 1.3fr) 150px minmax(130px, 1.2fr) 96px 16px;
}

/* THE USERNAME KEEPS ITS OWN COLUMN.
 *
 * Somebody who wrote in from Messenger, Instagram or Facebook is known by
 * their handle and by nothing else - no email, no phone. It is rendered by our
 * own contacts-inbox overlay as `a.crm-ci__at`, and it sits BESIDE THE NAME on
 * the first line. Left alone it would have been squeezed into the name column
 * against `nowrap` and clipped: the one identifier those contacts have, gone
 * from the screen.
 *
 * The column only exists where it is earned. contacts-list.js marks the body
 * when the list actually holds a handle, so a WhatsApp-only account is not
 * given a column of dashes to scroll past. */
body[data-crm-ct-handles] .crm-ct-head,
body[data-crm-ct-handles][data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 {
  grid-template-columns: 72px minmax(140px, 1.3fr) minmax(110px, .8fr) minmax(140px, 1.1fr) 150px minmax(120px, 1.1fr) 96px 16px;
}

body[data-crm-ct-handles][data-crm-contacts] a.crm-ci__at { grid-column: 3; }
body[data-crm-ct-handles][data-crm-contacts] .crm-ct-gap--handle { grid-column: 3; }
body[data-crm-ct-handles][data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > div.truncate.max-w-72,
body[data-crm-ct-handles][data-crm-contacts] .crm-ct-gap--email { grid-column: 4; }
body[data-crm-ct-handles][data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > span.text-sm,
body[data-crm-ct-handles][data-crm-contacts] .crm-ct-gap--phone { grid-column: 5; }
body[data-crm-ct-handles][data-crm-contacts] .crm-ct-labels { grid-column: 6; }
body[data-crm-ct-handles][data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > button { grid-column: 7; }
body[data-crm-ct-handles][data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 > button { grid-column: 8; }

/* It is a link, and it stays one. */
body[data-crm-contacts] a.crm-ci__at {
  grid-row: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12.5px;
}

/* ---------- the rows ---------- */

/* One list with hairlines, not a stack of floating cards. */
body[data-crm-contacts] div.flex.flex-col.gap-4:has(> div.relative) {
  gap: 0;
}

body[data-crm-contacts] div[class*="outline-n-container"] {
  outline: 0;
  box-shadow: none;
  border-radius: 0;
  border-bottom: 1px solid rgba(130, 140, 155, .1);
  background: transparent;
}

body[data-crm-contacts] div[class*="outline-n-container"]:hover {
  background: rgba(130, 140, 155, .055);
}

body[data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 {
  display: grid;
  align-items: center;
  column-gap: 16px;
  padding: 0 18px;
  min-height: 46px;
}

/* The row's own wrappers step out of the way so each field becomes a cell of
   the row's grid rather than a box inside a box. */
body[data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 > div.flex.items-center.justify-start.flex-1,
body[data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 div.flex.flex-col.flex-1,
body[data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 {
  display: contents;
}

/* Each field is placed BY NAME, never by position. That is what lets a row
   with no email - a group, or an Instagram contact carrying only a handle -
   still put its phone and its link under everybody else's. */
/* EVERY CELL IS PINNED TO ROW 1.
 *
 * Grid places an explicitly-columned item in the first row where that column
 * is free, but it never walks backwards: once the link had been put in column
 * 5, a dash asking for column 3 went to a second row instead. A group - which
 * has neither email nor phone, and so is all dashes - grew a second line and
 * stopped lining up with everything above it. */
body[data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 > *,
body[data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 div.relative.group.flex,
body[data-crm-contacts] div.flex.flex-wrap.items-center.gap-x-4,
body[data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > *,
body[data-crm-contacts] .crm-ct-gap { grid-row: 1; }

body[data-crm-contacts] div.relative.group.flex { grid-column: 1; }
/* THE AVATAR IS NOT SIZED HERE, AND MUST NOT BE.
 *
 * This once read `... flex span, ... flex img { width: 28px }`, which is a
 * DESCENDANT selector: it caught the initials and the photograph as well as
 * the circle. The circle did not move - the page writes `width: 42px` as an
 * INLINE style, which no stylesheet outranks - so the picture inside it was
 * pinned to 28px and every contact with a photo had a small squashed picture
 * adrift in a large circle, beside lettered avatars that filled theirs.
 *
 * The rule is gone rather than corrected. Nothing here needs to set a size:
 * 42px fits the 46px row, and what goes inside the circle is the business of
 * avatar-round.css, which tells it to fill whatever circle it is given. */

body[data-crm-contacts] div.flex.flex-wrap.items-center.gap-x-4 {
  grid-column: 2;
  min-width: 0;
  flex-wrap: nowrap;
}
body[data-crm-contacts] div.flex.flex-wrap.items-center.gap-x-4 span.text-base { font-size: 13px; }

body[data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > div.truncate.max-w-72 {
  grid-column: 3;
  max-width: none;
  font-size: 12.5px;
}
body[data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > span.text-sm {
  grid-column: 4;
  font-size: 12.5px;
  direction: ltr;
  font-variant-numeric: tabular-nums;
}
body[data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > button {
  grid-column: 6;
  justify-self: start;
}
body[data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 > button { grid-column: 7; }

/* The Labels column (contacts-list.js): the contact's labels as chips in
   their own colours, three at most and the rest as +N. */
body[data-crm-contacts] .crm-ct-labels {
  grid-column: 5;
  display: flex;
  flex-wrap: nowrap;
  gap: 4px;
  min-width: 0;
  overflow: hidden;
}
body[data-crm-contacts] .crm-ct-labels__chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
  max-width: 120px;
  height: 20px;
  padding: 0 8px;
  border-radius: 999px;
  border: 1px solid rgba(130, 140, 155, .28);
  font-size: 11.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  unicode-bidi: plaintext;
  color: rgb(var(--slate-12, 30 41 59));
}
body[data-crm-contacts] .crm-ct-labels__chip i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
}
body[data-crm-contacts] .crm-ct-labels__more {
  font-size: 11.5px;
  font-weight: 600;
  color: rgb(var(--slate-11, 100 116 139));
  align-self: center;
}

/* The thin vertical bars stood in for columns. There are columns now. */
body[data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > div.w-px { display: none; }

/* An empty cell says so, rather than leaving a hole the eye has to interpret. */
body[data-crm-contacts] .crm-ct-gap {
  color: rgb(var(--slate-10, 120 130 145));
  opacity: .55;
  font-size: 12.5px;
}
body[data-crm-contacts] .crm-ct-gap--email { grid-column: 3; }
body[data-crm-contacts] .crm-ct-gap--phone { grid-column: 4; }

/* ---------- the pagination bar ----------
 *
 * It ships as `sticky bottom-0 z-0` with no background of its own: transparent,
 * and beneath the rows' stacking contexts. Contacts scrolled visibly through
 * it, and the fifteenth sat permanently underneath - the list had no bottom
 * padding to let it clear.
 *
 * `rgb(var(--surface-1))` is the token the page's own `bg-n-surface-1` compiles
 * from, so it follows the theme. There is no `--n-surface-1`; a literal colour
 * here would have been a dark bar on a white screen.
 */
body[data-crm-contacts] footer.sticky.bottom-0 {
  z-index: 20;
  background-color: #fff;
  background-color: rgb(var(--surface-1));
  border-top: 1px solid rgba(130, 140, 155, .2);
}

body[data-crm-contacts] div.flex.flex-col.gap-4.pt-4.pb-6 { padding-bottom: 56px; }

/* ---------- the two buttons that moved into the ⋮ ----------
 *
 * They are hidden, not removed. contacts-menu.js adds a menu item that clicks
 * the real button, so every bit of their behaviour and state keeps working
 * with no second copy of it to drift; this only takes them out of a toolbar
 * where they sat beside the things people press every hour.
 *
 * `body[data-crm-contacts-menu]` is set by that script only once it has found
 * them, so nothing is ever hidden that was not going to be replaced.
 */
body[data-crm-contacts-menu] .crm-dupe__open,
body[data-crm-contacts-menu] .crm-ld__open {
  display: none !important;
}

/* A contact with no name shows its number there instead (contacts-list.js
   sets the attribute; the span itself stays empty). */
body[data-crm-contacts] span.text-base[data-crm-name]:empty::before {
  content: attr(data-crm-name);
  direction: ltr;
  unicode-bidi: isolate;
}

/* ---------- respond.io's table (owner, 2026-09-29) ----------
 *
 * Their contacts table measured live: a 44px header in 14px/700 grey
 * (#626f7f), 48px rows in 14px ink (#282e34), one hairline
 * rgba(53,60,69,.16) under each, a pale grey on hover that fades in 150ms
 * (colour only, nothing moves), and a 48px footer under a hairline. */
body[data-crm-contacts] {
  --ct-line: rgba(53, 60, 69, .16);
  --ct-ink: #282e34;
  --ct-muted: #626f7f;
  --ct-hover: #f5f6f7;
  --ct-card: #ffffff;
}
.dark body[data-crm-contacts], body.dark[data-crm-contacts], :root.dark body[data-crm-contacts] {
  --ct-line: #2c3138;
  --ct-ink: #e8eaed;
  --ct-muted: #9aa3af;
  --ct-hover: rgba(255, 255, 255, .04);
  --ct-card: rgb(var(--surface-1));
}

body[data-crm-contacts] .crm-ct-head {
  min-height: 44px;
  padding-block: 0;
  font-size: 14px;
  font-weight: 700;
  color: var(--ct-muted);
  border-bottom-color: var(--ct-line);
}

body[data-crm-contacts] div[class*="outline-n-container"] {
  border-bottom-color: var(--ct-line);
  transition: background-color .15s cubic-bezier(.4, 0, .2, 1);
}
body[data-crm-contacts] div[class*="outline-n-container"]:hover { background: var(--ct-hover); }

body[data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 { min-height: 48px; color: var(--ct-ink); }
body[data-crm-contacts] div.flex.flex-wrap.items-center.gap-x-4 span.text-base { font-size: 14px; font-weight: 500; color: var(--ct-ink); }
body[data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > div.truncate.max-w-72,
body[data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > span.text-sm,
body[data-crm-contacts] a.crm-ci__at { font-size: 14px; color: var(--ct-ink); }
body[data-crm-contacts] .crm-ct-gap { font-size: 14px; color: var(--ct-muted); opacity: 1; }

body[data-crm-contacts] footer.sticky.bottom-0 {
  min-height: 48px;
  border-top-color: var(--ct-line);
  font-size: 14px;
  color: var(--ct-muted);
}

/* The bar above it, as theirs: search first, the actions at the far end, a
   56px bar instead of the 80px one. The screen's name stays, smaller, so the
   page still says where you are. */
body[data-crm-contacts] main header.sticky > div.justify-between {
  justify-content: flex-start;
  gap: 16px;
  padding-block: 12px;
}
body[data-crm-contacts] main header.sticky > div.justify-between > span.text-xl { font-size: 16px; font-weight: 600; flex: none; }
body[data-crm-contacts] main header.sticky > div.justify-between > div.flex-shrink-0 { flex: 1 1 auto; min-width: 0; }
body[data-crm-contacts] main header.sticky > div.justify-between > div.flex-shrink-0 > div:first-child { width: 240px; flex: none; }
body[data-crm-contacts] main header.sticky > div.justify-between > div.flex-shrink-0 > div:nth-child(2) { margin-inline-start: auto; }

/* The first row sits right under the header, as theirs does. */
body[data-crm-contacts] div.flex.flex-col.gap-4.pt-4.pb-6 { padding-top: 0; row-gap: 0; }

/* The page is grey and the list one white box on it, its header inside
   (owner, 2026-09-30). `clip`, not `hidden`: hidden would make the box a
   scroller of its own and the sticky header would stop sticking. */
body[data-crm-contacts] div.flex.flex-col.gap-4.pt-4.pb-6 {
  margin-top: 4px;
  padding-bottom: 0;
  margin-bottom: 56px;
  border: 1px solid var(--ct-line);
  border-radius: 8px;
  overflow: clip;
  background: var(--ct-card);
}
body[data-crm-contacts] .crm-ct-head { background-color: var(--ct-card); }
body[data-crm-contacts] div.flex.flex-col.gap-4 > div.relative:last-child div[class*="outline-n-container"] { border-bottom: 0; }

/* THE OWNER COLUMN (Crm::ContactOwner, owner 2026-10-04): one more column
   before the actions, only on an account that switched owners on. */
body[data-crm-ct-owner] .crm-ct-head,
body[data-crm-ct-owner][data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 {
  grid-template-columns: 72px minmax(150px, 1.4fr) minmax(150px, 1.3fr) 150px minmax(130px, 1.2fr) minmax(110px, .9fr) 96px 16px;
}
body[data-crm-ct-owner][data-crm-contacts] .crm-ct-owner { grid-column: 6; }
body[data-crm-ct-owner][data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > button { grid-column: 7; }
body[data-crm-ct-owner][data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 > button { grid-column: 8; }

body[data-crm-ct-owner][data-crm-ct-handles] .crm-ct-head,
body[data-crm-ct-owner][data-crm-ct-handles][data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 {
  grid-template-columns: 72px minmax(140px, 1.3fr) minmax(110px, .8fr) minmax(140px, 1.1fr) 150px minmax(120px, 1.1fr) minmax(110px, .9fr) 96px 16px;
}
body[data-crm-ct-owner][data-crm-ct-handles][data-crm-contacts] .crm-ct-owner { grid-column: 7; }
body[data-crm-ct-owner][data-crm-ct-handles][data-crm-contacts] div.flex.flex-wrap.items-center.justify-start.gap-x-3 > button { grid-column: 8; }
body[data-crm-ct-owner][data-crm-ct-handles][data-crm-contacts] div.flex.w-full.gap-3.py-5.px-6 > button { grid-column: 9; }

body[data-crm-contacts] .crm-ct-owner {
  grid-row: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px;
}
