/* ==========================================================================
   chat.css — conversations
   --------------------------------------------------------------------------
   One set of components, mounted twice: as a full page (#/messages) and inside
   the topbar drawer. Everything below is written against `.chat`, and the two
   hosts only decide how tall and how wide that is. If a rule here needs to
   know which host it is in, that is the signal something belongs in the host
   instead.
   ========================================================================== */

/* Geen kaart, geen hoeken, geen rand. Het gesprek is niet iets dat óp de
   pagina ligt — het ís de pagina, van rand tot rand. De scheiding tussen de
   kolommen doet het werk dat een omlijsting hier zou doen. */
.chat {
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  min-height: 0;
  height: 100%;
  background: var(--surface-raised);
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   Left — the conversation list
   -------------------------------------------------------------------------- */

.chat__aside {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  border-right: 1px solid var(--border-subtle);
  background: var(--surface-page);
}

/* Geen onderrand. Het ontwerp heeft er geen — gemeten staat het kopblok daar
   op `[244,60,295,95]` met onderrand 0 — en er valt hier ook niets te scheiden:
   de tabbladen eronder zitten al in hun eigen verzonken bak, en die doet het
   werk dat een streep zou doen. Twee scheidingen onder elkaar zijn er één te
   veel. */
.chat__aside-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3);
}

.chat__aside-head .search { flex: 1; min-width: 0; }

/* De vier tabbladen: één bak met een schuifje erin, niet vier losse knoppen.
   Zo is te zien dat het een keuze uit vier is en niet vier dingen die je aan
   en uit kunt zetten. */
.chat__tabs {
  flex: none;
  display: flex;
  align-items: center;
  gap: 2px;
  margin: var(--space-3) var(--space-3) 0;
  padding: 3px;
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
}

/* `flex: 1 1 auto`, niet `flex: 1`. Met gelijke vakken krijgt "Alles" evenveel
   ruimte als "Ongelezen", en dan loopt het langste woord eruit terwijl het
   kortste ruimte overhoudt — gemeten: 82 pixels tekst in een vak van 66. Nu is
   de eigen breedte het uitgangspunt en wordt alleen de rest verdeeld. Dat de
   vakken daardoor verschillen is geen fout: de woorden verschillen ook. */
.chat__tab {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  height: 26px;
  padding: 0 var(--space-1);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease);
}

.chat__tab:hover { color: var(--text-primary); }
.chat__tab:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.chat__tab--on {
  background: var(--surface-raised);
  color: var(--text-primary);
  box-shadow: var(--shadow-xs);
}

.chat__tab-count {
  font-size: var(--text-2xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}
.chat__tab--on .chat__tab-count { color: var(--accent-soft-ink); }

.chat__list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-2);
  scrollbar-gutter: stable;
}

.chat__group-label {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: var(--space-3) var(--space-3) var(--space-2);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.chat__group-pin { width: 11px; height: 11px; flex: none; }

.chat__nomatch {
  margin: var(--space-6) var(--space-3);
  font-size: var(--text-md);
  color: var(--text-secondary);
  text-align: center;
}

/* Twee kolommen, niet drie: het tijdstip staat op de regel van de naam en de
   tellers op die van de voorvertoning, want dat is waar ze bij horen. Een
   derde kolom ernaast maakte van elke regel een tabel van drie dingen die
   niets met elkaar te maken hadden. */
.convo {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease);
}

.convo + .convo { margin-top: 1px; }
.convo:hover { background: var(--surface-hover); }
.convo[aria-current="true"] { background: var(--accent-soft); }
.convo[aria-current="true"] .convo__name { color: var(--accent-soft-ink); }

.convo__text {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  line-height: var(--leading-snug);
}

.convo__top { display: flex; align-items: baseline; gap: var(--space-2); }
.convo__line { display: flex; align-items: center; gap: 7px; }

.convo__name {
  flex: 1;
  min-width: 0;
  font-size: var(--text-md);
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.convo__at {
  flex: none;
  font-size: var(--text-2xs);
  color: var(--text-muted);
  white-space: nowrap;
}

.convo__preview {
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* An unread conversation is bolder AND badged — weight alone is too quiet
   next to a list of names that are all the same length. Het tijdstip kleurt
   mee: dat is het enige wat er dan nog grijs bij zou staan. */
.convo--unread .convo__name { font-weight: 600; }
.convo--unread .convo__preview { color: var(--text-secondary); font-weight: 500; }
.convo--unread .convo__at { color: var(--accent-soft-ink); font-weight: 600; }

/* De projectcode onder de regel, in de kleur van zijn eigen project. De
   waarden komen uit `--proj-N-bg`/`--proj-N-ink`, gezet door de renderer. */
.convo__tag {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  height: 17px;
  padding: 0 6px;
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
}

/* Genoemd worden staat naast de teller, niet erin: het aantal zegt hoevéél er
   staat en het @ zegt waarom je moet kijken. */
.convo__mention {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--serious-bg);
  color: var(--serious-ink);
}
.convo__mention svg { width: 11px; height: 11px; }

.convo__count {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-ink);
  font-size: var(--text-2xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* `.convo__count--mention` stond hier: de teller werd amber als je genoemd
   was. Dat is nu `.convo__mention` ernaast — het @ zegt wát er aan de hand is,
   waar een kleur je liet raden. `.convo__pin` is om dezelfde reden weg: de kop
   "Vastgezet" zegt het één keer in plaats van op elke regel opnieuw. */

/* --------------------------------------------------------------------------
   Avatars — a stack for groups, a presence dot for people
   -------------------------------------------------------------------------- */

.chat-avatar { position: relative; flex-shrink: 0; }

.chat-avatar__dot {
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 2px solid var(--surface-page);
  background: var(--text-faint);
}

.chat-avatar__dot[data-state="online"] { background: var(--status-good); }
.chat-avatar__dot[data-state="away"]   { background: var(--status-warning); }
.chat-avatar__dot[data-state="offline"] { background: var(--stone-300); }

.avatar--group {
  background: var(--accent-soft);
  color: var(--accent-soft-ink);
}

.avatar__icon { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.avatar--sm .avatar__icon { width: 13px; height: 13px; }

/* --------------------------------------------------------------------------
   Right — the thread
   -------------------------------------------------------------------------- */

.chat__main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background: var(--surface-raised);
}

.chat__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  flex-shrink: 0;
}

.chat__head-text { min-width: 0; line-height: var(--leading-snug); flex: 1; }

/* One line each, cut with an ellipsis. min-width: 0 lets this column shrink,
   but without clipping the text simply overflows the box it was shrunk into
   and lands on top of the buttons next to it. */
.chat__head-name,
.chat__head-meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat__head-name { font-size: var(--text-lg); font-weight: 600; }
.chat__head-meta { font-size: var(--text-xs); color: var(--text-muted); }

.chat__back { display: none; }

/* De projectchip in de kop: de code in de kleur van het project, en het woord
   ernaast. Hij groeit nooit mee — de naam links krimpt, deze niet, want een
   projectcode die halverwege is afgekapt is geen projectcode meer. */
.chat__head-project {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 30px;
  padding: 0 var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: none;
  color: var(--text-primary);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}

.chat__head-project:hover { border-color: var(--border-strong); background: var(--surface-hover); }
.chat__head-project:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.chat__head-project[hidden] { display: none; }

.chat__head-code {
  padding: 2px 5px;
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
}

/* --------------------------------------------------------------------------
   Project context — what this conversation is about, and what to do about it

   De strook is nu de terugvaloptie, niet de eerste plek. Staat de detailkolom
   er, dan zegt die kaart hetzelfde en uitgebreider, en dan zou de strook
   dezelfde voortgang en dezelfde deadline vier centimeter verderop herhalen.
   Is er geen kolom — het paneel in de topbar, een smal scherm, of de kolom
   dichtgeklapt — dan is de strook het enige wat het project noemt en blijft
   hij staan. De regel die hem verbergt staat verderop bij het raster, bij de
   andere `:has()`-regel; hier zou hij overruled worden door wat eronder staat.
   -------------------------------------------------------------------------- */

.chat__context {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  background: var(--accent-soft);
  flex-shrink: 0;
}

.chat__context[hidden] { display: none !important; }
.chat__context-facts { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; min-width: 0; }

.chat__context-code {
  padding: 1px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--accent-soft-ink);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 600;
}

.chat__context-fact { font-size: var(--text-xs); color: var(--accent-soft-ink); }
.chat__context-fact--warn { font-weight: 600; }
.chat__context-actions { display: flex; gap: var(--space-1); margin-left: auto; }
.chat__context-actions .btn { color: var(--accent-soft-ink); }
.chat__context-actions .btn:hover { background: var(--surface-raised); }

.chat__scroll {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-4) var(--space-4) var(--space-2);
  scroll-behavior: smooth;
  overscroll-behavior: contain;
}

/* De draad zelf blijft een leeskolom, ook als het venster twee keer zo breed
   is. Regels van 1200 pixels lang lees je niet; de kolom ernaast schuift op,
   de tekst niet. `.chat__scroll` is geen flexcontainer, dus `margin-inline`
   zet hier niets uit — die val geldt voor flexitems. */
.chat__scroll > *:not(.chat__jump) {
  max-width: 760px;
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   Messages
   -------------------------------------------------------------------------- */

/* Een rij met een gezicht en een ballon. De jouwe staan rechts, de rest links:
   `flex-direction: row-reverse` draait de hele rij om, zodat het lege
   gezichtsvakje aan de goede kant valt en de ballon tegen de rand komt. */
.msg {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: 1px var(--space-2);
}

.msg + .msg { margin-top: 2px; }
.msg--head { margin-top: var(--space-4); }
.msg--mine { flex-direction: row-reverse; }

.msg__gutter { flex: none; width: 32px; }

/* 80 procent, zodat er altijd te zien is aan welke kant een ballon hangt —
   een regel die de hele breedte pakt leest als een blad, niet als iemand die
   iets zegt. */
.msg__body {
  min-width: 0;
  max-width: 80%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
}
.msg--mine .msg__body { align-items: flex-end; }

.msg__meta {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: 0 2px;
}

/* De ballon zelf. De hoek die naar de afzender wijst is de scherpe: linksonder
   bij een ander, rechtsonder bij jou. Bij een vervolgbericht van dezelfde
   persoon is hij overal rond — de punt wees al. */
.msg__bubble {
  min-width: 0;
  max-width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg) var(--radius-lg) var(--radius-lg) var(--radius-sm);
  background: var(--surface-raised);
}

.msg:not(.msg--head) .msg__bubble { border-radius: var(--radius-lg); }

/* De rand is de wassing van de accentkleur zelf, niet `--good-line`: die staat
   voor "gelukt" en een bericht van jou is geen uitslag. */
.msg--mine .msg__bubble {
  border-color: var(--accent-soft-hover);
  border-radius: var(--radius-lg) var(--radius-lg) var(--radius-sm) var(--radius-lg);
  background: var(--accent-soft);
}
.msg--mine:not(.msg--head) .msg__bubble { border-radius: var(--radius-lg); }

.msg__bubble--media { padding: 3px; }

.msg__author { font-size: var(--text-md); font-weight: 600; }
.msg__time { font-size: var(--text-2xs); color: var(--text-muted); }
.msg__edited { font-size: var(--text-2xs); color: var(--text-muted); font-style: italic; }

.msg__text {
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  color: var(--text-primary);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.msg--deleted .msg__text { color: var(--text-muted); font-style: italic; }
.msg--pending { opacity: 0.6; }
.msg--failed .msg__text { color: var(--text-danger); }

/* Hier stond: "je eigen bericht krijgt een streep, geen gekleurde ballon — in
   een groep van zes is zes kleuren ballon een lappendeken". Dat bezwaar ging
   over zes kleuren, één per persoon. Het ontwerp doet iets anders: iedereen
   wit, alleen jij groen, en jouw kant is rechts. Dat zijn twee kleuren en één
   as, en het beantwoordt "welke van deze schreef ik" al voordat je leest.
   Blijft er één kleur per persoon voorgesteld worden, dan geldt het oude
   bezwaar onverkort. */

/* Een vermelding is het enige wat je halverwege het scrollen moet zien. Op de
   ballon en niet op de rij: de rij is nu grotendeels leeg en een wassing over
   de volle breedte zou naar de verkeerde kant wijzen. */
.msg--mentioned .msg__bubble {
  border-color: var(--warning-line);
  background: var(--warning-bg);
}

.mention {
  padding: 0 3px;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent-soft-ink);
  font-weight: 500;
}

.msg__hit { background: var(--warning-bg); color: var(--warning-ink); border-radius: 2px; }

/* Het citaat bovenin de ballon — een blokje mét een vlak, niet alleen een
   streepje. In een ballon die zelf al een vlak is moet het geciteerde zich
   ergens aan vasthouden, anders leest het als de eerste regel van het bericht.
   Twee regels: van wie, en wat. */
.msg__quote {
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 100%;
  min-width: 0;
  margin-bottom: 7px;
  padding: 6px 9px;
  border: 0;
  border-left: 3px solid var(--border-strong);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--surface-page);
  font-size: var(--text-xs);
  color: var(--text-secondary);
  cursor: pointer;
  text-align: left;
}

.msg--mine .msg__quote {
  border-left-color: var(--accent);
  background: var(--surface-raised);
}

.msg__quote:hover { border-left-color: var(--accent); }
.msg__quote:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.msg__quote-author { font-weight: 700; font-size: var(--text-2xs); }
.msg__quote-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Attachments — de bovenmarge hoort bij "er stond tekst boven mij". Staat het
   plaatje alleen in de ballon, dan is er niets om afstand van te houden. */
.msg__media {
  display: block;
  max-width: min(320px, 100%);
  margin-top: var(--space-2);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-subtle);
}

.msg__gif {
  display: block;
  max-width: min(220px, 100%);
  margin-top: var(--space-2);
  border-radius: var(--radius-md);
}

.msg__bubble--media .msg__media,
.msg__bubble--media .msg__gif { margin-top: 0; }
.msg__bubble--media .msg__media { border: 0; }

.msg__file {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-page);
  color: inherit;
  text-decoration: none;
  max-width: 100%;
}

.msg__file:hover { border-color: var(--border-strong); background: var(--surface-hover); }
/* In een groene ballon zou `--surface-page` een grijs vlak in het groen zijn.
   `--surface-raised` is daar het lichtste vlak dat er wél bij hoort. */
.msg--mine .msg__file { background: var(--surface-raised); }
.msg__file svg { width: 18px; height: 18px; stroke: var(--text-muted); fill: none; stroke-width: 1.6; flex-shrink: 0; }
.msg__file-name { font-size: var(--text-sm); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.msg__file-size { font-size: var(--text-2xs); color: var(--text-muted); }

/* Reactions — onder de ballon, aan dezelfde kant als de ballon zelf. */
.reactions { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.msg--mine .reactions { justify-content: flex-end; }

.reaction {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px var(--space-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  background: var(--surface-page);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
  cursor: pointer;
  line-height: 1.6;
}

.reaction:hover { border-color: var(--border-strong); }
.reaction[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-soft-ink); }

/* Row actions — hidden until the message is hovered or focused, because eight
   buttons per message is a toolbar, not a conversation. */
/* Een vaste rij onder de ballon, aan dezelfde kant als de ballon. Hier stond
   een zwevende balk die pas bij hover verscheen — met een tik-om-te-openen
   uitzondering voor aanraakschermen erbij. Dat waren twee gedragingen voor één
   rij knoppen, en op een telefoon zag je hem alleen als je wist dat hij er was.
   Nu staat hij er gewoon: klein, grijs, en pas donker als je erheen gaat. */
.msg__actions {
  display: flex;
  align-items: center;
  gap: 1px;
  margin-top: 1px;
}

.msg { position: relative; }

.msg__actions .btn {
  width: 24px;
  height: 24px;
  padding: 0;
  color: var(--text-muted);
}
.msg__actions .btn:hover { color: var(--text-primary); background: var(--surface-hover); }
.msg__actions .receipt { margin-left: 3px; }

/* Receipts — one tick sent, two ticks read. Never colour alone: the title
   attribute and the shape both say it. */
.receipt { display: inline-flex; align-items: center; color: var(--text-muted); }
.receipt svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.receipt[data-state="read"] { color: var(--accent); }

/* --------------------------------------------------------------------------
   Dividers
   -------------------------------------------------------------------------- */

.daydiv {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-5) 0 var(--space-2);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.daydiv::before, .daydiv::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border-subtle);
}

/* An activity line — a task finished, a week handed in — says where to look.
   The rules on either side of a day divider would swallow it, so this sits
   inside the text and keeps its own background. */
.daydiv__link {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 1px var(--space-2);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent-soft-ink);
  font: inherit;
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  cursor: pointer;
}

.daydiv__link:hover { background: var(--accent-soft-hover); }
.daydiv__link:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.daydiv__link svg { width: 13px; height: 13px; stroke: currentColor; fill: none; stroke-width: 2; }

/* Hier stond `color: var(--status-serious)` — een vlák-kleur als inkt, wat op
   de lichte pagina 2,64:1 haalde. Dat viel nooit op omdat deze lijn tot
   vandaag helemaal niet verscheen (`Chat.markRead` wiste hem voordat je hem
   zag). Nu hij er staat: een pil in de wassing van het accent, met de inkt die
   daarbij hoort. Niet oranje — nieuwe berichten zijn geen alarm. */
.newdiv {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: var(--space-4) 0 var(--space-2);
  font-size: var(--text-2xs);
  font-weight: 700;
  color: var(--accent-soft-ink);
}

.newdiv::before, .newdiv::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--accent-soft-hover);
}

.newdiv__pill {
  flex: none;
  padding: 2px var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
}

/* --------------------------------------------------------------------------
   Typing indicator
   -------------------------------------------------------------------------- */

.typing {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 20px;
  padding: 0 var(--space-4) var(--space-1);
  font-size: var(--text-xs);
  color: var(--text-muted);
  flex-shrink: 0;
}

.typing__dots { display: inline-flex; gap: 3px; }

.typing__dots i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text-muted);
  animation: typing-bounce 1.1s ease-in-out infinite;
}

.typing__dots i:nth-child(2) { animation-delay: 0.16s; }
.typing__dots i:nth-child(3) { animation-delay: 0.32s; }

@keyframes typing-bounce {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.45; }
  30%           { transform: translateY(-4px); opacity: 1; }
}

/* --------------------------------------------------------------------------
   Jump-to-latest
   -------------------------------------------------------------------------- */

.chat__jump {
  position: absolute;
  right: var(--space-4);
  bottom: var(--space-3);
  z-index: 2;
  box-shadow: var(--shadow-md);
}

.chat__jump[hidden] { display: none; }

/* --------------------------------------------------------------------------
   Composer
   -------------------------------------------------------------------------- */

.composer {
  flex-shrink: 0;
  padding: var(--space-3) var(--space-4) var(--space-4);
  border-top: 1px solid var(--border-subtle);
}

.composer__reply {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-left: 2px solid var(--accent);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  background: var(--surface-sunken);
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.composer__reply-text { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.composer__attachments { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-2); }

/* Something waiting to be sent, so you can write a line about it first. */
.composer__ref { display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.composer__ref[hidden] { display: none !important; }
.composer__ref .ref-card { flex: 1; min-width: 0; }
.composer__ref-drop { flex-shrink: 0; }

/* The card is the message here, so it may use the whole bubble. */
.msg .ref-card { margin-top: var(--space-1); }
.msg--mine .ref-card { background: var(--surface-raised); }

.attach-chip {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-page);
  font-size: var(--text-xs);
}

.attach-chip img { width: 28px; height: 28px; object-fit: cover; border-radius: var(--radius-sm); }
.attach-chip__name { max-width: 160px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Dezelfde leeskolom als de draad erboven: het invoerveld staat recht onder de
   ballonnen en niet over de volle breedte van het venster. */
.composer__box {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  max-width: 760px;
  margin-inline: auto;
  padding: var(--space-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface-page);
  transition: border-color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}

.composer__box:focus-within {
  border-color: var(--border-focus);
  box-shadow: var(--focus-ring);
}

.composer__input {
  flex: 1;
  min-width: 0;
  min-height: 24px;
  max-height: 168px;
  padding: var(--space-1) var(--space-2);
  border: 0;
  background: transparent;
  color: var(--text-primary);
  font: inherit;
  font-size: var(--text-md);
  line-height: var(--leading-normal);
  resize: none;
  overflow-y: auto;
}

.composer__input:focus { outline: none; }
.composer__input::placeholder { color: var(--text-muted); }

.composer__tools { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.composer__tools .btn { width: 32px; height: 32px; padding: 0; }
.composer__send { flex: none; }

.composer__hint {
  max-width: 760px;
  margin-inline: auto;
  margin-top: var(--space-2);
  font-size: var(--text-2xs);
  /* muted, not faint: at 11px --text-faint measures about 3.5:1, and AA wants
     4.5 for anything under 18pt. Every readable string in here uses muted. */
  color: var(--text-muted);
}

.composer__hint kbd {
  padding: 1px 4px;
  border: 1px solid var(--border-subtle);
  border-bottom-width: 2px;
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  font-family: var(--font-mono);
  font-size: 0.9em;
}

/* --------------------------------------------------------------------------
   Pickers — emoji, GIFs, mentions
   -------------------------------------------------------------------------- */

.picker {
  position: absolute;
  right: var(--space-4);
  bottom: calc(100% + var(--space-2));
  z-index: 40;
  width: calc(100vw - 2rem);
  max-width: 368px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.composer { position: relative; }
.picker[hidden] { display: none; }

.picker__tabs { display: flex; gap: var(--space-1); padding: var(--space-2); border-bottom: 1px solid var(--border-subtle); }
.picker__search { padding: var(--space-2); border-bottom: 1px solid var(--border-subtle); }

.picker__body { max-height: 320px; overflow-y: auto; padding: var(--space-2); }

.picker__label {
  padding: var(--space-2) var(--space-1) var(--space-1);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.emoji-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px; }

.emoji-grid button {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
}

.emoji-grid button:hover { background: var(--surface-hover); }

.gif-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); }

.gif-grid button {
  display: grid;
  gap: 2px;
  padding: 0;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-page);
  cursor: pointer;
  overflow: hidden;
}

.gif-grid button:hover { border-color: var(--accent); }
.gif-grid img { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; }
.gif-grid span { padding: 2px 0 4px; font-size: var(--text-2xs); color: var(--text-muted); }

/* Mention autocomplete rides above the composer */
.mention-menu {
  position: absolute;
  left: var(--space-4);
  bottom: calc(100% + var(--space-2));
  z-index: 45;
  width: calc(100% - 2rem);
  max-width: 280px;
  max-height: 220px;
  overflow-y: auto;
  padding: var(--space-1);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  box-shadow: var(--shadow-lg);
}

.mention-menu[hidden] { display: none; }

.mention-menu button {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  font-size: var(--text-sm);
}

.mention-menu button:hover,
.mention-menu button[aria-selected="true"] { background: var(--accent-soft); color: var(--accent-soft-ink); }
.mention-menu small { color: var(--text-muted); margin-left: auto; }

/* --------------------------------------------------------------------------
   Search results, in place of the list
   -------------------------------------------------------------------------- */

.hit {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.hit:hover { background: var(--surface-hover); }
.hit__where { display: flex; justify-content: space-between; gap: var(--space-2); font-size: var(--text-2xs); color: var(--text-muted); }
.hit__where b { color: var(--text-secondary); font-weight: 600; }
.hit__text { font-size: var(--text-sm); color: var(--text-secondary); line-height: var(--leading-snug); }
.hit__text mark { background: var(--warning-bg); color: var(--warning-ink); border-radius: 2px; }

/* --------------------------------------------------------------------------
   Dialogs — native <dialog>, so focus trapping and Esc come for free
   -------------------------------------------------------------------------- */

.dialog {
  /* base.css zeroes every margin, which also kills the `margin: auto` a
     <dialog> relies on to centre itself. Put it back here rather than carving
     an exception into the reset. */
  margin: auto;
  width: calc(100vw - 2rem);
  max-width: 460px;
  padding: 0;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  color: var(--text-primary);
  box-shadow: var(--shadow-lg);
}

.dialog::backdrop { background: var(--scrim); }
.dialog__head { padding: var(--space-5) var(--space-5) var(--space-3); }
.dialog__title { font-size: var(--text-lg); font-weight: 600; }
.dialog__sub { margin-top: var(--space-1); font-size: var(--text-sm); color: var(--text-secondary); }
.dialog__body { display: grid; gap: var(--space-4); padding: 0 var(--space-5); max-height: 56vh; overflow-y: auto; }

.dialog__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5) var(--space-5);
}

.picklist { display: grid; gap: 1px; }

/* Een sjabloonregel: naam en aantal links, gebruiken en weghalen rechts. */
.tpl-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
}
.tpl-row:hover { background: var(--surface-hover); }
.tpl-row__text { flex: 1; min-width: 0; display: grid; gap: 1px; }
.tpl-row__drop {
  border: 0;
  background: none;
  color: var(--text-muted);
  font-size: var(--text-base);
  line-height: 1;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.tpl-row__drop:hover { background: var(--critical-bg); color: var(--critical-ink); }
.tpl-save { display: flex; gap: var(--space-2); }
.tpl-save .input { flex: 1; }

.dialog__body .search + .chips { margin-top: var(--space-3); }
.dialog__body .search + .picklist,
.dialog__body .chips + .picklist { margin-top: var(--space-2); }

.picklist label {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  cursor: pointer;
}

.picklist label:hover { background: var(--surface-hover); }
.picklist__meta { margin-left: auto; font-size: var(--text-xs); color: var(--text-muted); }

.picklist__head {
  padding: var(--space-3) var(--space-2) var(--space-1);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.picklist__head:first-child { padding-top: 0; }

/* The share dialog: the card first, then where it goes. */
.dialog__body > .ref-card { margin-bottom: var(--space-4); }
.dialog__body .picklist { max-height: 260px; overflow-y: auto; }
.dialog__body .tabs { margin-bottom: var(--space-3); }

.chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 2px var(--space-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  background: var(--surface-page);
  font-size: var(--text-xs);
}

.chip button {
  border: 0;
  background: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
  line-height: 1;
  font-size: 1rem;
}

.chip button:hover { color: var(--text-danger); }

/* --------------------------------------------------------------------------
   "Message this person", inside the employee table
   Hidden until the row is hovered or the button itself is focused, so the
   directory still reads as a list of people rather than a list of buttons —
   but it is always reachable by keyboard.
   -------------------------------------------------------------------------- */

.cell-primary__action {
  width: 28px;
  height: 28px;
  padding: 0;
  margin-left: auto;
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease);
}

tr:hover .cell-primary__action,
.cell-primary__action:focus-visible { opacity: 1; }

@media (hover: none) {
  .cell-primary__action { opacity: 1; }
}

/* --------------------------------------------------------------------------
   Host 1 — the full page
   -------------------------------------------------------------------------- */

/* De enige pagina zonder marge en zonder maximum. `.page` centreert alles op
   `--content-max` met ruimte eromheen, en dat klopt voor een blad met kaarten
   erop; een gesprek van drie kolommen die tot de rand doorlopen is geen blad.
   Dit staat ná `.page` in de laadvolgorde van `index.html`, dus het wint. */
.page--chat {
  display: flex;
  flex-direction: column;
  height: calc(100vh - var(--topbar-height));
  max-width: none;
  padding: 0;
  min-height: 0;
}

.page--chat .chat { flex: 1; min-height: 0; }

/* --------------------------------------------------------------------------
   Host 2 — the topbar drawer
   -------------------------------------------------------------------------- */

.chat-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  width: min(440px, 100vw);
  display: flex;
  flex-direction: column;
  background: var(--surface-raised);
  border-left: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-lg);
  transform: translateX(100%);
  transition: transform var(--duration-base) var(--ease);
}

.chat-drawer[data-open="true"] { transform: translateX(0); }

.chat-drawer__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--topbar-height);
  padding: 0 var(--space-3) 0 var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  flex-shrink: 0;
}

.chat-drawer__title { font-size: var(--text-md); font-weight: 600; flex: 1; }
.chat-drawer__mount { flex: 1; min-height: 0; display: flex; }
.chat-drawer__mount .chat { flex: 1; }

/* The drawer is one column wide: the list and the thread take turns, and the
   header's back button is what moves between them. Same components, so there
   is nothing to keep in sync. */
.chat-drawer__mount .chat { grid-template-columns: minmax(0, 1fr); }
.chat-drawer__mount .chat__aside { border-right: 0; }
.chat-drawer__mount .chat[data-pane="list"] .chat__main,
.chat-drawer__mount .chat[data-pane="thread"] .chat__aside { display: none; }
.chat-drawer__mount .chat[data-pane="thread"] .chat__back { display: inline-flex; }

/* A count on the topbar button, so you don't have to open the drawer to find
   out whether opening it was worth it. */
.topbar__chat { position: relative; }

.topbar__chat-count {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 10px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.topbar__chat-count[hidden] { display: none; }

/* --------------------------------------------------------------------------
   Responsive — the full page turns into one column, same trick as the drawer
   -------------------------------------------------------------------------- */

@media (max-width: 860px) {
  .chat { grid-template-columns: minmax(0, 1fr); }
  .chat__aside { border-right: 0; }
  .chat[data-pane="list"] .chat__main,
  .chat[data-pane="thread"] .chat__aside { display: none; }
  .chat[data-pane="thread"] .chat__back { display: inline-flex; }
  .page--chat { height: calc(100vh - var(--topbar-height)); }
  .msg { grid-template-columns: 28px minmax(0, 1fr); gap: var(--space-2); }
  .picker { right: var(--space-2); left: var(--space-2); width: auto; }
}

/* On a phone the header is a name and six controls in 350 pixels. Tightening
   the gaps and the buttons buys back the room the name needs; hiding any of
   the controls would mean calling someone is a thing you can only do at a
   desk. The context strip's captions go instead — its buttons keep their
   labels for screen readers and lose only the printed word. */
@media (max-width: 620px) {
  .chat__head { gap: var(--space-2); padding-left: var(--space-3); padding-right: var(--space-3); }
  .chat__head .page__actions { gap: 0; }
  .chat__head .page__actions .btn--icon { width: 32px; height: 32px; }
  .chat__head-name { font-size: var(--text-md); }

  /* De chip gaat weg, niet de knoppen. Op deze breedte staat de kolom er niet
     en is de strook eronder dus zichtbaar — en daar staat "Projectpagina" al.
     De chip is er dan een tweede weg naar dezelfde plek, en die kost 104 van
     de 356 pixels die de kop heeft. Gemeten: mét chip duwde hij de laatste
     twee knoppen buiten beeld. */
  .chat__head-project { display: none; }

  .chat__context { padding-left: var(--space-3); padding-right: var(--space-3); flex-wrap: nowrap; }
  .chat__context-facts { flex: 1; overflow: hidden; }
  .chat__context-fact { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .chat__context-actions .btn span { display: none; }
  .chat__context-actions .btn { padding-left: var(--space-2); padding-right: var(--space-2); }

  /* Five controls beside the text field leave about a hundred pixels to type
     in. The GIF button is the one that can go: the picker it opens has a GIF
     tab next to the emoji tab, so the emoji button reaches the same drawer one
     tap later, and nothing is actually removed. */
  .composer__tools [data-act="open-gif"] { display: none; }
}

/* --------------------------------------------------------------------------
   An attachment is also a file on Bestanden — the way over to it. Quiet until
   the message is under the pointer, like the rest of a message's actions.
   -------------------------------------------------------------------------- */

.msg__media-wrap { position: relative; display: inline-block; max-width: 100%; }

.msg__file-drive {
  flex: none;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  margin-left: auto;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-muted);
  cursor: pointer;
  opacity: 0;
}

.msg__media-wrap .msg__file-drive {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  background: var(--surface-raised);
  box-shadow: var(--shadow-sm);
}

.msg__file-drive .btn__icon {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.msg:hover .msg__file-drive,
.msg__file-drive:focus-visible { opacity: 1; }
.msg__file-drive:hover { background: var(--surface-hover); color: var(--text-primary); }
.msg__file-drive:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 1px; }

@media (hover: none) {
  .msg__file-drive { opacity: 1; }
}

/* ==========================================================================
   De detailkolom — wie er in dit gesprek zit, en wat eruit kwam
   --------------------------------------------------------------------------
   Alleen op de pagina, nooit in het paneel: messages.js hangt hem alleen op
   als het ophangpunt erom vraagt. Hij bezit niets — het project komt uit
   Projects, de gezichten uit Chat, de bestanden uit Drive.
   ========================================================================== */

.chat__rail {
  width: 280px;
  flex: none;
  min-width: 0;
  padding: var(--space-4);
  border-left: 1px solid var(--border-subtle);
  background: var(--surface-raised);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

/* Onder 1200 is er geen plek voor drie kolommen naast elkaar: dan wint het
   gesprek zelf. Deze regel staat ná `.chat__rail` met opzet — een mediaquery
   telt niet mee voor specificiteit. */
@media (max-width: 1200px) {
  .chat__rail { display: none; }
}

.chat__rail-block { display: flex; flex-direction: column; gap: var(--space-3); }

.chat__rail-label {
  margin: 0;
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

.chat__rail-project {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-page);
}

.chat__rail-top { display: flex; align-items: center; gap: var(--space-2); }

.chat__rail-code {
  flex: none;
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 700;
}

.chat__rail-name {
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat__rail-track {
  height: 5px;
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  overflow: hidden;
}
.chat__rail-fill { height: 100%; border-radius: var(--radius-pill); }

.chat__rail-facts {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-2xs);
  color: var(--text-secondary);
}
.chat__rail-due { margin-left: auto; font-weight: 600; white-space: nowrap; }
.chat__rail-due--warn { color: var(--critical-ink); }

.chat__rail-book { width: 100%; justify-content: center; }

.chat__rail-person,
.chat__rail-file,
.chat__rail-task {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
}

.chat__rail-file,
.chat__rail-task {
  padding: var(--space-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
}
.chat__rail-file:hover,
.chat__rail-task:hover { border-color: var(--border-strong); background: var(--surface-page); }
.chat__rail-file:focus-visible,
.chat__rail-task:focus-visible { outline: none; box-shadow: var(--focus-ring); }

.chat__rail-face { position: relative; flex: none; display: inline-flex; }

.chat__rail-dot {
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 9px;
  height: 9px;
  border: 2px solid var(--surface-raised);
  border-radius: 50%;
  background: var(--status-good);
}

.chat__rail-who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }

.chat__rail-person-name,
.chat__rail-file-name,
.chat__rail-task-title {
  font-size: var(--text-sm);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat__rail-role {
  font-size: var(--text-2xs);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat__rail-file-icon { width: 16px; height: 16px; flex: none; color: var(--text-secondary); }

.chat__rail-prio { width: 3px; height: 22px; flex: none; border-radius: var(--radius-pill); }

.chat__rail-none { margin: 0; font-size: var(--text-xs); color: var(--text-muted); }

.chat__rail-add {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 0;
  border: none;
  background: none;
  color: var(--text-link);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  cursor: pointer;
}
.chat__rail-add:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-sm); }

.chat__rail-ring {
  width: 28px;
  height: 28px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--good-line);
  border-radius: 50%;
}
.chat__rail-ring svg { width: 14px; height: 14px; }

/* Drie kolommen zodra de detailkolom er is. Dit staat achteraan met opzet: de
   basisregel van `.chat` blijft twee kolommen — dat is wat het paneel krijgt,
   en dat is ook wat de pagina krijgt zodra de kolom dicht staat. `:has()` laat
   het raster meebewegen met wat er werkelijk in staat, zonder dat de renderer
   een klasse op de wortel hoeft te zetten die hij daarna moet bijhouden. */
@media (min-width: 1201px) {
  .chat:has(> .chat__rail:not([hidden])) {
    grid-template-columns: minmax(0, 300px) minmax(0, 1fr) 280px;
  }
  /* En dan is de strook onder de kop overbodig — zie de uitleg daar. */
  .chat:has(> .chat__rail:not([hidden])) .chat__context { display: none; }
}
