/* ================================================================
   THE TEAM SCREEN
   ================================================================
   Three surfaces over one set of people: a cluster where size is the seat, a
   card holding everything about one person, and a list for finding a name.
   The reasoning for each is in its own module (src/views/team-cluster.ts,
   team-card.ts, team-list.ts); what is here is how they are drawn.

   IT REPLACES A FIVE-COLUMN ROW THAT NEVER FITTED. The old .cb-member grid put
   an address, a seat menu the width of a search field, five unlabelled glyphs
   and a Remove on one line. The address lost: an invited row rendered it as
   `g...`, one letter, on the screen that says who can read every prospect's
   contact details. The seen column was max-content, so it was not a column and
   the dates never lined up. Below the lg breakpoint the grid dropped to three
   tracks and still received five children. Those rules are gone from
   console-data.css; nothing should bring a nine-control row back.

   Every value here is a token step (rule 13). The disc sizes and the pitch are
   custom properties on .cb-cluster BECAUSE the lattice maths needs to read them
   back (team-cluster.ts, layOut): one source, in the stylesheet where a size
   belongs, rather than a second copy in TypeScript that could drift.
   ================================================================ */

/* ---- Cluster or list, as two named things ---- */
.cb-team-switch {
  display: inline-flex;
  gap: var(--cb-space-xxs);
  padding: var(--cb-space-xxs);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-sunken);
}
.cb-team-shape {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-sm) var(--cb-space-lg);
  border: 0;
  border-radius: var(--cb-radius-full);
  background: transparent;
  color: var(--cbc-ink-muted);
  font: inherit;
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-medium);
  cursor: pointer;
  transition:
    background var(--cb-motion-fast) var(--cbc-spring),
    color var(--cb-motion-fast) var(--cbc-spring);
}
.cb-team-shape:hover {
  color: var(--cbc-ink);
}
.cb-team-shape[aria-pressed="true"] {
  background: var(--cbc-surface);
  color: var(--cbc-ink);
  box-shadow: var(--cbc-shadow);
}
.cb-team-shape .cb-icon {
  inline-size: var(--cb-space-xl);
  block-size: var(--cb-space-xl);
}

/* ---- The two things somebody has to answer ----
   Absent entirely when nobody is waiting, which is nearly always. A strip that
   is there every day is one people stop reading. */
.cb-team-wait {
  display: flex;
  align-items: center;
  gap: var(--cb-space-xl);
  flex-wrap: wrap;
  margin: var(--cb-space-lg) var(--cb-space-3xl) 0;
  padding: var(--cb-space-lg) var(--cb-space-xl);
  border: 1px solid var(--cbc-accent);
  border-radius: var(--cb-radius-2xl);
  background: var(--cbc-accent-wash);
  font-size: var(--cb-type-sm-size);
}
.cb-team-wait-said {
  flex: 1 1 auto;
  min-inline-size: 0;
}

/* ================= THE CLUSTER ================= */

/* The cluster and the card share one box, and the card takes its width from a
   track that is zero until somebody is open. A grid rather than an overlay so
   the discs are never underneath it: the whole value of this screen is seeing
   the team, and a panel covering half of them to talk about one is the list's
   fault in a different shape. */
.cb-team-stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 0fr;
  transition: grid-template-columns var(--cb-motion-slow) var(--cbc-spring);
}
.cb-team-stage[data-open="true"] {
  grid-template-columns: minmax(0, 1fr) var(--cbc-person-w);
}

.cb-team-field {
  min-inline-size: 0;
  padding: var(--cb-space-6xl) var(--cb-space-3xl) var(--cb-space-4xl);
}

.cb-cluster {
  /* ---- THE LATTICE READS THESE BACK. Do not move them into TypeScript. ----

     AND EACH ONE IS A SINGLE TOKEN, NEVER A calc(). That is not tidiness, it is
     the difference between a cluster and a pile. `getComputedStyle` resolves
     var() inside a custom property but does NOT evaluate calc() in one, because
     an unregistered custom property computes to a token stream rather than to a
     length. So layOut read "calc(96px + 20px)", parseFloat gave NaN, the pitch
     fell to zero and all eleven discs landed on the same spot at the middle of
     the screen. Every one of these has to survive parseFloat on its own.

     The steps are chosen so the pitch is one token above the largest disc,
     which is what makes the packing read as a honeycomb: 96 against 80 leaves
     sixteen between two admins, and the smaller seats sit further apart because
     they are smaller, not because the lattice moved. */
  --cb-bub-admin: var(--cb-space-8xl);
  --cb-bub-editor: var(--cb-space-7xl);
  --cb-bub-viewer: var(--cb-space-6xl);
  --cb-bub-harness: var(--cb-space-8xl);
  --cb-bub-pitch: var(--cb-space-9xl);
  --cbc-person-w: calc(var(--cb-space-11xl) + var(--cb-space-11xl) + var(--cb-space-5xl));

  position: relative;
  margin-inline: auto;
  inline-size: var(--cb-bub-w, 0);
  block-size: var(--cb-bub-h, 0);
}
/* The card's width is read on the stage, which is the cluster's parent's
   sibling, so it is stated once more at the top of the tree. */
.cb-team-stage {
  --cbc-person-w: calc(var(--cb-space-11xl) + var(--cb-space-11xl) + var(--cb-space-5xl));
}

/* ---- One person, as a disc ---- */
.cb-bub {
  position: absolute;
  inset-inline-start: var(--cb-bub-x, 0);
  inset-block-start: var(--cb-bub-y, 0);
  inline-size: var(--cb-bub-d);
  block-size: var(--cb-bub-d);
  margin-inline-start: calc(var(--cb-bub-d) / -2);
  margin-block-start: calc(var(--cb-bub-d) / -2);
  padding: 0;
  border: 0;
  border-radius: var(--cb-radius-full);
  background: transparent;
  cursor: pointer;
  transition:
    transform var(--cb-motion-base) var(--cbc-spring),
    opacity var(--cb-motion-base) var(--cbc-spring);
}
/* SIZE IS AUTHORITY. This is the whole idea of the screen. */
.cb-bub[data-seat="admin"] {
  --cb-bub-d: var(--cb-bub-admin);
}
.cb-bub[data-seat="editor"] {
  --cb-bub-d: var(--cb-bub-editor);
}
.cb-bub[data-seat="viewer"] {
  --cb-bub-d: var(--cb-bub-viewer);
}
.cb-bub[data-seat="harness"] {
  --cb-bub-d: var(--cb-bub-harness);
}
.cb-bub[data-seat="invited"] {
  --cb-bub-d: var(--cb-bub-viewer);
}

.cb-bub-face {
  inline-size: 100%;
  block-size: 100%;
  font-size: var(--cb-type-md-size);
  box-shadow: var(--cbc-shadow);
  transition: box-shadow var(--cb-motion-base) var(--cbc-spring);
}

/* CHANNEL ONE: is there a second step on this account.
   Solid when there is, dashed when there is not. Nothing at all on an
   invitation, because there is no account behind one to ask about. */
.cb-bub-ring {
  position: absolute;
  inset: calc(var(--cb-space-sm) * -1);
  border-radius: var(--cb-radius-full);
  pointer-events: none;
}
.cb-bub[data-lock="on"] .cb-bub-ring {
  border: 2px solid var(--cbc-good);
}
.cb-bub[data-lock="off"] .cb-bub-ring {
  border: 2px dashed var(--cbc-warn);
}

/* CHANNEL TWO: has anybody actually USED this access.
   A grant nobody has touched in three months drains of colour, which answers
   "should this person still have it" at a glance rather than by reading ten
   dates down a column.

   NOT ON AN INVITATION, which is already drawn as an outline below. Both
   treatments at once multiplied out to about a third of full strength on a
   washed-out hue, and the disc all but disappeared: an invitation is somebody
   the team is waiting on, not something to be hidden. */
.cb-bub[data-live="cold"]:not([data-seat="invited"]) .cb-bub-face {
  filter: saturate(0.2);
  opacity: 0.5;
}

/* An invitation is a place somebody is expected to be, so it is drawn as one:
   an outline with nothing filled in. */
.cb-bub[data-seat="invited"] .cb-bub-face {
  background: transparent;
  box-shadow: none;
  border: 2px dashed var(--cbc-line-strong);
  color: var(--cbc-ink-muted);
}

/* CHANNEL THREE: somebody is waiting on you. */
.cb-bub-pip {
  position: absolute;
  inset-block-start: 0;
  inset-inline-end: 0;
  inline-size: var(--cb-space-2xl);
  block-size: var(--cb-space-2xl);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-accent);
  border: 2px solid var(--cbc-surface);
  animation: cb-bub-breathe var(--cbc-loop-calm) var(--cb-motion-ease) infinite;
}
@keyframes cb-bub-breathe {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.16);
  }
}

/* ---- The name, on approach ----

   ON HOVER AND FOCUS ONLY, INCLUDING YOUR OWN. It was pinned on for your own
   disc, and a label sitting under a disc is a label sitting ON the disc in the
   row below: at a pitch of 96 with an 80 disc there are sixteen pixels between
   two neighbours and a line of text needs eighteen, so "you" was printed across
   the top of whoever the lattice put beneath you. Every other disc only labels
   itself on approach, and while it is doing that the rest of the cluster has
   already stepped back, so the label has the room.

   "You" is said by the ring inside the disc instead. See below. */
.cb-bub-who {
  position: absolute;
  inset-block-start: calc(100% + var(--cb-space-md));
  inset-inline-start: 50%;
  transform: translateX(-50%) translateY(calc(var(--cb-space-xs) * -1));
  white-space: nowrap;
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-medium);
  color: var(--cbc-ink-muted);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity var(--cb-motion-fast) var(--cbc-spring),
    transform var(--cb-motion-fast) var(--cbc-spring);
}
.cb-bub:hover .cb-bub-who,
.cb-bub:focus-visible .cb-bub-who {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ---- YOUR OWN DISC, marked INSIDE the edge rather than around it ----

   The outer ring at -6px already means "there is a second step on this
   account", and a second ring at that inset is one ring nobody can read.

   AN OVERLAY RATHER THAN AN INSET SHADOW ON THE FACE, and the difference is
   whether it is visible at all: an inset box-shadow paints over the element's
   background and UNDER its content, and a colleague with a photograph has an
   `img` filling the disc, so the mark was drawn and then covered by the one
   thing it was meant to sit on. Anybody with a sweet saw it; anybody with a
   photograph did not. Its own layer, above the face, and it costs no layout. */
.cb-bub[data-self="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--cb-radius-full);
  border: 2px solid var(--cbc-ink);
  pointer-events: none;
}

/* Rule 14: highlighting one thing holds the rest back rather than shouting the
   one in front. The whole cluster steps away from whichever disc you approach. */
.cb-cluster:hover .cb-bub:not(:hover) {
  opacity: 0.4;
  transform: scale(0.94);
}
.cb-bub:hover {
  transform: scale(1.06);
  z-index: 2;
}
/* NOT ON AN INVITATION, which is drawn above as an outline with nothing
   filled in and says `box-shadow: none` to mean it. That rule and this one
   are both (0,3,0), so before the :not() the winner was whichever came later
   in the file, and this one does: hovering an invitation put a drop shadow
   under a dashed, transparent ring. It never showed while the shadow here was
   invalid CSS and silently dropped; restoring the shadow is what made the
   conflict live. The :not() is the fix rather than a reorder because it makes
   the two rules mutually exclusive, so this cannot come back the next time
   somebody moves a block. */
.cb-bub:hover:not([data-seat="invited"]) .cb-bub-face {
  box-shadow: var(--cbc-shadow-high);
}
.cb-bub:focus-visible {
  outline: var(--cbc-focus);
  outline-offset: var(--cb-space-xs);
  z-index: 2;
}

/* ---- The same, held rather than hovered, once somebody is open ----
   THE OPEN ONE IS THE EXCEPTION, and leaving it out was a real bug: the
   container flag held every disc back including the person the card was
   about, so opening somebody dimmed them along with everybody else and the
   cluster pointed at nothing. */
.cb-cluster[data-picked] .cb-bub:not([data-on]) {
  opacity: 0.35;
  transform: scale(0.92);
}
.cb-cluster[data-picked] .cb-bub:not([data-on]):hover {
  opacity: 0.7;
}
.cb-cluster[data-picked] .cb-bub[data-on] {
  transform: scale(1.08);
  z-index: 2;
}
.cb-cluster[data-picked] .cb-bub[data-on]:not([data-seat="invited"]) .cb-bub-face {
  box-shadow: var(--cbc-shadow-high);
}
.cb-cluster[data-picked] .cb-bub[data-on] .cb-bub-who,
.cb-cluster .cb-bub[data-found] .cb-bub-who {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.cb-cluster .cb-bub[data-found] {
  opacity: 1;
  transform: scale(1.08);
  z-index: 2;
}

/* Held back by the legend: further back than a hover, and out of reach, because
   this one is a filter rather than an emphasis. */
.cb-cluster .cb-bub[data-held="true"] {
  opacity: 0.12;
  transform: scale(0.86);
  pointer-events: none;
}

/* ---- The entrance: one bloom outward from the middle ----
   On --cbc-step, which reads --i, which layOut sets to the ring number. So the
   admins land first and the cluster opens around them: one orchestrated
   arrival rather than eleven discs each animating for itself (rule 14). Only
   under [data-bloom], which is set on the first build of a visit and never on
   a redraw (team-cluster.ts). */
.cb-cluster[data-bloom] .cb-bub {
  animation: cb-bub-in var(--cb-motion-slow) var(--cbc-spring) var(--cbc-step) both;
}
@keyframes cb-bub-in {
  from {
    opacity: 0;
    transform: scale(0.3);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

/* ---- The legend, which is also the filter ---- */
.cb-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cb-space-md);
  padding: var(--cb-space-xl) var(--cb-space-3xl);
  border-block-start: 1px solid var(--cbc-line);
  background: var(--cbc-sunken);
}
.cb-legend-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-md);
  padding: var(--cb-space-sm) var(--cb-space-lg);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-surface);
  color: var(--cbc-ink-muted);
  font: inherit;
  font-size: var(--cb-type-xs-size);
  cursor: pointer;
  transition:
    border-color var(--cb-motion-fast) var(--cbc-spring),
    color var(--cb-motion-fast) var(--cbc-spring);
}
.cb-legend-chip:hover {
  background: var(--cbc-hover);
  color: var(--cbc-ink);
}
.cb-legend-chip[aria-pressed="true"] {
  border-color: var(--cbc-ink);
  color: var(--cbc-ink);
  font-weight: var(--cb-font-weight-medium);
}
/* The dot is the size the disc is, so the key states the rule it is explaining
   rather than describing it. */
.cb-legend-dot {
  border-radius: var(--cb-radius-full);
  background: var(--cbc-ink-faint);
  inline-size: var(--cb-space-lg);
  block-size: var(--cb-space-lg);
}
.cb-legend-chip[data-seat="admin"] .cb-legend-dot {
  inline-size: var(--cb-space-xl);
  block-size: var(--cb-space-xl);
}
.cb-legend-chip[data-seat="editor"] .cb-legend-dot {
  inline-size: var(--cb-space-lg);
  block-size: var(--cb-space-lg);
}
.cb-legend-chip[data-seat="viewer"] .cb-legend-dot {
  inline-size: var(--cb-space-md);
  block-size: var(--cb-space-md);
}
/* An admin's authority, so an admin's size. */
.cb-legend-chip[data-seat="harness"] .cb-legend-dot {
  inline-size: var(--cb-space-xl);
  block-size: var(--cb-space-xl);
}
.cb-legend-chip[data-seat="invited"] .cb-legend-dot {
  background: transparent;
  border: 2px dashed var(--cbc-ink-faint);
}
.cb-legend-n {
  font-variant-numeric: tabular-nums;
  color: var(--cbc-ink-faint);
}
.cb-legend-note {
  margin-inline-start: auto;
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}

/* ================= THE PERSON CARD ================= */
.cb-person-rail {
  min-inline-size: 0;
  overflow: hidden;
  border-inline-start: 1px solid var(--cbc-line);
  background: var(--cbc-surface);
}
.cb-team-stage[data-open="false"] .cb-person-rail {
  border-inline-start-color: transparent;
}
.cb-person {
  inline-size: var(--cbc-person-w);
  padding: var(--cb-space-3xl);
  display: grid;
  gap: var(--cb-space-xl);
  align-content: start;
  animation: cb-person-in var(--cb-motion-base) var(--cbc-spring) both;
}
@keyframes cb-person-in {
  from {
    opacity: 0;
    transform: translateX(var(--cb-space-2xl));
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.cb-person-top {
  display: flex;
  align-items: flex-start;
  gap: var(--cb-space-xl);
}
.cb-person-face {
  inline-size: var(--cb-space-6xl);
  block-size: var(--cb-space-6xl);
  font-size: var(--cb-type-sm-size);
}
.cb-person-said {
  min-inline-size: 0;
  flex: 1 1 auto;
}
.cb-person-name {
  display: flex;
  align-items: center;
  gap: var(--cb-space-md);
  flex-wrap: wrap;
  font-size: var(--cb-type-md-size);
  font-weight: var(--cb-font-weight-semibold);
  line-height: var(--cb-type-md-line-height);
}
/* THE FIX. A whole line, wrapping on the address's own punctuation rather than
   competing with badges for width. This is the fault the card exists for; do
   not put it back in a flex row. */
.cb-person-mail {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-muted);
  overflow-wrap: anywhere;
}
.cb-person-shut {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: var(--cb-space-4xl);
  block-size: var(--cb-space-4xl);
  border: 0;
  border-radius: var(--cb-radius-md);
  background: transparent;
  color: var(--cbc-ink-muted);
  cursor: pointer;
  transition: background var(--cb-motion-fast) var(--cbc-spring);
}
.cb-person-shut:hover {
  background: var(--cbc-hover);
  color: var(--cbc-ink);
}
.cb-person-shut .cb-icon {
  inline-size: var(--cb-space-xl);
  block-size: var(--cb-space-xl);
}

.cb-person-block {
  display: grid;
  gap: var(--cb-space-md);
}
.cb-person-label {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-muted);
}

/* ---- The seat, as three named things ---- */
.cb-seat-pick {
  display: flex;
  gap: var(--cb-space-sm);
}
.cb-seat-opt {
  flex: 1 1 0;
  display: grid;
  gap: var(--cb-space-xxs);
  padding: var(--cb-space-md) var(--cb-space-sm);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-lg);
  background: var(--cbc-surface);
  font: inherit;
  text-align: center;
  cursor: pointer;
  transition:
    border-color var(--cb-motion-fast) var(--cbc-spring),
    background var(--cb-motion-fast) var(--cbc-spring);
}
.cb-seat-opt:hover {
  background: var(--cbc-hover);
}
.cb-seat-opt[aria-pressed="true"] {
  border-color: var(--cbc-ink);
  background: var(--cbc-hover);
}
/* Rule 15: turned off carries its reason, and still answers a pointer so the
   tooltip can say why. Never the disabled attribute. */
.cb-seat-opt[aria-disabled="true"] {
  cursor: default;
}
.cb-seat-opt[aria-disabled="true"]:not([aria-pressed="true"]) {
  opacity: 0.4;
}
.cb-seat-opt[aria-disabled="true"]:hover {
  background: var(--cbc-surface);
}
.cb-seat-opt[aria-pressed="true"][aria-disabled="true"]:hover {
  background: var(--cbc-hover);
}
.cb-seat-opt-name {
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-semibold);
}
.cb-seat-opt-gist {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}

/* ---- The four facts ---- */
.cb-person-facts {
  margin: 0;
  display: grid;
  border-block-start: 1px solid var(--cbc-line);
}
.cb-person-fact {
  display: grid;
  grid-template-columns: calc(var(--cb-space-9xl) + var(--cb-space-xl)) minmax(0, 1fr);
  gap: var(--cb-space-lg);
  align-items: start;
  padding: var(--cb-space-lg) 0;
  border-block-end: 1px solid var(--cbc-line);
  font-size: var(--cb-type-xs-size);
}
.cb-person-fact dt {
  color: var(--cbc-ink-muted);
}
.cb-person-fact dd {
  margin: 0;
  color: var(--cbc-ink);
  min-inline-size: 0;
}
.cb-person-tone[data-tone="good"] {
  color: var(--cbc-good-text);
  font-weight: var(--cb-font-weight-medium);
}
.cb-person-tone[data-tone="warn"] {
  color: var(--cbc-warn-text);
  font-weight: var(--cb-font-weight-medium);
}
.cb-person-line {
  display: flex;
  align-items: center;
  gap: var(--cb-space-md);
  flex-wrap: wrap;
  min-inline-size: 0;
}
.cb-person-note {
  overflow-wrap: anywhere;
}
.cb-person-box {
  inline-size: 100%;
  font-size: var(--cb-type-xs-size);
}
.cb-person-edit {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: var(--cb-space-3xl);
  block-size: var(--cb-space-3xl);
  border: 0;
  border-radius: var(--cb-radius-sm);
  background: transparent;
  color: var(--cbc-ink-faint);
  cursor: pointer;
  opacity: 0;
  transition:
    opacity var(--cb-motion-fast) var(--cbc-spring),
    background var(--cb-motion-fast) var(--cbc-spring);
}
/* A control shows its affordance when you approach it and not before (rule 14). */
.cb-person-fact:hover .cb-person-edit,
.cb-person-edit:focus-visible {
  opacity: 1;
}
.cb-person-edit:hover {
  background: var(--cbc-hover);
  color: var(--cbc-ink);
}
.cb-person-edit .cb-icon {
  inline-size: var(--cb-space-xl);
  block-size: var(--cb-space-xl);
}

/* ---- The rest of what can be done, as named rows ----
   Not a strip of glyphs. Five unlabelled icons on the old row meant every one
   of them needed a tooltip to say what it was, which is a control that cannot
   be read at rest. */
.cb-person-acts {
  display: grid;
  gap: var(--cb-space-md);
}
.cb-person-act {
  display: flex;
  align-items: center;
  gap: var(--cb-space-lg);
  inline-size: 100%;
  padding: var(--cb-space-lg) var(--cb-space-xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-lg);
  background: var(--cbc-surface);
  color: var(--cbc-ink);
  font: inherit;
  font-size: var(--cb-type-xs-size);
  text-align: start;
  text-decoration: none;
  cursor: pointer;
  transition:
    background var(--cb-motion-fast) var(--cbc-spring),
    border-color var(--cb-motion-fast) var(--cbc-spring);
}
.cb-person-act:hover {
  background: var(--cbc-hover);
}
.cb-person-act .cb-icon {
  flex: none;
  inline-size: var(--cb-space-xl);
  block-size: var(--cb-space-xl);
  color: var(--cbc-ink-muted);
}
.cb-person-act[data-danger] {
  color: var(--cbc-poor-text);
}
.cb-person-act[data-danger] .cb-icon {
  color: var(--cbc-poor-text);
}
.cb-person-act[data-danger]:hover {
  border-color: var(--cbc-poor);
  background: var(--cbc-accent-wash);
}
.cb-person-act[aria-disabled="true"] {
  opacity: 0.4;
  cursor: default;
}
.cb-person-act[aria-disabled="true"]:hover {
  background: var(--cbc-surface);
  border-color: var(--cbc-line);
}

/* ---- Somebody asking, or somebody locked out ----
   Moved here whole from console-data.css with the row it used to sit on. It is
   loud because on the card it is the only thing worth reading while it is
   there, and it is absent from everybody nobody is waiting on. */
.cb-ask-strip {
  display: grid;
  gap: var(--cb-space-lg);
  padding: var(--cb-space-lg) var(--cb-space-xl);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-lg);
  background: var(--cbc-hover);
}
/* Somebody who cannot get in at all: the same strip, said louder. This is the
   one state where a colleague is stopped from working and one press fixes it. */
.cb-ask-strip[data-tone="bad"] {
  border-color: var(--cbc-poor);
  background: var(--cbc-accent-wash);
}
.cb-ask-strip-said {
  display: grid;
  gap: var(--cb-space-xxs);
  min-inline-size: 0;
}
.cb-ask-strip-said strong {
  font-size: var(--cb-type-xs-size);
}
.cb-ask-strip-why {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}
.cb-ask-strip-acts {
  display: flex;
  align-items: center;
  gap: var(--cb-space-md);
  flex-wrap: wrap;
}

/* ================= THE LIST ================= */
.cb-team-list {
  display: grid;
}
.cb-team-band {
  display: flex;
  align-items: baseline;
  gap: var(--cb-space-md);
  padding: var(--cb-space-lg) var(--cb-space-3xl);
  background: var(--cbc-sunken);
  border-block: 1px solid var(--cbc-line);
}
.cb-team-band-name {
  font-size: var(--cb-type-xs-size);
  font-weight: var(--cb-font-weight-semibold);
}
.cb-team-band-n {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-muted);
  font-variant-numeric: tabular-nums;
}
.cb-team-band-gist {
  margin-inline-start: auto;
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-faint);
}

/* FOUR TRACKS, AND THE ADDRESS HAS ITS OWN LINE INSIDE ONE OF THEM. The row
   states facts and does nothing: every control is in the card, which is why
   this fits where the old one did not. */
.cb-team-row {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr) max-content max-content;
  align-items: center;
  gap: var(--cb-space-xl);
  inline-size: 100%;
  padding: var(--cb-space-lg) var(--cb-space-3xl);
  border: 0;
  border-block-end: 1px solid var(--cbc-line);
  background: transparent;
  font: inherit;
  text-align: start;
  cursor: pointer;
  transition: background var(--cb-motion-fast) var(--cbc-spring);
}
.cb-team-row:hover {
  background: var(--cbc-hover);
}
.cb-team-row[data-self="true"] {
  background: var(--cbc-hover);
}
.cb-team-row[data-status="invited"] .cb-team-row-face {
  opacity: 0.55;
}
.cb-team-row-face {
  inline-size: var(--cb-space-5xl);
  block-size: var(--cb-space-5xl);
  font-size: var(--cb-type-xs-size);
}
.cb-team-row-who {
  display: grid;
  gap: var(--cb-space-xxs);
  min-inline-size: 0;
}
.cb-team-row-name {
  display: flex;
  align-items: center;
  gap: var(--cb-space-md);
  min-inline-size: 0;
}
.cb-team-row-name > .cb-cell-strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cb-team-row-mail {
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cb-team-row-marks {
  display: flex;
  align-items: center;
  gap: var(--cb-space-sm);
  flex-wrap: wrap;
}
.cb-team-tag {
  padding: var(--cb-space-xxs) var(--cb-space-md);
  border: 1px solid var(--cbc-line);
  border-radius: var(--cb-radius-full);
  background: var(--cbc-sunken);
  color: var(--cbc-ink-muted);
  font-size: var(--cb-type-xs-size);
  white-space: nowrap;
}
.cb-team-tag[data-tone="good"] {
  color: var(--cbc-good-text);
  border-color: var(--cbc-good);
  background: transparent;
}
.cb-team-tag[data-tone="warn"] {
  color: var(--cbc-warn-text);
  border-color: var(--cbc-warn);
  background: transparent;
}
.cb-team-tag[data-tone="ask"] {
  color: var(--cbc-on-accent);
  border-color: var(--cbc-accent);
  background: var(--cbc-accent);
}
/* A COLUMN, WHICH THE OLD ONE WAS NOT. max-content sized it per row, so the
   dates never lined up with each other and the eye could not run down them. */
.cb-team-row-seen {
  inline-size: calc(var(--cb-space-11xl) - var(--cb-space-4xl));
  text-align: end;
  font-size: var(--cb-type-xs-size);
  color: var(--cbc-ink-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.cb-team-row-seen[data-tone="warn"] {
  color: var(--cbc-warn-text);
}

/* ---- Narrow ----
   The card stops being a column beside the cluster and becomes a sheet under
   it, and the list drops its two right-hand tracks under the name rather than
   keeping tracks it has no room for. The old row kept five children in three
   tracks, which wrapped them into places nobody designed. */
/* 1024px mirrors tokens.breakpoint.lg */
@media (max-width: 1024px) {
  .cb-team-stage,
  .cb-team-stage[data-open="true"] {
    grid-template-columns: minmax(0, 1fr);
  }
  .cb-person-rail {
    border-inline-start: 0;
    border-block-start: 1px solid var(--cbc-line);
  }
  .cb-person {
    inline-size: 100%;
  }
  .cb-team-field {
    padding-inline: var(--cb-space-xl);
  }
  /* Single tokens here too, and for the same reason. See the note above. */
  .cb-cluster {
    --cb-bub-admin: var(--cb-space-7xl);
    --cb-bub-editor: var(--cb-space-6xl);
    --cb-bub-viewer: var(--cb-space-5xl);
    --cb-bub-harness: var(--cb-space-7xl);
    --cb-bub-pitch: var(--cb-space-8xl);
  }
  .cb-team-row {
    grid-template-columns: max-content minmax(0, 1fr);
  }
  .cb-team-row-marks,
  .cb-team-row-seen {
    grid-column: 2;
  }
  .cb-team-row-seen {
    inline-size: auto;
    text-align: start;
  }
  .cb-legend-note {
    margin-inline-start: 0;
    flex-basis: 100%;
  }
}

/* ---- Less motion ----
   The bloom, the breath and the card's slide are all cut. What is left is the
   screen as it rests, which is what a cut means: the cluster is simply there,
   and the pip is simply on. */
@media (prefers-reduced-motion: reduce) {
  .cb-cluster[data-bloom] .cb-bub,
  .cb-bub-pip,
  .cb-person {
    animation: none;
  }
  .cb-cluster:hover .cb-bub:not(:hover),
  .cb-bub:hover {
    transform: none;
  }
  .cb-team-stage {
    transition: none;
  }
}
