:root {
  --bg: #f4f5f7;
  --surface: #ffffff;
  --surface-2: #fafbfc;
  --border: #dfe1e6;
  --text: #172b4d;
  --muted: #6b778c;
  --accent: #0b6bcb;
  --danger: #c9372c;
  --danger-soft: #ffecea;
  --ok: #216e4e;
  --shadow: 0 1px 2px rgba(9, 30, 66, 0.12);
  --radius: 12px;
  /* The green of a lit indicator, not of a leaf. */
  --led: #1f8f4e;
  --led-soft: #e2f7ea;
  /* The ink a tinted button writes in. In daylight it is the colour itself; the
     dark theme lifts it so it stays legible on a dark tint. */
  --accent-ink: var(--accent);
  --led-ink: var(--led);
  --danger-ink: var(--danger);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #0a0d18;
    --surface: #141a2e;
    --surface-2: #1d2440;
    --border: #29314f;
    --text: #edeff7;
    --muted: #949bba;
    --accent: #7a6cf7;
    --danger: #f2557b;
    --danger-soft: color-mix(in srgb, var(--danger) 17%, var(--surface));
    --ok: #74e6a8;
    --shadow: 0 10px 30px -20px rgba(0, 0, 0, 0.9);
    --led: #35e08a;
    --led-soft: color-mix(in srgb, var(--led) 17%, var(--surface));
    --accent-ink: #b8adff;
    --led-ink: #74e6a8;
    --danger-ink: #ff9db4;
  }
}

/* The same values again, for when the theme was chosen rather than inherited. */
:root[data-theme='dark'] {
    --bg: #0a0d18;
    --surface: #141a2e;
    --surface-2: #1d2440;
    --border: #29314f;
    --text: #edeff7;
    --muted: #949bba;
    --accent: #7a6cf7;
    --danger: #f2557b;
    --danger-soft: color-mix(in srgb, var(--danger) 17%, var(--surface));
    --ok: #74e6a8;
    --shadow: 0 10px 30px -20px rgba(0, 0, 0, 0.9);
    --led: #35e08a;
    --led-soft: color-mix(in srgb, var(--led) 17%, var(--surface));
    --accent-ink: #b8adff;
    --led-ink: #74e6a8;
    --danger-ink: #ff9db4;
  }


/* Derived from the accent so a chosen colour carries its own tint, and from the
   surface so it lands right in either theme. The flat value is the fallback where
   color-mix is unsupported. */
:root {
  --accent-soft: #e6f0fb;
  --accent-soft: color-mix(in srgb, var(--accent) 14%, var(--surface));
  --btn-radius: 10px;
}

* { box-sizing: border-box; }

/* A display value in an author stylesheet beats the browser's own
   [hidden] { display: none }, so hidden screens would otherwise all render
   at once. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font: 14px/1.45 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Ubuntu, sans-serif;
  background: var(--bg);
  color: var(--text);
}

.screen { min-height: 100vh; display: flex; flex-direction: column; }
.centered { align-items: center; justify-content: center; }
.muted { color: var(--muted); }
.spacer { flex: 1; }
.error { color: var(--danger); margin: 0; }

/* --- auth ------------------------------------------------------------ */

.card.auth {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 28px;
  width: min(360px, calc(100vw - 32px));
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.card.auth h1 { margin: 0; font-size: 22px; }
.card.auth p { margin: -8px 0 0; }
.card.auth label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--muted); }

input {
  font: inherit;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--btn-radius);
  padding: 9px 10px;
}
input:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

button {
  font: inherit;
  cursor: pointer;
  border-radius: var(--btn-radius);
  border: 1px solid transparent;
  background: var(--accent);
  color: #fff;
  padding: 9px 14px;
}
button:hover { filter: brightness(1.08); }
button.ghost { background: transparent; color: var(--muted); border-color: var(--border); }
button.ghost:hover { color: var(--text); }

/* --- top bar --------------------------------------------------------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.brand { font-weight: 700; letter-spacing: 0.2px; flex: 0 0 auto; }

.burger {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 30px;
  height: 26px;
  padding: 0 5px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--btn-radius);
}
.burger span {
  display: block;
  height: 2px;
  border-radius: 1px;
  background: var(--muted);
}
.burger:hover { background: var(--surface-2); border-color: var(--border); filter: none; }
.burger:hover span { background: var(--text); }

.settings {
  position: fixed;
  z-index: 45;
  min-width: 240px;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 28px rgba(9, 30, 66, 0.28);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.settings-label {
  display: block;
  margin-bottom: 6px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--muted);
}
.settings-row { display: flex; flex-wrap: wrap; gap: 6px; }
.settings-row button {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--btn-radius);
  padding: 5px 10px;
  font-size: 12px;
}
.settings-row button:hover { color: var(--text); filter: none; }
.settings-row button.active {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}
.settings-row.swatches button {
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 50%;
}
.settings-row.swatches button.active { outline: 2px solid var(--accent); outline-offset: 2px; }
.settings-row.swatches button[data-value='default'] {
  background: linear-gradient(135deg, #0b6bcb 50%, #5aa2f0 50%);
}

/* The strip takes whatever room is left and scrolls inside it, so adding tabs
   never pushes the buttons on the right off the bar. */
/* The add button lives in the strip but outside the scrolling list, so it stays
   at the edge whatever the tabs are doing. */
.strip .add {
  flex: 0 0 auto;
  margin-left: 6px;
  /* Same padding as a tab, and a line box the same height as a tab's text, so the
     rectangle matches exactly rather than nearly. */
  padding: 6px 12px;
  font-size: 15px;
  line-height: 20px;
}
.chips-wrap { align-items: center; }

.strip {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 1 auto;
  min-width: 0;
}
/* Only inside the bar does a strip take the room that is left; the chip strip is
   a row in a column layout, where growing means growing downwards. */
.topbar .strip { flex: 1 1 auto; }
.tabs {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  /* Smoothness is asked for per call in the arrow handler; forcing it here would
     also animate scrollIntoView and any future programmatic scroll. */
  scrollbar-width: none;
  /* Shrink when the tabs do not fit, but never grow: otherwise the strip would
     stretch across the bar and drag the add button away from the last tab. */
  flex: 0 1 auto;
  min-width: 0;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs button { flex: 0 0 auto; }

/* Plain glyphs beside the strip: no circle, nothing to click, and their own slot
   so a tab can never slide under one. The slots only exist while the strip
   actually scrolls. */
.arrow {
  display: none;
  flex: 0 0 auto;
  width: 12px;
  text-align: center;
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
  user-select: none;
  pointer-events: none;
}
.strip.scrollable .arrow { display: block; visibility: hidden; }
.strip.scrollable.can-left .arrow.left { visibility: visible; }
.strip.scrollable.can-right .arrow.right { visibility: visible; }
.tabs button {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  padding: 6px 12px;
  flex: 0 0 auto;
}
.tabs button.active { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.tabs .badge {
  margin-left: 6px;
  background: var(--accent);
  color: #fff;
  border-radius: 10px;
  padding: 0 6px;
  font-size: 11px;
}
.tabs button.active .badge { background: var(--accent); }
.tabs .tab-edit {
  font: inherit;
  padding: 0 4px;
  width: 8em;
  background: var(--surface-2);
}
.sync { font-size: 12px; color: var(--muted); }

/* --- dropdown menu ---------------------------------------------------- */

.menu {
  position: fixed;
  z-index: 40;
  min-width: 180px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 6px 20px rgba(9, 30, 66, 0.25);
  padding: 4px;
  display: flex;
  flex-direction: column;
}
.menu button {
  background: transparent;
  color: var(--text);
  border: none;
  text-align: left;
  padding: 7px 10px;
  border-radius: 5px;
}
.menu button:hover { background: var(--accent-soft); filter: none; }
.menu button.checked::after { content: ' ✓'; color: var(--accent); }
.menu button.danger { color: var(--danger); }

/* A small window at the button that opened it, sized to its fields rather than to
   the screen: it asks for two things and gets out of the way. */
.popover {
  position: fixed;
  z-index: 46;
  width: 280px;
  max-width: calc(100vw - 16px);
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 28px rgba(9, 30, 66, 0.28);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.popover-title { font-weight: 600; font-size: 13px; }
.popover label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--muted);
}
.popover input,
.popover textarea {
  font: inherit;
  font-size: 13px;
  text-transform: none;
  letter-spacing: normal;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--btn-radius);
  padding: 6px 8px;
}
.popover textarea { resize: vertical; min-height: 64px; }
.popover-actions { display: flex; justify-content: flex-end; gap: var(--action-gap); }
.popover-actions button { height: var(--action-h); padding: 0 12px; font-size: 12px; }

.alert {
  margin: 10px 16px 0;
  padding: 8px 12px;
  border-radius: var(--btn-radius);
  background: var(--danger-soft);
  color: var(--danger);
  border: 1px solid var(--danger);
  font-size: 13px;
}

/* --- column chips (phones only) --------------------------------------- */

.chips-wrap { display: none; }

.chips {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  flex: 0 1 auto;
  min-width: 0;
}
.chips::-webkit-scrollbar { display: none; }
.chips button {
  background: transparent;
  color: var(--muted);
  /* The same rectangle as a tab, so the two strips read as one system. */
  border: 1px solid var(--border);
  border-radius: var(--btn-radius);
  height: 34px;
  padding: 0 12px;
  font-size: 13px;
  white-space: nowrap;
  flex: 0 0 auto;
}

/* A square, measured against the chips beside it rather than guessed at. */
.chips-wrap .add {
  width: 34px;
  height: 34px;
  padding: 0;
  margin-left: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.chips button.active {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}
.chips .n {
  margin-left: 6px;
  font-size: 11px;
  opacity: 0.75;
}
.chips .n:empty { display: none; }

/* --- board ----------------------------------------------------------- */

/* One grid track per column, all the same size, always sharing the screen width
   however many there are. minmax(0, 1fr) is what lets a track shrink below its
   content: with plain 1fr the cards would refuse to narrow and the board would
   overflow instead. */
.board {
  flex: 1;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 12px;
  padding: 12px 16px 20px;
  overflow-x: auto;
  align-items: start;
}

.column {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  min-width: 0;
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 90px);
}
.column > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--action-gap);
  /* The right inset matches where a card's own content ends: the column padding,
     the card's border and padding, and the scrollbar gutter the cards reserve but
     the header does not. --sbw is measured at boot. */
  padding: 10px calc(21px + var(--sbw, 0px)) 10px 12px;
  border-bottom: 1px solid var(--border);
}
.column h2 {
  margin: 0;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.col-title { cursor: text; }
.col-title:hover { color: var(--text); }
.col-edit {
  flex: 1;
  min-width: 0;
  padding: 2px 6px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.col-tools { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
/* Raising a task belongs to the column it lands in, so the button lives in that
   column's own header. The hub has none: nothing is raised there, things arrive. */
.col-add {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: var(--action-h);
  padding: 0;
  font-size: 15px;
  line-height: 1;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--btn-radius);
}
.col-add:hover { color: var(--accent); border-color: var(--accent); filter: none; }
.col-del {
  background: transparent;
  color: var(--muted);
  border: none;
  padding: 0 2px;
  font-size: 16px;
  line-height: 1;
  opacity: 0;
}
.column:hover .col-del { opacity: 1; }
.col-del:hover { color: var(--danger); }
.col-action {
  background: transparent;
  color: var(--muted);
  border-radius: var(--btn-radius);
  /* Pushed to the right so it sits next to the conversation count rather than
     hanging off the heading. */
  margin-left: auto;
  white-space: nowrap;
}
.col-action:hover { color: var(--text); border-color: var(--muted); }
.count { font-size: 12px; color: var(--muted); }
/* The gutter is reserved whether or not the column is scrolling, so a card's
   right edge sits in the same place in every column. */
.cards {
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
  scrollbar-gutter: stable;
  min-height: 60px;
}
.cards.dragover { background: var(--accent-soft); }

.card-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--btn-radius);
  box-shadow: var(--shadow);
  padding: 10px;
}
.card-item.dragging { opacity: 0.45; }

/* --- hub ------------------------------------------------------------- */

/* Everything below the header is one row: the conversation on the left, the two
   actions on the right. Both actions and the send button share a width, so they
   line up in a single column down the edge of the card. */
/* One width, one height and one gap for every button on a card, declared once so
   nothing can drift out of line. The source badge shares the height because it
   sits in the same row as a button. */
:root { --action-w: 84px; --action-h: 26px; --action-gap: 6px; }

.thread .split { display: flex; align-items: stretch; gap: var(--action-gap); }
.thread .main { flex: 1 1 auto; min-width: 0; }

/* The dashed rule sits above the row, so the buttons fall below it. */
.thread .split { margin-top: var(--action-gap); }
.thread.open .split {
  padding-top: var(--action-gap);
  border-top: 1px dashed var(--border);
}

.thread .side {
  display: flex;
  flex-direction: column;
  gap: var(--action-gap);
  flex: 0 0 auto;
  width: var(--action-w);
}
/* Ordinary buttons, like the rest of the screen: soft fill, hairline border. */
.thread .side button,
.thread .reply button,
.thread .head .move,
.col-action {
  width: var(--action-w);
  height: var(--action-h);
  padding: 0 8px;
  font-size: 12px;
  border: 1px solid var(--border);
  white-space: nowrap;
  /* Centred both ways by the box itself: a button inherits the header's
     line-height, which is taller than its own content box, and the label ends up
     sitting low. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.thread .side .drop { background: var(--danger-soft); color: var(--danger); }
.thread .side .totask { background: var(--led-soft); color: var(--led); }
/* The one exception to the shared height: it takes whatever the conversation
   beside it happens to be, and stops at the reply row rather than running past. */
.thread .side .totask { flex: 1 1 auto; height: auto; min-height: var(--action-h); }

/* The send button takes the height of the field beside it, so the two read as
   one control rather than a button parked next to a taller box. */
.thread .reply { display: flex; align-items: stretch; gap: var(--action-gap); margin-top: var(--action-gap); }
.thread .reply input { flex: 1 1 auto; min-width: 0; }
.thread .reply button {
  flex: 0 0 auto;
  height: auto;
  background: var(--accent-soft);
  color: var(--accent);
}

/* One line, always: source, name, then pencil, time and move hard against the
   right. The name is the only thing that gives way, and it does so by ellipsis
   rather than by pushing anything onto a second row. */
.thread .head {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--action-gap);
  cursor: pointer;
  font-size: 21px;
  /* Match the buttons in the row, so the header's own line box does not add a
     couple of pixels to the gap below it. */
  line-height: var(--action-h);
}
/* Back to the body size. The row around it stays as tall as it was, so the
   pencil, the time and the move button do not shift. */
.thread .name { flex: 1 1 auto; min-width: 0; font-size: 14px; }
.thread .chan { flex: 0 0 auto; }
.thread .head .rename,
.thread .head .time,
.thread .head .move { flex: 0 0 auto; }

/* Directly above the column of buttons below it, and the same size as them. */
.thread .head .move {
  background: var(--surface-2);
  color: var(--muted);
  border-radius: var(--btn-radius);
  opacity: 1;
}
.thread .head .move:hover { color: var(--accent); border-color: var(--accent); }
/* A collapsed card is half again as tall. The fixed-height buttons keep their
   height and the onward button takes the slack, rather than everything shrinking
   to share it. */
.thread:not(.open) { min-height: 118px; }

/* Quiet control: it belongs to the card, not to the eye. Revealed on hover, and
   always visible on touch, where there is no hover to reveal it. */
/* An icon, not one of the action buttons — but the same height, so it does not
   disturb the row it sits in. */
.thread .rename {
  background: transparent;
  color: var(--muted);
  border: none;
  width: 20px;
  height: var(--action-h);
  padding: 0;
  font-size: 13px;
  opacity: 0;
}
.thread .rename:hover { color: var(--accent); }
.thread:hover .rename { opacity: 1; }
.thread .head .time { font-size: 0.62em; }
/* A single letter in a box rather than the channel's name: it says where the
   message came from without eating the width the name needs. The height and the
   lettering are the same as before. */
.thread .chan {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: var(--action-h);
  font-size: 0.48em;
  text-transform: uppercase;
  letter-spacing: 0;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0;
}
.thread .unread {
  background: var(--accent);
  color: #fff;
  border-radius: 10px;
  font-size: 0.52em;
  padding: 0 6px;
}
.thread .preview {
  color: var(--muted);
  margin-top: 6px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.thread .msg-list { display: flex; flex-direction: column; gap: 8px; }

.msg { border-left: 3px solid var(--border); padding: 2px 0 2px 8px; }
.msg.out { border-left-color: var(--accent); }
.msg .text { white-space: pre-wrap; overflow-wrap: anywhere; }
.msg .media { margin-bottom: 6px; }
.msg .media img, .msg .media video {
  max-width: 100%;
  max-height: 260px;
  border-radius: var(--btn-radius);
  display: block;
}
.msg .media audio { width: 100%; }
.msg .media a { color: var(--accent); }
.msg .meta { font-size: 11px; color: var(--muted); margin-top: 3px; }


/* --- task cards ------------------------------------------------------ */

.task .title { font-weight: 500; overflow-wrap: anywhere; }
/* Three lines at most, so one long task cannot push the rest of the column out
   of sight. */
.task .desc {
  margin-top: 4px;
  font-size: 12px;
  color: var(--muted);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.task .sub { font-size: 11px; color: var(--muted); margin-top: 6px; display: flex; gap: 8px; flex-wrap: wrap; }
.task .prio { border-radius: 4px; padding: 0 5px; }
.task .prio.HIGH, .task .prio.URGENT { background: var(--danger-soft); color: var(--danger); }
.task .overdue { color: var(--danger); }
.task .actions { display: flex; gap: 6px; margin-top: 8px; }
.task button { padding: 3px 8px; font-size: 12px; }
.task .pick { background: transparent; color: var(--muted); border-color: var(--border); }
.task .pick:hover { color: var(--accent); border-color: var(--accent); }

/* --- drag-to-delete -------------------------------------------------- */

.trash {
  position: fixed;
  left: 0;
  top: 90px;
  bottom: 20px;
  width: 84px;
  background: var(--danger-soft);
  border: 2px dashed var(--danger);
  border-radius: 0 var(--radius) var(--radius) 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--danger);
  font-weight: 600;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  z-index: 20;
}
.trash.hot { background: var(--danger); color: #fff; }

.toast {
  position: fixed;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--text);
  color: var(--bg);
  padding: 9px 16px;
  border-radius: 20px;
  z-index: 30;
}

.empty { color: var(--muted); font-size: 13px; text-align: center; padding: 14px 0; }

@media (max-width: 700px) {
  /* One column at a time, chosen by chip rather than swiped to: a horizontal
     gesture would fight the conversation thread that expands inside the hub. */
  .chips-wrap { display: flex; padding: 10px 12px 2px; }

  .board {
    display: block;
    padding: 10px 12px 20px;
    overflow-x: hidden;
  }
  .alert { margin: 8px 12px 0; }
  .column { display: none; }
  .column.shown {
    display: flex;
    max-height: none;
  }
  .cards { overflow-y: visible; }
  /* Nothing scrolls here, so there is no gutter to compensate for — which matters
     on a desktop window narrowed past the breakpoint, where a scrollbar width is
     still measured. */
  .column > header { padding-right: 21px; }

  /* Touch has no hover, so controls that reveal on hover must simply be there. */
  .col-del, .thread .rename { opacity: 1; }
  .topbar { gap: 8px; padding: 8px 12px; }
  .topbar .sync, .topbar #who { display: none; }

  /* Row one is the name and the way out; the tab strip takes the whole of row
     two, which is what pushes the sign-out button up beside the name. */
  .brand { flex: 1 1 auto; }
  #btn-logout { order: 1; }
  .tabs-wrap { order: 2; width: 100%; }

  /* No arrows over the tabs: the plus rides at the end of the strip and going
     past it is itself the sign that the row keeps going. Two classes on the wrap
     to match the specificity of the rule that shows them. */
  .strip.tabs-wrap .arrow { display: none; }

  /* Column navigation belongs under the thumb, so it sits at the bottom of the
     screen and stays there while the board scrolls. */
  .chips-wrap {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 15;
    padding: 8px 12px;
    background: var(--surface);
    border-top: 1px solid var(--border);
  }
  /* Room for it, so the last card is never hidden underneath. */
  .board { padding-bottom: 68px; }
}

/* --- Hercules dark ------------------------------------------------------- */

/* Two faint pools of light behind the board, the way the Hercules panels sit on
   their background. Daylight keeps a flat surface. */
:root { --bg-glow: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg-glow:
      radial-gradient(1200px 600px at 15% -10%, #161d38 0%, transparent 55%),
      radial-gradient(900px 500px at 110% 0%, #181542 0%, transparent 50%);
  }
}
:root[data-theme='dark'] {
  --bg-glow:
    radial-gradient(1200px 600px at 15% -10%, #161d38 0%, transparent 55%),
    radial-gradient(900px 500px at 110% 0%, #181542 0%, transparent 50%);
}
body { background: var(--bg-glow), var(--bg); background-attachment: fixed; }

/* One run of buttons down the right edge: every one the same box, its label
   centred by the flex box itself so no browser drifts off the baseline. */
.thread .side button,
.thread .reply button,
.thread .head .move,
.col-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  line-height: 1;
}
/* "В дело" used to stretch to the conversation's height; now it matches the rest. */
.thread .side .totask { flex: 0 0 auto; height: var(--action-h); min-height: 0; }
/* And the send button matches them too, instead of taking the field's height. */
.thread .reply button { height: var(--action-h); }
.thread .reply input { height: var(--action-h); text-align: left; }

/* Each tinted button carries a thin line of its own colour, as "В дело" does. */
.thread .side .drop {
  background: var(--danger-soft);
  color: var(--danger-ink);
  border-color: color-mix(in srgb, var(--danger) 42%, transparent);
}
.thread .side .totask {
  background: var(--led-soft);
  color: var(--led-ink);
  border-color: color-mix(in srgb, var(--led) 42%, transparent);
}
.thread .reply button {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: color-mix(in srgb, var(--accent) 42%, transparent);
}

/* A card raised by hand has no channel, so its badge stays quiet. */
.thread .chan.own { background: transparent; color: var(--muted); border-color: var(--border); }

/* The column heading no longer sits on a rule. */
.column > header { border-bottom: none; }
