/* ==========================================================================
   Clients / CRM — page styles

   What the Clients table says about price, and the New Client form. The
   `<style>` blocks still in clients.html are the column-flex sizing tool's
   generated output plus its temporary review overlay; they are that tool's to
   write and are left alone.

   THE MODEL THIS PAGE DRAWS. A client belongs to ONE type, and that type is
   their price category. A type MAY carry a price list; one that carries none
   leaves its members on base. Nothing is resolved and nothing is compared —
   what a client pays is read off the single type they are in, and every place
   the price shows, that type is named beside it. The types themselves — their
   names and what each one prices at — are edited in one dialog off this page's
   gear. WHO is in a type is not set there: that is a field on the client.
   ========================================================================== */

/* ---------- On the Clients table -----------------------------------------
   Every group a client is in is worth seeing, so the cell lists them — up to
   four, the group setting their price first, one per line. The badge box is
   dropped: four boxes stacked read as a stack of buttons, and the only thing
   the box was carrying — which price list the group has — is already in the
   dot. Names take the ordinary text colour so the dots are what differ. */
.cg-chip { display: flex; padding: 0; background: none; border-color: transparent; }
.cg-chip + .cg-chip { margin-top: 2px; }
.cg-chip .cg-chip-n { min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--color-text); }
/* A price list is reached through a group, so the cell names the group it came
   through — the list alone does not say why this client is on it. */
.cg-via { display: block; margin-top: 2px; font-size: 11px; color: var(--color-text-subtle); }
/* The kind of thing the name is — a note on the name, so it is set below it. */
.cg-via-kind { font-size: 10px; }

/* ---------- The Groups cell ------------------------------------------------
   Which lists this client is on. Two names and then a count: a cell that spells
   out six groups is a cell nobody reads, and the sixth is never the one being
   looked for. The count carries the rest in its title, which is where "which
   ones" belongs — it is a follow-up question, not the answer.

   Boxed, unlike the price cell beside it: a group name is a label, and without
   the box "Spring Campaign" and "Miami Metro" run together as one phrase. */
td.col-groups { white-space: normal; }
/* Block, not the badge's inline-flex: one group per line, each box only as wide
   as its own name, and a name too long for the column trails off rather than
   pushing the column wider. */
.grp-chip {
  display: block; width: fit-content; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis;
}
.grp-chip + .grp-chip { margin-top: 3px; }
/* Not a link and not clickable, so it takes neither the blue nor the pointer,
   and not the help cursor either — the arrow never changes. Resting on it is
   the whole interaction, and the panel that opens is what says so. */
.grp-more {
  display: block; margin-top: 3px;
  font-size: 11px; color: var(--color-text-muted); cursor: default;
}

/* The rest of the groups, on a pale gold card instead of the black box the
   browser draws for a `title`. Fixed rather than absolute because the table
   scrolls its own overflow and would otherwise clip the panel; one element is
   shared by every `+N` on the page, moved to whichever is under the cursor.
   One name per line — a comma-run of names is the thing that was hard to read. */
.grp-tip {
  position: fixed; z-index: 60; pointer-events: none;
  max-width: 240px; padding: 8px 11px;
  background: var(--color-warn-50); border: 1px solid var(--color-warn); border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .12);
  color: var(--color-text); font-size: 12px; line-height: 1.5;
  white-space: pre-line;
}

/* The list name keeps the blue it had as a link, because it is still the thing
   in the cell worth pointing at. The `cursor: help` went with the hover card it
   was advertising — a cursor promising an explanation that never arrives is a
   worse control than a plain one. */
.cg-list-name { color: var(--color-primary-600); }

/* ---------- The salesperson band ------------------------------------------
   Who sells to a client used to be a line inside every row — the same name
   written out eight times down one column. It is a band instead: said once,
   with the size of that book beside it, and the clients stepped in beneath.
   Folding a band closes that salesperson's whole book. Unassigned is a band
   like any other, quieter, and last. */
/* WHERE THE SPACE GOES. A rep's clients must sit closer to that rep than the
   rep below sits to them, or the last client in a book reads as the first
   client of the next one. Even spacing above and below a band says nothing
   about which side a row belongs to, so the space is deliberately lopsided:
   about 11px from a band down to its first client, about 26px from the last
   client down to the next band.

   The gap lives ABOVE the band and takes the page's own colour rather than the
   band's, which is why the grey moves off the cell and onto the button. Grey
   space above a band would only make the band taller; white space separates.

   Qualified through `.data-table tbody` on purpose: the base cell rules there
   are two-element deep, and a shorter selector here loses to them however far
   down the file it sits. */
.data-table tbody tr.rep-band > td {
  padding: 16px 0 0;
  text-align: left;
  background: transparent;
  border-top: 0;
}
/* The band's own ground closes the row above it; the per-cell mark would be a
   second boundary drawn one pixel away from this one. */
.data-table tbody tr.rep-band > td::after { content: none; }
/* The row hover would now tint the gap as well as the band, which would paint
   the separation shut every time the cursor passed over it. The band answers a
   hover on its own name instead. */
.data-table tbody tr.rep-band:hover { background: transparent; }
/* The first band opens the table — there is no previous rep to be parted from,
   and the header's own edge is already the line above it. */
.data-table tbody tr.rep-band:first-child > td { padding-top: 0; }
.data-table tbody tr.rep-band:first-child .rep-band__btn { border-top: 0; }

/* The first client under a band is pulled up against it. This is the whole
   other half of the grouping — a band that only pushed the next rep away would
   leave its own clients no nearer than before. */
.data-table tbody tr.rep-band + tr.client-row > td { padding-top: 4px; }

/* The last row of a band carries no mark: the next band's own full-width border
   already closes it, and the mark would be a second, shorter boundary drawn a
   few pixels above the first. The last band closes on the card's edge the same
   way.
   The chain is what "the next VISIBLE row" costs in CSS. Between a client row
   and the band below it sit that client's contact rows, which are in the table
   the whole time and merely `hidden` while the client is collapsed — so the
   band is one, two or three rows further down than it looks. */
.data-table tbody tr:has(+ tr.rep-band) > td::after,
.data-table tbody tr:has(+ tr[hidden] + tr.rep-band) > td::after,
.data-table tbody tr:has(+ tr[hidden] + tr[hidden] + tr.rep-band) > td::after,
.data-table tbody tr:has(+ tr[hidden] + tr[hidden] + tr[hidden] + tr.rep-band) > td::after,
.data-table tbody tr:has(+ tr[hidden]:last-child) > td::after,
.data-table tbody tr:has(+ tr[hidden] + tr[hidden]:last-child) > td::after,
.data-table tbody tr:has(+ tr[hidden] + tr[hidden] + tr[hidden]:last-child) > td::after {
  content: none;
}

.rep-band__btn {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 7px var(--table-pad-x);
  border: 0; border-top: 1px solid var(--color-border);
  background: var(--color-surface-alt);
  cursor: pointer; font: inherit; text-align: left;
}
.rep-band__btn svg {
  width: 15px; height: 15px; flex: 0 0 auto;
  color: var(--color-text-subtle); transition: transform 120ms;
}
.rep-band__btn[aria-expanded="true"] svg { transform: rotate(90deg); }
.rep-band__name { font-size: 13px; font-weight: 600; color: var(--color-text); }
.rep-band__btn:hover .rep-band__name { color: var(--color-primary-700); }
/* The count belongs to the name it follows, so it sits against it — number
   first, word after, no gap for the eye to cross. */
.rep-band__count { font-size: 11px; color: var(--color-text-muted); }
.rep-band__count strong {
  font-weight: 600; color: var(--color-text); font-variant-numeric: tabular-nums;
}
.rep-band--none .rep-band__name { font-weight: 500; color: var(--color-text-muted); }

/* Inside the band the client steps in, and their contacts step in again — the
   indent is what says the row belongs to the band above it. */
.data-table tbody tr.client-row > td:first-child,
.data-table tbody tr.contact-child > td:first-child { padding-left: 30px; }

/* ---------- Ungrouped: the rep under the client ---------------------------
   By Salesperson off is the same list read the other way. The bands step aside and
   the rep follows the client down into their own cell, a third line under the
   name and the town — smaller than either, because it answers a question you
   only ask about a client you have already found. It stays out of sight while
   the bands are up: a line repeating the band above it eight times is what
   the band was invented to replace, and the width it would cost is the width
   the client names are using.

   Everything the bands were doing to the rows goes with them: the step-in
   that said a row belonged to one, the tightening of the first client up
   against it, and the row marks a band was suppressing because its own edge
   already closed the book above. With no band between them, the client above
   another client is simply the row above, and gets the mark back. */
.row-rep { display: none; font-size: 10px; color: var(--color-text-subtle); }
#tbl-flex-1.is-flat .row-rep { display: block; }
#tbl-flex-1.is-flat tbody tr.rep-band { display: none; }
#tbl-flex-1.is-flat tbody tr.client-row > td:first-child,
#tbl-flex-1.is-flat tbody tr.contact-child > td:first-child { padding-left: var(--table-pad-x); }
#tbl-flex-1.is-flat tbody tr.rep-band + tr.client-row > td { padding-top: 10px; }
#tbl-flex-1.is-flat tbody tr:has(+ tr.rep-band) > td::after,
#tbl-flex-1.is-flat tbody tr:has(+ tr[hidden] + tr.rep-band) > td::after,
#tbl-flex-1.is-flat tbody tr:has(+ tr[hidden] + tr[hidden] + tr.rep-band) > td::after,
#tbl-flex-1.is-flat tbody tr:has(+ tr[hidden] + tr[hidden] + tr[hidden] + tr.rep-band) > td::after {
  content: '';
}

/* All Open belongs to the bands, so with the bands gone it has nothing left to
   open — but it goes invisible, not away. Taking it out of the flow hands its
   width back to the toolbar, and the search box, which splits whatever is free
   with the spacer, widens by some fifty pixels the moment By Salesperson is flipped:
   a control jumping under the cursor on a toggle that was never about it.
   Hidden this way it keeps its slot, and drops out of the tab order with it. */
.toolbar .switch-field.is-vacant { visibility: hidden; }

/* ---------- The client cell ----------------------------------------------
   Who a client is: the name and where they are. Who you ring there used to sit
   under it and is now a column of its own — one name tucked beneath a company
   was a name with nothing beside it to compare it to. */
.client-line { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.client-line .main { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- The contacts column -------------------------------------------
   The person you ring, and how many others are behind them — on one line, so
   every row in the table is the same height whether a client has one contact
   or nine. Listing several made the row with four taller than the row with
   three, which turned a fact about the client into a change in the rhythm of
   the list.

   The count is also the control that opens the rest: the number is where the
   eye already is when the question is "who else?". */
/* The count sits under the name, not beside it: the same two-line shape the
   price cell has, so the columns read down the row at the same rhythm. */
.contact-list {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 2px; min-width: 0;
}
.contact-name {
  font-size: 12px; color: var(--color-text);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Colour and weight carry the hover; no underline. */
.contact-count {
  flex: 0 0 auto; padding: 0;
  border: 0; background: none; cursor: pointer; font: inherit;
  font-size: 10px; color: var(--color-text-subtle);
  font-variant-numeric: tabular-nums;
}
.contact-count:hover,
.contact-count[aria-expanded="true"] { color: var(--color-primary-700); font-weight: 500; }

/* The contact rows folded under a client. The hand-written ones carry these
   three values inline; a row the New Client dialog builds reads them from here,
   so the two are the same row however it came to exist. */
.contact-child .cell-media { padding-left: 30px; }
.contact-child .child-branch { color: var(--color-text-subtle); }
.contact-child .main .badge { font-size: 10px; }

/* ---------- New Client dialog ---------------------------------------------
   Two records are made here — the company, and the person you ring there — so
   the dialog is the tabbed body the Edit Product dialogs already use, and each
   half has room for every field the rest of the app stores against it. */

/* The delivery-address switch and its folded block are `.ship-switch` /
   `.ship-block` in app.css — Edit Client on the client's own page asks the same
   question, and two copies of the rule under two names is how the two dialogs
   would drift apart. */


/* The two export icons open a dialog rather than going anywhere, so they carry
   no href — and without one the pointer would not say they can be clicked. */
.page-actions a[data-modal-open] { cursor: pointer; }

/* ---------- New / Edit Group dialog --------------------------------------- */
.cg-form-note { margin: 4px 0 0; font-size: 12px; }
.cg-pick-note { margin: 0 0 8px; font-size: 12px; line-height: 1.45; color: var(--color-text-muted); }
/* The four price lists and the option of none, as the radio rows this page
   already assigns salespeople with. */
.cg-pick { display: flex; flex-direction: column; gap: 6px; }
.cg-pick .assign-opt { display: flex; }
/* Sized to "Base", the widest thing it holds — a swatch that shrink-wraps its
   own text would leave the five names starting on five different columns. */
.cg-pick-off {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 30px; flex: 0 0 auto;
  border-radius: var(--radius);
  background: var(--color-surface-alt); color: var(--color-text-muted);
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.cg-pick-off svg { width: 15px; height: 15px; }

/* ==========================================================================
   THE CLIENT GROUPS TAB

   A group is a named list of clients and nothing else. It carries no price and
   no tier: what a client pays is read off their Client Type, which they have
   exactly one of, and a group that could also price would be a second answer to
   a question already answered. So nothing in this panel talks about money —
   the only figures here are how many clients are in a list.
   ========================================================================== */

/* ONE card: a rail that picks a group, and the rest of it that IS that group.
   It was three cards standing side by side, and side by side is all they were —
   nothing said the middle one held the left one's members, and the third read as
   a separate page that happened to be open. A shared ground and a single seam
   between the two say it instead: what is on the right belongs to what is lit on
   the left. No gap, because a gap is what made them three things. */
.cg-split {
  display: grid; align-items: stretch;
  grid-template-columns: minmax(240px, 320px) 1fr;
}
/* The seam. One line, and the rail carries the quieter ground so the eye reads
   the detail side as the front of the card. The rail rounds its own two outer
   corners rather than the card clipping them for it — the card cannot clip,
   because the add result is a layer that has to be free to be taller than the
   group it floats over. */
.cg-rail {
  border-right: 1px solid var(--color-border);
  background: var(--color-surface-alt);
  border-radius: var(--radius-md) 0 0 var(--radius-md);
  display: flex; flex-direction: column; min-width: 0;
}
/* The toolbar comes with the card's own white ground and a top radius, both of
   which would draw a lid across the rail. It takes the rail's ground instead,
   and its field takes white — a control has to differ from what it sits on, and
   on this tint the usual control grey is the tint. */
.cg-rail .toolbar {
  background: transparent;
  border-radius: 0;
}
.cg-rail .toolbar .input { background: var(--color-surface); }
.cg-detail { min-width: 0; }

/* ---------- The group list (master) --------------------------------------- */
.cg-list { display: flex; flex-direction: column; }
.cg-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 10px 12px 10px 14px;
  border: 0; border-bottom: 1px solid var(--color-border);
  background: none; cursor: pointer; text-align: left; font: inherit;
}
.cg-item:last-child { border-bottom: 0; }
.cg-item:hover { background: var(--color-surface); }
/* Which group is open — and the join between the two halves. The open row takes
   the detail side's own ground and reaches across the seam to cover it, so the
   row and the panel read as one shape rather than as a highlight facing a card.
   It is also the only row that changes weight: colour alone would be the whole
   signal on a screen that cannot show it. */
.cg-item[aria-selected="true"] {
  position: relative;
  margin-right: -1px;
  background: var(--color-surface);
  box-shadow: inset 3px 0 0 var(--color-primary);
}
.cg-item[aria-selected="true"] .cg-i-name { font-weight: 600; color: var(--color-primary-700); }

.cg-i-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.cg-i-name { font-size: 13px; font-weight: 500; }
.cg-i-meta { font-size: 11px; color: var(--color-text-muted); }
/* A group without a description is not a lesser group — plenty of them need no
   explaining. Said in the same quiet type, not marked as something missing. */
.cg-i-meta--none { color: var(--color-text-subtle); }
/* The count is the figure the eye runs down, so it holds the right edge and
   gives no ground to a long group name beside it. */
.cg-i-count {
  flex: 0 0 auto; font-size: 12px; color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}
.cg-list-empty { padding: 22px 14px; font-size: 12px; color: var(--color-text-muted); text-align: center; }

/* ---------- The open group (detail) --------------------------------------- */
/* Nothing is chosen when the panel opens: this is a list of groups to be
   recognised, and picking one for the reader would answer the only question
   the pane is asking. */
/* It holds the whole detail side rather than a block at the top of it, so the
   card keeps its shape whether a group is open or not. */
.cg-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-height: 320px; height: 100%; padding: 54px 22px;
  text-align: center; font-size: 13px; color: var(--color-text-muted);
}
.cg-empty svg { width: 26px; height: 26px; color: var(--color-text-subtle); margin-bottom: 10px; }

.cg-head-title { display: flex; align-items: center; gap: 9px; }
.cg-head-title h2 { margin: 0; }
.cg-head-acts { display: flex; align-items: center; gap: 6px; }

/* Columns, because a member row is a name and a line of small type and neither
   of them wants 1200px — one per line left two thirds of the panel empty and
   made a group of eight look like a long list. The count is not fixed: the
   panel takes as many 380px columns as it has room for, which is one on a
   narrow screen and three on a wide one, and the rows never restyle.

   The 420px cap and its scrollbar went with them. It was there so a group of
   forty did not leave the rail beside it looking like a stub, and three
   columns already shorten that list by two thirds. It also cannot come back
   while a member row opens a panel: a scroll box would cut the panel off at
   the bottom of the list, which is exactly where the last rows are. */
.cg-members {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
  overflow-x: clip;   /* the seam only; the panel still escapes downwards */
  /* The last row's rule would otherwise sit a hair above the card's own edge
     and read as a double line; the card border covers it instead. */
  margin-bottom: -1px;
}
.cg-member {
  position: relative;   /* the panel hangs off the row it was opened from */
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px 9px 14px;
  border-bottom: 1px solid var(--color-border);
  /* The seam between columns. A shadow, not a border, so it costs no width and
     the one on the last column falls outside the box and is clipped — no rule
     is left hanging at the right edge. */
  box-shadow: 1px 0 0 var(--color-border);
}
/* The row a panel is open on stays lit while it is being worked on. */
.cg-member.is-open { background: var(--color-surface-alt); z-index: 1; }
.cg-member .avatar { width: 30px; height: 30px; font-size: 11px; flex: 0 0 auto; }
/* The name is the way into every group this client is in, so it is a control
   and says so on hover — a change of colour and weight, never a rule under it. */
.cg-m-body {
  display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1;
  padding: 0; border: 0; background: none; font: inherit;
  text-align: left; cursor: pointer;
}
.cg-m-name { font-size: 13px; font-weight: 500; }
.cg-m-body:hover .cg-m-name { color: var(--color-primary-700); }
.cg-member.is-open .cg-m-name { color: var(--color-primary-700); font-weight: 600; }
/* Where else this client is reached from. The question a member row raises is
   whether taking them out here takes them off everything, and the row answers
   it before the × is pressed rather than after. */
.cg-m-meta { font-size: 11px; color: var(--color-text-muted); }

/* Destructive, so it stays quiet until the row is being worked on. */
.cg-m-off {
  flex: 0 0 auto; padding: 5px;
  border: 0; border-radius: 5px; background: none; cursor: pointer;
  color: var(--color-text-subtle); line-height: 0;
  opacity: 0; transition: opacity 120ms, color 120ms, background 120ms;
}
.cg-m-off svg { width: 15px; height: 15px; }
.cg-member:hover .cg-m-off,
.cg-m-off:focus-visible { opacity: 1; }
.cg-m-off:hover { background: var(--color-danger-50); color: var(--color-danger); }
@media (hover: none) { .cg-m-off { opacity: 1; } }

.cg-members-empty { padding: 30px 16px; text-align: center; font-size: 12px; color: var(--color-text-muted); }

/* ---------- Every group one member is in ----------------------------------
   The row named the other groups and then left the reader to go and find each
   one in the rail to take the client off it — three trips to undo one thing.
   The panel is the same list, made of controls, and it holds THIS group too:
   "what is this client on" and "take them off it" are one question, and a list
   that answered it with a hole where the current group should be would be a
   list the reader has to correct while reading.

   Built as the portal's dropdown is built, because that is what it is. */
.cg-m-pop {
  position: absolute; z-index: 25; top: calc(100% - 4px); left: 54px;
  min-width: 248px; max-width: calc(100% - 68px);
  padding: 6px;
  background: var(--color-surface);
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}
.cg-m-pop__row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 6px 6px 10px; border-radius: var(--radius-sm);
  font-size: 13px;
}
.cg-m-pop__row:hover { background: var(--color-primary-50); }
.cg-m-pop__n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Which of them is the one being looked at. A note on the name, not a badge —
   it is orientation, and there is nothing to press. */
.cg-m-pop__here { flex: 0 0 auto; font-size: 10px; color: var(--color-text-subtle); }
/* Always shown, unlike the × on the row: this panel was opened on purpose, and
   a menu whose items reveal their controls on hover is a menu that looks like
   it has none. */
.cg-m-pop__off {
  flex: 0 0 auto; padding: 4px;
  border: 0; border-radius: 5px; background: none; cursor: pointer;
  color: var(--color-text-subtle); line-height: 0;
  transition: color 120ms, background 120ms;
}
.cg-m-pop__off svg { width: 14px; height: 14px; }
.cg-m-pop__off:hover { background: var(--color-danger-50); color: var(--color-danger); }

/* ---------- Adding clients ------------------------------------------------
   In place, not in a dialog: adding six clients to a group is one job, and a
   dialog that has to be reopened per client turns it into six. The column is a
   search box and nothing else until it is used — a standing list of everyone
   outside the group is a second table of clients beside the members table, and
   the two are not worth telling apart. What appears under the box is the search
   result, and the box stays put as clients are taken from it, because nobody
   adds exactly one.

   It sits under the group's own name, inside the same card, because the group
   it adds to is the one named directly above it. Standing in a card of its own
   it had to repeat that name in its heading to say what it was for. */
.cg-add { padding: 12px 14px; border-bottom: 1px solid var(--color-border); }
.cg-add .search { position: relative; }
.cg-add .search input { padding-left: 32px; }
.cg-add .search svg {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; color: var(--color-text-subtle); pointer-events: none;
}
/* The answer floats over the group rather than sitting in it. A result pushed
   the members down the page, so asking who else there is moved the people
   already there — and a strip that is plainly not the group is easier to read
   as a layer over it than as another band inside it. It hangs off the box that
   was typed into, and goes when that box is cleared. */
.cg-add-pop {
  position: absolute; z-index: 30; left: 0; right: 0; top: calc(100% + 4px);
  background: var(--color-surface);
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.cg-add-pop[hidden] { display: none; }
/* Same columns as the members below it: it is the same kind of row, and a
   single file of names down a panel this wide is what was wrong with it. */
.cg-add-list {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  max-height: 280px; overflow-y: auto;
  margin-bottom: -1px;   /* the layer's own edge covers the last row's rule */
}
/* Nothing typed, or nobody left to match: no strip, no border, no gap. */
.cg-add-list:empty { display: none; }
.cg-add-row {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 8px 11px;
  border: 0; border-bottom: 1px solid var(--color-border);
  background: none; cursor: pointer; text-align: left; font: inherit;
  box-shadow: 1px 0 0 var(--color-border);
}
.cg-add-row:hover { background: var(--color-primary-50); }
.cg-add-row .thumb { width: 28px; height: 28px; font-size: 10px; flex: 0 0 auto; }
.cg-add-row .cg-a-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.cg-add-row .cg-a-name { font-size: 13px; font-weight: 500; }
.cg-add-row .cg-a-meta { font-size: 11px; color: var(--color-text-muted); }
/* Also a search result, so it stands on the same layer as one. */
.cg-add-empty {
  padding: 18px 14px; text-align: center; font-size: 12px; color: var(--color-text-muted);
}

@media (max-width: 1100px) {
  /* The rail gives up width before it gives up its place — a group name and a
     count still read at 200px, and stacking too early costs the join. */
  .cg-split { grid-template-columns: minmax(190px, 240px) 1fr; }
}
@media (max-width: 820px) {
  /* Side by side stops working long before the page does — the members pane
     runs out of room for a name and a city on one line. The seam turns
     horizontal so the two halves stay one card. */
  .cg-split { grid-template-columns: 1fr; }
  .cg-rail {
    border-right: 0; border-bottom: 1px solid var(--color-border);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
  }
  .cg-item[aria-selected="true"] { margin-right: 0; margin-bottom: -1px; }
  .cg-empty { min-height: 180px; }
}
