/* "Currents" — kanban boards. The launcher reuses the whiteboard launcher
   classes (.wb-launcher / .wb-grid / .wb-card / .wb-bar). These rules cover the
   board itself: a horizontally scrolling row of columns full of cards. */

.kb-board { flex: 1; min-height: 0; display: flex; flex-direction: column; background: var(--main-bg); }
.kb-board-title { flex: 1; min-width: 0; background: transparent; border: none; color: var(--text); font-size: 16px; font-weight: 700; outline: none; padding: 5px 8px; border-radius: 7px; }
.kb-board-title:focus { background: var(--bg-2); }

/* Thumbnail tint on the launcher cards. */
.wb-thumb.kb-thumb { background: linear-gradient(135deg, #2f80ed, #14b8a6); color: #fff; }

/* Board rhythm: 12px between lists and around them (the end inset scrolls into view with the
   last column), 12px inside each list on both axes, 8px between cards. */
.kb-canvas { flex: 1; min-height: 0; overflow-x: auto; overflow-y: hidden; padding: 0; }
.kb-cols { display: flex; gap: var(--sp-3); align-items: flex-start; height: 100%; box-sizing: border-box; padding: var(--sp-3); width: max-content; min-width: 100%; }
.kb-view-list .kb-cols { width: auto; min-width: 0; }

.kb-col {
  width: 286px; flex: 0 0 286px; max-height: 100%; box-sizing: border-box;
  display: flex; flex-direction: column;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius-lg); padding: var(--sp-3);
}
.kb-col.drop { outline: 2px dashed var(--accent); outline-offset: -2px; }

.kb-col-head { display: flex; align-items: center; gap: var(--sp-1); padding: 0 0 var(--sp-2); cursor: grab; }
.kb-list-title { flex: 1; min-width: 0; background: transparent; border: none; color: var(--text); font-weight: 700; font-size: 14px; outline: none; padding: 4px 6px; margin-left: -6px; border-radius: 6px; }
.kb-list-title:focus { background: var(--bg-0); }
.kb-count { color: var(--faint); font-size: 12px; min-width: 20px; text-align: center; }
.kb-col-more { flex: none; width: var(--control-sm); height: var(--control-sm); display: inline-flex; align-items: center; justify-content: center; color: var(--dim); border-radius: var(--radius-md); font-size: 13px; }
.kb-col-more:hover { color: var(--text); background: var(--hover); }

/* The 2px inset keeps card focus rings and shadows inside the scroll box without moving the cards. */
.kb-cards { flex: 1; min-height: 8px; overflow-y: auto; display: flex; flex-direction: column; gap: var(--sp-2); padding: 2px; margin: -2px; }
.kb-empty-drop { border: 1px dashed var(--line); border-radius: var(--radius-md); color: var(--faint); font-size: var(--fs-sm); padding: var(--sp-4) var(--sp-3); text-align: center; }

.kb-card {
  background: var(--bg-1); border: 1px solid var(--line); border-radius: 8px; padding: 9px 11px;
  cursor: pointer; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.kb-card:hover { border-color: var(--accent); }

/* Live drag: someone else is holding this card right now. Tinted dashed
   outline in their presence color + a name chip, pulsing until they drop. */
.kb-card { position: relative; }
.kb-card.kb-held { outline: 2px dashed var(--held, var(--accent)); outline-offset: 2px; opacity: 0.8; animation: kb-held-pulse 1.1s ease-in-out infinite; }
@keyframes kb-held-pulse { 50% { opacity: 0.55; } }
.kb-held-chip {
  position: absolute; top: -9px; right: 8px; z-index: 2;
  font-size: 10px; font-weight: 700; color: #fff; border-radius: 999px; padding: 2px 8px;
  display: inline-flex; gap: 4px; align-items: center; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}
.kb-card-title { color: var(--text); font-size: 14px; white-space: pre-wrap; word-break: break-word; }
.kb-card-desc-flag { display: inline-block; color: var(--faint); font-size: 11px; }

/* A list that scrolls further than it shows fades at its bottom edge (.has-more, set while there is more
   below), so the last visible card never ends on a hard cut. */
.kb-cards.has-more { -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 24px), transparent); mask-image: linear-gradient(to bottom, #000 calc(100% - 24px), transparent); }
.kb-add-btn { margin-top: var(--sp-3); width: 100%; text-align: left; color: var(--dim); padding: 8px 10px; border-radius: 8px; font-size: 13px; }
.kb-add-btn:hover { background: var(--hover); color: var(--text); }

.kb-add-card { margin-top: var(--sp-3); display: flex; flex-direction: column; gap: var(--sp-2); }
.kb-add-card textarea {
  width: 100%; resize: none; box-sizing: border-box; font-family: inherit; font-size: 14px;
  background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--radius-md); padding: 8px 10px; color: var(--text); outline: none;
}
.kb-add-card textarea:focus { outline: none; border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.kb-add-row { display: flex; gap: var(--sp-2); }

.kb-col-new { background: transparent; border: 1px dashed var(--line); gap: var(--sp-2); }
.kb-newlist { background: transparent; border: none; color: var(--text); font-size: 14px; outline: none; padding: 6px; width: 100%; box-sizing: border-box; }
.kb-newlist::placeholder { color: var(--faint); }

/* Primary actions on the board and in the card window: a solid accent with its readable ink. */
.kb-board .btn-primary, .kb-board .btn-primary:hover { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.kb-board .btn-primary:hover { background: color-mix(in srgb, var(--accent) 88%, var(--text)); }

/* Toolbar: the card count only shows while a filter narrows the board. */
.kb-filter-status { color: var(--dim); font-size: var(--fs-sm); }
.kb-toolbar-end { margin-left: auto; }
.kb-filter-toggle { gap: var(--sp-2); }
.kb-filter-count { min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box; border-radius: var(--radius-full); background: var(--accent); color: var(--on-accent); font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; }
/* No-match bar: one centred 36px row with 12px padding on both axes; it holds the only "Clear filters". */
.kb-filter-empty { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--sp-3); margin: var(--sp-3) var(--sp-3) 0; padding: var(--sp-3); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-1); color: var(--dim); font-size: var(--fs-md); }
.kb-filter-empty .kp-library-control { height: var(--control-md); min-height: var(--control-md); box-sizing: border-box; }
.kb-filter-sheet { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); padding: 0 var(--sp-3) var(--sp-3); background: var(--bg-1); border-bottom: 1px solid var(--line); }
.kb-filter-sheet .kp-library-search { flex-basis: 100%; }

@media (max-width: 760px) {
  .kb-col { width: 84vw; flex-basis: 84vw; }
  .kb-view-auto .kb-cols { width: auto; min-width: 0; }
  .kp-current-board-filters .kp-library-search { flex-basis: 100%; }
  /* One filter row, one 44px touch height: Filter, "Assigned to me" and the assignee select. */
  .kp-current-board-filters { flex-wrap: nowrap; padding: var(--sp-2) var(--sp-3); }
  .kp-current-board-filters .kp-current-filters { flex: 1; min-width: 0; flex-wrap: nowrap; }
  .kp-current-board-filters .kp-current-filters .kp-select { flex: 1; min-width: 0; }
  .kb-filter-toggle, .kp-current-board-filters :is(.kp-library-control, .kp-select-trigger), .kb-filter-sheet :is(.kp-library-control, .kp-library-search) { height: var(--control-touch); min-height: var(--control-touch); box-sizing: border-box; }
  .kb-filter-toggle { position: relative; flex: none; width: var(--control-touch); padding: 0; justify-content: center; }
  .kb-filter-toggle .kb-filter-count { position: absolute; top: -6px; right: -6px; }
  .kp-current-board-filters .kp-current-filters .kp-library-control { flex: none; white-space: nowrap; }
  /* One 56px board bar: ←, the title, ⋯ (the layout switch and department live in ⋯). */
  .app-shell .kb-board > .wb-bar { flex-wrap: nowrap; min-height: 56px; padding-block: 6px; }
  .app-shell .kb-board > .wb-bar .kb-board-title { flex: 1; min-width: 0; }
  /* While a Current is open on a phone, its board takes the calendar strip's row (the strip comes
     back in the library and in the other tools), so the first card starts high on the screen. */
  .main:has(> .tab-pane:not(.tab-hidden) .kp-document-panel:not([hidden]) .kb-board) > .studio-calendar-strip { display: none; }
}

/* ---- Card metadata (labels / due / assignees) ---- */
/* Labels never mix: when any label on a card has a name, all are 18px pills (named ones show the name,
   unnamed ones only a dot); when none has a name, all are stripes. */
.kb-labels { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-bottom: 6px; }
.kb-label { width: 32px; height: 6px; border-radius: 3px; display: inline-block; background: var(--label); }
.kb-label:is(.is-named, .is-dot) { width: auto; height: 18px; padding: 0 7px; box-sizing: border-box; display: inline-flex; align-items: center; border-radius: var(--radius-full); background: color-mix(in srgb, var(--label) 22%, var(--bg-1)); border: 1px solid color-mix(in srgb, var(--label) 60%, transparent); color: var(--text); font-size: 11px; font-weight: var(--fw-semibold); line-height: 1; white-space: nowrap; }
.kb-label.is-dot { width: 18px; padding: 0; justify-content: center; }
.kb-label.is-dot::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--label); }
/* No date or badges: the avatars end the title row. */
.kb-card-title-row { display: flex; align-items: flex-start; gap: var(--sp-2); }
.kb-card-title-row > .kb-card-title { flex: 1; min-width: 0; }
.kb-card-meta { display: flex; align-items: center; gap: 8px; margin-top: 7px; }
.kb-due { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: var(--dim); background: var(--bg-0); border: 1px solid var(--line); padding: 2px 7px; border-radius: 6px; }
.kb-due.overdue { color: #fff; background: var(--red, #ed4245); border-color: transparent; }
.kb-avatars { margin-left: auto; display: inline-flex; align-items: center; }
.kb-avatars > * { margin-left: -5px; }
.kb-avatars > *:first-child { margin-left: 0; }
.kb-ava-more { font-size: 10px; color: var(--dim); background: var(--bg-3); border: 1px solid var(--line); border-radius: 50%; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; }

/* ---- Board categories (launcher sections + create modal) ---- */
.kb-cats-scroll { flex: 1; min-height: 0; overflow-y: auto; padding-bottom: 16px; }
.kb-cat-head {
  display: flex; align-items: center; gap: 9px; padding: 18px 18px 0;
  font-size: 12px; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; color: var(--dim);
}
.kb-cat-head i { color: var(--cat); font-size: 14px; }
.kb-cat-count { color: var(--faint); font-weight: 600; }
.wb-grid.kb-sec { flex: none; overflow: visible; padding-top: 10px; }
.kb-cat-options { display: flex; flex-wrap: wrap; gap: 8px; }
.kb-cat-opt {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 14px; border-radius: 9px; font-size: 13px; font-weight: 600; cursor: pointer;
  background: var(--bg-3); border: 2px solid var(--line); color: var(--text);
}
.kb-cat-opt i { color: var(--cat); }
.kb-cat-opt:hover { border-color: var(--cat); }
.kb-cat-opt.on { border-color: var(--cat); background: color-mix(in srgb, var(--cat) 18%, transparent); }
.kb-cat-chip {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  color: #fff; font-size: 12px; font-weight: 700; padding: 4px 11px; border-radius: 999px;
}

/* ---- Media: card covers, board bg ---- */
.kb-card-cover { width: calc(100% + 22px); margin: -9px -11px 8px; max-height: 140px; object-fit: cover; display: block; border-radius: 8px 8px 0 0; background: #000; }
.kb-viewers { display: inline-flex; align-items: center; gap: 2px; margin-left: 6px; }
.kb-viewers > * { margin-left: -5px; }
.kb-viewers > *:first-child { margin-left: 0; }
.kb-viewers-label { color: var(--faint); font-size: 11px; margin-left: 7px; }
.kb-dim-pop {
  position: absolute; top: 52px; right: 16px; z-index: 80;
  display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0,0,0,.45);
}
.kb-dim-label { color: var(--dim); font-size: 12px; display: inline-flex; gap: 6px; align-items: center; white-space: nowrap; }
.kb-board { position: relative; }

/* Department filter chips (shared by Currents / Whiteboards / Charts) */
.dept-filter { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* Auto-collapsing filter: the strip never wraps and never scrolls — when the
   chips can't fit the available width, the component swaps itself for a
   single dropdown button (the invisible strip stays mounted for measuring). */
.df-wrap { flex: 1 1 auto; min-width: 0; position: relative; display: flex; align-items: center; }
.df-strip { flex: 1; min-width: 0; flex-wrap: nowrap; overflow: hidden; }
.df-strip .df-chip { flex: none; white-space: nowrap; }
.df-strip.ghost { visibility: hidden; position: absolute; inset: 0; pointer-events: none; }
.df-compact { display: inline-flex; flex: none; }
.df-caret { font-size: 10px; margin-left: 2px; color: var(--faint); }
/* The title/crumbs yield leftover header space to the filter. */
.wb-head:has(.df-wrap) .wb-crumbs { flex: 0 0 auto; }
.ch-side-filter .df-wrap { width: 100%; }
.df-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--dim); font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.df-chip:hover { color: var(--text); border-color: var(--cat, var(--accent)); }
.df-chip.on { color: var(--text); border-color: var(--cat, var(--accent)); background: color-mix(in srgb, var(--cat, var(--accent)) 18%, transparent); }
.df-chip i { color: var(--cat, var(--dim)); font-size: 11px; }

/* Manage-departments modal (shared by Currents / Whiteboards / Charts) */
.dept-list { display: flex; flex-direction: column; gap: 2px; max-height: 56vh; overflow-y: auto; }
.dept-row { display: flex; align-items: center; gap: 10px; padding: 5px 8px; border-radius: 8px; }
.dept-row:hover { background: var(--hover); }
.dept-dot { width: 28px; height: 28px; border-radius: 8px; color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; flex: none; }
.dept-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-size: 14px; }
.dept-acts { display: flex; gap: 2px; opacity: 0; }
.dept-row:hover .dept-acts { opacity: 1; }
.dept-acts button { width: 26px; height: 26px; border-radius: 6px; color: var(--dim); }
.dept-acts button:hover { background: var(--hover); color: var(--text); }
.dept-acts button.danger:hover { color: #ed4245; }
.dept-style { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px 12px; }
.dept-icons { display: flex; gap: 4px; flex-wrap: wrap; }
.dept-ic { width: 26px; height: 26px; border-radius: 6px; color: var(--dim); }
.dept-ic:hover { background: var(--hover); color: var(--text); }
.dept-ic.sel { outline: 2px solid var(--accent); color: var(--text); }

/* ---- Card window ----
   One surface: a header (list name, save note, ⋯, ×), then details on the left and
   comments on the right, each column scrolling on its own. Field groups: heading → control
   8px, group → group 24px. Fields are chat's surface (--bg-1, 1px --line, 8px radius); focus
   turns the border into a 2px accent line with no outer ring. */
/* Red words (Delete card, Overdue, save errors) stay ≥4.5:1: on dark surfaces the red is lifted toward the text colour. */
.kb-card-modal { --kbm-danger-text: color-mix(in srgb, var(--danger) 60%, var(--text)); }
[data-scheme='light'] .kb-card-modal { --kbm-danger-text: color-mix(in srgb, var(--danger) 75%, var(--text)); }
/* A field whose save failed wears the danger border (what Retry will send). */
.kb-card-modal :is(.kbm-title, .kbm-field, .kbm-select).has-error, .kb-card-modal .kb-due-row.has-error .kp-date-trigger { border-color: var(--danger); box-shadow: inset 0 0 0 1px var(--danger); }
.kb-card-modal :is(.kb-label-row, .kbm-label-edit, .kb-assignees).has-error { outline: 2px solid var(--danger); outline-offset: 4px; border-radius: var(--radius-md); }
.kb-card-modal { --kbm-pad: var(--sp-5); max-width: 920px !important; width: 100%; height: min(860px, calc(100dvh - 48px)); max-height: none; padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.kbm-cover { flex: none; height: 140px; background-size: cover; background-position: center; background-color: #000; position: relative; }
.kbm-cover-btn { font-size: 12px; background: var(--media-chip); color: var(--on-media); padding: 6px 12px; border-radius: 8px; cursor: pointer; }
.kbm-cover-btn:hover { background: var(--media-chip-hover); }
.kbm-cover-actions { position: absolute; right: var(--sp-3); bottom: var(--sp-3); display: flex; gap: var(--sp-2); }

/* Header: one 56px row: the list name at body size, the save note, then ⋯ and × as 36px boxed icon buttons. */
.kbm-head { flex: none; height: 56px; box-sizing: border-box; background: var(--surface-head); display: flex; align-items: center; gap: var(--sp-2); padding: 0 var(--sp-3) 0 var(--kbm-pad); border-bottom: 1px solid var(--line); }
.kbm-crumb { flex: 1; display: inline-flex; align-items: center; gap: var(--sp-2); color: var(--text); font-size: var(--fs-md); font-weight: var(--fw-semibold); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.kbm-crumb > i { color: var(--dim); }
.kbm-head .kbm-save { flex: none; font-size: var(--fs-sm); color: var(--dim); margin-right: var(--sp-1); }
.kbm-head .kbm-save.is-error { color: var(--kbm-danger-text); }
.kbm-icon-btn { flex: none; width: var(--control-md); height: var(--control-md); box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius-md); color: var(--text); font-size: 15px; }
.kbm-head .kbm-icon-btn { background: var(--bg-2); border: 1px solid var(--line); }
.kbm-icon-btn.sm { width: var(--control-sm); height: var(--control-sm); font-size: 13px; color: var(--dim); }
.kbm-icon-btn:hover { background: var(--hover); color: var(--text); }
.kbm-done-bar { display: none; }

.kbm-body { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) 320px; }
.kbm-main { min-width: 0; min-height: 0; overflow-y: auto; margin: 0; border: 0; padding: var(--kbm-pad); display: flex; flex-direction: column; gap: var(--sp-5); }
.kbm-main > * { flex-shrink: 0; }
.kbm-side { min-width: 0; min-height: 0; overflow-y: auto; border-left: 1px solid var(--line); padding: var(--kbm-pad); }

/* Title: wraps and grows up to three lines, then scrolls; never clipped to one line. */
.kb-card-modal .kbm-title { display: block; width: 100%; box-sizing: border-box; resize: none; overflow-y: auto; font: inherit; font-size: var(--fs-xl); font-weight: var(--fw-bold); line-height: 1.3; color: var(--text); background: transparent; border: 1px solid transparent; border-radius: var(--radius-md); padding: 4px 8px; margin: -5px -9px; width: calc(100% + 18px); max-height: calc(3 * 1.3em + 10px); outline: none; }
.kb-card-modal .kbm-title:hover:not(:disabled) { border-color: var(--line); }
.kb-card-modal .kbm-title:focus { background: var(--bg-1); border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }

.kbm-group-head { display: flex; align-items: center; gap: var(--sp-2); min-height: 20px; margin-bottom: var(--sp-2); }
.kbm-group-head h4 { margin: 0; font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--dim); text-transform: none; letter-spacing: 0; }
/* Comments | Activity, the card window's right column. */
.kbm-tabs { display: flex; gap: var(--sp-1); margin: calc(-1 * var(--sp-1)) 0 var(--sp-4); border-bottom: 1px solid var(--line); }
.kbm-tabs [role=tab] { padding: var(--sp-2) 10px; margin-bottom: -1px; border-bottom: 2px solid transparent; color: var(--dim); font-size: 13px; font-weight: var(--fw-semibold); }
.kbm-tabs [role=tab][aria-selected=true] { color: var(--text); border-bottom-color: var(--accent); }
.kbm-tabs [role=tab]:hover { color: var(--text); }
.kbm-save { font-size: var(--fs-xs); color: var(--faint); white-space: nowrap; }
.kbm-save.is-error { color: var(--kbm-danger-text); }
.kbm-save button { color: inherit; font: inherit; font-weight: var(--fw-semibold); text-decoration: underline; padding: 0; }
.kbm-text-btn { margin-left: auto; height: 24px; padding: 0 var(--sp-2); border-radius: var(--radius-sm); color: var(--dim); font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
.kbm-text-btn:hover:not(:disabled) { background: var(--hover); color: var(--text); }
.kbm-text-btn[aria-expanded='true'] { color: var(--text); }
.kbm-empty { color: var(--faint); font-size: 13px; }

/* Field surfaces, chat's look. */
.kb-card-modal :is(.kbm-field, .kp-date-trigger, .kbm-select) { box-sizing: border-box; background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--radius-md); color: var(--text); font: inherit; font-size: var(--fs-md); outline: none; box-shadow: none; }
.kb-card-modal :is(.kbm-field, .kp-date-trigger, .kbm-select):hover:not(:disabled) { background: var(--bg-1); border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }
.kb-card-modal :is(.kbm-field, .kp-date-trigger, .kbm-select):is(:focus, :focus-visible, [aria-expanded='true']) { outline: none; border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.kb-card-modal :is(.kbm-field, .kp-date-trigger, .kbm-select):disabled { opacity: 1; cursor: default; }
.kb-people-pop .kbm-field { box-sizing: border-box; width: 100%; height: var(--control-md); padding: 0 12px; background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--radius-md); color: var(--text); font: inherit; outline: none; }
.kb-people-pop .kbm-field:is(:focus, :focus-visible) { outline: none; border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }

/* Labels: named pills; on = filled with the label colour, a check, aria-pressed. */
.kb-label-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.kb-label-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; background: var(--label); }
.kb-label-pill { display: inline-flex; align-items: center; gap: var(--sp-2); height: 32px; box-sizing: border-box; padding: 0 12px 0 10px; border-radius: var(--radius-full); background: var(--bg-1); border: 1px solid var(--line); color: var(--text); font-size: var(--fs-sm); font-weight: var(--fw-semibold); cursor: pointer; }
.kb-label-pill.unnamed { color: var(--dim); }
.kb-label-pill:hover:not(:disabled) { border-color: var(--label); }
.kb-label-pill.on { background: color-mix(in srgb, var(--label) 26%, var(--bg-1)); border-color: var(--label); color: var(--text); }
.kb-label-pill > i { font-size: 11px; }
.kb-label-pill:disabled { cursor: default; }
.kbm-label-edit { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-2); }
.kbm-label-name { display: flex; align-items: center; gap: var(--sp-2); }
.kbm-label-name .kbm-field { flex: 1; min-width: 0; height: var(--control-md); padding: 0 12px; }

/* Due date + list: one top edge, both 36px, 8px apart. */
.kbm-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-2); }
.kbm-field-group { min-width: 0; }
/* The date field always shows the whole date; "in 5 days" sits beside it, or under it (4px) when it can't fit. */
.kb-due-row { display: flex; flex-wrap: wrap; column-gap: var(--sp-2); row-gap: 4px; align-items: center; min-width: 0; }
.kb-card-modal .kb-due-row .kp-date { flex: 1 0 auto; min-width: max-content; margin-top: 0; }
.kb-card-modal .kp-date .kp-date-trigger { min-height: var(--control-md); height: var(--control-md); padding: 0 12px; }
.kbm-due-words { flex: none; font-size: var(--fs-sm); color: var(--dim); white-space: nowrap; }
.kbm-due-words.overdue { color: var(--kbm-danger-text); font-weight: var(--fw-semibold); }
.kbm-select { display: flex; align-items: center; gap: var(--sp-2); width: 100%; height: var(--control-md); padding: 0 12px; cursor: pointer; text-align: left; }
.kbm-select .n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kbm-select i { font-size: 10px; color: var(--dim); }

/* Description: grows with its text (the column scrolls, not the field). */
.kb-card-modal .kb-desc { display: block; width: 100%; min-height: 88px; resize: none; overflow: hidden; padding: 10px 12px; line-height: var(--lh-body); }

/* Assignees: chips plus "Add person". */
.kb-assignees { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.kb-assignee-chip { display: inline-flex; align-items: center; gap: var(--sp-2); height: 32px; padding: 0 4px 0 6px; box-sizing: border-box; border-radius: var(--radius-full); background: var(--bg-1); border: 1px solid var(--line); font-size: var(--fs-md); max-width: 100%; }
.kb-assignee-chip:not(:has(button)) { padding-right: 12px; }
.kb-assignee-chip .ka-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-assignee-chip button { flex: none; width: 24px; height: 24px; border-radius: 50%; color: var(--dim); font-size: 12px; display: inline-flex; align-items: center; justify-content: center; }
.kb-assignee-chip button:hover { background: var(--hover); color: var(--text); }
.kb-assignee-add { display: inline-flex; align-items: center; gap: var(--sp-2); height: 32px; box-sizing: border-box; padding: 0 12px; border-radius: var(--radius-full); border: 1px dashed var(--line); color: var(--dim); font-size: var(--fs-md); }
.kb-assignee-add:hover, .kb-assignee-add[aria-expanded='true'] { border-color: var(--accent); color: var(--text); }
.kb-people-pop { position: fixed; z-index: var(--z-popover); box-sizing: border-box; padding: var(--sp-2); background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-2); color: var(--text); }
.kb-people-pop [role='listbox'] { margin-top: var(--sp-2); max-height: var(--list-max, 288px); overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.kb-person { display: flex; align-items: center; gap: var(--sp-2); height: var(--control-md); padding: 0 var(--sp-2); border-radius: var(--radius-md); cursor: pointer; font-size: var(--fs-md); }
.kb-person.is-active { background: var(--hover); }
.kb-person.is-empty { color: var(--dim); cursor: default; }

/* Attachments: plain rows with dividers; the row downloads, ⋯ holds the rest. */
.kbm-atts { list-style: none; margin: 0; padding: 0; }
.kbm-att { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-2) 0; }
.kbm-att + .kbm-att { border-top: 1px solid var(--line); }
.kbm-att-open { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--sp-3); color: var(--text); text-decoration: none; border-radius: var(--radius-md); }
.kbm-att-open:hover .kbm-att-name { text-decoration: underline; }
.kbm-att-thumb { width: 48px; height: 48px; flex: none; object-fit: cover; border-radius: var(--radius-md); background: var(--bg-0); border: 1px solid var(--line); box-sizing: border-box; }
.kbm-att-file { display: inline-flex; align-items: center; justify-content: center; color: var(--dim); font-size: 18px; }
.kbm-att-meta { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.kbm-att-name { font-size: var(--fs-md); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kbm-att-kind { font-size: var(--fs-xs); color: var(--dim); }

.kbm-submissions { display: flex; flex-direction: column; gap: var(--sp-2); }
.kbm-submissions > .kbm-group-head { margin-bottom: 0; }
.kbm-submission { background: var(--bg-1); border: 1px solid var(--line); border-radius: var(--radius-md); padding: var(--sp-2) var(--sp-3); font-size: 13px; display: grid; gap: 2px; overflow-wrap: anywhere; }
.kbm-submission small { color: var(--dim); font-size: 12px; }
.kbm-archive { align-self: flex-start; display: inline-flex; align-items: center; gap: var(--sp-2); padding: 0; color: var(--dim); font-size: var(--fs-md); font-weight: var(--fw-semibold); }
.kbm-archive:hover { color: var(--text); text-decoration: underline; }

/* Comments column. */
.kbm-comments { display: flex; flex-direction: column; gap: var(--sp-4); }
.kb-card-modal .kbm-comment-input { width: 100%; height: var(--control-md); padding: 0 12px; margin: 0; }
.kbm-comment-list { display: flex; flex-direction: column; gap: var(--sp-4); }
.kbm-comment { display: flex; gap: var(--sp-3); }
.kbm-comment-body { min-width: 0; flex: 1; }
.kbm-comment-head { position: relative; display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--sp-2); font-size: 12px; color: var(--dim); }
.kbm-comment-head > * { white-space: nowrap; }
.kbm-comment-head b { color: var(--text); font-size: 13px; }
.kbm-comment-head:has(.kbm-comment-del) { padding-right: var(--sp-5); }
.kbm-comment-del { position: absolute; top: 0; right: 0; color: var(--faint); cursor: pointer; }
.kbm-comment-del:hover { color: var(--danger); }
.kbm-comment-text { font-size: 13px; margin-top: 2px; white-space: pre-wrap; word-break: break-word; }
.kbm-activity { color: var(--faint); font-size: 12px; padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.kbm-activity b { color: var(--dim); }

/* Phone: a full-screen sheet that scrolls once (cover, details, comments); only the 56px header stays
   pinned, actions live in ⋯, and a full-width Done bar sits at the bottom for thumb reach. */
@media (max-width: 760px) {
  .overlay.kbm-overlay { padding: 0; }
  .kb-card-modal { --kbm-pad: var(--sp-4); width: 100vw; max-width: none !important; height: 100dvh; border-radius: 0; border: 0; overflow-y: auto; overscroll-behavior: contain; }
  .kbm-cover { height: 120px; }
  .kb-card-modal .kbm-title { max-height: none; overflow: hidden; }
  .kbm-head { position: sticky; top: 0; z-index: 3; padding-left: var(--kbm-pad); background: var(--surface-head); }
  .kbm-head .kbm-icon-btn { width: var(--control-touch); height: var(--control-touch); }
  .kbm-body { display: block; flex: none; }
  .kbm-done-bar { display: block; position: sticky; bottom: 0; z-index: 3; margin-top: auto; padding: var(--sp-2) var(--kbm-pad) calc(var(--sp-2) + env(safe-area-inset-bottom)); background: var(--surface-head); border-top: 1px solid var(--line); }
  .kbm-done-bar .btn-primary { width: 100%; height: var(--control-touch); padding: 0; background: var(--accent); color: var(--on-accent); }
  .kbm-main, .kbm-side { overflow: visible; }
  .kbm-side { border-left: 0; border-top: 1px solid var(--line); }
  .kbm-pair { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
  .kb-card-modal .kp-date .kp-date-trigger, .kbm-select, .kb-card-modal .kbm-comment-input, .kbm-label-name .kbm-field { height: var(--control-touch); min-height: var(--control-touch); }
  .kbm-label-edit { grid-template-columns: minmax(0, 1fr); }
  .kbm-archive { display: none; }
  .kb-label-pill, .kb-assignee-chip, .kb-assignee-add { height: var(--control-touch); }
}

/* ---- Archive and activity (KanbanArchive.tsx, BRIEF §2) ---- */
/* The read-only banner: an archived card (under the card window's header) or board (under its toolbar). */
.kb-arch-banner { flex: none; display: flex; align-items: center; gap: var(--sp-3); padding: 10px 20px 10px var(--kbm-pad, 24px); background: color-mix(in srgb, var(--warning) 14%, var(--bg-1)); border-bottom: 1px solid color-mix(in srgb, var(--warning) 40%, var(--line)); color: var(--text); font-size: var(--fs-md); }
.kb-arch-banner > i { color: var(--warning); }
.kb-arch-banner > span { flex: 1; min-width: 0; }
.kb-board-archived .kb-arch-banner { margin: var(--sp-4); border: 1px solid color-mix(in srgb, var(--warning) 40%, var(--line)); border-radius: var(--radius-md); }
h2.kb-board-title { margin: 0; }
/* A drawer on the right of the board (Archived items, Activity) or of the library (Archived boards). */
.kp-library-launcher:has(> .kb-drawer) { position: relative; }
/* Under the card window's overlay (z-index 50), which opens over it. */
.kb-drawer { position: absolute; z-index: 40; top: 0; right: 0; bottom: 0; width: 400px; max-width: 100%; display: flex; flex-direction: column; background: var(--bg-1); border-left: 1px solid var(--line); box-shadow: var(--shadow-3); color: var(--text); outline: none; }
.kb-drawer-head { flex: none; height: 56px; box-sizing: border-box; display: flex; align-items: center; gap: var(--sp-2); padding: 0 12px 0 20px; border-bottom: 1px solid var(--line); background: var(--surface-head); }
.kb-drawer-head h3 { flex: 1; margin: 0; font-size: var(--fs-lg); }
.kb-drawer-close { width: 36px; height: 36px; box-sizing: border-box; display: inline-grid; place-items: center; border-radius: var(--radius-md); border: 1px solid var(--line); background: var(--bg-2); color: var(--text); }
.kb-drawer-tools { flex: none; display: flex; flex-direction: column; gap: 12px; padding: 16px 20px; border-bottom: 1px solid var(--line); }
.kb-drawer-tools .kp-select { align-self: flex-start; }
.kb-drawer-search { width: 100%; max-width: none; }
.kb-drawer-body { flex: 1; min-height: 0; overflow: auto; padding: 4px 20px 20px; }
.kb-seg { display: flex; gap: 3px; padding: 3px; width: max-content; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); }
.kb-seg [role=tab] { padding: 6px 12px; border-radius: 5px; color: var(--dim); font-size: 13px; font-weight: var(--fw-semibold); }
.kb-seg [role=tab][aria-selected=true] { background: var(--active); color: var(--text); }
.kb-arch-list { list-style: none; margin: 0; padding: 0; }
.kb-arch-row { display: flex; flex-direction: column; gap: 3px; padding: 12px 0; border-bottom: 1px solid var(--line); }
.kb-arch-row:last-child { border-bottom: 0; }
.kb-arch-title { align-self: flex-start; padding: 0; font-size: var(--fs-md); font-weight: var(--fw-semibold); color: var(--text); text-align: left; overflow-wrap: anywhere; }
.kb-arch-title.is-link:hover { text-decoration: underline; }
.kb-arch-sub { font-size: var(--fs-sm); color: var(--dim); }
.kb-arch-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-2); }
.kb-arch-btn { height: 28px; padding: 0 10px; display: inline-flex; align-items: center; gap: 6px; border-radius: var(--radius-md); border: 1px solid var(--line); background: var(--bg-2); color: var(--text); font-size: 13px; font-weight: var(--fw-semibold); }
/* Restore first, where the hand lands; deleting for good is at the far end of the row. */
.kb-arch-btn.is-danger { margin-left: auto; background: transparent; color: var(--kbm-danger-text, var(--danger)); }
/* Activity rows: an icon, who, what, and when (dim, on its own line). */
.kb-ev-list { display: flex; flex-direction: column; }
.kb-ev-day { margin: 16px 0 4px; font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--dim); }
.kb-ev-day:first-child { margin-top: 8px; }
.kb-ev { display: flex; gap: 10px; align-items: flex-start; padding: 8px 0; font-size: 13px; line-height: 1.45; }
.kb-ev-icon { flex: none; width: 24px; height: 24px; box-sizing: border-box; display: grid; place-items: center; border-radius: 50%; border: 1px solid var(--line); background: var(--bg-2); color: var(--dim); font-size: 11px; }
.kb-ev-text { min-width: 0; overflow-wrap: anywhere; }
.kb-ev-text b { font-weight: var(--fw-semibold); }
.kb-ev-when { display: block; margin-top: 2px; color: var(--dim); font-size: 12px; }
.kb-ev-card { padding: 0; color: var(--text); font: inherit; text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 3px; }
.kb-ev-card:hover { text-decoration-color: currentColor; }
.kb-ev-card.is-gone { text-decoration: none; color: var(--dim); }
/* "Show older": a full-width text row at the list's left edge. */
.kb-ev-older { display: block; width: 100%; margin-top: 4px; padding: 10px 0; border-top: 1px solid var(--line); text-align: left; color: var(--accent); font-size: 13px; font-weight: var(--fw-semibold); }
.kb-ev-older:hover { text-decoration: underline; }
.kb-ev-empty { margin: 16px 0; color: var(--dim); font-size: var(--fs-md); }
.kb-ev-retry { padding: 0; color: var(--accent); font-weight: var(--fw-semibold); }
/* "Card archived." with Undo, for 10 seconds: centred over the board's scroll area, 16px above its bottom. */
.kb-undo-toast { position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%); z-index: 45; display: flex; align-items: center; gap: 12px; max-width: calc(100% - 32px); box-sizing: border-box; padding: 8px 8px 8px 16px; border-radius: 10px; border: 1px solid var(--line); background: var(--bg-3); color: var(--text); font-size: 13px; white-space: nowrap; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4); }
.kb-undo-toast span { overflow: hidden; text-overflow: ellipsis; }
.kb-undo-toast button { flex: none; height: 28px; padding: 0 12px; border-radius: var(--radius-md); background: var(--accent); color: var(--on-accent); font-weight: var(--fw-semibold); }
/* An archived board, for everyone but owners and admins: what it was, and the way back. */
.kb-archived-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-2); padding: var(--sp-6, 32px) var(--sp-4); text-align: center; }
.kb-archived-tile { width: 56px; height: 56px; margin-bottom: var(--sp-2); display: grid; place-items: center; border-radius: var(--radius-lg); background: var(--bg-2); border: 1px solid var(--line); color: var(--dim); font-size: 22px; }
.kb-archived-empty h3 { margin: 0; font-size: var(--fs-xl); overflow-wrap: anywhere; }
.kb-archived-empty p { margin: 0 0 var(--sp-3); color: var(--dim); font-size: var(--fs-md); }
/* An archived card reads as a record: values as plain text, no field chrome, no hovers. */
.kb-card-modal.is-archived .kbm-main { cursor: default; }
.kb-card-modal .kbm-title.is-static { margin: 0; padding: 0; border: 0; background: none; box-shadow: none; height: auto; font-size: var(--fs-xl); font-weight: var(--fw-bold); line-height: 1.3; overflow-wrap: anywhere; }
.kbm-static { display: block; min-height: 20px; color: var(--text); font-size: var(--fs-md); line-height: 1.5; overflow-wrap: anywhere; }
.kbm-static.is-none { color: var(--dim); }
.kbm-desc-text { white-space: pre-wrap; }
.kb-label-pill.is-static { cursor: default; }
.kb-label-pill.is-static:hover { border-color: var(--label); }
@media (max-width: 760px) {
  .kb-drawer { width: 100%; }
  .kb-drawer-close, .kb-arch-btn { min-height: var(--control-touch); }
  .kb-arch-banner { padding-left: var(--sp-4); }
  .kb-undo-toast { bottom: calc(16px + env(safe-area-inset-bottom)); }
}

/* ---- My work (KanbanMyWork.tsx, BRIEF §3) ---- */
/* Overdue text reads on every theme, as in the card window. */
.kb-mw, .kb-home-toggle { --kb-mw-danger: color-mix(in srgb, var(--danger) 60%, var(--text)); }
[data-scheme='light'] .kb-mw { --kb-mw-danger: color-mix(in srgb, var(--danger) 75%, var(--text)); }
.kb-home-toggle { display: flex; gap: 3px; padding: 3px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-2); }
.kb-home-toggle [role=tab] { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px; border-radius: 5px; color: var(--dim); font-size: 13px; font-weight: var(--fw-semibold); }
.kb-home-toggle [role=tab][aria-selected=true] { background: var(--active); color: var(--text); }
.kb-home-count { min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box; border-radius: 9px; background: var(--accent); color: var(--on-accent); font-size: 11px; display: inline-grid; place-items: center; }
.kb-home-count.is-overdue { background: var(--danger); color: #fff; }
.kb-mw-spacer { flex: 1; }
.kb-mw-chip { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-radius: var(--radius-full); border: 1px solid var(--line); background: var(--bg-1); color: var(--text); font-size: 13px; font-weight: var(--fw-semibold); }
.kb-mw-chip[aria-pressed=true] { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--bg-1)); }
/* The list runs edge to edge of the header's content: group labels line up with the "Currents" title. */
.kb-mw { display: flex; flex-direction: column; gap: 20px; }
.kb-mw-group h3 { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--dim); }
.kb-mw-n { color: var(--faint); font-weight: var(--fw-regular); }
.kb-mw-group.is-overdue h3 { color: var(--kb-mw-danger); }
.kb-mw-list { list-style: none; margin: 0; padding: 0; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-1); overflow: hidden; }
.kb-mw-row { display: flex; align-items: center; border-bottom: 1px solid var(--line); }
.kb-mw-row:last-child { border-bottom: 0; }
.kb-mw-open { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 8px 8px 8px 16px; box-sizing: border-box; text-align: left; color: var(--text); }
.kb-mw-row:hover { background: var(--hover); }
.kb-mw-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.kb-mw-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.kb-mw-top .kb-labels { flex: none; flex-wrap: nowrap; margin: 0; }
.kb-mw-title { min-width: 0; font-size: var(--fs-md); font-weight: var(--fw-semibold); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kb-mw-sub { font-size: var(--fs-sm); color: var(--dim); overflow-wrap: anywhere; }
.kb-mw-due { flex: none; width: 140px; text-align: right; font-size: var(--fs-sm); color: var(--dim); white-space: nowrap; }
.kb-mw-due.is-overdue { color: var(--kb-mw-danger); font-weight: var(--fw-semibold); }
/* "Due today" as the card link chips show it: an amber edge. */
.kb-mw-today { display: inline-flex; align-items: center; height: 22px; padding: 0 7px; box-sizing: border-box; border: 1px solid color-mix(in srgb, var(--warning) 55%, var(--line)); border-radius: 6px; background: var(--bg-0); color: var(--text); }
.kb-mw-people { flex: none; width: 64px; justify-content: flex-end; margin-left: 0; }
.kb-mw-more { flex: none; width: 32px; height: 32px; margin-right: 8px; display: grid; place-items: center; border-radius: var(--radius-md); color: var(--dim); }
.kb-mw-more:hover { background: var(--bg-2); color: var(--text); }
.kb-mw-more.is-empty { visibility: hidden; }
.kb-mw-state { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 56px 16px; text-align: center; color: var(--dim); font-size: var(--fs-md); }
.kb-mw-state > .kb-archived-tile { margin-bottom: 4px; }
.kb-mw-state h2 { margin: 0; font-size: var(--fs-lg); color: var(--text); }
.kb-mw-state p { margin: 0 0 4px; }
/* "Due date…": a small window whose calendar opens at once. */
.kb-mw-dialog { width: min(360px, calc(100vw - 32px)); display: flex; flex-direction: column; gap: 12px; padding: 20px; box-sizing: border-box; overflow: visible; }
.kb-mw-dialog h3 { margin: 0; font-size: var(--fs-lg); }
.kb-mw-dialog-card { margin: 0; color: var(--dim); font-size: var(--fs-md); overflow-wrap: anywhere; }
.kb-mw-dialog .kp-date { margin-top: 0; }
.kb-mw-dialog-actions { display: flex; justify-content: flex-end; gap: 8px; }
@media (max-width: 760px) {
  /* ⋯ sits over the row's top-right corner, so the avatars' right edge lines up with its right edge. */
  .kb-mw-row { position: relative; }
  .kb-mw-open { flex-wrap: wrap; gap: 6px 12px; padding: 12px 4px 10px 12px; }
  .kb-mw-main { flex: 1 1 100%; box-sizing: border-box; padding-right: calc(var(--control-touch) + 4px); }
  /* Labels always on their own line, as on board cards. */
  .kb-mw-top { flex-wrap: wrap; }
  .kb-mw-top .kb-labels { flex-basis: 100%; }
  .kb-mw-title { white-space: normal; }
  .kb-mw-due { width: auto; flex: 1; text-align: left; }
  .kb-mw-people { width: auto; }
  .kb-mw-more { position: absolute; top: 6px; right: 4px; width: var(--control-touch); height: var(--control-touch); margin: 0; }
}
@media (max-width: 640px) {
  /* My work on a phone takes the board's rule: one 56px bar (Browse, the title, ⋯; New board, New folder and
     Archived boards live in ⋯), no subtitle, the toggle and "Show done" on one 44px row, no calendar strip. */
  .kp-library.is-replaced .kp-library-header { flex-wrap: nowrap; height: 56px; box-sizing: border-box; padding: 0 16px; gap: 12px; }
  .kp-library.is-replaced .kp-library-heading { flex: 1; flex-basis: auto; }
  .kp-library.is-replaced .kp-library-heading :is(p, .kp-library-breadcrumbs), .kp-library.is-replaced .kp-library-create > :not(.kp-library-more) { display: none; }
  .kp-library.is-replaced h1 { font-size: 20px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .kp-library.is-replaced .kp-library-browse { width: var(--control-touch); height: var(--control-touch); padding: 0; gap: 0; font-size: 0 !important; }
  .kp-library.is-replaced .kp-library-browse > i { font-size: 16px; }
  .kp-library.is-replaced .kp-library-more { width: var(--control-touch); height: var(--control-touch); }
  .kp-library.is-replaced .kp-library-toolbar { flex-wrap: nowrap; padding: 6px 16px 12px; } /* 12px above and below the row */
  .kp-library.is-replaced :is(.kb-home-toggle, .kb-mw-chip) { height: var(--control-touch); box-sizing: border-box; }
  .kp-library.is-replaced .kb-home-toggle [role=tab] { height: 100%; }
  .main:has(> .tab-pane:not(.tab-hidden) .kp-library-launcher:not([hidden]) > .kp-library.is-replaced) > .studio-calendar-strip { display: none; }
}

/* ---- Currents notifications (BRIEF §4) ---- */
/* The board bell: Watch shows in the accent, Mute as a struck bell. */
.kb-bell.is-watch { color: var(--accent); }
.kb-bell-menu { width: 320px; }
/* @mentions in a card's comment and description: the people picker floats under the field (KbMentions.tsx
   places it), over the card window. */
.kb-mention-pop { margin: 0; z-index: var(--z-menu); }
.kb-mention-pop .mention-row > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kb-mention-pop .mention-row > .mu { flex: none; margin-left: auto; }
.mention-row.is-away:not(.sel, :hover) > span:not(.mu) { color: var(--dim); }
.kb-mention-warning { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 8px 0 0; color: var(--dim); font-size: var(--fs-sm); }
.kb-mention-warning > i { color: var(--warning); }
.kb-mention-warning > span { flex: 1; min-width: 0; }
.kbm-comment-text .mention { color: var(--accent); font-weight: var(--fw-semibold); }
/* User settings › Currents notifications: the toggle-row pattern, the app's switch (studio.css) first at the
   content edge, 8px to its label, a dim line under it. */
.kb-notify-rows { display: flex; flex-direction: column; margin-top: 12px; }
.kb-toggle-row { display: flex; align-items: flex-start; gap: 8px; padding: 8px 0; cursor: pointer; }
.kb-toggle-row input { margin: 0; }
.kb-toggle-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.kb-toggle-text strong { font-size: var(--fs-md); font-weight: var(--fw-semibold); line-height: 22px; }
.kb-toggle-text small { font-size: var(--fs-sm); color: var(--dim); }
.kb-notify-hours { margin: 12px 0 0; font-size: var(--fs-sm); color: var(--dim); }
.kb-link { padding: 0; border: 0; background: none; color: var(--accent); font: inherit; text-decoration: underline; cursor: pointer; }
.kb-notify-error { margin: 8px 0 0; color: var(--danger); font-size: var(--fs-sm); }
/* Inside User settings, whose labels are field captions. */
.profile-editor .modal-body .kb-toggle-row { display: flex; margin: 0; font-size: inherit; font-weight: inherit; color: var(--text); text-transform: none; letter-spacing: 0; }
/* The Currents notifications tab is settings only: no profile preview beside it. */
.profile-editor-layout.is-settings-only { grid-template-columns: minmax(0, 1fr); }
.profile-editor-layout.is-settings-only > .profile-editor-preview { display: none; }
.kp-select{display:inline-flex;min-width:0;max-width:100%;vertical-align:middle}.kp-select .kp-select-trigger{display:flex;align-items:center;justify-content:space-between;gap:14px;min-width:0;width:100%;padding:9px 12px;border:1px solid var(--line);border-radius:10px;background:var(--bg-0);color:var(--text);font:inherit;text-align:left;cursor:pointer;transition:border-color var(--dur-fast),box-shadow var(--dur-fast),background var(--dur-fast)}.kp-select-trigger>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kp-select-trigger>i{font-size:10px;color:var(--dim);transition:transform .18s}.kp-select-trigger[aria-expanded=true]>i{transform:rotate(180deg)}.kp-select-trigger:hover{background:var(--hover)}.kp-select-trigger:focus-visible,.kp-select-trigger[aria-expanded=true]{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 22%,transparent)}.kp-select-trigger:disabled{opacity:.45;cursor:default}.kp-select-menu{position:fixed;z-index:100100;overflow:auto;box-sizing:border-box;padding:4px;background:color-mix(in srgb,var(--text) 6%,var(--pop-bg,var(--bg-2)));color:var(--text);border:1px solid var(--ctl-line);border-radius:var(--radius-md);box-shadow:var(--shadow-2);font-size:14px;overscroll-behavior:contain;animation:kp-select-enter .14s ease-out}.kp-select-menu.is-closing{opacity:0;transform:translateY(-3px);transition:opacity .12s,transform .12s;pointer-events:none}.kp-select-option{display:flex;align-items:center;gap:12px;justify-content:space-between;padding:0 12px;min-height:36px;box-sizing:border-box;border-radius:var(--radius-sm);cursor:pointer;transition:background .1s;overflow-wrap:anywhere}.kp-select-option>span{min-width:0}.kp-select-option.is-active{background:var(--hover)}.kp-select-option[aria-selected=true]{color:var(--text);background:var(--accent-dim)}.kp-select-option>i{color:var(--accent);font-size:11px;flex-shrink:0}.kp-select-option[aria-disabled=true]{opacity:.4;cursor:default}.kp-select-group{font-size:12px;letter-spacing:.04em;font-weight:600;color:var(--dim);padding:12px 12px 6px;overflow-wrap:anywhere}.dd-workspace-bar .kp-select{flex:1;max-width:520px}.ds-panel label>.kp-select{width:100%}.dd-head>.kp-select.dd-depot-sel{padding:0;border:0;background:transparent}@keyframes kp-select-enter{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}@media(prefers-reduced-motion:reduce){.kp-select-menu{animation:none}.kp-select-menu.is-closing,.kp-select .kp-select-trigger,.kp-select-trigger>i,.kp-select-option{transition:none}}

/* Select popups may be portalled outside their app surface. */
.kp-select-trigger,.kp-select-menu{-webkit-user-select:none;user-select:none}
/* The filter box of a searchable menu stays on top of the list. */
.kp-select-menu .kp-select-search{position:sticky;top:0;z-index:1;display:block;width:100%;box-sizing:border-box;height:var(--control-md);margin:0 0 4px;padding:0 12px;border:1px solid color-mix(in srgb,var(--text) 22%,transparent);border-radius:var(--radius-md);background:color-mix(in srgb,var(--text) 4%,var(--pop-bg,var(--bg-2)));color:var(--text);font:inherit;outline:none;user-select:text;transition:border-color var(--dur-fast),box-shadow var(--dur-fast)}
.kp-select-menu .kp-select-search:focus{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 22%,transparent)}
.kp-select-menu .kp-select-search::placeholder{color:var(--dim)}
.kp-select-empty{margin:0;padding:12px;color:var(--dim);font-size:14px}
.kp-select-trigger>i.kp-select-icon{flex:none;width:16px;font-size:14px;text-align:center;color:var(--dim);transform:none}
/* Design tokens. The one scale every stylesheet draws from: spacing, radius,
   type, elevation, stacking and motion, plus the semantic colours that themes
   do not set themselves. Themes (themes.css, custom themes) only provide the
   surface/text/accent palette; whether a theme is light or dark is told by
   data-scheme on <html> (set in theme.ts). Loaded before every other sheet. */
:root {
  /* Spacing */
  --sp-0: 2px; --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px; --sp-7: 48px;
  /* Corner radius */
  --radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; --radius-full: 999px;
  /* Type: sizes, weights, line heights */
  --fs-xs: 11px; --fs-sm: 12px; --fs-md: 14px; --fs-lg: 16px; --fs-xl: 20px;
  --fs-2xl: 28px;  /* display: What's new release titles only */
  --fw-regular: 400; --fw-semibold: 600; --fw-bold: 700;
  --lh-tight: 1.25; --lh-body: 1.5;
  /* Control sizes: compact controls, standard controls, touch targets */
  --control-sm: 28px; --control-md: 36px; --control-touch: 44px;
  /* Elevation */
  --shadow-color: rgb(0 0 0 / 0.36);
  --shadow-1: 0 1px 3px var(--shadow-color);
  --shadow-2: 0 8px 24px var(--shadow-color);
  --shadow-3: 0 24px 64px var(--shadow-color);
  /* Headers and bars that stay put while content scrolls under them: always opaque, in every theme.
     (--main-bg is transparent over the studio's colour field, so it can't be one.) Computed here
     from the page theme's --bg-0/--bg-1: a subtree that re-themes itself with its own --bg-* (a
     theme preview) must redeclare --surface-head too if it ever holds a sticky header. */
  --surface-head: color-mix(in srgb, var(--bg-1) 95%, var(--bg-0));
  /* Stacking layers, lowest to highest */
  --z-raised: 1; --z-sticky: 10; --z-drawer-backdrop: 110; --z-drawer: 120;
  --z-popover: 1000; --z-scrim: 4000; --z-menu: 4001; --z-safe-area: 5000; --z-toast: 10000;
  /* Motion */
  --dur-fast: 120ms; --dur-base: 200ms; --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  /* Endless loops (pulses, blinks) breathe evenly instead of rushing and stalling each cycle. */
  --ease-loop: ease-in-out;

  /* Fixed palette colours: the same in every theme and scheme (themes set --teal, --green, --blue
     and --accent themselves, in styles.css and themes.css). */
  --orange: #f2683c; --purple: #9b6dff; --yellow: #f0b232;
  /* Warnings drawn on the call stage, which stays dark in every theme until Task 4 themes it. */
  --warning-on-dark: #f0b232;

  /* Semantic colours, dark schemes */
  color-scheme: dark;
  --danger: #ed4245; --success: #3ba55d; --warning: #f0b232;
  --online: #3ba55d; --idle: #f0b232; --dnd: #ed4245; --offline: #80848e;
  --on-accent: var(--bg-0);
  --on-danger: #fff; /* text on a red fill (mention badges and pills, Live): white in every theme */
  --overlay: rgb(4 6 10 / 0.6);
  /* Controls drawn over photos and banners: the same in every theme. */
  --on-media: #fff; --media-chip: rgb(16 24 32 / 0.7); --media-chip-hover: rgb(16 24 32 / 0.9);
  --scrim-blur: 4px;

  /* The call (Task 4). Voice-only stages follow the theme; video sits on a dark panel in every theme,
     and anything drawn over video is dark glass (--stage-glass) with fixed light text. */
  --radius-xl: 16px;
  --z-floater: 900; /* the pop-out call: below popovers, menus and toasts */
  --stage-gap: var(--sp-3);
  --stage-bg: color-mix(in srgb, var(--bg-1) 72%, var(--bg-0));
  --stage-tile: color-mix(in srgb, var(--text) 5%, var(--bg-2));
  --stage-tile-line: color-mix(in srgb, var(--text) 10%, transparent);
  --stage-video-base: #0a0b0e;
  --stage-video-bg: color-mix(in srgb, var(--bg-0) 14%, var(--stage-video-base));
  --stage-video-tile: color-mix(in srgb, var(--bg-0) 22%, #15171c);
  --stage-video-text: #f2f4f7;
  --stage-glass: rgb(14 16 20 / 0.74);
  --stage-glass-line: rgb(255 255 255 / 0.14);
  --stage-speaking: var(--success);
  --stage-hand: var(--yellow);
  --success-text: color-mix(in srgb, var(--success) 70%, var(--text));
  --warning-text: var(--warning);
  --danger-text: color-mix(in srgb, var(--danger) 62%, var(--text));
  --danger-fill: #c62f32; /* red fills under white text or icons (Leave, Live, badges): 5.3:1 */
  /* Call controls. "On" is an inverse neutral fill; red only for "off"; green only for speaking. */
  --ctl-size: var(--control-touch);
  --ctl-gap: var(--sp-2);
  --ctl-bg: color-mix(in srgb, var(--text) 9%, var(--bg-2));
  --ctl-bg-hover: color-mix(in srgb, var(--text) 15%, var(--bg-2));
  --ctl-line: color-mix(in srgb, var(--text) 14%, transparent);
  --ctl-rim: color-mix(in srgb, var(--text) 22%, transparent);
  --ctl-fg: var(--text);
  --ctl-off-bg: color-mix(in srgb, var(--danger) 18%, var(--bg-2));
  --ctl-off-fg: color-mix(in srgb, var(--danger) 55%, var(--text));
  --ctl-on-bg: var(--text);
  --ctl-on-fg: var(--bg-0);
  --ctl-hand-fg: #1d1606;
  --bar-bg: color-mix(in srgb, var(--bg-1) 92%, transparent);
  --pop-bg: var(--bg-2);

  /* Names other stylesheets used before tokens existed. */
  --red: var(--danger); --text-1: var(--text); --text-2: var(--dim); --text-dim: var(--dim);
  --accent-dim: color-mix(in srgb, var(--accent) 22%, transparent); --bg-hover: var(--hover);
}
[data-scheme='light'] {
  color-scheme: light;
  --shadow-color: rgb(16 24 40 / 0.14);
  --danger: #c62f32; --success: #23864a; --warning: #8a5600; /* 4.5:1 or more on the light surfaces (was #a86b00, 4.0:1) */
  --online: #23a55a; --idle: #d79a15; --dnd: #d83a3d; --offline: #8a919c;
  --overlay: rgb(20 26 36 / 0.32);
  --success-text: var(--success); --danger-text: var(--danger);
  --warning-text: color-mix(in srgb, var(--warning) 78%, var(--text));
  --stage-bg: color-mix(in srgb, var(--bg-1) 80%, var(--bg-3));
  --stage-tile: var(--bg-0);
  --stage-tile-line: color-mix(in srgb, var(--text) 12%, transparent);
  --ctl-bg: color-mix(in srgb, var(--text) 6%, var(--bg-0));
  --ctl-bg-hover: color-mix(in srgb, var(--text) 11%, var(--bg-0));
  --ctl-off-bg: color-mix(in srgb, var(--danger) 12%, var(--bg-0));
  --ctl-off-fg: var(--danger);
  --bar-bg: color-mix(in srgb, var(--bg-0) 94%, transparent);
  --pop-bg: var(--bg-0);
}
/* Over video, in every theme: the controls are dark glass with fixed light marks. */
.on-video {
  --ctl-bg: rgb(255 255 255 / 0.1); --ctl-bg-hover: rgb(255 255 255 / 0.18);
  --ctl-line: rgb(255 255 255 / 0.14); --ctl-rim: rgb(255 255 255 / 0.24); --ctl-fg: #f2f4f7;
  --ctl-off-bg: #4a2023; --ctl-off-fg: #ffb3b4; --ctl-on-bg: #f2f4f7; --ctl-on-fg: #0a0b0e;
  --bar-bg: var(--stage-glass);
}
@media (prefers-reduced-motion: reduce) {
  :root { --dur-fast: 0ms; --dur-base: 0ms; }
  /* Nothing keeps moving: every animation (spinners, typing dots, flashes, pulses) settles at
     once on its end state, and there are no transitions (0s, not a tiny duration: even a 0.01ms
     transition paints its starting frame, e.g. a menu flashing at its first position). No code
     waits for animation or transition events, so this is safe app-wide. A busy indicator that truly
     needs motion can only opt out with a more specific !important (none does today). */
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; animation-delay: 0s !important; transition-duration: 0s !important; transition-delay: 0s !important; scroll-behavior: auto !important; }
}
/* Shared controls used across Kelp Pup (chat, Emoji Studio, Drydock). */

/* Switch: <button role="switch" class="switch" aria-checked> with an optional label span and a .switch-track. */
.switch { display: inline-flex; align-items: center; gap: var(--sp-2); min-height: var(--control-sm); padding: var(--sp-1) 0 var(--sp-1) var(--sp-1); background: transparent; color: var(--dim); font: inherit; font-size: var(--fs-xs); white-space: nowrap; }
.switch:hover { color: var(--text); }
.switch:focus-visible { outline: 2px solid var(--accent); outline-offset: var(--sp-1); border-radius: var(--radius-sm); }
.switch-track { display: inline-flex; align-items: center; width: 32px; height: 20px; padding: var(--sp-0); border-radius: var(--radius-full); background: var(--bg-0); box-shadow: inset 0 0 0 1px var(--line); transition: background-color var(--dur-fast) var(--ease); }
.switch-track > span { width: 16px; height: 16px; border-radius: 50%; background: var(--dim); transition: transform var(--dur-base) var(--ease), background-color var(--dur-fast) var(--ease); }
.switch[aria-checked='true'] .switch-track { background: var(--accent); }
.switch[aria-checked='true'] .switch-track > span { background: var(--bg-0); transform: translateX(12px); }
:root {
  --teal: #159a8a;
  --green: #5bc88a;
  --blue: #2f80ed;
  /* Primary-action / selected-highlight color. Change THIS ONE value to
     restyle every primary button (Join voice, Create channel, Save, etc.) and
     every blue "selected/active" highlight app-wide. */
  --accent: #5db23b;
  /* --orange, --purple and --yellow never change with the theme: they live in tokens.css. */

  --bg-0: #0f1216;
  --bg-1: #161a20;
  --bg-2: #1c2128;
  --bg-3: #232a33;
  --hover: #272e38;
  --active: #2e3742;
  --line: #2a313b;
  --text: #e7ebf0;
  --dim: #98a2b0;
  --faint: #6b7480;

  /* Surface gradients (one set per theme; see themes.css for the variants).
     --sidebar-bg: side columns, dark at top → lighter blue at the bottom.
     --panel-bg:   the bottom-left "me" panel, a subtle golden circular glow.
     --main-bg:    the central chat column, a flat darker surface (no gradient). */
  --sidebar-bg: linear-gradient(180deg, #0f131b 0%, #16203a 60%, #1d2c4e 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(241,185,67,0.17), rgba(241,185,67,0.05) 44%, rgba(0,0,0,0) 72%), #0d1117;
  --main-bg: #0e1116;
  /* Full-screen image viewer backdrop — dark by default; each theme tints it
     to match (medium gray on the light theme; see themes.css). */
  --lb-backdrop: rgba(8, 10, 14, 0.95);

  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body, #root { height: 100%; }
body { font-family: var(--sans); background: var(--bg-0); color: var(--text); font-size: 14px; -webkit-font-smoothing: antialiased; }
button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; }
input, select { font-family: inherit; }
a { color: var(--blue); cursor: pointer; }
/* Scrollbars follow the theme: thumb derived from the theme's text/background
   mix so it adapts to every preset AND custom themes. */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--text) 20%, var(--bg-0)); border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--text) 32%, var(--bg-0)); }
::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent; }

.splash { display: grid; place-items: center; height: 100%; color: var(--dim); }

/* ---------------- auth + setup ---------------- */
.auth-wrap { display: grid; place-items: center; height: 100%; background: radial-gradient(circle at 50% 0%, #16242a, var(--bg-0) 60%); padding: 20px; }
.auth-card { width: 360px; background: var(--bg-1); border: 1px solid var(--line); border-radius: 16px; padding: 32px 28px; display: flex; flex-direction: column; }
.auth-card.wide { width: 440px; }
.auth-logo { width: 64px; height: 64px; align-self: center; margin-bottom: 8px; }
.auth-card h1 { text-align: center; font-size: 24px; letter-spacing: -0.02em; }
.auth-sub { text-align: center; color: var(--dim); margin-bottom: 20px; }
.auth-card label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--dim); margin: 12px 0 6px; }
.auth-card input, .settings-form input, .settings-form select {
  background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; padding: 11px 13px; color: var(--text); font-size: 14px; outline: none;
}
.auth-card input:focus { border-color: var(--accent); }
.auth-error { margin-top: 12px; color: #ff8a8a; font-size: 13px; }
.hint { font-size: 12px; color: var(--faint); margin-top: 8px; }
.btn-primary { background: var(--accent); color: #fff; font-weight: 600; border-radius: 8px; padding: 10px 16px; font-size: 14px; }
.btn-primary:hover { background: color-mix(in srgb, var(--accent) 86%, #000); }
.btn-primary:disabled { opacity: 0.5; cursor: default; }
.btn-ghost { background: var(--bg-3); color: var(--dim); border-radius: 8px; padding: 10px 16px; font-weight: 600; }
.btn-ghost:hover { background: var(--hover); color: var(--text); }
.auth-toggle { text-align: center; margin-top: 16px; color: var(--dim); font-size: 13px; }

.wiz-dots { display: flex; gap: 6px; justify-content: center; margin-bottom: 18px; }
.wiz-dot { width: 28px; height: 4px; border-radius: 3px; background: var(--hover); }
.wiz-dot.on { background: var(--accent); }
.wiz-h { font-size: 16px; font-weight: 700; margin-bottom: 4px; }
.wiz-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 22px; }
.radio-row { display: flex; gap: 10px; }
.radio-card { flex: 1; border: 1px solid var(--line); border-radius: 9px; padding: 12px; cursor: pointer; }
.radio-card.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
.radio-card .rc-t { font-weight: 700; font-size: 13px; }
.radio-card .rc-d { font-size: 12px; color: var(--dim); margin-top: 3px; }

/* ---------------- bubbles (top tab bar) + app shell ---------------- */
.app-shell { height: 100%; display: flex; flex-direction: column; min-height: 0; }
.app-shell > .app { flex: 1; min-height: 0; height: auto; }

.bubble-bar {
  flex: 0 0 auto; display: flex; align-items: center; gap: 6px;
  padding: 6px 10px; background: var(--sidebar-bg); border-bottom: 1px solid var(--line);
  overflow-x: auto; scrollbar-width: none;
  user-select: none; -webkit-user-select: none;
}
.bubble-bar::-webkit-scrollbar { display: none; }
.bubble {
  display: inline-flex; align-items: center; gap: 8px; white-space: nowrap;
  padding: 6px 14px; border-radius: 999px; border: 1px solid transparent;
  background: var(--bg-3); color: var(--dim); font-size: 13px; font-weight: 600; cursor: pointer;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.bubble:hover { color: var(--text); background: var(--hover); }
.bubble.active { background: var(--accent); color: #fff; border-color: transparent; }
.bubble .dd-off-chip { margin-left: 2px; }

/* On a tool bubble the tool fills the width. Use FLEX (not the grid with
   0-width side columns): display:none-ing grid items makes .main reflow into
   the first 0-width column and collapse — flex just drops the hidden panels. */
.app.on-tool { display: flex !important; }
.app.on-tool .sidebar { display: none; }
.app.on-tool .main { flex: 1 1 auto; min-width: 0; }

/* Keep-alive tool/chat panes: only the active one shows; the rest stay mounted.
   `display:contents` makes the visible wrapper layout-transparent, so each tool
   lays out exactly as if it were a direct child of .main (its original context);
   hidden panes are pulled out of layout entirely but stay mounted. */
.tab-pane { display: contents; }
.tab-pane.tab-hidden { display: none; }

/* ---------------- app shell (three panes) ---------------- */
.app { display: grid; grid-template-columns: 240px 1fr; height: 100%; }

.sidebar { background: var(--sidebar-bg); border-right: 1px solid var(--line); display: flex; flex-direction: column; min-height: 0; }

.user-panel { border-top: 1px solid var(--line); background: var(--panel-bg); display: flex; align-items: center; gap: 9px; padding: 8px 10px; }
.user-panel .meta { flex: 1; min-width: 0; }
.user-panel .name { font-size: 13px; font-weight: 700; display: flex; align-items: center; gap: 6px; white-space: nowrap; overflow: hidden; }
/* The role tag is never cut: the name gives way first (with "…"). */
.user-panel .name .display-name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.user-panel .name:has(.role-tag) { gap: var(--sp-2); }
.user-panel .name .role-tag { flex: none; }
/* One line, ending in "…" when long, so a long status never grows the panel. */
.user-panel .status { font-size: 11px; color: var(--dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-panel .status .presence-dot { display: inline-block; margin-right: 5px; vertical-align: middle; }
.user-panel .status .member-activity { margin-top: 0; } /* your meeting or day off, in place of Online */
.dot { width: 8px; height: 8px; border-radius: 50%; }
.logout { color: var(--dim); font-size: 17px; padding: 6px; border-radius: 6px; }
.logout:hover { background: var(--hover); color: var(--text); }

/* ---------------- main ---------------- */
.main { background: var(--main-bg); display: flex; flex-direction: column; min-width: 0; }
/* Extra breathing room before a new author's block; consecutive messages from
   the same person (grouped) stay tight. */

.voice-placeholder { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; color: var(--dim); }
.voice-placeholder img { width: 56px; height: 56px; opacity: 0.8; }
.voice-placeholder h3 { color: var(--text); }

/* ---------------- role tags ---------------- */
.role-tag { font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.03em; padding: 1px 5px; border-radius: 4px; }
.t-owner { background: rgba(240, 178, 50, 0.18); color: var(--yellow); }
.t-admin { background: rgba(155, 109, 255, 0.18); color: var(--purple); }
.t-member { background: rgba(47, 128, 237, 0.16); color: #8fb4ff; }
.t-guest { background: rgba(120, 130, 145, 0.18); color: #9aa3af; }

/* ---------------- settings modal ---------------- */
.overlay { position: fixed; inset: 0; background: rgba(8, 9, 11, 0.72); display: flex; align-items: center; justify-content: center; padding: 24px; z-index: 50; }
.modal { background: var(--bg-2); border: 1px solid var(--line); border-radius: 14px; width: 100%; max-width: 640px; max-height: 84vh; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5); }
.modal-head { display: flex; align-items: center; padding: 18px 22px; border-bottom: 1px solid var(--line); }
.modal-head h3 { font-size: 17px; }
.modal-close { margin-left: auto; width: 30px; height: 30px; border-radius: 7px; color: var(--dim); font-size: 16px; }
.modal-close:hover { background: var(--hover); color: var(--text); }
.tabs { display: flex; gap: 4px; padding: 0 22px; border-bottom: 1px solid var(--line); }
.modal > .tabs { flex-wrap: wrap; } /* Workspace settings: no label is cut at the edge */
.tab { padding: 12px 14px; font-size: 13px; font-weight: 600; color: var(--dim); border-bottom: 2px solid transparent; margin-bottom: -1px; }
.tab.active { color: #fff; border-color: var(--accent); }
.tab:hover { color: var(--text); }
.modal-body { padding: 20px 22px; overflow-y: auto; }
.settings-form { display: flex; flex-direction: column; max-width: 320px; }
.settings-form label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--dim); margin: 14px 0 6px; }
.settings-form .btn-primary { margin-top: 20px; align-self: flex-start; }
/* Workspace › Default timezone, in the newer field style (the rest of this form's restyle is its own task):
   a sentence-case label, the themed select, its hint 4px under it; Save as the accent primary. */
.settings-form .ws-field-label { margin: 14px 0 6px; font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--text); }
.settings-form .ws-zone { width: 100%; }
.settings-form .ws-field-hint { margin: 4px 0 0; font-size: var(--fs-sm); color: var(--dim); }
.settings-form .ws-save, .settings-form .ws-save:hover { background: var(--accent); border-color: var(--accent); color: var(--on-accent); box-shadow: none; }
.settings-form .ws-save:hover { background: color-mix(in srgb, var(--accent) 88%, var(--text)); }
/* Space between the last field (or error) and the Log in / Create account
   button — the glass glow otherwise touches the password input. */
.auth-card .btn-primary { margin-top: 20px; }

table { width: 100%; border-collapse: collapse; font-size: 13px; }
th { text-align: left; color: var(--faint); font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; padding: 8px 10px; border-bottom: 1px solid var(--line); }
td { padding: 9px 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
td select { background: var(--bg-0); border: 1px solid var(--line); border-radius: 6px; padding: 5px 8px; color: var(--text); }
.muted { color: var(--faint); }
.pill { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 10px; }
.pill.on { background: rgba(91, 200, 138, 0.16); color: var(--green); }
.pill.off { background: rgba(120, 130, 145, 0.16); color: var(--dim); }
.mini { font-size: 12px; color: var(--dim); padding: 4px 9px; border-radius: 6px; border: 1px solid var(--line); }
.mini:hover { background: var(--hover); color: var(--text); }
.invite-create { display: flex; gap: 8px; align-items: center; margin-bottom: 16px; flex-wrap: wrap; }
.invite-create select, .invite-create input { background: var(--bg-0); border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; color: var(--text); outline: none; }

@media (max-width: 1100px) { .app { grid-template-columns: 220px 1fr; } }
@media (max-width: 640px) { .app { grid-template-columns: 1fr; } .sidebar { display: none; }  }
/* Attachments + upload UI (M2) */

/* Image/media attachments line up with the message text column — i.e. the
   image's left edge starts exactly where text begins (under the username), with
   no extra indent. align-items: flex-start so the wrappers (and the image
   inside) shrink-wrap to the photo's real width instead of stretching to the
   full message width — otherwise a portrait photo gets letterboxed/centered
   (object-fit: contain) inside an over-wide element and looks indented. */
.attachments { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; margin-top: 4px; }

/* No frame — the photo sits in the message at its true aspect ratio, with just
   softly rounded corners (no border, no background fill). */
.att-image {
  max-width: 420px; max-height: 320px; width: auto; height: auto; border-radius: 8px;
  cursor: pointer; display: block; object-fit: contain; background: transparent;
}
.att-video { max-width: 480px; max-height: 340px; border-radius: 8px; border: 1px solid var(--line); background: #000; }
.att-audio { width: 360px; max-width: 100%; }
/* The file's name, small, over its player. */
.att-audio-box { width: 360px; max-width: 100%; }
.att-audio-box .att-audio { display: block; width: 100%; }
.att-audio-name { padding: 0 14px 4px; font-size: 12px; color: var(--text-dim); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

.att-file {
  display: flex; align-items: center; gap: 12px; max-width: 360px;
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 13px; text-decoration: none; color: var(--text);
}
.att-file:hover { border-color: var(--accent); }
.att-file .fi { width: 36px; height: 36px; border-radius: 7px; background: color-mix(in srgb, var(--accent) 18%, transparent); display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
.att-file .fn { font-weight: 600; font-size: 13px; color: #cdd9ff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-file .fs { font-size: 11px; color: var(--faint); }

.att-processing {
  display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: var(--dim);
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px;
}
.att-processing .spin { width: 12px; height: 12px; border: 2px solid var(--faint); border-top-color: var(--accent); border-radius: 50%; animation: kp-spin 0.8s linear infinite; }
@keyframes kp-spin { to { transform: rotate(360deg); } }

/* composer upload chips */
.upload-chips { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 16px 8px; }
.chip {
  display: flex; align-items: center; gap: 8px; background: var(--bg-3); border: 1px solid var(--line);
  border-radius: 8px; padding: 7px 10px; max-width: 240px; font-size: 12px;
}
.chip .cn { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 120px; }
.chip .bar { width: 60px; height: 4px; background: #3a4049; border-radius: 3px; overflow: hidden; }
.chip .bar > i { display: block; height: 100%; background: var(--accent); border-radius: 3px; transition: width 0.15s; }
.chip .x { color: var(--faint); cursor: pointer; font-size: 14px; }
.chip .x:hover { color: var(--text); }
.chip.err { border-color: var(--orange); color: #ffb39a; }
.chip .ok { color: var(--green); }

/* Inline links + Discord-style unfurl preview cards. */

.link-card {
  display: block; max-width: 440px; margin-top: 6px; padding: 10px 12px;
  border-left: 4px solid var(--accent); background: var(--bg-2);
  border-radius: 4px 8px 8px 4px; text-decoration: none; overflow: hidden;
}
.link-card:hover { background: var(--bg-3); }
.lc-body { min-width: 0; }
.lc-site { color: var(--dim); font-size: 12px; margin-bottom: 3px; }
.lc-title { color: var(--accent); font-weight: 700; font-size: 15px; line-height: 1.3; word-break: break-word; }
.lc-desc {
  color: var(--dim); font-size: 13px; margin-top: 4px; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.lc-thumb {
  position: relative; margin-top: 10px; border-radius: 8px;
  width: 100%; aspect-ratio: 16 / 9; max-height: 300px;
  background-size: cover; background-position: center; background-color: var(--bg-0);
}
/* Portrait thumbnails (e.g. TikTok 9:16) are letterboxed, not cropped, and kept
   to a sensible height so the card doesn't dominate the message list. */
.lc-thumb.portrait {
  aspect-ratio: auto; height: 320px; max-width: 240px;
  background-size: contain; background-repeat: no-repeat;
}
.lc-play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.lc-play i {
  width: 56px; height: 56px; border-radius: 50%; background: rgba(0, 0, 0, 0.55); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 20px; padding-left: 3px;
}
.link-card:hover .lc-play i { background: rgba(0, 0, 0, 0.72); }

/* ---- Inline 3D model viewer ---- */
.mv-wrap {
  position: relative; width: min(520px, 100%); border-radius: 12px; overflow: hidden;
  background: radial-gradient(120% 130% at 50% 20%, #1c2230, #0b0e14 75%);
  border: 1px solid var(--line);
}
/* Works for both native fullscreen and the iOS CSS fallback: fixed+inset
   pins the viewer over the app; dvh tracks the collapsing browser chrome. */
.mv-wrap.fs { position: fixed; inset: 0; width: 100vw; height: 100dvh; z-index: 2000; border-radius: 0; background: var(--bg-2); }
.mv-canvas { width: 100%; height: 300px; cursor: grab; }
.mv-wrap.fs .mv-canvas { height: calc(100% - 40px); }
.mv-canvas:active { cursor: grabbing; }
.mv-canvas canvas { display: block; }
.mv-status {
  position: absolute; inset: 0 0 40px; display: flex; align-items: center; justify-content: center; gap: 10px;
  color: #8fa0b5; font-size: 13px; pointer-events: none;
}
.mv-status.err { color: #e8a0a2; }
.mv-bar {
  display: flex; align-items: center; gap: 8px; height: 40px; padding: 0 10px;
  background: rgba(8, 10, 14, 0.75); border-top: 1px solid var(--line);
}
.mv-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; color: #c8d2de; display: flex; gap: 8px; align-items: center; }
.mv-actions { display: flex; gap: 4px; }
.mv-actions button, .mv-actions a {
  width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 7px; color: #9fb0c3; font-size: 12.5px; cursor: pointer; background: transparent;
}
.mv-actions button:hover, .mv-actions a:hover { background: rgba(255, 255, 255, 0.1); color: #fff; }
.mv-actions button.on { background: var(--accent); color: #fff; }
.mv-mats {
  position: absolute; right: 10px; bottom: 48px; width: 290px; z-index: 5;
  max-width: calc(100% - 20px);
  /* Never taller than the viewer: cap to the wrap and scroll the slot list
     inside — otherwise long slot lists clip against the viewer's edges. */
  max-height: calc(100% - 58px);
  display: flex; flex-direction: column;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.5); padding: 12px;
}
.mv-mats-head, .mv-mats-foot, .mv-mats-empty { flex: 0 0 auto; }
.mv-mats-head { font-size: 12.5px; font-weight: 700; margin-bottom: 10px; }
.mv-mats-head .muted { display: block; font-weight: 400; font-size: 11px; margin-top: 2px; }
.mv-mat-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.mv-mat-label { width: 92px; flex: none; font-size: 12px; color: var(--dim); }
.mv-mat-row select {
  flex: 1; min-width: 0; background: var(--bg-3); color: var(--text); border: 1px solid var(--line);
  border-radius: 7px; padding: 5px 8px; font-size: 12px; outline: none;
}
.mv-mats-foot { display: flex; gap: 6px; margin-top: 10px; align-items: center; flex-wrap: wrap; }
.mv-mats-foot button { white-space: nowrap; }
@media (max-width: 760px) { .mv-canvas { height: 240px; } }
.mv-mats-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.mv-slot { padding: 6px 0; }
.mv-slot + .mv-slot { border-top: 1px solid var(--line); }
.mv-slot-name { font-size: 12px; font-weight: 700; color: var(--text); margin-bottom: 6px; display: flex; align-items: center; gap: 7px; }
.mv-slot-name i { color: var(--accent); font-size: 11px; }
.mv-mats-empty { font-size: 12px; color: var(--text-dim); line-height: 1.5; padding: 8px 10px; background: color-mix(in srgb, var(--accent) 8%, transparent); border: 1px dashed var(--line); border-radius: 8px; margin: 6px 0; }
.mv-mats-empty b { color: var(--text); font-weight: 600; }
.mv-wrap.droptex { outline: 2px dashed var(--accent); outline-offset: -2px; }
.mv-wrap.droptex::after { content: 'Drop textures to add them to this model'; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--bg-2) 72%, transparent); color: var(--text); font-weight: 700; font-size: 14px; z-index: 6; pointer-events: none; border-radius: inherit; }

/* Inline YouTube player (click-to-load facade → iframe). */
.link-card.yt-card { max-width: 480px; padding: 10px 12px 12px; }
.yt-embed, .yt-facade {
  position: relative; display: block; width: 100%; aspect-ratio: 16 / 9;
  margin-top: 8px; padding: 0; border: none; border-radius: 10px; overflow: hidden;
  background-color: #000; background-position: center; background-size: cover; background-repeat: no-repeat;
  cursor: pointer;
}
.yt-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.yt-play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.yt-play i { font-size: 52px; color: #ff0000; filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5)); transition: transform .12s ease; }
.yt-facade:hover .yt-play i { transform: scale(1.08); }
/* Voice room (M3) */
.voice-join {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; color: var(--dim);
}
.voice-join img { width: 56px; height: 56px; }
.voice-join h3 { color: var(--text); }
.voice-join .btn-primary { margin-top: 8px; }

/* The call (stage, tiles, bar, spotlight, pop-out, sidebar panel): voice/call.css. */

/* sidebar voice participants */
.vc-members { padding: 0 0 var(--sp-1); }
/* Who's in a voice channel: a 28px sub-list under its row, faces lined up with the
   channel's name (row inset + icon column + gap). Each opens that person's voice menu. */
.vc-member { display: flex; align-items: center; gap: var(--sp-2); box-sizing: border-box; width: 100%; min-height: 28px; padding: 0 var(--sp-2) 0 calc(var(--sp-2) * 2 + 24px); border: 0; border-radius: var(--radius-md); background: none; color: var(--dim); font: inherit; font-size: var(--fs-sm); text-align: left; cursor: pointer; }
.vc-member:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.vc-member .va {
  width: 18px; height: 18px; border-radius: 50%; background: linear-gradient(135deg, var(--teal), var(--blue));
  color: #fff; font-size: 9px; font-weight: 700; display: flex; align-items: center; justify-content: center;
}
/* Real-time speaking highlight in the sidebar call list — green ring on the
   avatar + brighter name, matching the call tiles/pucks. */
.vc-member .avatar { box-shadow: 0 0 0 0 transparent; transition: box-shadow var(--dur-fast) var(--ease); }
.vc-member.speaking .avatar { box-shadow: 0 0 0 2px var(--bg-1), 0 0 0 4px var(--stage-speaking); transition-duration: var(--dur-fast); }
.vc-member .avatar { transition: box-shadow var(--dur-base) var(--ease); }
.vc-member.speaking { color: var(--text); }
/* Live / muted / deafened marks, right-aligned after the name. */
.vc-member .vc-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vc-state { flex: none; display: inline-flex; align-items: center; gap: 6px; color: var(--dim); font-size: 12px; }
.vc-live {
  padding: 1px 6px; border-radius: 999px; background: var(--danger-fill); color: var(--on-danger);
  font-size: 11px; font-weight: 700; /* "Live", the same word and casing as on the tiles */
}

/* M4 collaboration polish: reactions, replies, mentions, pins, typing, search, DMs */

/* Settings → Emojis tab */
.emj-tab { display: flex; flex-direction: column; gap: 12px; }
.emj-add { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.emj-naming { display: flex; align-items: center; gap: 6px; }
.emj-naming input { background: var(--bg-2); border: 1px solid var(--line); border-radius: 8px; color: var(--text); padding: 6px 10px; font-family: ui-monospace, monospace; font-size: 13px; width: 220px; }
.emj-preview { width: 32px; height: 32px; object-fit: contain; }
.emj-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; max-height: 46vh; overflow-y: auto; }
.emj-cell { position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 10px 6px; border: 1px solid var(--line); border-radius: 10px; }
.emj-cell:hover { background: var(--hover); }
.emj-img { width: 32px; height: 32px; object-fit: contain; }
.emj-name { font-size: 11px; color: var(--dim); font-family: ui-monospace, monospace; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.emj-del { position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; border-radius: 6px; color: var(--dim); opacity: 0; }
.emj-cell:hover .emj-del { opacity: 1; }
.emj-del:hover { color: #ed4245; background: var(--hover); }

/* Discord-style "who reacted" tooltip on hover */

.emoji-pop {
  position: absolute; z-index: 30; background: var(--bg-3); border: 1px solid var(--line);
  border-radius: 9px; padding: 6px; display: flex; gap: 4px; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
}
.emoji-pop button { font-size: 18px; padding: 3px 5px; border-radius: 6px; }
.emoji-pop button:hover { background: var(--hover); }

.reply-bar {
  padding: 6px 18px; font-size: 12px; color: var(--dim); display: flex; align-items: center; gap: 8px;
}
.reply-bar { background: var(--bg-3); border-top: 1px solid var(--line); }
.reply-bar .x { margin-left: auto; cursor: pointer; color: var(--faint); }
.reply-bar .x:hover { color: var(--text); }

/* search + pins panels (reuse .overlay/.modal from styles.css) */
.search-box { display: flex; gap: 8px; margin-bottom: 14px; }
.search-box input { flex: 1; background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; padding: 10px 13px; color: var(--text); outline: none; }
.search-box input:focus { border-color: var(--accent); }
.result { padding: 10px 8px; border-bottom: 1px solid var(--line); cursor: pointer; border-radius: 6px; }
.result:hover { background: #1e242c; }
.result .rh { display: flex; gap: 8px; align-items: baseline; font-size: 12px; }
.result .rh b { color: #fff; }
.result .rh .where { color: var(--faint); }
.result .rc { color: #dce0e6; margin-top: 2px; }

.icon-btn { width: 32px; height: 32px; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: var(--dim); }
.icon-btn:hover { background: var(--hover); color: var(--text); }
/* M4b: read-only composer + notification menu */

.notif-wrap { position: relative; }
.notif-menu {
  position: absolute; right: 0; top: 38px; z-index: 30; width: 200px;
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 9px; padding: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}
.notif-menu .item { display: flex; align-items: center; gap: 8px; padding: 7px 9px; border-radius: 6px; font-size: 13px; cursor: pointer; width: 100%; text-align: left; }
.notif-menu .item:hover { background: var(--hover); }
.notif-menu .item.sel { color: #fff; }
.notif-menu .item.sel::after { content: '✓'; margin-left: auto; color: var(--accent); }
.notif-menu .sep { height: 1px; background: var(--line); margin: 5px 2px; }
.icon-btn.has-menu.on { color: #fff; }
/* Layout robustness: the "chrome" (headers, composer, user panel) must always
   stay visible; only the scroll regions flex. Fixes elements getting clipped
   when the window is resized. The crucial bit is min-height:0 on the flex
   columns so a tall message list scrolls instead of pushing the composer off. */

.app { min-height: 0; }
.sidebar, .main { min-height: 0; min-width: 0; }

.user-panel,
.reply-bar,
.upload-chips,
.voice-bar {
  flex-shrink: 0;
}

.voice-stage {
  min-height: 0;
}

.user-panel .meta { min-width: 0; }
.user-panel .name { text-overflow: ellipsis; }

/* Brand: bigger Dogfish Games badge on the login screen. */
.auth-logo { width: 96px; height: 96px; }
/* Avatars as images */

/* Context menu (right-click) */
.ctx-menu {
  position: fixed; z-index: 200; min-width: 210px; background: var(--bg-3); border: 1px solid var(--line);
  border-radius: 10px; padding: 5px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
}
.ctx-item {
  position: relative; display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 7px;
  font-size: 13px; color: var(--text); cursor: pointer; user-select: none;
}
.ctx-item:hover { background: var(--accent); color: #fff; }
/* The item whose submenu is open beside it (ContextMenu flyout). */
.ctx-item.is-active:not(:hover) { background: var(--hover); }
.ctx-item.danger { color: #ff8a8a; }
.ctx-item.danger:hover { background: var(--red, #ed4245); color: #fff; }
.ctx-item.disabled { opacity: 0.4; cursor: default; }
.ctx-item.disabled:hover { background: transparent; color: var(--text); }
.ctx-item .ci { width: 18px; text-align: center; }
.ctx-item .cl { flex: 1; }
/* A checked item's ✓ keeps clear of its label, in the trailing column. */
.ctx-item .cl + .cc { padding-left: 24px; }
/* A label with a dim second line (MenuItem.hint). */
.ctx-item .cl.has-hint { display: flex; flex-direction: column; gap: 2px; text-align: left; }
.ctx-item .cl .ch { font-size: 12px; color: var(--dim); }
.ctx-item:hover .cl .ch { color: color-mix(in srgb, #fff 80%, transparent); }
.ctx-item .ca { color: var(--dim); }

/* Voice user menu (right-click a person in a call) */
.vum-head {
  display: flex; align-items: center; gap: 9px; padding: 8px 9px 9px; margin-bottom: 3px;
  border-bottom: 1px solid var(--line);
}
.vum-name { font-weight: 700; font-size: 13.5px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vum-vol { padding: 8px 10px 10px; }
.vum-vol-top { display: flex; align-items: center; justify-content: space-between; font-size: 12.5px; color: var(--dim); margin-bottom: 7px; }
.vum-vol-top .fa-solid { margin-right: 6px; }
.vum-pct { font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.vum-vol input[type="range"] { display: block; }
.vum-sub { padding-left: 24px; }
.vum-sub .ci { color: var(--dim); }
.ctx-item:hover .ca { color: #fff; }
.ctx-item .ck { color: var(--accent); }
.ctx-item:hover .ck { color: #fff; }
.ctx-item.on { color: #fff; }
.ctx-sep { height: 1px; background: var(--line); margin: 5px 4px; }
.ctx-submenu {
  position: absolute; left: 100%; top: -6px; min-width: 190px; background: var(--bg-3); border: 1px solid var(--line);
  border-radius: 10px; padding: 5px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
}
/* Flip the submenu when it would run off the viewport edge. */
.ctx-submenu.up { top: auto; bottom: -6px; }
.ctx-submenu.left { left: auto; right: 100%; }

/* Create-channel modal */
.create-modal { max-width: 480px; }
.ctype { display: flex; gap: 10px; margin-bottom: 16px; }
.ctype-opt { flex: 1; display: flex; align-items: center; gap: 10px; text-align: left; border: 1px solid var(--line); border-radius: 10px; padding: 12px; color: var(--text); }
.ctype-opt.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
.ctype-opt .ct-ic { width: 34px; height: 34px; border-radius: 8px; background: var(--bg-0); display: flex; align-items: center; justify-content: center; font-size: 17px; color: var(--dim); }
.create-modal label, .profile-modal label { display: block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--dim); margin: 12px 0 6px; }
.create-modal input, .create-modal select, .profile-modal input, .profile-modal textarea {
  width: 100%; background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; color: var(--text); font-size: 14px; outline: none; font-family: inherit;
}
.create-modal input:focus, .profile-modal input:focus, .profile-modal textarea:focus { border-color: var(--accent); }
.name-row { display: flex; gap: 8px; }
.emoji-btn { width: 44px; flex-shrink: 0; background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; font-size: 18px; }
.emoji-btn:hover { border-color: var(--accent); }
.emoji-grid { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.emoji-grid .eg { width: 32px; height: 32px; border-radius: 7px; font-size: 17px; }
.emoji-grid .eg:hover { background: var(--hover); }
.emoji-grid .eg.sel { background: color-mix(in srgb, var(--accent) 20%, transparent); }

/* Profile modal */
.profile-modal { max-width: 460px; }
.profile-view { text-align: center; }
.profile-view h2 { font-size: 22px; }
.pf-status { margin-top: 8px; font-size: 14px; }
.pf-bio { margin-top: 12px; color: var(--dim); white-space: pre-wrap; }
.pf-row { margin-top: 10px; font-size: 13px; }
.pf-avatar-row { display: flex; align-items: center; gap: 16px; margin-bottom: 8px; }

/* drag-reorder */
.user-panel .name { cursor: pointer; }
.user-panel .name:hover { text-decoration: underline; }

.toast {
  position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%); z-index: 250;
  background: var(--bg-3); border: 1px solid var(--line); color: var(--text);
  padding: 9px 16px; border-radius: 10px; font-size: 13px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
}
/* Keep logos at their natural aspect ratio inside fixed boxes. */
.voice-join img, .voice-room img { object-fit: contain; }

/* ---- Themed confirm dialog (replaces window.confirm) ---- */
.confirm-overlay {
  position: fixed; inset: 0; z-index: 3000;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: rgba(6, 8, 11, 0.6);
}
.confirm-box {
  width: 100%; max-width: 380px;
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 14px;
  padding: 22px 22px 18px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
}
.confirm-title { font-size: 16px; font-weight: 700; margin-bottom: 8px; }
.confirm-msg { font-size: 14px; line-height: 1.5; color: var(--dim); white-space: pre-wrap; }
.confirm-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }
.confirm-actions button { padding: 9px 18px; border-radius: 8px; font-size: 14px; font-weight: 600; }
.btn-danger { background: #dc3c3e; color: #fff; border-radius: 8px; }
.btn-danger:hover { background: #e4494b; }

/* ---- "View as" preview (owner only) ---- */
.preview-wrap { position: relative; margin-left: auto; }
.preview-eye { padding: 0 12px; }
.preview-eye.on { background: var(--yellow); color: #1a1200; border-color: var(--yellow); }
.preview-scrim { position: fixed; inset: 0; z-index: 3000; }
.preview-menu {
  /* Fixed + portalled to <body>: the bubble bar's overflow-x would otherwise
     clip it, and no z-index can escape an ancestor that clips. */
  position: fixed; z-index: 3001; transform: translateX(-100%);
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px;
  padding: 8px; min-width: 170px; box-shadow: 0 10px 30px rgba(0,0,0,.45);
  display: flex; flex-direction: column; gap: 2px;
}
.preview-menu p { margin: 2px 6px 6px; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; }
.preview-menu button {
  text-align: left; padding: 7px 10px; border-radius: 7px;
  background: transparent; color: var(--text); font-size: 13px; cursor: pointer;
}
.preview-menu button:hover { background: var(--hover); }

.preview-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 16px; font-size: 13px;
  background: var(--yellow); color: #1a1200; font-weight: 600;
}
.preview-bar i { opacity: .8; }
.preview-bar .mini {
  margin-left: auto; background: rgba(0,0,0,.22); color: #1a1200;
  border: none; font-weight: 700;
}
.preview-bar .mini:hover { background: rgba(0,0,0,.34); }
/* Color schemes. Dark is the default (defined in styles.css :root). Each theme
   also defines its own surface gradients: --sidebar-bg (side columns, dark top →
   lighter/bluer bottom), --panel-bg (bottom-left "me" panel, a subtle golden
   circular glow) and --main-bg (flat central chat surface). */

[data-theme='light'] {
  --bg-0: #ffffff; --bg-1: #f3f5f8; --bg-2: #ffffff; --bg-3: #eef1f5;
  --hover: #e7edf3; --active: #dbe4ee; --line: #e1e6ec;
  --text: #1b2330; --dim: #5c6573; --faint: #8b94a1;
  --sidebar-bg: linear-gradient(180deg, #eef1f6 0%, #e6edf8 58%, #d9e7fc 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(240,184,64,0.22), rgba(240,184,64,0.06) 45%, rgba(255,255,255,0) 72%), #eef1f5;
  --main-bg: #ffffff;
  /* Light theme keeps the viewer readable with a medium gray (not near-black). */
  --lb-backdrop: rgba(82, 88, 97, 0.96);
}

[data-theme='gray'] {
  --bg-0: #1f2123; --bg-1: #292c2f; --bg-2: #303336; --bg-3: #393d41;
  --hover: #41464c; --active: #4b5158; --line: #3c4147;
  --text: #e6e8ea; --dim: #a3a8af; --faint: #777d85;
  --sidebar-bg: linear-gradient(180deg, #232527 0%, #29313f 58%, #2e3a52 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(240,184,64,0.16), rgba(240,184,64,0.045) 44%, rgba(0,0,0,0) 72%), #202224;
  --main-bg: #1a1c1e;
}

[data-theme='retro'] {
  --bg-0: #1a1410; --bg-1: #221a13; --bg-2: #2a2017; --bg-3: #34281d;
  --hover: #3d3022; --active: #4a3a28; --line: #3a2d1f;
  --text: #f0d9b5; --dim: #c2a47c; --faint: #8a7050;
  --blue: #e0a13e; --green: #a7c957; --teal: #c98b2e;
  /* Warm variant: top dark amber → lighter toasted amber at the bottom. */
  --sidebar-bg: linear-gradient(180deg, #1c150e 0%, #2a1f14 55%, #3a2c1a 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(224,161,62,0.24), rgba(224,161,62,0.07) 46%, rgba(0,0,0,0) 72%), #1a130c;
  --main-bg: #17110b;
}

[data-theme='sea'] {
  --bg-0: #061a2b; --bg-1: #0b2436; --bg-2: #0e2c42; --bg-3: #123851;
  --hover: #164460; --active: #1c5272; --line: #15415d;
  --text: #e0f3fb; --dim: #8fc1da; --faint: #5e93ad;
  --blue: #22b8c4; --teal: #1fb6a8; --green: #4fd1a6;
  /* Deep navy → brighter teal at the bottom. */
  --sidebar-bg: linear-gradient(180deg, #061a2b 0%, #0b2f48 55%, #114f60 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(240,184,64,0.18), rgba(240,184,64,0.05) 45%, rgba(0,0,0,0) 72%), #07202f;
  --main-bg: #051420;
}

/* Light theme readability: several elements hardcode white text that assumed a
   dark background. On the light theme those backgrounds are pale, so switch the
   text to the theme's dark --text (or accent) to keep them readable. */
[data-theme='light'] .tab.active,
[data-theme='sakura'] .tab.active,
[data-theme='light'] .icon-btn.has-menu.on,
[data-theme='sakura'] .icon-btn.has-menu.on,
[data-theme='light'] .ctx-item.on,
[data-theme='sakura'] .ctx-item.on,
[data-theme='light'] .notif-menu .item.sel, [data-theme='sakura'] .notif-menu .item.sel { color: var(--accent); }
[data-theme='light'] .result .rh b, [data-theme='sakura'] .result .rh b { color: var(--text); }

/* =====================================================================
   Desktop (Electron) custom title bar. Each theme sets --titlebar to the
   same color as the TOP of its --sidebar-bg gradient, so the window chrome
   reads as one continuous surface (like Discord). --titlebar-text drives
   both our label and the native min/max/close symbols (via IPC). */
:root { --titlebar: #0f131b; --titlebar-text: #e7ebf0; }
[data-theme='light'] { --titlebar: #eef1f6; --titlebar-text: #1b2330; }
[data-theme='gray'] { --titlebar: #232527; --titlebar-text: #e6e8ea; }
[data-theme='retro'] { --titlebar: #1c150e; --titlebar-text: #f0d9b5; }
[data-theme='sea'] { --titlebar: #061a2b; --titlebar-text: #e0f3fb; }
[data-theme='midnight'] { --titlebar: #0a0a14; --titlebar-text: #e6e4f5; }
[data-theme='forest'] { --titlebar: #0d1710; --titlebar-text: #e3f0e6; }
[data-theme='sakura'] { --titlebar: #fdeef3; --titlebar-text: #3a2a33; }
[data-theme='sunset'] { --titlebar: #1a0f18; --titlebar-text: #f5e3dc; }
[data-theme='nord'] { --titlebar: #2b303b; --titlebar-text: #eceff4; }
[data-theme='terminal'] { --titlebar: #030503; --titlebar-text: #c8facc; }



/* ---- Six additional themes ---- */

[data-theme='midnight'] {
  --bg-0: #0a0a12; --bg-1: #10101c; --bg-2: #151525; --bg-3: #1c1c30;
  --hover: #24243c; --active: #2d2d4a; --line: #202036;
  --text: #e6e4f5; --dim: #a29ec4; --faint: #6d6a92;
  --accent: #7c5cff; --blue: #7c5cff; --teal: #5cb3ff;
  --sidebar-bg: linear-gradient(180deg, #0a0a14 0%, #131332 58%, #1b1b48 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(124,92,255,0.20), rgba(124,92,255,0.06) 45%, rgba(0,0,0,0) 72%), #0a0a12;
  --main-bg: #07070d;
}

[data-theme='forest'] {
  --bg-0: #0f1a12; --bg-1: #14211a; --bg-2: #182920; --bg-3: #1f3428;
  --hover: #274031; --active: #2f4d3b; --line: #23392c;
  --text: #e3f0e6; --dim: #9fc0a9; --faint: #6b8f77;
  --accent: #4caf6e; --green: #4caf6e; --teal: #3d9c82;
  --sidebar-bg: linear-gradient(180deg, #0d1710 0%, #14291c 55%, #1b3a26 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(76,175,110,0.18), rgba(76,175,110,0.05) 45%, rgba(0,0,0,0) 72%), #0e1811;
  --main-bg: #0b140d;
}

[data-theme='sakura'] {
  --bg-0: #fff7f9; --bg-1: #fbeef2; --bg-2: #ffffff; --bg-3: #f7e4ea;
  --hover: #f3d9e2; --active: #eccbd8; --line: #eed7de;
  --text: #3a2a33; --dim: #8a6a78; --faint: #b394a2;
  --accent: #e0559a;
  --sidebar-bg: linear-gradient(180deg, #fdeef3 0%, #fbdce8 58%, #f7cbdd 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(224,85,154,0.16), rgba(224,85,154,0.05) 45%, rgba(255,255,255,0) 72%), #fbeef2;
  --main-bg: #ffffff;
  --lb-backdrop: rgba(97, 78, 88, 0.96);
}

[data-theme='sunset'] {
  --bg-0: #1a1016; --bg-1: #221520; --bg-2: #2a1a26; --bg-3: #35202e;
  --hover: #422939; --active: #4f3143; --line: #3a2433;
  --text: #f5e3dc; --dim: #c9a49c; --faint: #90716c;
  --accent: #ff7849; --blue: #ff9f68; --teal: #ff6d8a;
  --sidebar-bg: linear-gradient(180deg, #1a0f18 0%, #3a1b33 55%, #5a2440 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(255,120,73,0.20), rgba(255,120,73,0.06) 45%, rgba(0,0,0,0) 72%), #190f15;
  --main-bg: #150c12;
}

[data-theme='nord'] {
  --bg-0: #2e3440; --bg-1: #333a48; --bg-2: #3b4252; --bg-3: #434c5e;
  --hover: #4c566a; --active: #566078; --line: #454e60;
  --text: #eceff4; --dim: #aeb6c5; --faint: #7d8697;
  --accent: #88c0d0; --blue: #81a1c1; --green: #a3be8c; --teal: #8fbcbb;
  --sidebar-bg: linear-gradient(180deg, #2b303b 0%, #333a48 58%, #3b4557 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(136,192,208,0.16), rgba(136,192,208,0.05) 45%, rgba(0,0,0,0) 72%), #2c313d;
  --main-bg: #292e39;
}

[data-theme='terminal'] {
  --bg-0: #050805; --bg-1: #081008; --bg-2: #0a150c; --bg-3: #0e1e10;
  --hover: #132916; --active: #18341c; --line: #122815;
  --text: #c8facc; --dim: #7fbf88; --faint: #4d7d55;
  --accent: #33ff66; --green: #33ff66; --blue: #37d9a0; --teal: #2bd482;
  --sidebar-bg: linear-gradient(180deg, #030503 0%, #07140a 55%, #0a1f0e 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(51,255,102,0.14), rgba(51,255,102,0.04) 45%, rgba(0,0,0,0) 72%), #040704;
  --main-bg: #030503;
}
[data-theme='terminal'] .btn-primary { color: #04140a; }

/* ---- Under the Sea: ambient effects (bubbles + drifting fish) ----
   Rendered by SeaEffects.tsx inside both side columns; invisible on every
   other theme, and fully disabled for reduced-motion users. */
.sea-fx { display: none; }
/* overflow keeps fish/bubbles clipped inside the bars. position: relative is
   desktop-only: on mobile the bars are position:fixed drawers, and this
   higher-specificity rule must NOT override that (it collapsed the whole
   phone layout when it did — the drawers fell back into the grid flow). */
[data-theme='sea'] .sidebar { overflow: hidden; }
@media (min-width: 761px) {
  [data-theme='sea'] .sidebar { position: relative; }
}
[data-theme='sea'] .sea-fx { display: block; position: absolute; inset: 0; pointer-events: none; z-index: 0; }

.sea-bubble {
  position: absolute; bottom: -14px; border-radius: 50%;
  background: rgba(180, 230, 255, 0.14);
  box-shadow: inset 0 0 4px rgba(220, 245, 255, 0.4);
  animation: sea-rise linear infinite;
}
@keyframes sea-rise {
  0%   { transform: translate(0, 0); opacity: 0; }
  8%   { opacity: 0.75; }
  30%  { transform: translate(6px, -30vh); }
  55%  { transform: translate(-5px, -55vh); }
  80%  { transform: translate(7px, -80vh); opacity: 0.45; }
  100% { transform: translate(0, -104vh); opacity: 0; }
}

.sea-fish { position: absolute; left: 0; animation: sea-swim linear infinite; opacity: 0.55; }
.sea-fish img { display: block; animation: sea-bob 5.5s ease-in-out infinite alternate; }
.sea-fish.rev { animation-name: sea-swim-rev; }
.sea-fish.rev img { transform: scaleX(-1); }
@keyframes sea-swim { from { translate: -70px 0; } to { translate: 380px 0; } }
@keyframes sea-swim-rev { from { translate: 380px 0; } to { translate: -70px 0; } }
@keyframes sea-bob { from { margin-top: -5px; rotate: -2deg; } to { margin-top: 6px; rotate: 2.5deg; } }

@media (prefers-reduced-motion: reduce) { .sea-fx { display: none !important; } }

/* ---- Custom theme editor ---- */
.th-fields { display: flex; flex-direction: column; gap: 8px; }
.th-field {
  display: flex; align-items: center; gap: 12px; padding: 8px 10px;
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 10px; cursor: pointer;
}
.th-field input[type='color'] {
  width: 40px; height: 30px; border: none; background: none; padding: 0; cursor: pointer;
}
.th-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.th-label { font-size: 14px; font-weight: 600; }
.th-hint { font-size: 11px; color: var(--faint); }
.th-hex { font-family: var(--mono); font-size: 12px; color: var(--dim); }


/* ---- Theme-change transition: bouncy circle reveal ----
   The new theme's snapshot pops out of the last click point (--vt-x/--vt-y,
   set by theme.ts), overshoots with a springy scale wobble, and settles.
   Only runs when theme.ts calls document.startViewTransition. */
::view-transition-old(root),
::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
::view-transition-old(root) { z-index: 1; }
::view-transition-new(root) {
  z-index: 2;
  animation: kp-theme-pop 640ms cubic-bezier(0.34, 1.4, 0.64, 1) both;
  transform-origin: var(--vt-x, 50%) var(--vt-y, 50%);
}
@keyframes kp-theme-pop {
  0%   { clip-path: circle(0px at var(--vt-x, 50%) var(--vt-y, 50%)); transform: scale(0.96); }
  55%  { clip-path: circle(145% at var(--vt-x, 50%) var(--vt-y, 50%)); transform: scale(1.014); }
  74%  { transform: scale(0.995); }
  88%  { transform: scale(1.004); }
  100% { clip-path: circle(150% at var(--vt-x, 50%) var(--vt-y, 50%)); transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none !important; }
}

/* Studio palette refresh. Keep existing IDs so saved preferences survive. */
[data-theme='sea'] {
  --accent: #53d8cc; --blue: #53d8cc; --dim: #a6cbd8; --faint: #7aa6b8;
  --sidebar-bg: radial-gradient(ellipse at 100% 0%, #166075 0%, transparent 60%), linear-gradient(155deg, #071d30 10%, #10344c 55%, #12605b);
  --main-bg: linear-gradient(155deg, #081a29, #081820 75%, #0b262c);
  --panel-bg: linear-gradient(120deg,#0d3545,#10443f); --titlebar: #0b293c;
}
[data-theme='sea'] .sea-fx { opacity: .55; }
[data-theme='sunset'] {
  --accent: #ffac86; --blue: #ffac86; --dim: #d7b5bd; --faint: #b18a97;
  --sidebar-bg: radial-gradient(ellipse at 100% 100%, #ad593a 0%, transparent 65%), linear-gradient(155deg,#251831,#58304c 58%,#7d3d46);
  --main-bg: linear-gradient(150deg,#1c1420,#21151f 70%,#302027);
  --panel-bg: linear-gradient(110deg,#44243a,#6a393e); --titlebar: #251831;
}
[data-theme='midnight'] { --accent: #b39aff; --blue: #b39aff; --sidebar-bg: radial-gradient(ellipse at 0% 100%,#44327a,transparent 75%),linear-gradient(150deg,#111329,#242248); --main-bg: linear-gradient(150deg,#10101d,#171529); }
[data-theme='forest'] { --accent: #8aceab; --sidebar-bg: radial-gradient(ellipse at 100% 100%,#526844,transparent 75%),linear-gradient(150deg,#13291e,#254539); --main-bg: linear-gradient(150deg,#101c17,#162820); }
[data-theme='retro'] { --accent: #e9bb7c; --sidebar-bg: linear-gradient(145deg,#30271f,#645040 70%,#846549); --panel-bg: #362c23; }
[data-theme='gray'] { --accent: #b7c5d5; --sidebar-bg: linear-gradient(145deg,#252a30,#414954); --panel-bg: #2a3038; }
[data-theme='nord'] { --sidebar-bg: linear-gradient(145deg,#303b50,#495d73 65%,#527d85); --main-bg: linear-gradient(155deg,#292f3b,#303a47); }
[data-theme='light'] { --accent: #365fb0; --blue: #365fb0; --sidebar-bg: linear-gradient(145deg,#edf0fa,#dfebf5 55%,#d4e7e4); --panel-bg: #e5edf3; --faint: #697788; }
[data-theme='sakura'] { --accent: #a83971; --dim: #755263; --faint: #866477; --sidebar-bg: linear-gradient(145deg,#f9e4ed,#e9dff4 58%,#f4d9d3); --panel-bg: #eedee8; }
[data-theme='terminal'] { --accent: #81dfa4; --sidebar-bg: linear-gradient(145deg,#061710,#12382b); --panel-bg: #0c241b; }

[data-theme='aurora'] {
  --bg-0:#101c23; --bg-1:#14252d; --bg-2:#1b303a; --bg-3:#243e47;
  --hover:#2d4b54; --active:#365660; --line:#34515a; --text:#e5f5f3; --dim:#a7c9c8; --faint:#80a7aa;
  --accent:#86ddce; --blue:#86ddce; --teal:#a5b3ed;
  --sidebar-bg: linear-gradient(145deg,#29264c,#225763 55%,#407966);
  --main-bg:linear-gradient(150deg,#111f2a,#152e32); --panel-bg:#233d46; --titlebar:#29264c; --titlebar-text:#e5f5f3;
}
[data-theme='lagoon'] {
  --bg-0:#0c1b2c; --bg-1:#10253a; --bg-2:#173149; --bg-3:#203e56;
  --hover:#294c64; --active:#325972; --line:#2c4b62; --text:#e8f4ff; --dim:#abc5dd; --faint:#83a7c4;
  --accent:#78ccef; --blue:#78ccef; --teal:#73d4bc;
  --sidebar-bg:linear-gradient(140deg,#182b67,#165b78 60%,#258d86);
  --main-bg:linear-gradient(155deg,#0d1b30,#112c3b); --panel-bg:#153e55; --titlebar:#182b67; --titlebar-text:#e8f4ff;
}
[data-theme='ember'] {
  --bg-0:#25191a; --bg-1:#2e2020; --bg-2:#3a2927; --bg-3:#47332e;
  --hover:#563f36; --active:#65493d; --line:#594036; --text:#f7ece2; --dim:#d3b8a4; --faint:#b79781;
  --accent:#efbf7b; --blue:#efbf7b; --teal:#e89f95;
  --sidebar-bg:linear-gradient(145deg,#382330,#744735 58%,#a47b3e);
  --main-bg:linear-gradient(155deg,#241a20,#30211c); --panel-bg:#4a3028; --titlebar:#382330; --titlebar-text:#f7ece2;
}
[data-theme='dusk'] {
  --bg-0:#211b30; --bg-1:#2a233b; --bg-2:#352d48; --bg-3:#423853;
  --hover:#514461; --active:#5d4e70; --line:#53465f; --text:#f3edfb; --dim:#c8b9dc; --faint:#ac98c4;
  --accent:#d8aff4; --blue:#d8aff4; --teal:#9fc9e8;
  --sidebar-bg:linear-gradient(145deg,#313269,#62517e 60%,#986a88);
  --main-bg:linear-gradient(150deg,#211d30,#30243a); --panel-bg:#42334f; --titlebar:#313269; --titlebar-text:#f3edfb;
}
/* Custom tags */
.utag { display: inline-flex; align-items: center; height: 16px; padding: 0 6px; border-radius: 8px; font-size: 10px; font-weight: 700; color: #fff; letter-spacing: .2px; white-space: nowrap; text-shadow: 0 1px 1px rgba(0,0,0,.25); }
.row-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }

/* ---- Theme-aware text colors (audit). ---- */
.result .rh b { color: var(--text); }
.result .rc { color: var(--dim); }
.att-file .fn { color: var(--text); }
[data-theme='light'] .tab.active,
[data-theme='sakura'] .tab.active,
[data-theme='light'] .ctx-item.on,
[data-theme='sakura'] .ctx-item.on,
[data-theme='light'] .notif-menu .item.sel,
[data-theme='sakura'] .notif-menu .item.sel,
[data-theme='light'] .icon-btn.has-menu.on, [data-theme='sakura'] .icon-btn.has-menu.on { color: var(--accent); }

/* Suspended members */
tr.row-suspended td { opacity: .6; }

/* Attachment expiry note */
.att-wrap { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 3px; max-width: 100%; }
.att-expiry { font-size: 11px; color: var(--faint); display: flex; align-items: center; gap: 4px; }

/* ---- Resizable, wider sidebar (drag the right edge: -10% to +20%). ---- */
.app { grid-template-columns: var(--col-l, var(--sidebar-w, 280px)) 1fr; }
.sidebar { position: relative; }
.sidebar-grip { position: absolute; top: 0; right: -3px; width: 7px; height: 100%; cursor: col-resize; z-index: 40; touch-action: none; }
/* The edge stays quiet: a hairline in the theme's own text colour on hover, the accent while dragging.
   Double-click it for the default width. */
.sidebar-grip::after { content: ''; position: absolute; top: 0; bottom: 0; left: 3px; width: 1px; background: transparent; transition: background .12s; }
.sidebar-grip:hover::after { background: color-mix(in srgb, var(--text) 22%, transparent); }
.sidebar-grip.dragging::after { background: var(--accent); }
body.side-resizing, body.side-resizing * { cursor: col-resize !important; -webkit-user-select: none !important; user-select: none !important; }
@media (max-width: 760px) { .sidebar-grip { display: none; } }

/* The sidebar call panel, the stage, the spotlight and the pop-out: voice/call.css. */

/* Drag-to-resize grip at the bottom of the voice dock. */
/* Drag-to-resize grip at the bottom of the voice dock. It sits above the
   floating composer (.composer-dock, z-index 6), which docks to the bottom of
   <main> and would otherwise sit on top of an 8px transparent strip and eat
   every pointer event aimed at it. The pill is always faintly visible so the
   handle is findable without hunting for a dead zone. */
.voice-resize {
  height: 11px; flex: 0 0 11px; cursor: ns-resize; background: transparent; touch-action: none;
  position: relative; z-index: 7;
  display: flex; align-items: center; justify-content: center;
}
.voice-resize::before {
  content: ''; width: 46px; height: 3px; border-radius: 999px;
  background: var(--line); opacity: .8; transition: background .12s ease, width .12s ease, opacity .12s ease;
}
.voice-resize:hover::before { background: var(--blue); width: 78px; opacity: 1; }

/* Minimized voice room: keep the audio alive but render nothing here — the
   sidebar "On Voice" panel is the control surface. */
.voice-dock.mini { position: absolute; width: 0; height: 0; overflow: hidden; pointer-events: none; }
.voice-bg { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Shared drawing overlay + tools + cursors */
.draw-wrap { position: absolute; inset: 0; pointer-events: none; }
.draw-canvas { position: absolute; inset: 0; pointer-events: none; }
.draw-canvas.active { pointer-events: auto; cursor: crosshair; touch-action: none; }
.draw-canvas.erasing { cursor: cell; }
.draw-cursors { position: absolute; inset: 0; pointer-events: none; }
.draw-cursor { position: absolute; transform: translate(-3px, -3px); display: flex; align-items: center; gap: 4px; }
.dc-dot { width: 10px; height: 10px; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0,0,0,.5); flex-shrink: 0; }
.dc-name { color: #fff; font-size: 11px; font-weight: 700; padding: 1px 6px; border-radius: 6px; white-space: nowrap; text-shadow: 0 1px 1px rgba(0,0,0,.45); }
.draw-tools { position: absolute; top: 10px; left: 10px; display: flex; align-items: center; gap: 6px; background: rgba(0,0,0,.55); border-radius: 999px; padding: 5px 8px; pointer-events: auto; }
.draw-tools .dt { background: transparent; color: #fff; font-size: 15px; padding: 2px 6px; border-radius: 6px; cursor: pointer; }
.draw-tools .dt.on { background: var(--accent); }
.draw-tools .dt-color { width: 18px; height: 18px; border-radius: 50%; border: 2px solid rgba(255,255,255,.5); cursor: pointer; }
.draw-tools .dt-color.sel { border-color: #fff; transform: scale(1.12); }
.draw-tools .dt-size { width: 84px; accent-color: var(--accent); cursor: pointer; }
.draw-tools .dt-labelled { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 650; padding: 4px 10px; }
.draw-tools .dt-labelled i { font-size: 13px; }
.draw-tools .dt-done { background: var(--accent); margin-left: 2px; }
.draw-tools .dt-sep { width: 1px; height: 18px; background: rgba(255,255,255,.2); }
.draw-tools .dt:focus-visible, .draw-tools .dt-color:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Persistent voice dock */
.voice-dock.expanded { display: flex; flex-direction: column; max-height: 46vh; min-height: 200px; overflow: hidden; border-bottom: 1px solid var(--line); }
.voice-dock.expanded .voice-room { flex: 1; min-height: 0; }
.voice-cta { display: flex; align-items: center; gap: 14px; padding: 14px 18px; border-bottom: 1px solid var(--line); background: var(--bg-1); }
.voice-cta > img { width: 40px; height: 40px; opacity: .9; }
.voice-cta .vcta-text { display: flex; flex-direction: column; min-width: 0; }
.voice-cta .vcta-text b { font-size: 15px; }
.voice-cta .vcta-text span { color: var(--text); font-size: 14px; }
.voice-cta .btn-primary { margin-left: auto; flex-shrink: 0; }

/* New-DM member picker */
.dm-search { width: 100%; background: var(--bg-3); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; color: var(--text); outline: none; font-size: 14px; }
.dm-search:focus { border-color: var(--accent); }
.dm-pick-list { margin-top: 12px; max-height: 52vh; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.dm-pick-row { display: flex; align-items: center; gap: 10px; padding: 8px; border-radius: 8px; cursor: pointer; }
.dm-pick-row:hover { background: var(--hover); }
.dpr-meta { min-width: 0; }
.dpr-name { font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.dpr-user { font-size: 12px; color: var(--dim); }
.dm-pick-row.picked { background: var(--active); }
.dm-pick-row.picked .dpr-user { color: inherit; opacity: 0.75; }
.dpr-check { margin-left: auto; color: var(--accent); }
.dm-pick-row.picked .dpr-check { color: inherit; }

/* Multi-select "To:" chips (group DMs) */
.dm-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 10px; }
.dm-chips-to { color: var(--dim); font-size: 13px; margin-right: 2px; }
.dm-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--bg-3); border: 1px solid var(--line); border-radius: 999px; padding: 3px 10px; font-size: 13px; }
.dm-chip .x { cursor: pointer; color: var(--dim); display: inline-flex; }
.dm-chip .x:hover { color: var(--text); }

/* GIF (Giphy) picker + emoji board */
.emoji-btn { background: transparent; font-size: 18px; padding: 0 6px; line-height: 1; }
.emoji-backdrop { position: fixed; inset: 0; z-index: 200; }
.emoji-popover { position: absolute; bottom: calc(100% + 10px); right: 8px; z-index: 201; box-shadow: 0 16px 44px rgba(0,0,0,.5); border-radius: 10px; }
.giphy-modal { max-width: 560px; }
.giphy-attr { margin-left: 10px; font-size: 10px; color: var(--faint); letter-spacing: 1.5px; align-self: center; }
.giphy-grid { columns: 3; column-gap: 8px; margin-top: 12px; max-height: 52vh; overflow-y: auto; }
.giphy-cell { display: block; width: 100%; margin: 0 0 8px; padding: 0; border: none; background: var(--bg-1); border-radius: 8px; overflow: hidden; cursor: pointer; break-inside: avoid; }
.giphy-cell img { width: 100%; display: block; }
.giphy-cell:hover { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Profile banner editor */
.pf-banner-preview { height: 100px; border-radius: 10px; background-size: cover; background-position: center; display: flex; align-items: flex-end; justify-content: center; margin-bottom: 32px; }
.banner-tabs { display: flex; align-items: center; gap: 8px; margin: 6px 0 10px; flex-wrap: wrap; }
.seg { border: 1px solid var(--line); background: transparent; color: var(--text); padding: 5px 12px; border-radius: 8px; font-size: 13px; cursor: pointer; }
.seg.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.banner-colors { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.bc-row { display: flex; align-items: center; gap: 10px; }
.bc-label { width: 60px; font-size: 12px; color: var(--dim); }
.crop-stage.banner { width: 320px; height: 120px; border-radius: 10px; }

/* Settings */
.row-actions { white-space: nowrap; }
.row-actions .mini { margin-left: 4px; }
.mini.danger { color: var(--red, #ed4245); border-color: var(--red, #ed4245); }
.tag-picker { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 0; }
.tag-toggle { border: 1px solid var(--line); background: transparent; color: var(--text); border-radius: 12px; padding: 3px 10px; font-size: 12px; cursor: pointer; }
.tag-toggle.on { color: #fff; }
.tag-create { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.swatches { display: flex; gap: 5px; flex-wrap: wrap; }
.swatch { width: 22px; height: 22px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; }
.swatch.sel { border-color: var(--text); }
.tag-list { display: flex; flex-direction: column; gap: 8px; }
.tag-row { display: flex; align-items: center; gap: 10px; }
.audit-list { display: flex; flex-direction: column; gap: 6px; }
.audit-row { display: flex; gap: 10px; align-items: baseline; padding: 6px 8px; border-radius: 6px; background: var(--bg-1); font-size: 13px; }
.audit-when { color: var(--faint); font-size: 11px; white-space: nowrap; min-width: 130px; }
.audit-text { color: var(--dim); }
.audit-text b { color: var(--text); }

/* GIF framing stage (banner-ratio window, drag/zoom the animated GIF). */
.crop-stage.gif-stage { width: 320px; height: 110px; border-radius: 12px; background-color: #000; }

/* ---- Two-factor section (Edit Profile) ---- */
.tfa { background: var(--bg-3); border: 1px solid var(--line); border-radius: 10px; padding: var(--sp-3); }
.tfa-row { display: flex; align-items: center; gap: 10px; }
.tfa-row .muted { flex: 1; font-size: 13px; }
.tfa-on { flex: 1; color: var(--text); font-size: 13px; display: flex; align-items: center; gap: 8px; }
.tfa-on i { color: var(--green, #3ba55d); }  /* the shield carries the colour; the words stay AA */
.tfa-setup { display: flex; gap: 14px; align-items: flex-start; }
.tfa-qr { width: 132px; height: 132px; border-radius: 10px; background: #fff; padding: 6px; flex: none; }
.tfa-steps { display: flex; flex-direction: column; gap: 8px; font-size: 13px; min-width: 0; }
.tfa-steps code { font-family: var(--mono); font-size: 11px; word-break: break-all; background: var(--bg-0); padding: 2px 6px; border-radius: 5px; }
.tfa-confirm { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.tfa-confirm input { width: 110px; font-family: var(--mono); letter-spacing: 3px; }
/* The password step before setup: one label, one 36px row (field and both buttons share an edge),
   one gap; focus and error are the field's own border, drawn inside it (one frame, no ring). */
.tfa-pw { display: flex; flex-direction: column; gap: var(--sp-1); }
.tfa-pw label { font-size: var(--fs-sm); color: var(--dim); }
.tfa-pw .tfa-row { gap: var(--sp-2); align-items: stretch; }
/* (Scoped under the settings modal to outrank its general form-field rule: min-height 42px, 10px 12px.) */
.profile-editor .modal-body .tfa .tfa-pw input, .profile-editor .modal-body .tfa .tfa-pw button { box-sizing: border-box; height: var(--control-md); min-height: 0; margin: 0; }
.profile-editor .modal-body .tfa .tfa-pw button { padding: 0 var(--sp-4); }
.profile-editor .modal-body .tfa .tfa-pw input {
  flex: 1; min-width: 0; padding: 0 var(--sp-3); border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--bg-1); color: var(--text); outline: none; box-shadow: none;
}
.profile-editor .modal-body .tfa .tfa-pw input:focus, .profile-editor .modal-body .tfa .tfa-pw input:focus-visible { outline: none; border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.profile-editor .modal-body .tfa .tfa-pw input[aria-invalid="true"] { border-color: var(--danger); box-shadow: inset 0 0 0 1px var(--danger); }
.tfa-pw-msg { font-size: var(--fs-sm); color: var(--dim); }  /* on the field's edge, with the label */
/* Danger, nudged toward the text colour: AA on the panel in every theme (pure --danger is ~3.8:1 on dark). */
.tfa-pw-msg.tfa-error { color: color-mix(in srgb, var(--danger) 72%, var(--text)); }
.tfa-note { flex: 1; font-size: var(--fs-sm); color: var(--dim); }
/* The Password card's Save row sits as far below the last field as each label does (the settings
   label's 14px top margin, studio.css), so every field-to-next-row gap is the same. */
.tfa-pw .pw-actions { margin-top: 14px; }

/* ---- "New version available" banner (versionCheck.ts). Theme-driven. ---- */
.kp-upd {
  position: fixed;
  /* Clear the mobile status bar / notch — it also swallowed taps before. */
  top: calc(12px + env(safe-area-inset-top, 0px));
  left: 50%; transform: translateX(-50%);
  z-index: 2147483646;
  display: flex; align-items: center; gap: 10px;
  width: max-content; max-width: min(94vw, 480px);
  padding: 8px 10px 8px 16px; border-radius: 16px;
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--line);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
  font-size: 13.5px; font-weight: 500;
  -webkit-app-region: no-drag;
}
/* Electron: the 40px custom titlebar is above everything and draggable —
   sit below it or the banner is clipped and unclickable. */
.kp-upd.desktop { top: 52px; }
.kp-upd-msg { flex: 1 1 auto; min-width: 0; }
.kp-upd .btn-primary { white-space: nowrap; flex: 0 0 auto; }
.kp-upd-x {
  background: transparent; border: none; color: var(--text-dim, var(--text));
  cursor: pointer; font-size: 15px; line-height: 1; padding: 6px 8px; flex: 0 0 auto;
}
.kp-upd-x:hover { color: var(--text); }
/* The owner two-factor reminder (Chat.tsx): a bar under the conversation header, in the flow, so it
   covers nothing. Warning-tinted, on the header's own column inset; the action is a text button, and
   the × puts it away for the session. */
.owner-2fa-bar {
  display: flex; flex-shrink: 0; align-items: center; gap: var(--sp-2);
  min-height: 36px; box-sizing: border-box; padding: var(--sp-1) var(--sp-3) var(--sp-1) var(--sp-4);
  background: color-mix(in srgb, var(--warning) 14%, var(--surface-head));
  border-bottom: 1px solid color-mix(in srgb, var(--warning) 35%, transparent);
  color: var(--text); font-size: var(--fs-sm); line-height: var(--lh-body);
}
.owner-2fa-bar > i { flex: none; color: var(--warning); }
.owner-2fa-text { min-width: 0; }
/* A phone gets the short sentence: two lines at most. */
.owner-2fa-short { display: none; }
@media (max-width: 760px) { .owner-2fa-long { display: none; } .owner-2fa-short { display: inline; } }
.owner-2fa-act {
  flex: none; padding: var(--sp-1) var(--sp-2); border: 0; border-radius: var(--radius-sm); background: none;
  color: var(--text); font: inherit; font-weight: var(--fw-semibold); text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
.owner-2fa-act:hover { background: color-mix(in srgb, var(--warning) 18%, transparent); }
.owner-2fa-x {
  display: grid; flex: none; place-items: center; width: 28px; height: 28px; margin-left: auto;
  border: 0; border-radius: var(--radius-sm); background: none; color: var(--dim); cursor: pointer;
}
.owner-2fa-x:hover { color: var(--text); }


/* ---- Focused-workspace layout (big tools auto-collapse the side panels) ---- */
@media (min-width: 761px) {
  .app.tool-focus { transition: grid-template-columns .18s ease; }
  .app.tool-focus .sidebar { overflow: hidden; }
  .app.tool-left-collapsed { --col-l: 0px; }
}
/* Small edge tabs to collapse/expand each panel while in a tool. */
.tool-edge {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 30;
  width: 20px; height: 48px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-2); color: var(--dim);
  border: 1px solid var(--line); cursor: pointer;
  opacity: 0.65; transition: opacity .12s ease, background .12s ease, color .12s ease;
  font-size: 12px;
}
.tool-edge:hover { opacity: 1; color: var(--text); background: var(--bg-3); }
.tool-edge.left { left: 0; border-left: none; border-radius: 0 8px 8px 0; }
/* Right panel is hidden below 1100px anyway; drop its tab there. Both tabs go
   on phones, where tools already use the full width. */
@media (max-width: 760px) { .tool-edge { display: none; } }
/* ---- Whiteboards ---- */

/* Sidebar entry (pinned above the channel list). */
.wb-nav-btn {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: transparent; color: var(--text); border: none; cursor: pointer;
  padding: 7px 10px; border-radius: 8px; font-size: 14px; font-weight: 600; margin-bottom: 4px;
}
.wb-nav-btn:hover { background: var(--hover); }
.wb-nav-btn.active { background: var(--active, var(--hover)); color: var(--accent); }
.wb-nav-btn .npi { font-size: 15px; }

/* Sidebar: collapsible live list of boards under the Whiteboards entry. */
.wb-nav { margin-bottom: 4px; }
.wb-nav .wb-nav-btn { margin-bottom: 2px; }
.wb-nav-toggle { margin-left: auto; display: grid; place-items: center; width: 22px; height: 22px; border-radius: 5px; opacity: .55; font-size: 11px; }
.wb-nav-toggle:hover { opacity: 1; background: rgba(255,255,255,.1); }
.wb-nav-list { display: flex; flex-direction: column; margin: 0 0 4px 12px; padding-left: 8px; border-left: 1px solid var(--line); }
.wb-nav-note { font-size: 12px; color: var(--text-2); padding: 4px 8px; }
.wb-nav-sub { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text-2); padding: 6px 8px 2px; }
.wb-nav-item { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; background: transparent; border: none; color: var(--text); cursor: pointer; padding: 4px 8px; border-radius: 6px; font-size: 13px; min-width: 0; }
.wb-nav-item:hover { background: var(--hover); }
.wb-item-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-nav-item.is-active .wb-item-name { font-weight: 600; }
.wb-item-count { flex: none; font-size: 11px; color: var(--text-2); background: rgba(255,255,255,.09); border-radius: 9px; padding: 0 6px; line-height: 16px; }
.wb-live { flex: none; width: 7px; height: 7px; border-radius: 50%; background: #10b981; animation: wb-live-pulse 2s infinite; }
@keyframes wb-live-pulse { 0% { box-shadow: 0 0 0 0 rgba(16,185,129,.5); } 70% { box-shadow: 0 0 0 5px rgba(16,185,129,0); } 100% { box-shadow: 0 0 0 0 rgba(16,185,129,0); } }
.wb-item-dot { flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--text-2); opacity: .35; }
/* Tiny board cover in the sidebar list; a green ring marks an active board. */
.wb-item-cover { flex: none; width: 18px; height: 18px; border-radius: 4px; background-size: cover; background-position: center; background-color: var(--bg-2); }
.wb-item-cover.live { box-shadow: 0 0 0 1px var(--bg-1), 0 0 0 2px #10b981; }

/* Launcher */
.wb-launcher { flex: 1; min-height: 0; display: flex; flex-direction: column; background: var(--bg-2); }
.wb-head { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--line); }
.wb-crumbs { display: flex; align-items: center; gap: 4px; flex: 1; min-width: 0; flex-wrap: wrap; }
.wb-crumb-wrap { display: inline-flex; align-items: center; gap: 4px; }
.wb-crumb { background: transparent; border: none; color: var(--text); font-size: 15px; font-weight: 700; cursor: pointer; padding: 2px 4px; border-radius: 6px; }
.wb-crumb:hover { background: var(--hover); }
.wb-sep { color: var(--faint); }
.wb-actions { display: flex; gap: 6px; flex-shrink: 0; }
.btn-ghost.sm, .btn-primary.sm { padding: 6px 12px; font-size: 13px; border-radius: 8px; }

.wb-grid { flex: 1; overflow: auto; padding: 16px; display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); align-content: start; }
.wb-card {
  display: flex; flex-direction: column; padding: 0; border: 1px solid var(--line); border-radius: 12px;
  overflow: hidden; background: var(--bg-1); cursor: pointer; text-align: left; transition: border-color .12s, transform .08s;
}
.wb-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.wb-thumb { height: 110px; display: flex; align-items: center; justify-content: center; font-size: 34px; color: rgba(255,255,255,.55); }
/* Board cover image: cropped to fill the tile, consistent across all boards. */
.wb-cover { background-size: cover; background-position: center; background-repeat: no-repeat; }
.wb-folder-thumb { background: linear-gradient(160deg, #2a2f37, #1b1e24); color: #cdd3dc; }
/* Department-colored folder cards (color set inline via --dept). */
.wb-folder { border-color: color-mix(in srgb, var(--dept, var(--line)) 40%, var(--line)); }
.wb-card-foot { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-top: 1px solid var(--line); }
.wb-name { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wb-dots { color: var(--dim); padding: 0 4px; border-radius: 6px; font-weight: 700; }
.wb-dots:hover { background: var(--hover); color: var(--text); }

.wb-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; color: var(--dim); }

/* Board view */
.wb-board { flex: 1; min-height: 0; display: flex; flex-direction: column; background: var(--bg-2); }
.wb-bar { display: flex; align-items: center; gap: 10px; padding: 8px 14px; border-bottom: 1px solid var(--line); }
.wb-back { background: var(--bg-3); border: none; color: var(--text); width: 32px; height: 32px; border-radius: 8px; cursor: pointer; font-size: 16px; }
.wb-back:hover { background: var(--hover); }
.wb-title { font-weight: 700; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
.wb-title { display: inline-flex; align-items: center; gap: 8px; cursor: text; }
.wb-title-edit-btn { opacity: 0; background: none; border: none; color: var(--dim); cursor: pointer; font-size: 12px; padding: 2px 4px; border-radius: 5px; flex-shrink: 0; }
.wb-title:hover .wb-title-edit-btn { opacity: 0.75; }
.wb-title-edit-btn:hover { opacity: 1; background: rgba(255,255,255,0.1); }
.wb-title-edit { flex: 1; min-width: 0; max-width: 340px; font-weight: 700; font-size: 15px; color: var(--text); background: var(--bg-0); border: 1px solid var(--accent); border-radius: 7px; padding: 5px 9px; outline: none; }
.wb-peers { display: flex; gap: -6px; align-items: center; }
.wb-peer { display: inline-flex; margin-left: -6px; border-radius: 50%; outline: 2px solid var(--accent); outline-offset: 0; background: var(--bg-2); }
.wb-peer:first-child { margin-left: 0; }

.wb-canvas { position: relative; flex: 1; min-height: 0; }
.wb-canvas .excalidraw { height: 100%; }
.wb-canvas > div { height: 100%; }
.wb-loading { display: flex; align-items: center; justify-content: center; height: 100%; color: var(--dim); font-size: 14px; }
.wb-overlay { position: absolute; inset: 0; background: var(--bg-2); }

/* Keep the Excalidraw editor below our app modals/menus. */
.excalidraw { --zIndex-layerUI: 4; }

@media (max-width: 760px) {
  .wb-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); padding: 12px; }
}
/* "Liquid glass" treatments — frosted blur + a bright top rim + soft shadow,
   PLUS true refraction via the #kp-glass SVG displacement filter (defined in
   index.html), the same technique BYD uses. The plain blur is the fallback;
   the url() line adds the warp on browsers that support SVG filters in
   backdrop-filter (Chromium: Chrome/Edge). Firefox/Safari keep just the blur. */

/* =====================================================================
   Global glass buttons — every chrome button across the app is round and
   glassy. Neutral controls get a dark tint; primary actions get the accent
   color; leave/danger get red; the composer Send stays gold (below). Tiny
   inline controls (reactions, message-hover icons, color swatches, context-menu
   rows, the emoji picker) keep their own styles so menus and pickers stay usable. */
.icon-btn, .hamburger, .add,
.wb-nav-btn, .wb-back, .vctrl, .vs-btn, .modal-close, .seg, .tab, .mini,
.theater-fs, .vbtn, .tag-toggle,
.btn-ghost, .btn-primary {
  border-radius: 999px;
  -webkit-backdrop-filter: blur(8px) saturate(1.4);
  backdrop-filter: blur(8px) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-top-color: rgba(255, 255, 255, 0.32);
  box-shadow: 0 5px 16px rgba(0, 0, 0, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.15);
}

/* Neutral dark-tinted glass. */
.icon-btn, .hamburger, .add,
.wb-nav-btn, .wb-back, .vctrl, .vs-btn, .modal-close, .seg, .tab, .mini,
.theater-fs, .vbtn, .tag-toggle, .btn-ghost {
  background: rgba(14, 18, 24, 0.42);
  color: #e8ebf1;
}
.icon-btn:hover, .hamburger:hover, .add:hover, .wb-nav-btn:hover, .wb-back:hover, .vctrl:hover,
.vs-btn:hover, .modal-close:hover, .seg:hover, .tab:hover, .mini:hover, .theater-fs:hover, .vbtn:hover, .tag-toggle:hover, .btn-ghost:hover {
  background: rgba(30, 36, 46, 0.52);
  border-color: rgba(255, 255, 255, 0.24);
  color: #fff;
}

/* Primary / selected = accent glass (driven by --accent). */
.btn-primary, .seg.on, .tab.active, .tag-toggle.on, .vctrl.on, .vs-btn.on {
  background: color-mix(in srgb, var(--accent) 74%, transparent);
  color: #fff;
  border: 1px solid color-mix(in srgb, var(--accent) 55%, #ffffff);
  border-top-color: color-mix(in srgb, var(--accent) 25%, #ffffff);
  box-shadow: 0 6px 20px color-mix(in srgb, var(--accent) 34%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
.btn-primary:hover { background: color-mix(in srgb, var(--accent) 88%, transparent); color: #fff; }

/* Leave / danger = red glass. */
.vctrl.leave, .vs-hang, .mini.danger {
  border-radius: 999px;
  background: rgba(220, 60, 62, 0.72);
  color: #fff;
  border: 1px solid rgba(255, 175, 175, 0.5);
  border-top-color: rgba(255, 222, 222, 0.85);
  box-shadow: 0 5px 16px rgba(120, 20, 20, 0.32), inset 0 1px 0 rgba(255, 255, 255, 0.35);
  -webkit-backdrop-filter: blur(8px) saturate(1.4);
  backdrop-filter: blur(8px) saturate(1.4);
}
.vctrl.leave:hover, .vs-hang:hover, .mini.danger:hover { background: rgba(237, 76, 78, 0.9); }

.btn-primary:disabled, .btn-ghost:disabled { opacity: 0.55; }

/* =====================================================================
   Floating top info bar that OVERLAYS the message list, so the chat frosts
   and refracts through it as it scrolls behind. Fully pill-shaped, like the
   message bar. Absolutely positioned inside .chat-pane (which sits BELOW the
   voice panel in flow, so they never collide). */
.chat-pane { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* Reserve space so content begins below the floating bar. */
.chat-pane .voice-cta { margin-top: 76px; }
/* Header buttons stay subtle (no nested glass). */
@media (max-width: 760px) {
  .chat-pane .voice-cta { margin-top: 72px; }
}

/* Emoji picker opened from a modal (channel-name editor): centered, so it
   escapes the modal's clipped overflow. */
.emoji-popover.center {
  position: fixed; top: 50%; left: 50%; right: auto; bottom: auto;
  transform: translate(-50%, -50%);
}

/* =====================================================================
   Modal / dialog windows (Create channel, New message, Workspace settings,
   etc.) — dark-tinted liquid glass that frosts and refracts the app behind.
   The scrim is softened so the refraction stays visible. */
.overlay {
  background: rgba(8, 9, 11, 0.5);
}
.modal {
  background: rgba(16, 20, 27, 0.62);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  backdrop-filter: blur(20px) saturate(1.5);
  backdrop-filter: url(#kp-glass) blur(16px) saturate(1.5);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-top-color: rgba(255, 255, 255, 0.26);
  box-shadow: 0 28px 70px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.14);
}
/* The wiz footer sits OUTSIDE the padded .modal-body, so its buttons were
   flush against the modal edges. Inset them to match the body's padding. */
.modal .wiz-foot { padding: 0 22px 22px; }

/* Light theme: a bright frosted panel instead of the dark tint. */
[data-theme='light'] .overlay, [data-theme='sakura'] .overlay { background: rgba(18, 22, 30, 0.34); }
[data-theme='light'] .modal, [data-theme='sakura'] .modal {
  background: rgba(255, 255, 255, 0.62);
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-top-color: rgba(255, 255, 255, 0.92);
  box-shadow: 0 28px 70px rgba(0, 0, 0, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.7);
}
/* Loaded LAST so these rules win over styles.css and features.css. */

/* Right-aligned modal footer (fixes the odd Cancel/Save spacing). */
.wiz-foot.end { justify-content: flex-end; gap: 10px; }

/* Mobile nav toggles — hidden on desktop. */
.hamburger { display: none; width: 32px; height: 32px; border-radius: 6px; align-items: center; justify-content: center; font-size: 18px; color: var(--dim); margin-right: 4px; flex-shrink: 0; }
.hamburger:hover { background: var(--hover); color: var(--text); }
.nav-backdrop { display: none; }

/* Emoji board container hugs the picker (emoji-mart renders a fixed width), and
   never overflows a narrow viewport. */
.emoji-popover { width: max-content; max-width: min(360px, calc(100vw - 16px)); }

/* Floating "jump to newest" button (Slack/Discord style). */
.main { position: relative; }

/* The call's layout at every width (its bar's levels, the phone): voice/call.css. */

@media (max-width: 760px) {
  .app { grid-template-columns: 1fr !important; }

  /* Left channel sidebar slides in. The `display:flex !important` overrides the
     old `.sidebar { display:none }` mobile rule in styles.css that was hiding it. */
  .sidebar {
    display: flex !important;
    position: fixed; left: 0; top: 0; bottom: 0; width: 84vw; max-width: 300px; z-index: 120;
    transform: translateX(-102%); transition: transform .2s ease;
  }
  .sidebar.open { transform: translateX(0); box-shadow: 0 0 50px rgba(0,0,0,.6); }

  .hamburger { display: flex; }

  /* Tools (Whiteboards / Currents) are desktop experiences: hidden on phones. */
  .wb-nav, .wb-nav-btn { display: none; }
  .nav-backdrop { display: block; position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 110; }

  .modal { max-width: 100% !important; max-height: 92vh; }
  .att-image, .att-video { max-width: 100%; }

  .giphy-grid { columns: 2; }
  .emoji-popover { left: 8px; right: auto; }

  .voice-cta { flex-wrap: wrap; }
  .voice-cta .btn-primary { margin-left: 0; }
  .voice-dock.expanded { max-height: 52vh; }

  /* Modals share the glass translucency problem on phones — go opaque. */
  .modal { background: var(--bg-2) !important; }
}

/* Avatar crop */
.crop-wrap { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.crop-stage { width: 280px; height: 280px; border-radius: 50%; overflow: hidden; background: #000; cursor: grab; touch-action: none; box-shadow: 0 0 0 4px var(--bg-3); }
.crop-stage:active { cursor: grabbing; }
.crop-stage canvas { display: block; }
.crop-controls { width: 280px; max-width: 100%; }

.theme-dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; }

/* =====================================================================
   Mobile overhaul (phones / installed PWA).
   - No pinch zoom, no whole-page scrolling: only the message list, channel
     list, and member list scroll.
   - The liquid-glass blur doesn't render well on mobile — everything goes
     flat, using the theme's own surface colors.
   - Simpler composer: just [+] [message] [Send]; GIF + attachments live in
     the + menu, and the phone's keyboard provides emoji. */
@media (max-width: 760px) {
  /* --- lock the frame; scroll only inside designated panes --- */
  html, body, #root { height: 100dvh; }
  body { position: fixed; inset: 0; overflow: hidden; overscroll-behavior: none; }
  .app { height: 100dvh; max-width: 100vw; overflow: hidden; }
  .main { max-width: 100vw; overflow-x: hidden; }

  /* --- flat surfaces: kill every blur/glass effect --- */
  * { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }

  /* Top bar: full-width flat bar under the status bar (safe-area aware). */
  .chat-pane .voice-cta { margin-top: calc(60px + env(safe-area-inset-top)); }

  /* Drawers respect the notch and go flat. */
  .sidebar { padding-top: env(safe-area-inset-top); }

  /* Buttons/pills elsewhere: flat theme surfaces instead of glass. */
  .icon-btn, .hamburger, .add,
  .vctrl, .vs-btn, .modal-close, .seg, .tab, .mini, .btn-ghost {
    background: var(--bg-3); border-color: var(--line); box-shadow: none;
    color: var(--text); /* glass's light icon colour would vanish on a light theme's surface */
  }
  .btn-primary { background: var(--accent); border-color: var(--accent); box-shadow: none; }
}
/* Font Awesome icon alignment. Icons are rendered as <i class="fa-solid fa-…">
   inside buttons and inline labels that previously held emoji. These rules keep
   them centered, inheriting the button's color, and sized consistently. */
.fa-solid, .fa-regular, .fa-brands, i.fa, i[class*="fa-"] {
  line-height: 1;
  vertical-align: -0.05em;
}

/* Inline icons that sit before a text label (sidebar buttons, menu rows, voice
   strip, chips) get a touch of trailing space. */
.npi.fa-solid, .vs-chan .fa-solid, .ctx-ic { margin-right: 2px; }

/* Context-menu leading icon: fixed-width so labels line up. */
.ctx-ic { display: inline-block; width: 18px; text-align: center; font-size: 13px; opacity: 0.92; }

/* Channel-list and header type glyphs render at a comfortable size. */
.hash .fa-solid { font-size: 0.82em; }
/* Full-screen image viewer (Discord-style). The photo is centered and scaled to
   fit the window with ~130px of breathing room on every side; the glass control
   pill floats 50px below the picture. The backdrop tints to the active theme
   (--lb-backdrop): dark on dark themes, medium gray on the light theme. */
.lb-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: var(--lb-backdrop, rgba(8, 10, 14, 0.95));
  display: flex; align-items: center; justify-content: center;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  overscroll-behavior: contain; overflow: hidden;
}

/* Shrink-wraps the image so the toolbar can anchor to the picture's edges. */
.lb-stage {
  position: relative;
  display: flex; align-items: center; justify-content: center;
}

/* Scaled to fit inside the viewport minus 130px on each side, aspect preserved
   (never upscaled past natural size). */
.lb-img {
  display: block;
  max-width: calc(100vw - 260px);
  max-height: calc(100vh - 260px);
  width: auto; height: auto;
  object-fit: contain;
  border-radius: 8px;
  box-shadow: 0 18px 70px rgba(0, 0, 0, 0.55);
  transform-origin: center center;
  user-select: none; -webkit-user-drag: none;
  touch-action: none;   /* one finger pans, two pinch: the page must not take the gesture */
  will-change: transform;
}
/* Only click / button / key zooms ease; wheel, drag and pinch follow the pointer directly. */
.lb-img.lb-anim { transition: transform 0.15s ease-out; }
@media (prefers-reduced-motion: reduce) { .lb-img.lb-anim { transition: none; } }

/* Toolbar — a big pill of liquid glass, centered 50px under the photo. */
.lb-bar {
  position: absolute; z-index: 2;
  top: calc(100% + 50px);
  left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px;
  border-radius: 999px;
  background: rgba(14, 18, 24, 0.5);
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: url(#kp-glass) blur(14px) saturate(1.5);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-top-color: rgba(255, 255, 255, 0.36);
  box-shadow: 0 12px 38px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.lb-btn {
  width: 50px; height: 50px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: #e8ebf1; font-size: 20px; background: transparent; cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}
.lb-btn:hover { background: rgba(255, 255, 255, 0.14); color: #fff; }

.lb-more-wrap { position: relative; display: inline-flex; }

/* "More" menu pops up above the ⋯ button. */
.lb-menu {
  position: absolute; bottom: calc(100% + 14px); right: 0; min-width: 196px;
  background: #1c2027; border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 12px;
  padding: 6px; box-shadow: 0 16px 44px rgba(0, 0, 0, 0.55); z-index: 3;
}
.lb-mi {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 10px 11px; border-radius: 8px; color: #e8ebf1; font-size: 13.5px; cursor: pointer;
}
.lb-mi:hover { background: rgba(255, 255, 255, 0.10); color: #fff; }
.lb-mi i { width: 16px; text-align: center; opacity: 0.9; }
.lb-sep { height: 1px; background: rgba(255, 255, 255, 0.1); margin: 5px 4px; }

/* Details card floats above the toolbar. */
.lb-details {
  position: absolute; bottom: calc(100% + 14px); left: 50%; transform: translateX(-50%);
  width: 290px; max-width: 86vw;
  background: #1c2027; border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 12px;
  padding: 11px 13px; box-shadow: 0 16px 44px rgba(0, 0, 0, 0.55); z-index: 3;
}
.lb-d-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; color: #fff; font-size: 13px; }
.lb-d-head button { color: var(--faint, #9aa3af); width: 22px; height: 22px; border-radius: 6px; }
.lb-d-head button:hover { color: #fff; background: rgba(255, 255, 255, 0.1); }
.lb-d-row { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; font-size: 12px; color: #9aa3af; }
.lb-d-row b { color: #e8ebf1; font-weight: 600; max-width: 175px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Tiny confirmation toast (e.g. "Image copied"). */
.lb-toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); z-index: 310;
  background: #1c2027; border: 1px solid rgba(255, 255, 255, 0.14); color: #fff;
  padding: 9px 16px; border-radius: 10px; font-size: 13px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}

/* Tighter on small screens — 130px padding would leave no photo. */
@media (max-width: 760px) {
  .lb-img { max-width: calc(100vw - 32px); max-height: calc(100vh - 180px); }
  .lb-bar { top: calc(100% + 28px); gap: 4px; padding: 7px 9px; }
  .lb-btn { width: 44px; height: 44px; font-size: 18px; }
}
/* Shared studio shell. Colors deliberately use existing preset/custom tokens.
   Own layout here rather than reserving guessed space for floating chrome. */
.app-shell { display: grid; grid-template-columns: 88px minmax(0,1fr); grid-template-rows: auto minmax(0,1fr); overflow: hidden; }
.app-shell > .app { grid-column: 2; grid-row: 2; width: 100%; height: auto; min-height: 0; }
.app-shell > .preview-bar { grid-column: 2; grid-row: 1; }
.studio-rail { grid-column: 1; grid-row: 1 / 3; background: var(--sidebar-bg); border-right: 1px solid var(--line); display: flex; flex-direction: column; align-items: center; overflow-y: auto; padding: 14px 6px; gap: 20px; }
.studio-logo { width: 46px; height: 46px; object-fit: contain; }
.studio-destinations { width: 100%; display: flex; flex-direction: column; gap: 8px; }
.studio-rail .bubble { width: 100%; min-height: 66px; flex-direction: column; gap: 7px; padding: 10px 2px; border-radius: 9px; background: transparent; color: var(--dim); font-size: 11px; }
.studio-rail .bubble > i { font-size: 20px; }
/* Kelpie's mark sits where the other tools' icons do, in the same color. */
.studio-rail .bubble > .bubble-mark { width: 24px; height: 24px; flex: none; }
.studio-rail .bubble:hover { background: var(--hover); color: var(--text); }
.studio-rail .bubble.active { background: color-mix(in srgb, var(--accent) 17%, var(--bg-1)); color: var(--text); box-shadow: inset 3px 0 var(--accent); }
.studio-rail .preview-wrap { margin: 16px 0 0; }
.studio-mobile-header { display: none; }
.studio-switcher { border: 1px solid var(--line); border-radius: 18px 18px 0 0; color: var(--text); background: var(--bg-1); width: min(100%, 520px); max-width: 100%; max-height: 90dvh; padding: 0; margin: auto auto 0; }
.studio-switcher::backdrop { background: #0008; }
.studio-switcher-body { padding: 20px 16px max(20px, env(safe-area-inset-bottom)); }
.studio-switcher header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.studio-switcher h2 { font-size: 20px; }
.studio-switcher p { margin-top: 6px; color: var(--dim); }
.studio-switcher header button { width: 44px; height: 44px; border-radius: 8px; background: var(--bg-3); }
.studio-switcher nav { display: grid; gap: 8px; }
.studio-switcher .bubble { min-height: 52px; width: 100%; border-radius: 9px; background: var(--bg-2); color: var(--text); font-size: 16px; text-align: left; }
.studio-switcher .bubble i { width: 24px; text-align: center; }
.studio-switcher .bubble .bubble-mark { width: 24px; height: 24px; flex: none; }
/* Kelpie's editor fills its tool pane (the library beside it is hidden while a scene is open). */
.kelpie-editor-pane { display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }
.kelpie-editor-pane[hidden] { display: none; }
.kelpie-editor-pane > * { flex: 1; min-height: 0; }
/* The editor needs about 900 px; narrower screens get a note and the way back to the library. */
.kelpie-narrow-note { display: none; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 24px; text-align: center; color: var(--dim); }
.kelpie-narrow-note svg { color: var(--accent); }
.kelpie-narrow-note h2 { color: var(--text); font-size: 18px; }
.kelpie-narrow-note p { max-width: 320px; line-height: 1.45; }
@media (max-width: 760px) {
  .kelpie-editor-pane > .kelpie-narrow-note { display: flex; }
  .kelpie-editor-pane > :not(.kelpie-narrow-note) { display: none; }
}
.studio-switcher .bubble.active { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 15%, var(--bg-2)); }
.studio-switcher .preview-wrap { margin: 0; }
/* Consistent interaction vocabulary, retaining colors from custom themes. */
.app-shell :is(.icon-btn, .hamburger, .wb-back, .btn-primary, .btn-ghost, .mini, .modal-close) { border-radius: 8px; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
.app-shell :is(.icon-btn, .hamburger, .wb-back, .btn-ghost, .mini) { background: var(--bg-2); border-color: var(--line); color: var(--text); }
/* Default focus ring; :where() keeps it overridable by any component's own focus style. */
.app-shell :where(button,[role='button'],input,textarea,select):focus-visible, .studio-switcher :where(button):focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.app-shell button:disabled { cursor: not-allowed; }
/* Solid in-flow chat chrome; growing composer takes its real height. */
.app-shell .chat-pane .voice-cta { margin-top: 0; }
/* Board libraries: readable titles and balanced grids, not fixed tiny tiles. */
.app-shell .wb-bar { min-height: 56px; height: auto; padding: 12px 18px; gap: 10px; flex-wrap: wrap; background: var(--bg-1); }
.app-shell .wb-grid { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 16px; padding: 16px 20px 24px; }
.app-shell .wb-card { border-radius: 10px; box-shadow: none; }
.app-shell .wb-card-foot { min-height: 60px; padding: 10px 12px; }
.app-shell .wb-name { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-height: 1.4; font-size: 14px; }
.kb-view-toggle { display: flex; padding: 3px; gap: 3px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-2); }
.kb-view-toggle button { padding: 6px 10px; border-radius: 5px; color: var(--dim); }
.kb-view-toggle button[aria-pressed='true'] { background: var(--active); color: var(--text); }
.kb-view-list .kb-canvas { overflow-y: auto; }
.kb-view-list .kb-cols { display: flex; flex-direction: column; height: auto; max-width: 960px; margin-inline: auto; }
.kb-view-list .kb-col { width: 100%; flex: none; max-height: none; }
.kb-view-list .kb-cards { overflow: visible; }
.kb-view-list .kb-card { padding: 14px; }
@media (max-width: 1100px) and (min-width: 761px) {
  .app-shell { grid-template-columns: 78px minmax(0,1fr); }
  .app-shell .app { grid-template-columns: minmax(190px, 230px) minmax(0,1fr); }
}
@media (max-width: 760px) {
  .app-shell { grid-template-columns: minmax(0,1fr); grid-template-rows: auto auto minmax(0,1fr); height: 100dvh; }
  .studio-rail { display: none; }
  .studio-mobile-header { display: flex; align-items: center; gap: 10px; grid-row: 1; padding: calc(6px + env(safe-area-inset-top)) 12px 6px; min-width: 0; background: var(--sidebar-bg); border-bottom: 1px solid var(--line); }
  .studio-mobile-header img { width: 32px; height: 32px; object-fit: contain; }
  .studio-workspace { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; color: var(--dim); }
  .studio-mobile-header button { min-height: 44px; padding: 8px 12px; border-radius: 8px; background: var(--bg-2); color: var(--text); display: flex; align-items: center; gap: 10px; font-weight: 600; }
  .app-shell > .app { grid-column: 1; grid-row: 3; height: auto; max-width: 100%; }
  .app-shell > .preview-bar { grid-column: 1; grid-row: 2; }
  .app-shell .wb-bar { padding: 10px 12px; }
  .app-shell .wb-bar button { min-height: 44px; }
  .app-shell .wb-grid { grid-template-columns: repeat(auto-fill, minmax(145px,1fr)); gap: 12px; padding: 12px; }
  .app-shell .wb-nav-btn { display: flex; }
  .app-shell .kbm-overlay { padding: 0; }
  .app-shell .kb-card-modal { width: 100%; max-height: 100dvh; border-radius: 0; }
  .kb-view-auto .kb-canvas { overflow-y: auto; }
  .kb-view-auto .kb-cols { flex-direction: column; height: auto; }
  .kb-view-auto .kb-col { width: 100%; flex: none; max-height: none; }
  .kb-view-auto .kb-cards { overflow: visible; }
  .kb-view-auto .kb-card { padding: 14px; }
  .kb-view-auto .kb-view-toggle button:first-child { background: var(--active); color: var(--text); }
  .kb-view-board .kb-col { width: min(84vw, 320px); flex-basis: min(84vw, 320px); }
}
@media (prefers-reduced-motion: reduce) { .app-shell *, .studio-switcher * { scroll-behavior: auto; } }
.ch-mobile-browse { display: none; }
.app-shell .wb-head { flex-wrap: wrap; gap: 12px; padding: 14px 20px; }
.app-shell .wb-actions { flex-wrap: wrap; }
.app-shell .wb-grid.kb-sec { grid-template-columns: repeat(auto-fill,minmax(190px,230px)); }
.app-shell .kb-cat-head { padding: 20px 20px 0; color: var(--dim); letter-spacing: .04em; }
@media (max-width: 760px) {
  /* Follow the visual viewport, including Safari's focus-induced panning.
     Keep document scroll separate from the message list's own scrolling. */
  .app-shell { position: fixed; left: 0; right: 0; top: var(--studio-viewport-top, 0px); height: var(--studio-viewport-height, 100dvh); }
  .app-shell .wb-head { padding: 12px; }
  .app-shell .wb-actions { width: 100%; }
  .app-shell .wb-actions button { min-height: 44px; }
  .app-shell .wb-grid.kb-sec { grid-template-columns: repeat(2,minmax(0,1fr)); margin-left: 0 !important; }
  .app-shell .kb-cat-head { margin-left: 0 !important; padding: 20px 12px 0; }
  .app-shell .ch-shell { display: flex; flex-direction: column; }
  .app-shell .ch-side { display: none; }
  .app-shell .ch-main { flex: 1; }
  .app-shell .ch-browsing .ch-side { display: flex; flex: 1; border: 0; }
  .app-shell .ch-browsing .ch-main { display: none; }
  .ch-mobile-browse { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 10px 14px; background: var(--bg-2); color: var(--text); border-bottom: 1px solid var(--line); flex-shrink: 0; }
  .app-shell .ch-side-head { flex-wrap: wrap; }
  .app-shell .ch-side-btn { min-width: 40px; height: 44px; }
  .app-shell .ch-toolbar { flex-wrap: nowrap; overflow-x: auto; flex-shrink: 0; }
  .app-shell .ch-tool { min-width: 40px; height: 44px; }
  .app-shell .ch-canvas { padding: 12px 8px 30px; }
  .app-shell .ch-sheet { padding: 20px 16px; min-height: 0; }
  .app-shell .ch-doc-title { font-size: 26px; }
  .app-shell .ntl-root { padding: 12px; }
  .app-shell .ntl-head { flex-wrap: wrap; }
  .app-shell .ntl-bar { flex-wrap: wrap; }
}
.library-controls { display: flex; gap: 12px; align-items: center; padding: 12px 20px; border-bottom: 1px solid var(--line); }
.library-controls label { display: flex; align-items: center; gap: 10px; flex: 1; max-width: 440px; color: var(--dim); }
.library-controls input { width: 100%; min-width: 0; padding: 9px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-1); color: var(--text); font-size: 14px; }
.library-controls > div { display: flex; margin-left: auto; gap: 3px; background: var(--bg-1); border: 1px solid var(--line); border-radius: 8px; padding: 3px; }
.library-controls button { padding: 7px 10px; color: var(--dim); border-radius: 5px; }
.library-controls button[aria-pressed='true'] { background: var(--active); color: var(--text); }
.app-shell .library-list .wb-grid { grid-template-columns: minmax(0,1fr); }
.app-shell .library-list .wb-card { flex-direction: row; align-items: stretch; min-height: 72px; }
.app-shell .library-list .wb-thumb { width: 92px; height: 72px; flex: none; font-size: 28px; border-radius: 9px 0 0 9px; }
.app-shell .library-list .wb-card-foot { flex: 1; min-width: 0; border-top: 0; }
@media (max-width: 760px) {
  .library-controls { padding: 10px 12px; gap: 8px; }
  .library-controls input { font-size: 16px; }
  .library-controls button { min-height: 38px; }
  .kb-board > .wb-bar .kb-board-title { min-width: calc(100% - 110px); }
  .kb-board > .wb-bar .kb-cat-chip { order: 2; }
  .kb-board > .wb-bar .kb-view-toggle { order: 3; margin-left: auto; }
}
.bubble-copy { display: flex; flex-direction: column; gap: 4px; }
.bubble-description { display: none; }
.studio-switcher .bubble-description { display: block; font-size: 12px; font-weight: 400; color: var(--dim); }
.studio-switcher .bubble { white-space: normal; }
@media (max-height: 600px) { .studio-switcher .bubble { min-height: 44px; padding-block: 8px; } .studio-switcher .bubble-description { display: none; } }
.wb-mobile-actions { display: none; }
.wb-title-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 760px) {
  .app-shell .wb-desktop-actions { display: none !important; }
  .wb-mobile-actions { display: flex; flex-shrink: 0; gap: 8px; padding: 6px 12px; background: var(--bg-1); border-bottom: 1px solid var(--line); overflow-x: auto; }
  .app-shell .wb-mobile-actions button { flex-shrink: 0; min-width: 44px; height: 44px !important; background: var(--bg-2) !important; border-color: var(--line) !important; color: var(--text) !important; }
  .app-shell .wb-title-edit-btn { opacity: 1; }
}
.app-shell :is(.add) { background: var(--bg-2); color: var(--text); border: 1px solid var(--line); border-radius: 8px; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
.app-shell .studio-rail .bubble { font-size: 12px; }
/* Preserve the existing voice theater's collapsed-chat behavior. */
.mobile-channel-dialog { color: var(--text); background: var(--bg-1); border: 1px solid var(--line); padding: 0; width: calc(100% - 16px); max-width: 560px; max-height: calc(100dvh - env(safe-area-inset-top) - 16px); margin: calc(env(safe-area-inset-top) + 8px) auto auto; border-radius: 20px; box-shadow: 0 16px 60px #0006; }
.mobile-channel-dialog::backdrop { background: #0005; backdrop-filter: blur(6px); }
.mobile-channel-page { display: flex; flex-direction: column; min-height: 0; max-height: inherit; animation: channel-enter 160ms ease-out; }
.mobile-channel-page header { display: flex; flex-shrink: 0; gap: 12px; align-items: center; padding: 14px; border-bottom: 1px solid var(--line); }
.mobile-channel-page header button { width: 44px; height: 44px; border-radius: 50%; background: var(--bg-2); color: var(--text); flex-shrink: 0; }
.mobile-channel-page h2 { font-size: 18px; margin: 0; overflow-wrap: anywhere; }
.mobile-channel-page p { color: var(--dim); margin: 4px 0 0; font-size: 13px; }
.mobile-channel-actions { padding: 12px; overflow-y: auto; }
.mobile-channel-actions button { display: flex; width: 100%; align-items: center; gap: 14px; min-height: 56px; padding: 12px; background: transparent; color: var(--text); border-radius: 12px; text-align: left; font-size: 16px; }
.mobile-channel-actions button:hover { background: var(--hover); }
.mobile-channel-actions button span { margin-left: auto; color: var(--dim); }
.mobile-channel-actions .mobile-channel-topic { padding: 4px 12px 16px; }
@keyframes channel-enter { from { opacity: 0; translate: 0 10px; } to { opacity: 1; translate: 0 0; } }
@media (max-width: 760px) {
  .app-shell::after { content: ''; position: fixed; top: 0; left: 0; right: 0; height: env(safe-area-inset-top); z-index: 5000; pointer-events: none; background: linear-gradient(var(--bg-1), color-mix(in srgb, var(--bg-1) 80%, transparent)); backdrop-filter: blur(12px); }
  /* The home-indicator inset belongs to the profile panel (its background runs to the screen's edge), not to
     an empty strip of sidebar under it. */
  .app-shell .sidebar { padding-top: env(safe-area-inset-top); }
  .app-shell .sidebar .user-panel { padding-bottom: calc(8px + env(safe-area-inset-bottom)); }
}
@media (prefers-reduced-motion: reduce) { .mobile-channel-page { animation: none; } }
.mobile-channel-dialog button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Interface chrome behaves like controls; working content remains copyable. */
:is(button, [role='button'], nav, .studio-rail, .studio-mobile-header, .sidebar, .wb-bar, .wb-head, .wb-card, .kb-cat-head, .ch-side, .ch-toolbar, .ntl-nav, .ctx-menu, .mobile-channel-page header, .mobile-channel-actions) {
  -webkit-user-select: none;
  user-select: none;
}
:is(input, textarea, [contenteditable='true'], .tiptap, .msg-text, .ch-sheet) {
  -webkit-user-select: text;
  user-select: text;
}
:is(.studio-logo, .studio-mobile-header img, .sidebar img) { -webkit-user-drag: none; }
@media (pointer: coarse) {
  /* Keep normal scrolling, but exclude browser pinch and double-tap zoom.
     Canvas tools retain their own touch-action:none and zoom controls. */
  html { touch-action: pan-x pan-y; }
  :is(button, [role='button'], nav, .sidebar) { -webkit-tap-highlight-color: transparent; }
  :is(input, textarea, select) { font-size: max(16px, 1em); }
}

.theme-picker { width: min(540px, calc(100vw - 24px)); max-height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 24px); margin: auto; border: 1px solid var(--line); border-radius: 20px; padding: 0; color: var(--text); background: var(--bg-1); box-shadow: 0 24px 80px #0007; }
.theme-picker::backdrop { background: #0007; backdrop-filter: blur(8px); }
.theme-picker > header { display: flex; justify-content: space-between; align-items: start; gap: 16px; padding: 24px 24px 16px; }
.theme-picker h2 { margin: 0; font-size: 20px; }
.theme-picker p { color: var(--dim); font-size: 13px; margin: 6px 0 0; }
.theme-picker header button { width: 36px; height: 36px; border-radius: 10px; color: var(--text); background: var(--bg-2); }
.theme-swatches { display: grid; grid-template-columns: repeat(5,minmax(0,1fr)); gap: 16px 12px; padding: 8px 24px 24px; }
.theme-swatches > button { min-width: 0; padding: 0; background: transparent; color: var(--dim); text-align: left; }
.theme-swatch { display: block; height: 60px; border-radius: 12px; background: var(--sidebar-bg); position: relative; border: 1px solid #ffffff25; box-shadow: inset 0 1px 0 #ffffff18; transition: transform 140ms ease; }
.theme-swatches > button:hover .theme-swatch { transform: translateY(-2px); }
.theme-swatches > button[aria-pressed='true'] .theme-swatch { outline: 3px solid var(--accent); outline-offset: 3px; }
.theme-swatches > button[aria-pressed='true'] { color: var(--text); }
.theme-swatch > i { position: absolute; right: -5px; top: -5px; border: 2px solid var(--bg-1); background: var(--accent); color: var(--bg-0); border-radius: 50%; padding: 5px; font-size: 10px; }
.theme-swatch-lines { position: absolute; left: 12px; right: 12px; top: 18px; height: 5px; border-radius: 5px; background: var(--text); opacity: .35; box-shadow: 0 12px 0 color-mix(in srgb,var(--text) 55%,transparent); }
.theme-swatch-label { display: block; font-size: 11px; line-height: 1.4; margin-top: 9px; }
.theme-picker footer { border-top: 1px solid var(--line); padding: 16px 24px 24px; }
.theme-custom { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; padding: 8px 0; color: var(--text); background: transparent; text-align: left; }
.theme-custom > i:last-child { margin-left: auto; font-size: 11px; }
.theme-picker footer label { display: flex; align-items: center; gap: 10px; min-height: 44px; font-size: 13px; }
.theme-picker input { accent-color: var(--accent); }
.theme-picker button:focus-visible { outline: 2px solid var(--accent); outline-offset: 5px; border-radius: 8px; }
@media(max-width:760px) { .theme-swatches { grid-template-columns: repeat(3,minmax(0,1fr)); } .theme-picker { overscroll-behavior: contain; } }
@media(prefers-reduced-motion:reduce) { .theme-swatch { transition: none; } }
.theme-swatch > i { right: 5px; top: 5px; width: 22px; height: 22px; display: grid; place-items: center; padding: 0; }
.theme-picker footer p { display: flex; align-items: center; gap: 8px; }

/* One studio-wide color field. Panels tint that field, never restart it. */
:root:not([data-theme='custom']) .app-shell {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--bg-0) 82%, var(--accent)) 0%,
    var(--bg-0) 48%,
    color-mix(in srgb, var(--bg-0) 87%, var(--teal)) 100%);
  --sidebar-bg: color-mix(in srgb, var(--bg-0) 22%, transparent);
  --main-bg: transparent;
  --panel-bg: color-mix(in srgb, var(--bg-2) 42%, transparent);
  --field-opacity: 70%; /* chat surfaces (composer) let the colour field show through */
}
:root:not([data-theme='custom']) .app-shell :is(.main, .chat-pane, .tab-pane) { background: transparent; }
:root:not([data-theme='custom']) .app-shell :is(.wb-bar, .wb-head) { background: color-mix(in srgb, var(--bg-0) 24%, transparent); }
:root:not([data-theme='custom']) .app-shell .sea-fx { opacity: .2; }
@media (max-width: 1100px) {
  /* Overlays need an opaque surface so underlying messages do not bleed through. */
}
@media (max-width: 760px) {
  :root:not([data-theme='custom']) .app-shell .sidebar.open { background: var(--bg-1); }
}
:root:not([data-theme='custom']) .app-shell :is(.wb-launcher, .ch-shell, .ch-main, .ntl-root, .dd-root) { background: transparent; }
:root:not([data-theme='custom']) .app-shell .ch-side { background: var(--sidebar-bg); }
.theme-swatch { background: linear-gradient(135deg, color-mix(in srgb,var(--bg-0) 82%,var(--accent)), var(--bg-0) 48%, color-mix(in srgb,var(--bg-0) 87%,var(--teal))); }
.app-shell .att-wrap { max-width: 100%; }

/* Theme reveal: twice the original 640ms, with a calm expanding edge. */
::view-transition-new(root) {
  animation: kp-theme-unfold 1280ms linear both;
  transform: none;
}
@keyframes kp-theme-unfold {
  0% { clip-path: var(--vt-shape-0); }
  25% { clip-path: var(--vt-shape-1); }
  50% { clip-path: var(--vt-shape-2); }
  75% { clip-path: var(--vt-shape-3); }
  100% { clip-path: var(--vt-shape-4); }
}
.theme-celebration { position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: transparent; overflow: hidden; pointer-events: none; z-index: 10000; }
.theme-celebration::backdrop { background: transparent; pointer-events: none; }
.theme-shine { position: absolute; inset: 0; background: linear-gradient(115deg,transparent 40%,color-mix(in srgb,var(--accent) 14%,transparent) 48%,#ffffff14 50%,transparent 58%); animation: kp-theme-shine 780ms ease-out both; }
.theme-spark { position: absolute; left: var(--spark-x); top: var(--spark-y); width: var(--spark-size,6px); height: var(--spark-size,6px); filter: drop-shadow(0 0 2px var(--accent)); background: color-mix(in srgb,var(--accent) 45%,white); clip-path: polygon(50% 0,62% 38%,100% 50%,62% 62%,50% 100%,38% 62%,0 50%,38% 38%); animation: kp-theme-spark 820ms cubic-bezier(.15,.7,.3,1) both; }
@keyframes kp-theme-shine { 0% { opacity: 0; transform: translateX(-65%); } 25% { opacity: 1; } 100% { opacity: 0; transform: translateX(65%); } }
@keyframes kp-theme-spark { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.3); } 18% { opacity: 1; transform: translate(calc(-50% + var(--dx) * .35),calc(-50% + var(--dy) * .35)) scale(1) rotate(15deg); } 45% { opacity: 1; transform: translate(calc(-50% + var(--dx) * .65),calc(-50% + var(--dy) * .65)) scale(.85) rotate(25deg); } 100% { opacity: 0; transform: translate(calc(-50% + var(--dx)),calc(-50% + var(--dy))) scale(.2) rotate(35deg); } }
@media(prefers-reduced-motion:reduce) {
  ::view-transition-new(root) { animation: none !important; }
  .theme-celebration { display: none !important; }
}

.progressive-image { position: relative; overflow: hidden; border-radius: 8px; background: var(--bg-2); flex-shrink: 0; }
.progressive-image .progressive-preview, .progressive-image .progressive-full { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; object-fit: contain; }
.progressive-preview { filter: blur(18px); transform: scale(1.08); opacity: .8; pointer-events: none; transition: opacity 240ms ease; }
.progressive-full { opacity: 0; transition: opacity 240ms ease; }
.progressive-image.ready .progressive-full { opacity: 1; }
.progressive-image.ready .progressive-preview { opacity: 0; }
.progressive-retry { position: absolute; inset: auto 8px 8px; min-height: 44px; border-radius: 8px; color: var(--text); background: var(--bg-1); border: 1px solid var(--line); padding: 8px; }
@media(prefers-reduced-motion:reduce) { .progressive-preview, .progressive-full { transition: none; } }

.theme-applied { position: fixed; z-index: 10001; bottom: max(24px,env(safe-area-inset-bottom)); left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 12px; width: max-content; max-width: calc(100vw - 24px); padding: 8px 10px 8px 16px; border: 1px solid var(--line); border-radius: 24px; background: var(--bg-1); color: var(--text); box-shadow: 0 8px 28px #0004; font-size: 13px; }
.theme-applied button { border: 0; background: transparent; color: var(--accent); padding: 8px; border-radius: 16px; font: inherit; font-weight: 600; cursor: pointer; }
.theme-applied button:hover { background: var(--hover); }
.theme-applied button:focus-visible { outline: 2px solid var(--accent); }
@media (pointer:coarse) { .theme-applied button { min-height: 44px; } }

/* Desktop: one outer frame, with the workspace nested inside it. The native
   title bar already uses --titlebar, including user-defined custom themes. */
@media (min-width: 761px) {
  .app-shell .studio-rail { background: var(--titlebar); border-right: 0; --dim: color-mix(in srgb,var(--titlebar-text) 75%,var(--titlebar)); }
  .app-shell > .app { border-top-left-radius: 16px; overflow: clip; box-shadow: -1px -1px 0 color-mix(in srgb,var(--line) 65%,transparent), -4px 0 14px #0000000a; }
  .app-shell, :root:not([data-theme='custom']) .app-shell { background: var(--titlebar); }
  :root:not([data-theme='custom']) .app-shell > .app {
    background: linear-gradient(135deg,color-mix(in srgb,var(--bg-0) 82%,var(--accent)),var(--bg-0) 48%,color-mix(in srgb,var(--bg-0) 87%,var(--teal)));
  }
  .app-shell .sidebar { border-right-color: color-mix(in srgb,var(--line) 65%,transparent); }
}

/* The viewport controller owns anchoring, avoiding double browser compensation. */
.unread-nav { width: min(520px,calc(100vw - 24px)); max-height: min(700px,85dvh); margin: auto; padding: 20px; border: 1px solid var(--line); border-radius: 16px; background: var(--bg-1); color: var(--text); }
.unread-nav::backdrop { background: #0008; }
.unread-nav header, .unread-nav nav { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.unread-nav header h2 { flex: 1; }
.unread-nav button { min-height: 40px; border-radius: 8px; padding: 8px 12px; color: var(--text); background: var(--bg-2); }
.unread-nav nav button[aria-pressed=true] { box-shadow: inset 0 -2px var(--accent); background: var(--active); }
.unread-hint { color: var(--dim); font-size: 13px; margin-bottom: 16px; }
.unread-list { display: grid; gap: 8px; }
.unread-list button { display: grid; grid-template-columns: minmax(0,1fr) auto; text-align: left; gap: 6px; }
.unread-list strong { overflow-wrap: anywhere; }
.unread-list span { grid-row: 2; color: var(--dim); font-size: 12px; }
.unread-list i { grid-column: 2; grid-row: 1 / 3; align-self: center; }
@media(max-width:760px) { .unread-nav button { min-height: 44px; } }

/* Messaging tools share the theme surfaces; content stays selectable. */
.message-search,.thread-panel { color: var(--text); background: var(--bg-1); border: 1px solid var(--line); border-radius: 18px; padding: 0; margin: auto; width: min(760px,calc(100vw - 40px)); max-height: min(860px,calc(100dvh - 64px)); box-shadow: 0 24px 80px #0006; }
.message-search[open],.thread-panel[open] { display: flex; flex-direction: column; animation: messaging-enter 160ms ease-out; }
.message-search::backdrop,.thread-panel::backdrop { background: #0007; backdrop-filter: blur(4px); }
.message-search header,.thread-panel header { flex-shrink: 0; display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 20px 24px; border-bottom: 1px solid var(--line); }
.message-search h2,.thread-panel h2 { font-size: 20px; margin: 0 0 6px; }
.message-search header p,.thread-panel header p { color: var(--dim); font-size: 13px; margin: 0; }
.message-search button,.thread-panel button { color: var(--text); background: var(--bg-2); border: 1px solid var(--line); border-radius: 8px; min-height: 36px; padding: 8px 12px; cursor: pointer; }
.message-search button:hover,.thread-panel button:hover { background: var(--hover); }
.message-search button:disabled,.thread-panel button:disabled { opacity: .55; cursor: default; }
.message-search :focus-visible,.thread-panel :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.message-search form { padding: 18px 24px 12px; }
.search-query { display: flex; gap: 8px; }
.search-query input { min-width: 0; flex: 1; }
.message-search input,.message-search select { color: var(--text); background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; padding: 10px; width: 100%; min-width: 0; font: inherit; }
.search-filters { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 10px; margin-top: 14px; }
.search-filters label { display: grid; gap: 6px; color: var(--dim); font-size: 12px; min-width: 0; }
.search-feedback { padding: 0 24px 12px; font-size: 12px; color: var(--dim); }
.search-results,.thread-scroll { min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 0 24px 20px; }
.message-search .search-result { display: block; width: 100%; text-align: left; margin: 0 0 10px; padding: 16px; background: var(--bg-2); }
.search-result-meta { display: flex; flex-wrap: wrap; gap: 4px 10px; color: var(--dim); font-size: 12px; }
.search-result-meta strong { color: var(--text); }
.search-result-meta time { margin-left: auto; }
.search-result-text { display: block; margin: 10px 0; line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 9em; overflow: auto; user-select: text; }
.search-result-text mark { color: var(--text); background: color-mix(in srgb,var(--accent) 25%,transparent); border-radius: 3px; }
.search-result-action { color: var(--accent); font-size: 12px; }
.messaging-error { color: var(--text); border-left: 3px solid var(--accent); background: var(--bg-2); padding: 12px; margin: 0 24px 12px; font-size: 13px; line-height: 1.5; }
.message-empty { padding: 24px 0; color: var(--dim); line-height: 1.6; }
.thread-panel { width: min(620px,calc(100vw - 40px)); }
.thread-scroll { padding-top: 20px; }
.thread-file { display: block; color: var(--accent); overflow-wrap: anywhere; padding: 8px 0; }
.thread-panel .thread-context-link { background: transparent; color: var(--dim); padding: 6px 0; border: 0; font-size: 12px; }
.thread-divider { color: var(--dim); font-size: 12px; padding-top: 20px; }
.thread-panel footer { flex-shrink: 0; display: flex; align-items: center; justify-content: space-between; gap: 16px; border-top: 1px solid var(--line); padding: 16px 24px; }
.thread-panel footer span { font-size: 12px; color: var(--dim); max-width: 220px; }
.message-search .btn-primary,.thread-panel .btn-primary { color: var(--text); background: var(--active); border-color: var(--accent); }
@keyframes messaging-enter { from { opacity: 0; transform: translateY(6px) scale(.995); } to { opacity: 1; transform: none; } }
@media(max-width:760px) {
 .message-search,.thread-panel { width: 100%; max-width: 100%; height: var(--studio-viewport-height,100dvh); max-height: var(--studio-viewport-height,100dvh); margin: 0; border-radius: 0; border: 0; position: fixed; top: var(--studio-viewport-top,0px); }
 .message-search header,.thread-panel header { padding: calc(16px + env(safe-area-inset-top,0px)) 16px 16px; }
 .message-search form { padding: 12px 16px; }
 .search-filters { grid-template-columns: 1fr 1fr; }
 .message-search input,.message-search select { font-size: 16px; }
 .message-search button,.thread-panel button { min-height: 44px; }
 .search-results,.thread-scroll { padding-left: 16px; padding-right: 16px; padding-bottom: calc(20px + env(safe-area-inset-bottom,0px)); }
 .thread-panel footer { padding: 12px 16px calc(12px + env(safe-area-inset-bottom,0px)); }
 .thread-panel footer span { max-width: 130px; }
}
@media(prefers-reduced-motion:reduce) { .message-search[open],.thread-panel[open] { animation: none; } }

.thread-header-actions { display: flex; gap: 6px; }

/* Catch up: a brief, local finish rather than a screen-wide interruption. */
.unread-nav { isolation: isolate; overflow: hidden; }
.unread-nav .unread-list { max-height: min(450px,55dvh); overflow-y: auto; }
.unread-nav::backdrop { animation: catch-up-backdrop 180ms ease-out; }
.unread-nav.exiting::backdrop { animation: catch-up-backdrop-out 130ms ease-in forwards; }
.catch-up-empty { min-height: 240px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 28px 18px; }
.catch-up-check { display: grid; place-items: center; width: 54px; height: 54px; margin-bottom: 18px; border-radius: 50%; background: color-mix(in srgb,var(--accent) 14%,transparent); border: 1px solid color-mix(in srgb,var(--accent) 35%,transparent); color: var(--accent); font-size: 24px; }
.catch-up-empty h3 { margin: 0 0 9px; color: var(--text); font-size: 23px; letter-spacing: -.4px; }
.catch-up-empty p { margin: 0; color: var(--dim); font-size: 13px; line-height: 1.6; }
.catch-up-check { animation: catch-up-message 300ms cubic-bezier(.22,1,.36,1) both; }
.catch-up-empty h3,.catch-up-empty p { animation: catch-up-message 360ms 50ms cubic-bezier(.22,1,.36,1) both; }
.catch-up-finish { position: absolute; inset: 0; overflow: hidden; border-radius: inherit; pointer-events: none; z-index: 2; }
.catch-up-sheen { position: absolute; inset: -50%; background: linear-gradient(115deg,transparent 43%,color-mix(in srgb,var(--accent) 15%,transparent) 49%,#ffffff20 50%,transparent 57%); animation: catch-up-sheen 750ms ease-out both; }
.catch-up-spark { position: absolute; width: 4px; height: 4px; background: var(--accent); border-radius: 1px; opacity: 0; animation: catch-up-spark 650ms ease-out both; }
@keyframes catch-up-message { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
@keyframes catch-up-sheen { from { opacity: 0; transform: translateX(-45%); } 20% { opacity: 1; } to { opacity: 0; transform: translateX(45%); } }
@keyframes catch-up-spark { 0% { opacity: 0; transform: scale(.3) rotate(0); } 25% { opacity: .8; } 100% { opacity: 0; transform: translate(var(--dx),var(--dy)) scale(.4) rotate(100deg); } }
@keyframes catch-up-backdrop { from { background: #0000; } to { background: #0008; } }
@keyframes catch-up-backdrop-out { from { background: #0008; } to { background: #0000; } }
@media(prefers-reduced-motion:reduce) { .unread-nav::backdrop,.unread-nav.exiting::backdrop,.celebrating .catch-up-check,.catch-up-empty h3,.catch-up-empty p { animation: none; } .catch-up-finish { display: none; } }

/* Readable hierarchy and stable spacing independent of message actions. */
.attachments.image-gallery { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); width: min(100%,660px); gap: 8px; align-items: start; }
.image-gallery > .att-wrap { width: 100%; min-width: 0; }
.image-gallery > :not([data-kind=image]) { grid-column: 1 / -1; }
.image-gallery .progressive-image { width: 100% !important; height: auto !important; aspect-ratio: 4 / 3 !important; max-width: 100%; border: 1px solid var(--line); background: var(--bg-0); border-radius: 10px; }
.image-gallery .progressive-full { object-fit: contain; }
.image-gallery .att-expiry { font-size: 10px; }
.file-attachment { width: min(100%,480px); }
.file-attachment .att-file { width: 100%; max-width: 100%; text-align: left; }
.file-description { display: flex; flex-direction: column; gap: 5px; min-width: 0; flex: 1; }
.file-attachment .fn { white-space: normal; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.file-download { display: flex; flex-direction: column; align-items: center; gap: 5px; color: var(--dim); font-size: 10px; flex-shrink: 0; }
.file-download > i { font-size: 15px; }
.file-error { color: var(--dim); font-size: 12px; line-height: 1.5; margin: 8px 0 0; }
.attachment-unavailable { display: flex; align-items: center; gap: 12px; padding: 14px; border: 1px dashed var(--line); border-radius: 10px; color: var(--dim); max-width: 480px; }
.attachment-unavailable div { min-width: 0; }
.attachment-unavailable strong { display: block; color: var(--text); overflow-wrap: anywhere; margin-bottom: 5px; font-size: 13px; }
.attachment-unavailable span { font-size: 12px; line-height: 1.5; }

/* Message, action-sheet and thread interaction polish. Theme surfaces remain semantic. */
.accessible-menu { overflow-y:auto; overscroll-behavior:contain; box-sizing:border-box; animation:action-enter 150ms cubic-bezier(.2,.8,.2,1); background:var(--bg-1); color:var(--text); }
.accessible-menu.exiting { animation:action-exit 120ms ease-in forwards; pointer-events:none; }
.accessible-menu .ctx-item { width:100%; min-height:38px; border:0; background:transparent; color:var(--text); text-align:left; font:inherit; font-size:14px; }
.accessible-menu .ctx-item:hover,.accessible-menu .ctx-item:focus-visible { background:var(--active); color:var(--text); }
.accessible-menu .ctx-item.danger, .accessible-menu .ctx-item.danger:is(:hover,:focus-visible) { color:var(--danger); }
.accessible-menu .ctx-item.danger .ci { color:var(--red,#dc4545); }
.accessible-menu .ctx-item:disabled { opacity:.5; cursor:default; }
.accessible-menu :focus-visible { outline:2px solid var(--text); outline-offset:-3px; }
.ctx-scrim { position:fixed; inset:0; z-index:4000; background:#0007; backdrop-filter:blur(3px); touch-action:none; }
.mobile-action-sheet { border-radius:18px; padding:8px 8px calc(8px + env(safe-area-inset-bottom,0px)); box-shadow:0 12px 60px #0006; }
.mobile-action-sheet .ctx-item { min-height:48px; padding:10px 14px; font-size:15px; }
.action-sheet-heading { display:flex; align-items:center; justify-content:space-between; padding:0 6px 6px 14px; font-size:13px; font-weight:600; }
.action-sheet-heading button { min-width:44px; min-height:44px; background:transparent; border:0; color:var(--text); }
.thread-divider,.thread-panel header p,.thread-panel footer span { color:var(--text); opacity:.78; }
.thread-panel .thread-context-link { color:var(--text); opacity:.85; }
.thread-panel .thread-new-replies { position:absolute; bottom:90px; left:50%; transform:translateX(-50%); background:var(--bg-2); box-shadow:0 4px 20px #0004; }
.thread-panel { position:fixed; }
.thread-scroll { scrollbar-gutter:stable; }
.thread-panel .file-attachment { margin-top:8px; }
@keyframes action-enter { from {opacity:0;transform:translateY(8px) scale(.985)} to {opacity:1;transform:none} }
@keyframes action-exit { to {opacity:0;transform:translateY(6px) scale(.99)} }
@media(max-width:700px) { .thread-panel footer { gap:8px; } .thread-panel footer span { max-width:120px; } }
@media(prefers-reduced-motion:reduce) { .accessible-menu,.accessible-menu.exiting { animation:none; } }

/* Completion is a non-modal status toast; unread conversations retain their navigator. */
.caught-up-toast { position: fixed; z-index: 10000; left: 50%; bottom: max(24px, env(safe-area-inset-bottom)); translate: -50% 0; display: flex; align-items: center; gap: 12px; width: max-content; max-width: calc(100vw - 24px); padding: 10px 10px 10px 14px; border: 1px solid var(--line); border-radius: 16px; color: var(--text); background: var(--bg-1); box-shadow: 0 8px 32px #0003; isolation: isolate; overflow: hidden; animation: caught-up-toast-in 220ms cubic-bezier(.22,1,.36,1) both, caught-up-toast-settle 300ms 220ms ease-in-out; }
.caught-up-toast .catch-up-check { flex: none; width: 32px; height: 32px; font-size: 15px; margin: 0; }
.caught-up-toast [role=status] { font-size: 14px; font-weight: 600; }
.caught-up-toast button { flex: none; width: 36px; height: 36px; border-radius: 10px; background: transparent; color: var(--dim); }
.caught-up-toast button:hover,.caught-up-toast button:focus-visible { background: var(--active); color: var(--text); }
.caught-up-toast .catch-up-sheen { animation-delay: 220ms; }
.caught-up-toast.exiting { animation: caught-up-toast-out 160ms ease-in forwards; pointer-events: none; }
@keyframes caught-up-toast-in { from { opacity: 0; transform: translateY(12px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes caught-up-toast-settle { 0%,100% { transform: scale(1); } 35% { transform: scale(.99); } 65% { transform: scale(1.015); } }
@keyframes caught-up-toast-out { to { opacity: 0; transform: translateY(8px) scale(.97); } }
@media(max-width:760px) { .caught-up-toast { bottom: auto; top: calc(env(safe-area-inset-top) + 12px); } .caught-up-toast button { width: 44px; height: 44px; } }
@media(prefers-reduced-motion:reduce) { .caught-up-toast,.caught-up-toast.exiting,.caught-up-toast .catch-up-check { animation: none; } }

/* A full-size, solid presence mark with a clean cutout instead of a cramped ring. */
.name-style-editor { width: min(850px,calc(100vw - 24px)); max-height: calc(100dvh - 32px); padding:0; margin:auto; border:1px solid var(--line); border-radius:18px; background:var(--bg-1); color:var(--text); overflow:auto; }
.name-style-editor::backdrop { background:#0008; backdrop-filter:blur(4px); }
.name-style-editor header { display:flex; align-items:center; justify-content:space-between; padding:22px 24px; border-bottom:1px solid var(--line); }
.name-style-editor h2 { margin:0; font-size:21px; }.name-style-editor header p { color:var(--dim); margin:6px 0 0; font-size:13px; }
.name-style-editor button { min-height:40px; padding:8px 12px; border:1px solid var(--line); border-radius:9px; color:var(--text); background:var(--bg-2); }
.name-style-editor button[aria-pressed=true] { border-color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent); }
.name-style-editor button:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.name-style-layout { display:grid; grid-template-columns:1.15fr 1fr; }
.name-style-controls { padding:24px; }.name-style-controls fieldset { margin:0 0 22px; padding:0; border:0; }.name-style-controls legend { margin-bottom:10px; font-weight:650; }
.name-font-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px; }.name-font-grid button { display:flex; flex-direction:column; align-items:center; justify-content:center; min-height:76px; gap:6px; }.name-font-grid .display-name { font-size:23px; }.name-font-grid small { font-size:11px; color:var(--dim); }
.name-effect-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px; }.name-effect-grid button { padding:8px 5px; }
.name-toggle { display:flex; align-items:center; gap:9px; min-height:32px; font-size:13px; }.name-toggle input { accent-color:var(--accent); width:16px; height:16px; }
.name-palettes { display:flex; gap:10px; margin:10px 0; }.name-palettes button { width:44px; height:40px; }.name-color-inputs { display:flex; gap:18px; }.name-color-inputs label { display:flex; align-items:center; gap:8px; font-size:12px; }.name-color-inputs input { width:34px; height:30px; padding:0; border:0; }
.name-style-note { font-size:12px; color:var(--dim); line-height:1.6; }
.name-style-preview { padding:24px; background:var(--bg-0); border-left:1px solid var(--line); display:flex; flex-direction:column; justify-content:center; gap:16px; min-width:0; color:var(--text); }
.name-style-preview[data-preview-theme=light] { --bg-0:#f5f6f8; --bg-1:#fff; --bg-2:#e9ecf1; --text:#202532; --dim:#596170; --line:#ccd2dc; }
.name-style-preview[data-preview-theme=dark] { --bg-0:#10141c; --bg-1:#1b2130; --bg-2:#252d3e; --text:#f0f3fa; --dim:#a8b2c8; --line:#384153; }
.name-preview-tabs { display:flex; gap:6px; }.name-preview-tabs button { font-size:11px; text-transform:capitalize; flex:1; }
.name-preview-profile { border:1px solid var(--line); border-radius:14px; overflow:hidden; padding:0 18px 20px; background:var(--bg-1); }.name-preview-banner { height:65px; margin:0 -18px 0; background:var(--active); }.name-preview-profile .avatar { margin-top:-36px; margin-bottom:10px; box-shadow:0 0 0 4px var(--bg-1); }.name-preview-profile strong { display:block; font-size:22px; }.name-preview-profile small { color:var(--dim); }
.name-preview-message,.name-preview-member { display:flex; align-items:center; gap:12px; border:1px solid var(--line); background:var(--bg-1); border-radius:12px; padding:14px; min-width:0; }.name-preview-message>div { min-width:0; }.name-preview-message small { font-size:10px; color:var(--dim); }.name-preview-message p { margin:6px 0 0; font-size:12px; }.name-style-preview .avatar { flex-shrink:0; }
.name-style-editor footer { display:flex; align-items:center; gap:10px; padding:16px 24px; border-top:1px solid var(--line); flex-wrap:wrap; }.name-style-editor footer>div { flex:1; }.name-style-editor footer [role=alert] { width:100%; color:var(--text); margin:0; }.name-style-editor button:disabled { opacity:.5; cursor:wait; }.name-style-editor footer .btn-primary { background:var(--accent); color:var(--bg-0); }
@media(max-width:620px) { .name-style-layout { grid-template-columns:1fr; }.name-style-preview { border-left:0; border-top:1px solid var(--line); }.name-style-controls,.name-style-preview { padding:18px; }.name-style-editor button { min-height:44px; }.name-style-editor header { padding:16px; }.name-style-editor footer { padding:14px; }.name-style-editor { max-height:calc(100dvh - 24px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); } }

/* Compact writing area, with send preferences sharing the action row. */

.emoji-popover.anchored em-emoji-picker { width:100%; }

/* Profile workspace: neutral editing surfaces, personality reserved for previews. */
.editor-eyebrow { display:block; color:var(--dim); font-size:10px; font-weight:750; letter-spacing:.12em; margin-bottom:7px; }
.editor-description { color:var(--dim); font-size:12px; line-height:1.6; margin:4px 0 18px; }
.profile-editor-overlay { animation:editor-overlay-in 180ms ease-out both; }
.profile-editor-overlay.exiting { animation:editor-overlay-out 150ms ease-in forwards; }
.modal.profile-modal.profile-editor { width:min(920px,calc(100vw - 32px)); max-width:none; max-height:calc(100dvh - 40px); display:flex; flex-direction:column; border:1px solid var(--line); background:var(--bg-1); border-radius:20px; overflow:hidden; box-shadow:0 24px 90px #0005; animation:editor-in 220ms cubic-bezier(.22,1,.36,1) both; }
.profile-editor .modal-head { flex:none; background:transparent; padding:22px 26px; border-bottom:1px solid var(--line); }.profile-editor .modal-head h3 { font-size:22px; margin:0; }.profile-editor .modal-close { width:36px; height:36px; border:1px solid var(--line); border-radius:10px; background:transparent; }
.profile-editor-layout { display:grid; grid-template-columns:minmax(0,1fr) 310px; min-height:0; flex:1; }
.profile-editor-form { min-width:0; min-height:0; display:flex; flex-direction:column; }
.profile-editor-tabs { display:flex; padding:18px 24px 0; gap:4px; flex:none; }
.profile-editor-tabs button { flex:1; white-space:nowrap; padding:10px 8px; border-radius:9px; color:var(--dim); font-size:12px; font-weight:650; background:transparent; }
.profile-editor-tabs button[aria-pressed=true] { background:var(--active); color:var(--text); box-shadow:inset 0 -2px var(--accent); }
.profile-editor .modal-body { padding:22px 26px 26px; overflow-y:auto; min-height:0; max-height:none; }
.profile-editor-section:not([hidden]) { animation:editor-section-in 160ms ease-out; }.profile-editor-section[hidden] { display:none !important; }
.profile-editor-section h4 { margin:0 0 5px; font-size:15px; color:var(--text); }.profile-editor-section>h4:not(:first-child) { margin-top:22px; }
.profile-editor-section:first-child { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 16px; }.profile-editor-section:first-child>h4,.profile-editor-section:first-child>.editor-description,.profile-field.wide { grid-column:1/-1; }
.profile-editor .modal-body label { text-transform:none; font-size:12px; font-weight:600; letter-spacing:0; color:var(--dim); margin:14px 0 7px; display:block; }
.profile-editor .modal-body input:not([type=checkbox]),.profile-editor .modal-body textarea,.profile-editor .modal-body select { width:100%; box-sizing:border-box; min-height:42px; background:var(--bg-0); color:var(--text); border:1px solid var(--line); border-radius:9px; padding:10px 12px; font-size:14px; }
.profile-editor .modal-body textarea { min-height:90px; resize:vertical; }
.profile-editor :is(input,textarea,select):focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.profile-editor-preview { padding:24px 20px; background:var(--bg-0); border-left:1px solid var(--line); overflow-y:auto; }
.profile-preview-banner { height:105px; background-size:cover; background-position:center; }
.profile-preview-details { padding:0 18px 20px; }.profile-preview-details h3 { margin:12px 0 4px; font-size:22px; overflow-wrap:anywhere; }.profile-preview-details p { color:var(--dim); font-size:12px; line-height:1.6; margin:5px 0; overflow-wrap:anywhere; }.profile-role { display:inline-block; margin:10px 0; font-size:10px; text-transform:uppercase; letter-spacing:.05em; color:var(--text); background:var(--bg-2); padding:4px 7px; border-radius:5px; }.profile-preview-details .profile-preview-bio { color:var(--text); white-space:pre-wrap; }
.profile-editor .wiz-foot { display:flex; align-items:center; flex-wrap:wrap; gap:12px; padding:16px 26px; border-top:1px solid var(--line); background:var(--bg-1); flex:none; }.profile-save-note { font-size:11px; color:var(--dim); flex:1; }.profile-editor .wiz-foot [role=alert] { flex-basis:100%; color:var(--text); }
.profile-editor .btn-ghost { border:1px solid var(--line); border-radius:9px; min-height:38px; font-size:12px; }.profile-style-entry { display:flex; align-items:center; gap:14px; justify-content:space-between; padding:16px; border:1px solid var(--line); border-radius:12px; margin-bottom:22px; }.profile-style-entry .editor-description { margin:4px 0 0; }.profile-style-entry button { max-width:180px; }.profile-editor .banner-tabs { flex-wrap:wrap; gap:7px; margin:12px 0 18px; }.profile-editor .banner-colors { margin:12px 0; }.profile-editor .swatches { flex-wrap:wrap; gap:7px; }.profile-editor .swatch { width:22px; height:22px; }.profile-editor .hint { font-size:11px; line-height:1.6; }
.name-style-refined { animation:editor-in 220ms cubic-bezier(.22,1,.36,1) both; width:min(890px,calc(100vw - 28px)); }.name-style-refined.exiting { animation:editor-out 150ms ease-in forwards; }.name-style-refined::backdrop { animation:editor-overlay-in 180ms ease-out; }.name-style-refined header { padding:22px 26px; }.name-style-refined .name-style-controls { padding:24px 26px; }.name-style-refined .name-style-preview { justify-content:flex-start; gap:10px; padding:25px; }.name-style-refined .name-preview-tabs { margin-bottom:10px; background:var(--bg-1); border:1px solid var(--line); padding:3px; border-radius:9px; }.name-style-refined .name-preview-tabs button { min-height:30px; padding:4px; background:transparent; border:0; box-shadow:none; color:var(--dim); }.name-style-refined .name-preview-tabs button[aria-pressed=true] { background:var(--active); color:var(--text); }
.name-style-refined .name-font-grid button,.name-style-refined .name-effect-grid button { position:relative; transition:background 140ms, border-color 140ms, transform 140ms; }.name-style-refined .name-font-grid button:hover,.name-style-refined .name-effect-grid button:hover { background:var(--hover); transform:translateY(-1px); }.name-style-refined button[aria-pressed=true] { background-color:var(--active); box-shadow:none; }.name-style-refined .name-font-grid button[aria-pressed=true]:after { content:'✓'; position:absolute; right:7px; top:5px; font-size:10px; color:var(--accent); }.name-style-refined .name-font-grid { gap:7px; }.name-style-refined .name-font-grid button { min-height:66px; }.name-style-refined .name-style-controls fieldset { margin-bottom:20px; }
.name-preview-label { color:var(--dim); font-size:10px; letter-spacing:.05em; text-transform:uppercase; margin-top:8px; }.name-style-refined .name-preview-profile { padding-bottom:16px; }.name-style-refined .name-preview-profile strong { margin:6px 0; }.name-style-refined .name-preview-message small { margin-left:6px; }.name-style-refined .name-preview-message,.name-style-refined .name-preview-member { padding:13px; }
.name-style-refined .name-palettes { gap:8px; }.name-style-refined .name-palettes button { flex:1; min-width:0; height:40px; position:relative; }.name-style-refined .name-palettes button[aria-pressed=true]:after { content:'✓'; position:absolute; right:4px; bottom:3px; display:grid; place-items:center; width:17px; height:17px; border-radius:50%; background:var(--bg-0); color:var(--text); font-size:11px; }.name-theme-color { background:var(--bg-2); }.name-color-inputs { align-items:center; padding:9px 10px; border:1px solid var(--line); border-radius:9px; gap:12px; }.name-color-inputs>span { font-size:11px; color:var(--dim); margin-right:auto; }.name-color-inputs input[type=color] { appearance:none; border:0; border-radius:6px; overflow:hidden; width:24px; height:24px; background:transparent; cursor:pointer; }.name-color-inputs input::-webkit-color-swatch-wrapper { padding:0; }.name-color-inputs input::-webkit-color-swatch { border:0; border-radius:5px; }
.name-motion-toggle { display:flex; justify-content:space-between; padding-top:4px; gap:12px; }.name-motion-toggle strong { display:block; font-size:12px; }.name-motion-toggle small { display:block; font-size:11px; color:var(--dim); margin-top:4px; }.name-motion-toggle input { appearance:none; flex:none; width:32px; height:20px; border-radius:20px; background:var(--bg-0); border:1px solid var(--line); position:relative; transition:background 180ms; cursor:pointer; }.name-motion-toggle input:after { content:''; position:absolute; width:12px; height:12px; top:3px; left:3px; border-radius:50%; background:var(--dim); transition:transform 180ms cubic-bezier(.2,.8,.2,1.2); }.name-motion-toggle input:checked { background:var(--accent); }.name-motion-toggle input:checked:after { background:var(--bg-0); transform:translateX(12px); }
@keyframes editor-in { from { opacity:0; transform:translateY(8px) scale(.985); } to { opacity:1; transform:none; } }@keyframes editor-out { to { opacity:0; transform:translateY(5px) scale(.99); } }@keyframes editor-section-in { from { opacity:0; transform:translateY(4px); } to { opacity:1; transform:none; } }@keyframes editor-overlay-in { from { opacity:0; } to { opacity:1; } }@keyframes editor-overlay-out { to { opacity:0; } }
@media(max-width:700px) { .modal.profile-modal.profile-editor { width:calc(100vw - 20px); max-height:calc(100dvh - 24px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); }.profile-editor-layout { display:block; overflow-y:auto; }.profile-editor .modal-body { overflow:visible; padding:18px; }.profile-editor-preview { display:none; }.profile-editor-tabs { padding:12px 12px 0; }.profile-editor-tabs button { font-size:11px; padding:10px 4px; min-height:44px; }.profile-editor .modal-head { padding:18px; }.profile-editor .wiz-foot { padding:14px 18px; }.profile-editor-section:first-child { grid-template-columns:1fr; }.profile-field { grid-column:1/-1; }.profile-editor .modal-body input:not([type=checkbox]),.profile-editor .modal-body textarea,.profile-editor .modal-body select { font-size:16px; }.profile-style-entry { flex-direction:column; align-items:flex-start; }.profile-style-entry button { max-width:none; }.name-style-refined .name-style-preview,.name-style-refined .name-style-controls { padding:18px; } }
@media(prefers-reduced-motion:reduce) { .profile-editor-overlay,.profile-editor-overlay.exiting,.modal.profile-modal.profile-editor,.profile-editor-section:not([hidden]),.name-style-refined,.name-style-refined.exiting,.name-style-refined::backdrop { animation:none; }.name-style-refined button,.name-motion-toggle input,.name-motion-toggle input:after { transition:none !important; } }

@media(max-width:700px) { .profile-editor-preview[data-section=appearance] { display:block; border-left:0; border-top:1px solid var(--line); }.profile-editor-preview[data-section=appearance] .profile-preview-bio { display:none; } }

.profile-editor .modal-close { color:var(--text); }
.profile-editor .wiz-foot>.btn-primary { margin-left:auto; }

/* Small spacing polish: clear the field focus ring and protect rail labels. */
@media(min-width:761px) {
 .app-shell { grid-template-columns:100px minmax(0,1fr); }
 .app-shell .studio-rail .bubble { padding-inline:8px; box-sizing:border-box; }
}

/* Stable editor frame; sections scroll inside it rather than resizing the dialog. */
.modal.profile-modal.profile-editor { height:min(780px,calc(100dvh - 40px)); }
.profile-editor-section:not([hidden]) { animation:profile-section-slide 260ms cubic-bezier(.22,1,.36,1) both; }
@keyframes profile-section-slide { from { opacity:0; transform:translateX(12px); } to { opacity:1; transform:none; } }
.profile-editor .profile-size-picker { border:0; padding:0; margin:22px 0 12px; min-width:0; }
.profile-size-picker legend { color:var(--text); font-size:12px; font-weight:650; margin-bottom:12px; }
.profile-size-picker>div { display:flex; flex-wrap:wrap; gap:8px; }
.profile-editor .profile-size-picker label { margin:0; position:relative; cursor:pointer; }
.profile-size-picker input[type=radio] { position:absolute; opacity:0; width:1px !important; height:1px; min-height:0 !important; padding:0 !important; }
.profile-size-picker label>span { display:grid; place-items:center; min-width:42px; min-height:42px; padding:8px 12px; border:1px solid var(--line); border-radius:9px; color:var(--dim); background:var(--bg-0); transition:background 160ms,border-color 160ms,color 160ms; }
.profile-size-picker input:checked+span { color:var(--text); background:var(--active); border-color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent); }
.profile-size-picker input:focus-visible+span { outline:2px solid var(--accent); outline-offset:3px; }
.profile-size-picker label:hover>span { color:var(--text); }
/* Shared switch presentation. Document task checkboxes, tick boxes on a document being signed, and the consent to sign it, retain document semantics. */
input[type=checkbox]:not(.ProseMirror input):not([data-type=taskItem] input):not(:where(.ntl-page.paper input, .ntl-consent input)) { appearance:none; -webkit-appearance:none; box-sizing:border-box; display:inline-block; position:relative; flex-shrink:0; width:36px !important; min-width:36px; height:22px !important; min-height:22px; padding:0 !important; border:1px solid var(--line); border-radius:22px; background:var(--bg-0); vertical-align:middle; cursor:pointer; transition:background 180ms ease,border-color 180ms ease; }
input[type=checkbox]:not(.ProseMirror input):not([data-type=taskItem] input):not(:where(.ntl-page.paper input, .ntl-consent input))::after { content:''; position:absolute; top:3px; left:3px; width:14px; height:14px; border-radius:50%; background:var(--dim); transform:translateX(0); transition:transform 190ms cubic-bezier(.2,.8,.2,1.15),background 180ms; }
input[type=checkbox]:not(.ProseMirror input):not([data-type=taskItem] input):not(:where(.ntl-page.paper input, .ntl-consent input)):checked { background:var(--accent); border-color:var(--accent); }
input[type=checkbox]:not(.ProseMirror input):not([data-type=taskItem] input):not(:where(.ntl-page.paper input, .ntl-consent input)):checked::after { transform:translateX(14px); background:var(--bg-0); }
input[type=checkbox]:not(.ProseMirror input):not([data-type=taskItem] input):not(:where(.ntl-page.paper input, .ntl-consent input)):indeterminate::after { transform:translateX(7px); background:var(--accent); }
input[type=checkbox]:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
input[type=checkbox]:disabled { opacity:.5; cursor:not-allowed; }
@media(max-width:700px) { .modal.profile-modal.profile-editor { height:calc(100dvh - 24px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); } }
@media(prefers-reduced-motion:reduce) { .profile-editor-section:not([hidden]) { animation:none; } input[type=checkbox],input[type=checkbox]::after,.profile-size-picker label>span { transition:none !important; } }
/* Desktop: the (resizable) sidebar and the conversation; an open thread adds a third column (threads.css). */
@media (min-width: 1101px) {
  .app-shell .app { grid-template-columns: var(--col-l, var(--sidebar-w, 280px)) minmax(0, 1fr); }
}
/* One saved palette for both the actual profile and its live preview. */
.profile-preview-details > .avatar { margin-top: -36px; box-shadow: 0 0 0 4px color-mix(in srgb, var(--c1) 38%, var(--bg-1)); }

/* Keep typing feedback centered in the gap above the composer. */

.studio-feed-shortcut { display: none; }
@media (max-width:760px) { .studio-mobile-header .studio-feed-shortcut { display: inline-flex; padding-inline: 10px; gap: 7px; } }
/* The Chat icon's unread dot (Chat.tsx, while another section is open): white for unread, red when something is for you. */
.bubble:has(> .bubble-dot) { position: relative; }
.bubble-dot { position: absolute; top: 8px; right: calc(50% - 17px); width: 9px; height: 9px; border-radius: var(--radius-full); background: var(--text); box-shadow: 0 0 0 2px var(--bg-1); }
.bubble-dot.for-you { background: var(--danger); }
.studio-switcher .bubble-dot { position: static; flex: none; margin-left: auto; box-shadow: none; }
/* Profile card (ProfileCard.tsx) and its live preview in the profile editor.
   The card floats beside whatever opened it; ProfileCard.tsx sets left/top
   and the person's banner colours (--c1, --c2). */
.profile-card,
.profile-preview-card {
  --pc-surface: color-mix(in srgb, var(--c1) 38%, var(--bg-1));
  border: 2px solid transparent;
  background:
    linear-gradient(150deg, var(--pc-surface) 0%, color-mix(in srgb, var(--c2) 38%, var(--bg-1)) 100%) padding-box,
    linear-gradient(140deg, color-mix(in srgb, var(--c1) 80%, white), var(--c2)) border-box;
}
.profile-preview-card { overflow: hidden; margin: var(--sp-4) 0; border-radius: var(--radius-lg); }
.profile-card {
  --pc-banner: 100px;
  --pc-avatar: 80px;
  position: fixed;
  z-index: var(--z-popover);
  width: min(320px, calc(100vw - var(--sp-5)));
  max-height: min(680px, calc(var(--studio-viewport-height, 100dvh) - var(--sp-5)));
  overflow-y: auto;
  overscroll-behavior: contain;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
  color: var(--text);
}
.pc-banner {
  position: absolute;
  inset: 0 0 auto;
  height: var(--pc-banner);
  background-size: cover;
  background-position: center;
  border-bottom: 1px solid color-mix(in srgb, var(--on-media) 8%, transparent);
}

/* Close and quick actions sit on the banner image, so they use the on-media chip in every theme. */
.pc-close,
.pc-actions button {
  display: grid;
  place-items: center;
  width: var(--control-md);
  height: var(--control-md);
  border-radius: var(--radius-full);
  background: var(--media-chip);
  color: var(--on-media);
  font-size: var(--fs-sm);
  transition: background-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.pc-close:hover,
.pc-actions button:hover { background: var(--media-chip-hover); transform: translateY(-1px); }
.pc-close:active,
.pc-actions button:active { transform: scale(0.94); }
.pc-close { position: absolute; top: var(--sp-2); right: var(--sp-2); z-index: var(--z-raised); }
.pc-actions {
  position: absolute;
  top: var(--sp-2);
  right: calc(var(--sp-2) * 2 + var(--control-md));
  z-index: var(--z-raised);
  display: flex;
  gap: var(--sp-2);
}

.pc-body { position: relative; padding: calc(var(--pc-banner) - 36px) var(--sp-4) var(--sp-4); }
.pc-head { display: flex; flex-direction: column; gap: var(--sp-3); }
.pc-avatar {
  position: relative;
  width: var(--pc-avatar);
  height: var(--pc-avatar);
  border-radius: 50%;
  box-shadow: 0 0 0 4px var(--pc-surface);
}

.pc-id { min-width: 0; }
.pc-name { font-size: var(--fs-xl); font-weight: var(--fw-bold); line-height: var(--lh-tight); overflow-wrap: anywhere; }
.pc-handle { margin-top: var(--sp-0); color: var(--dim); font-size: var(--fs-sm); line-height: var(--lh-body); overflow-wrap: anywhere; user-select: text; -webkit-user-select: text; }
.pc-chips { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin-top: var(--sp-3); }
.pc-chips > * { max-width: 100%; padding: var(--sp-0) var(--sp-2); border-radius: var(--radius-sm); font-size: var(--fs-xs); line-height: var(--lh-body); overflow-wrap: anywhere; white-space: normal; }

.pc-voice {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid color-mix(in srgb, var(--online) 35%, transparent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--online) 14%, transparent);
  color: var(--text);
  font-size: var(--fs-sm);
}
.pc-voice-wave { display: inline-flex; align-items: flex-end; gap: var(--sp-0); height: 12px; }
.pc-voice-wave i { width: 3px; border-radius: var(--sp-0); background: var(--online); animation: pc-voice-wave 1s var(--ease-loop) infinite; }
.pc-voice-wave i:nth-child(1) { height: 6px; }
.pc-voice-wave i:nth-child(2) { height: 11px; animation-delay: 0.18s; }
.pc-voice-wave i:nth-child(3) { height: 8px; animation-delay: 0.34s; }
@keyframes pc-voice-wave { 0%, 100% { transform: scaleY(0.55); } 50% { transform: scaleY(1); } }

.pc-presence { margin-top: var(--sp-2); color: var(--dim); font-size: var(--fs-xs); }
.pc-activity { margin-top: var(--sp-1); font-size: var(--fs-xs); } /* a meeting, busy or a day off (MemberActivity) */
.pc-error { margin-top: var(--sp-3); padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-md); background: var(--bg-2); color: var(--text); }
.pc-status { margin-top: var(--sp-3); padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-md); background: var(--bg-2); font-size: var(--fs-md); line-height: var(--lh-body); overflow-wrap: anywhere; }
.pc-bio { margin-top: var(--sp-3); font-size: var(--fs-md); line-height: var(--lh-body); white-space: pre-wrap; overflow-wrap: anywhere; }
.pc-rows { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.pc-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1); color: var(--dim); font-size: var(--fs-sm); line-height: var(--lh-body); overflow-wrap: anywhere; }
.pc-row i { width: 14px; margin-right: var(--sp-1); text-align: center; }
.pc-row-dim { color: var(--faint); }

.profile-card .pc-edit {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  width: 100%;
  min-height: var(--control-md);
  margin-top: var(--sp-4);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--accent) 22%, var(--bg-2));
  color: var(--text);
  font-size: var(--fs-md);
}
.pc-dm {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin-top: var(--sp-4);
  padding: var(--sp-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-2);
}
.pc-dm:focus-within { border-color: var(--accent); }
.pc-dm-input { flex: 1; min-width: 0; padding: var(--sp-2); border: 0; background: transparent; color: var(--text); font-size: var(--fs-md); }
.pc-dm-input::placeholder { color: var(--dim); }
.pc-dm-input:focus-visible { outline: none; }
.pc-send {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--control-md);
  height: var(--control-md);
  border-radius: var(--radius-md);
  color: var(--dim);
}
.pc-send.ready { border: 1px solid var(--accent); background: color-mix(in srgb, var(--accent) 22%, var(--bg-2)); color: var(--text); }
.profile-card button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.profile-card button:disabled { opacity: 0.5; cursor: default; }

@media (pointer: coarse) {
  .pc-close, .pc-actions button { width: var(--control-touch); height: var(--control-touch); }
  .pc-actions { right: calc(var(--sp-2) * 2 + var(--control-touch)); }
  .profile-card .pc-edit, .pc-send { min-height: var(--control-touch); }
  .pc-dm-input { font-size: var(--fs-lg); }
}
@media (prefers-reduced-motion: reduce) {
  .pc-voice-wave i { animation: none; }
}
/* Emoji drawn inline with text: Twemoji images (FlatEmoji.tsx) and workspace
   custom emoji (CustomEmojiImage.tsx, MessageContent.tsx). Sized in em so they
   follow whatever text they sit in. */
/* The side margin keeps the gaps around an emoji even with the space a word leaves. */
.flat-emoji { display: inline-block; width: 1.2em; height: 1.2em; margin: 0 0.05em 0 0.1em; object-fit: contain; vertical-align: -0.3em; }
.cemoji { width: auto; height: 1.4em; max-width: 3em; object-fit: contain; vertical-align: -0.3em; }
/* Custom emoji are framed to the artwork's measured aspect ratio (--emoji-aspect). */
.cemoji-frame { position: relative; display: inline-block; flex-shrink: 0; width: calc(1.4em * var(--emoji-aspect, 1)); height: 1.4em; overflow: hidden; }
.cemoji-frame > :is(img, canvas) { position: absolute; inset: 0 auto auto 0; display: block; width: 100%; max-width: none; height: 100%; object-fit: contain; }
/* The conversation: message list, one message (MessageItem in Chat.tsx), its
   reactions and thread summary, the list's dividers and jump bars, and the
   formatting inside message text (MessageContent.tsx). */

/* List */
/* Up and down only: anything a little too wide (a link preview, an embed) must not let the whole conversation
   be dragged sideways on a phone. Code blocks keep their own sideways scroll. */
.messages { display: flex; flex: 1; flex-direction: column; min-height: 0; overflow-x: hidden; overflow-y: auto; overscroll-behavior-x: none; overflow-anchor: none; padding-block: var(--sp-4); }
/* Its one block of content: at the bottom when short, scrolling as usual when long (block layout
   inside, so the message rhythm's margins still collapse as before). */
.messages-list { flex-shrink: 0; margin-top: auto; }
.messages.drag { outline: 2px dashed var(--accent); outline-offset: calc(-1 * var(--sp-2)); }
body.kp-theater .messages { flex: 1 1 auto; min-height: 60px; transition: height var(--dur-base) var(--ease); }
body.kp-theater.kp-chat-min .messages { flex: 0 0 0; height: 0; min-height: 0; padding-block: 0; overflow: hidden; }

/* The start of a conversation: who it's with (or what it is), and a prompt when it's empty. */
.chat-intro { display: grid; justify-items: start; gap: var(--sp-1); padding: var(--sp-3) var(--sp-5) var(--sp-4); }
.chat-intro-face { margin-bottom: var(--sp-2); }
/* A group: up to five faces, overlapping, each ringed in the page colour. */
.chat-intro-group { display: flex; }
.chat-intro-group .avatar { box-shadow: 0 0 0 3px var(--main-bg, var(--bg-1)); border-radius: 50%; }
.chat-intro-group .avatar + .avatar { margin-left: calc(-1 * var(--sp-4)); }
/* One hero size for every conversation: a face, faces, or an icon tile, 64px. */
.chat-intro-face .avatar { --av: 64px; }
.chat-intro-icon { display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%; background: var(--bg-3); color: var(--dim); font-size: var(--fs-xl); }
.chat-intro-icon.has-emoji { font-size: 40px; }
.chat-intro-icon.has-emoji .flat-emoji { width: 40px; height: 40px; margin: 0; }
.chat-intro h2 { font-size: var(--fs-xl); }
.chat-intro p { color: var(--dim); }
.chat-intro .chat-intro-prompt { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); margin-top: var(--sp-2); color: var(--text); }
.chat-intro-wave { display: inline-flex; align-items: center; gap: var(--sp-1); min-height: var(--control-md); padding: 0 var(--sp-4); border: 1px solid var(--line); border-radius: var(--radius-full); background: var(--bg-2); color: var(--text); font-weight: var(--fw-semibold); }
.chat-intro-wave:hover { background: var(--hover); }

.load-older {
  display: block;
  margin: 0 auto var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-full);
  background: var(--bg-2);
  color: var(--text);
  font-size: var(--fs-sm);
}
.load-older:hover { background: var(--hover); }

.date-divider,
.unread-divider { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); font-weight: var(--fw-bold); }
.date-divider::before, .date-divider::after,
.unread-divider::before, .unread-divider::after { content: ''; flex: 1; height: 1px; }
.date-divider { margin: var(--sp-4) var(--sp-5) var(--sp-1); color: var(--faint); }
.date-divider::before, .date-divider::after { background: var(--line); }
.unread-divider { margin: var(--sp-2) var(--sp-5); color: var(--danger); text-transform: uppercase; letter-spacing: 0.04em; }
.unread-divider::before, .unread-divider::after { background: var(--danger); opacity: 0.45; }

/* A part of chat that crashed (ChatBoundary): what couldn't be shown, in that place's own chrome. */
.chat-error button { min-height: var(--control-md); padding: 0 var(--sp-3); border-radius: var(--radius-md); background: var(--bg-3); color: var(--text); font-weight: 600; }
.chat-error button:hover { background: var(--hover); }
.chat-error button.primary { background: var(--accent); color: var(--on-accent); }
.chat-error button.primary:hover { background: color-mix(in srgb, var(--accent) 88%, var(--text)); }
.chat-error button.link { min-height: 0; padding: 0; background: none; color: var(--blue); font-weight: 500; text-decoration: underline; }
.chat-error-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
/* Panels, modals and the page: icon, title, why, then the actions, centred. */
.chat-error-stack { display: grid; justify-items: center; gap: var(--sp-2); max-width: 320px; margin: auto; padding: var(--sp-5); text-align: center; color: var(--dim); font-size: var(--fs-md); }
.chat-error-stack > i { color: var(--danger); font-size: var(--fs-xl); }
.chat-error-stack > b { color: var(--text); font-size: var(--fs-lg); text-wrap: balance; }
.chat-error-stack > .chat-error-actions { justify-content: center; margin-top: var(--sp-2); }
.chat-error.panel { display: flex; flex-direction: column; height: 100%; }
.chat-error.page .chat-error-stack img { width: 64px; height: 64px; opacity: .85; }
/* A message: a quiet line in its place, the icon in the avatar column. */
.chat-error.row { display: flex; align-items: center; gap: var(--sp-3); margin-top: var(--sp-4); padding: 1px var(--sp-5); color: var(--dim); font-size: var(--fs-md); }
.chat-error.row > i { flex: none; width: 40px; color: var(--danger); text-align: center; }
/* The build dock: a sidebar card at the sidebar's inset, one left edge for its text and button. */
.chat-error.block { display: flex; gap: var(--sp-2); margin: var(--sp-2); padding: var(--sp-3); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-2); color: var(--dim); font-size: var(--fs-sm); }
.chat-error.block > i { margin-top: 2px; color: var(--danger); }
.chat-error.block b { display: block; color: var(--text); }
.chat-error.block .chat-error-actions { margin-top: var(--sp-2); }
.history-error { margin: var(--sp-4); padding: var(--sp-4); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-2); color: var(--text); }
.history-error button { margin-left: var(--sp-2); padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-md); background: var(--bg-3); color: var(--text); }

/* Bars above and below the list */
/* Connection: pinned above the list (visible wherever you're scrolled). */
/* Bars in the slot under the header share one height and the message column's inset. */
.connection-bar { display: flex; flex-shrink: 0; align-items: center; gap: var(--sp-2); min-height: var(--control-md); padding: var(--sp-2) var(--sp-5); border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--warning) 14%, var(--bg-1)); color: var(--text); font-size: var(--fs-sm); }
.connection-bar i { color: var(--warning); }
.connection-bar.offline { background: color-mix(in srgb, var(--danger) 12%, var(--bg-1)); }
.connection-bar.offline i { color: var(--danger); }
/* The list, with the loading skeleton laid over it until the conversation is ready. */
.messages-pane { position: relative; display: flex; flex: 1; flex-direction: column; min-height: 0; }
.messages-skeleton { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end; padding-block: var(--sp-4); overflow: hidden; mask-image: linear-gradient(to bottom, transparent, #000 45%); }
.msg-skeleton { display: flex; gap: var(--sp-3); padding: 1px var(--sp-5); margin-top: var(--sp-4); }
.msg-skeleton.grouped { margin-top: var(--sp-1); }
.sk-avatar, .sk-gutter { flex-shrink: 0; width: 40px; height: 40px; }
.sk-avatar { border-radius: 50%; }
.sk-gutter { height: 0; }
.sk-body { display: grid; flex: 1; gap: var(--sp-2); align-content: start; padding-top: var(--sp-1); }
.sk-name, .sk-line { display: block; max-width: 520px; height: 12px; border-radius: var(--radius-sm); }
.sk-name { height: 14px; max-width: 160px; }
.sk-avatar, .sk-name, .sk-line { background: linear-gradient(90deg, var(--bg-3) 0%, var(--hover) 50%, var(--bg-3) 100%) 0 0 / 200% 100%; animation: sk-shimmer 1.4s linear infinite; }
@keyframes sk-shimmer { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .sk-avatar, .sk-name, .sk-line { animation: none; } }
/* Older history: loading, or failed with Retry. */
.history-older { display: flex; align-items: center; justify-content: center; gap: var(--sp-2); min-height: var(--control-md); margin: var(--sp-2) var(--sp-5); color: var(--dim); font-size: var(--fs-sm); }
.history-older.error { color: var(--text); }
.history-older.error i { color: var(--danger); }
.history-older button { padding: 0 var(--sp-1); color: var(--text); font-weight: var(--fw-semibold); text-decoration: underline; text-underline-offset: 2px; }
.first-unread-dock { position: relative; flex-shrink: 0; height: 0; z-index: var(--z-sticky); }
.first-unread-dock > .first-unread-button { position: absolute; top: 0; left: 0; right: 0; }
.first-unread-button { flex-shrink: 0; min-height: var(--control-md); padding: var(--sp-2) var(--sp-5); border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--accent) 14%, var(--bg-1)); color: var(--text); text-align: left; }
.thread-return { display: flex; justify-content: space-between; gap: var(--sp-2); padding: var(--sp-1) var(--sp-3); border-bottom: 1px solid var(--line); background: var(--bg-2); }
.thread-return button { min-height: var(--control-md); background: transparent; color: var(--text); }
.jump-dock { position: relative; flex-shrink: 0; height: 0; }
.jump-dock > .jump-bottom { position: absolute; bottom: var(--sp-2); left: 50%; margin: 0; transform: translateX(-50%); white-space: nowrap; }
.jump-bottom {
  position: relative;
  z-index: var(--z-sticky);
  flex-shrink: 0;
  align-self: center;
  max-width: calc(100% - var(--sp-5));
  min-height: var(--control-md);
  margin: var(--sp-1) var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--accent);
  border-radius: var(--radius-full);
  background: var(--bg-2);
  color: var(--text);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
}

/* One message */
/* Rhythm: 16px between groups; within a group, 2px between messages (1px each side). */
.msg { position: relative; display: flex; gap: var(--sp-3); padding: 1px var(--sp-5); margin-top: var(--sp-4); }
.msg.grouped { margin-top: 0; }
.msg:hover { background: color-mix(in srgb, var(--hover) 65%, transparent); }
.msg:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--radius-md); }
.msg :is(button, a):focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
.msg.msg-flash { border-radius: var(--radius-md); animation: msg-flash 2.4s var(--ease); }
@keyframes msg-flash { 0%, 40% { background: color-mix(in srgb, var(--accent) 22%, transparent); } 100% { background: transparent; } }
/* Under reduced motion the flash is a still highlight, held while the class is on (2.4s), so the
   "this is the message" cue stays. */
@media (prefers-reduced-motion: reduce) { .msg.msg-flash { animation: none !important; background: color-mix(in srgb, var(--accent) 22%, transparent); } }

.msg-gutter { display: flex; flex-shrink: 0; justify-content: center; width: 40px; }
/* A grouped message's time, in the gutter on hover or focus, on its first line. */
.msg-gutter-time { visibility: hidden; color: var(--faint); font-size: var(--fs-xs); line-height: calc(var(--fs-lg) * var(--lh-body)); font-variant-numeric: tabular-nums; white-space: nowrap; }
.msg:is(:hover, :focus-within) .msg-gutter-time { visibility: visible; }
.msg-avatar { flex-shrink: 0; align-self: flex-start; border-radius: 50%; }
.msg-body { flex: 1; min-width: 0; }
.msg-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2); margin-bottom: var(--sp-1); }
.msg-author { color: var(--text); font-size: var(--fs-lg); font-weight: var(--fw-semibold); text-align: left; overflow-wrap: anywhere; }
.msg-author:hover { text-decoration: underline; }
.msg-time { color: var(--dim); font-size: var(--fs-xs); }
.msg-text { max-width: 86ch; color: var(--text); font-size: var(--fs-lg); line-height: var(--lh-body); white-space: pre-wrap; overflow-wrap: break-word; }
.msg-text.jumbo { font-size: calc(var(--fs-lg) * 2.625); line-height: var(--lh-tight); }
.msg-text.jumbo .cemoji { height: 48px; max-width: 5em; vertical-align: middle; }
/* One frame: the line border, accent while focused, danger after a failed save. Sized to the text. */
.msg-edit {
  display: block;
  width: 100%;
  max-height: 50vh;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-0);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
  resize: none;
  outline: none;
}
.msg-edit:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.msg-edit[aria-invalid='true'] { border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger); }
.msg-edit-hint { margin-top: var(--sp-1); color: var(--dim); font-size: var(--fs-xs); }
.msg-edit-hint button { padding: 0; color: var(--text); font-size: inherit; text-decoration: underline; text-underline-offset: 2px; }
.msg-edit-hint button:hover { color: var(--accent); }
.msg-edit-error { margin-top: var(--sp-1); color: var(--danger); font-size: var(--fs-xs); }
/* Your message on its way (OutgoingItem): dimmed until confirmed (links too: they aren't live yet).
   A failed one stays dimmed and gets a danger bar, plus its line with Retry and Discard. */
.outgoing .msg-text, .outgoing .msg-text .ch-link { color: var(--dim); }
.outgoing.failed { box-shadow: inset 2px 0 0 var(--danger); }
.outgoing-files { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); margin-top: var(--sp-1); color: var(--dim); font-size: var(--fs-sm); }
.outgoing-failed { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-3); margin-top: var(--sp-1); color: var(--danger); font-size: var(--fs-sm); }
.outgoing-failed button { min-height: 24px; padding: 0; border-radius: var(--radius-sm); color: var(--text); font-size: inherit; font-weight: var(--fw-semibold); text-decoration: underline; text-underline-offset: 2px; }
.outgoing-note { margin-top: var(--sp-1); color: var(--dim); font-size: var(--fs-sm); }
.outgoing-failed button:hover { color: var(--accent); }
/* "(edited)" sits inline after the text. */
.msg-edited { color: var(--faint); font-size: var(--fs-xs); white-space: nowrap; }
/* Messages that mention you (channel and thread). */
/* The band sits 4px around the content, top and bottom; its margins give the 3px back so the
   16px/2px rhythm between texts doesn't move. */
.msg.mentions-me { padding-block: var(--sp-1); margin-block: calc(var(--sp-4) - 3px) -3px; }
.msg.grouped.mentions-me { margin-top: -3px; }
.msg-text > :last-child { margin-bottom: 0; }
:is(.msg, .thread-post).mentions-me { background: color-mix(in srgb, var(--warning) 8%, transparent); box-shadow: inset 2px 0 0 var(--warning); }
.msg.mentions-me:hover { background: color-mix(in srgb, var(--warning) 12%, transparent); }
.msg-pin { display: inline-flex; align-items: center; gap: var(--sp-1); margin-top: var(--sp-1); color: var(--yellow); font-size: var(--fs-xs); }
.msg-body :is(.attachments, .msg-reactions, .msg-thread) { margin-top: var(--sp-2); }

.msg-reply { display: flex; align-items: center; gap: var(--sp-1); min-width: 0; max-width: 100%; margin-bottom: var(--sp-1); padding-block: var(--sp-0); color: var(--dim); font-size: var(--fs-sm); text-align: left; }
.msg-reply:disabled { cursor: default; }
.msg-reply-author { flex-shrink: 0; max-width: 30%; overflow: hidden; font-weight: var(--fw-semibold); text-overflow: ellipsis; white-space: nowrap; }
.msg-reply-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.msg-thread {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  width: fit-content;
  max-width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-2);
  color: var(--text);
  font-size: var(--fs-sm);
  text-align: left;
}
.msg-thread span { color: var(--dim); }
.msg-thread.has-unread { border-color: var(--accent); }
.msg-thread-new { display: inline-flex; align-items: center; margin-left: auto; padding: var(--sp-0) var(--sp-2); border-radius: var(--radius-sm); background: var(--active); font-weight: var(--fw-semibold); white-space: nowrap; }
.msg-thread .msg-thread-new { color: var(--text); }
.msg-thread-preview { flex-basis: 100%; min-width: 0; max-width: 420px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-thread .msg-thread-preview { color: var(--text); opacity: 0.85; }

/* Hover toolbar (channel and thread): recent reactions, then the tools. --actions-top is set by
   placeActions (messageActions.ts) to keep it inside the scroller on the first and last message. */
.msg-actions {
  position: absolute;
  top: var(--actions-top, calc(-1 * var(--sp-3)));
  right: var(--sp-4);
  z-index: var(--z-raised);
  display: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-2); /* the floating surface, as popovers use */
  box-shadow: var(--shadow-1);
}
:is(.msg, .thread-post):is(:hover, :focus-within) > .msg-actions { display: flex; }
.msg-actions button { display: grid; place-items: center; width: var(--control-sm); height: var(--control-sm); border-radius: var(--radius-sm); color: var(--dim); font-size: var(--fs-md); }
.msg-actions button:hover { background: var(--hover); color: var(--text); }
.msg-actions-rx { font-size: var(--fs-lg); }
.msg-actions-sep { align-self: stretch; width: 1px; margin: var(--sp-1) var(--sp-0); background: var(--line); }

/* Reactions (also previewed in Emoji Studio) */
.msg-reactions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.rx {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-0) var(--sp-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-3);
  font-size: var(--fs-xl);
}
.rx:hover { border-color: var(--accent-dim); }
.rx.mine { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, transparent); }
.rx > span:first-child { display: inline-flex; align-items: center; line-height: 1; }
.rx .flat-emoji { width: 24px; height: 24px; margin: 0; vertical-align: middle; }
.rx .cemoji-frame { width: calc(24px * var(--emoji-aspect, 1)); max-width: 48px; height: 24px; vertical-align: middle; }
.rx .cemoji { height: 20px; vertical-align: middle; }
.rx-count { color: var(--dim); font-size: var(--fs-md); font-weight: var(--fw-semibold); }
.rx-add { padding: var(--sp-0) var(--sp-2); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-3); color: var(--faint); font-size: var(--fs-md); opacity: 0; pointer-events: none; transition: opacity var(--dur-fast) var(--ease); }
.rx-add:hover { color: var(--text); }
.msg:is(:hover, :focus-within) .rx-add { opacity: 1; pointer-events: auto; }
.rx-tip {
  position: absolute;
  bottom: calc(100% + var(--sp-2));
  left: 50%;
  z-index: var(--z-popover);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: max-content;
  max-width: 240px;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-3);
  box-shadow: var(--shadow-2);
  text-align: left;
  white-space: normal;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateX(-50%) translateY(2px);
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.rx:hover .rx-tip { opacity: 1; visibility: visible; transform: translateX(-50%); transition-delay: 250ms; }
.rx-tip::after { content: ''; position: absolute; top: 100%; left: 50%; border: 6px solid transparent; border-top-color: var(--bg-3); transform: translateX(-50%); }
.rx-tip-emoji { font-size: 1.3em; line-height: 1; }
.rx-tip-emoji .cemoji-frame { width: calc(28px * var(--emoji-aspect, 1)); max-width: 56px; height: 28px; }
.rx-tip-text { color: var(--dim); font-size: var(--fs-sm); line-height: var(--lh-body); }
.rx-tip-text b { color: var(--text); font-weight: var(--fw-semibold); }

/* Formatting inside message text */
.mention,
.ch-link { color: color-mix(in srgb, var(--blue) 45%, var(--text)); }
.mention { padding: 0 var(--sp-0); border-radius: var(--radius-sm); background: color-mix(in srgb, var(--blue) 22%, transparent); font-weight: var(--fw-semibold); }
.mention.me { background: color-mix(in srgb, var(--warning) 30%, transparent); color: var(--text); }
/* In messages and threads, mentions and #channels are buttons (MessageContent.tsx). */
:is(button.mention, button.ch-link) { border: 0; font: inherit; cursor: pointer; }
button.ch-link { padding: 0; background: none; }
:is(button.mention, button.ch-link):hover { text-decoration: underline; }
:is(button.mention, button.ch-link):focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.inline-code { padding: 0 var(--sp-1); border-radius: var(--radius-sm); background: var(--bg-0); font-family: var(--mono); font-size: 0.875em; }
.code-block { position: relative; max-width: 100%; margin: var(--sp-2) 0; }
.message-code-block {
  max-width: 100%;
  margin: 0;
  /* Room on the right for the copy button, so it never covers the end of the code. */
  padding: var(--sp-3) calc(28px + var(--sp-1) + var(--sp-3)) var(--sp-3) var(--sp-4);
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-0);
  color: var(--text);
  font: var(--fs-md) / var(--lh-body) var(--mono);
  white-space: pre;
  tab-size: 4;
}
/* Copy, in a code block's corner, on hover or focus. */
.code-copy { position: absolute; top: var(--sp-1); right: var(--sp-1); display: grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-2); color: var(--dim); font-size: var(--fs-sm); opacity: 0; cursor: pointer; }
.code-block:is(:hover, :focus-within) .code-copy { opacity: 1; }
.code-copy-status, .chat-error-status { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.code-copy:hover { color: var(--text); }
.gif-embed { max-width: 320px; border-radius: var(--radius-md); cursor: pointer; }

/* Menus use the app's accent focus ring, except in a sheet a finger opened (until a key is pressed). */
.accessible-menu :focus-visible { outline-color: var(--accent); }
.accessible-menu[data-input=touch] :focus-visible { outline: none; }
/* A message's menu starts with which message it is (one dim line) and its quick reactions. */
.ctx-preview { margin: 0; padding: var(--sp-1) var(--sp-2) var(--sp-2); overflow: hidden; color: var(--dim); font-size: var(--fs-sm); text-overflow: ellipsis; white-space: nowrap; }
.ctx-preview b { color: var(--text); }
.quick-reactions { display: flex; gap: var(--sp-1); padding: var(--sp-1); margin-bottom: var(--sp-1); border-bottom: 1px solid var(--line); }
.quick-reactions button { display: grid; flex: 1; place-items: center; min-width: var(--control-touch); height: var(--control-touch); border-radius: var(--radius-md); background: var(--bg-2); color: var(--dim); font-size: var(--fs-xl); }
.quick-reactions button:is(:hover, :focus-visible) { background: var(--hover); color: var(--text); }
.quick-reactions .flat-emoji { width: 24px; height: 24px; margin: 0; }
/* Pinned messages list (PinsPanel) reuses the message layout. */
.pins-list .msg { margin-top: 0; padding: var(--sp-2) var(--sp-1); border-bottom: 1px solid var(--line); }
.pins-list .msg-actions { position: static; display: flex; }

@media (max-width: 760px) {
  .messages { overscroll-behavior: contain; }
  .msg { gap: var(--sp-2); padding-inline: var(--sp-3); }
  .chat-error.row { gap: var(--sp-2); padding-inline: var(--sp-3); }
  .chat-error.row > i { width: 32px; }
  .msg-gutter { width: 32px; }
  .msg-avatar .avatar { --av: 32px; }
  /* On a phone a message's actions are its long-press sheet (quick reactions first), not a
     toolbar laid over its own text. */
  :is(.msg, .thread-post) > .msg-actions.msg-actions { display: none; }
  /* A long-press opens the sheet (Copy Text is in it), not iOS's selection callout. */
  .msg { -webkit-touch-callout: none; }
  .msg:not(:focus-within) .rx-add { opacity: 0; pointer-events: none; }
  /* 44px to tap: the avatar's target reaches past its 32px face; bars and pills are 44 tall. */
  .msg-avatar { position: relative; }
  .msg-avatar::after { content: ''; position: absolute; inset: -6px; }
  .first-unread-button, .jump-bottom, .history-older { min-height: var(--control-touch); }
  .history-older button { min-height: var(--control-touch); }
  .outgoing-failed button { min-height: var(--control-touch); }
  .msg-thread { min-height: var(--control-touch); }
  .gif-embed { max-width: 100%; }
}
/* Writing a message: the dock under the message list (typing line, upload
   chips, reply/error bars) and the composer form itself (Chat.tsx), plus its
   suggestion list and the phone "+" menu. The composer is a grid: writing
   area on row 1, actions on row 2, status on row 3. */

/* Dock */
.composer-dock {
  position: relative;
  flex-shrink: 0;
  container-type: inline-size;
  padding: var(--sp-2) var(--sp-4) var(--sp-3);
  border-top: 1px solid var(--line);
  background: var(--main-bg);
}
.composer-dock:has(> .typing-line) { padding-top: 0; }
.typing-line { display: flex; align-items: center; gap: var(--sp-2); min-height: 28px; padding: var(--sp-1) var(--sp-3); color: var(--dim); font-size: var(--fs-sm); line-height: var(--lh-body); user-select: none; }
/* Three dots, drawn (not typed). */
.typing-line .dots { display: inline-flex; gap: 3px; }
.typing-line .dots span { width: 5px; height: 5px; border-radius: 50%; background: currentColor; animation: typing-blink 1.2s var(--ease-loop) infinite; }
.typing-line .dots span:nth-child(2) { animation-delay: 0.2s; }
.typing-line .dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes typing-blink { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }

.composer-reply {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-1);
  padding: var(--sp-2) var(--sp-3);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--bg-2);
  color: var(--dim);
  font-size: var(--fs-sm);
}
.composer-reply > div { flex: 1; min-width: 0; }
.composer-reply strong { color: var(--text); }
.composer-reply p { margin-top: var(--sp-0); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.composer-error {
  margin: var(--sp-1) 0 var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-left: 3px solid var(--danger);
  border-radius: var(--radius-md);
  background: var(--bg-2);
  color: var(--text);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
}
.composer-error button { margin-left: var(--sp-2); padding: var(--sp-1); background: transparent; color: var(--accent); }

/* Upload chips (ComposerAttachments.tsx) */
.composer-files { display: flex; gap: var(--sp-2); max-height: 124px; padding: var(--sp-1) 0 var(--sp-2); overflow-x: auto; }
.composer-file { display: flex; flex: 0 0 260px; align-items: center; gap: var(--sp-2); min-width: 0; padding: var(--sp-2); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); }
.composer-file > img,
.composer-file-icon { flex-shrink: 0; width: 48px; height: 48px; border-radius: var(--radius-sm); object-fit: cover; }
.composer-file-icon { display: grid; place-items: center; background: var(--bg-3); color: var(--dim); font-size: var(--fs-xl); }
.composer-file-info { display: grid; flex: 1; gap: var(--sp-1); min-width: 0; }
.composer-file-info strong { overflow: hidden; font-size: var(--fs-sm); text-overflow: ellipsis; white-space: nowrap; }
.composer-file-info :is(span, small) { color: var(--dim); font-size: var(--fs-xs); }
.composer-file progress { width: 100%; height: 4px; accent-color: var(--accent); }
.composer-file > button,
.composer-reply > button { flex-shrink: 0; display: grid; place-items: center; width: var(--control-sm); height: var(--control-sm); border-radius: var(--radius-md); background: transparent; color: var(--dim); }
.composer-file > button:hover,
.composer-reply > button:hover { background: var(--hover); color: var(--text); }

.composer-readonly { padding: var(--sp-3) var(--sp-4); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-3); color: var(--faint); font-size: var(--fs-md); text-align: center; }

/* Composer */
.composer {
  position: relative;
  display: grid;
  grid-template-columns: var(--control-md) auto var(--control-md) var(--control-md) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--bg-2) var(--field-opacity, 100%), transparent);
  outline: 2px solid transparent;
  outline-offset: -1px;
  transition: outline-color var(--dur-fast) var(--ease);
  /* Text inset of the writing area, shared by the textarea and its placeholder overlay. */
  --write-block: calc((var(--control-md) - var(--fs-lg) * var(--lh-body)) / 2);
  --write-end: calc(var(--control-md) + var(--sp-1));
}
.composer:focus-within { outline-color: var(--accent); }
.composer-writing-area { position: relative; grid-column: 1 / -1; grid-row: 1; min-width: 0; }
/* The placeholder, drawn over the empty textarea so channel emoji use the app's emoji style. */
.composer-placeholder {
  position: absolute;
  inset: 0 var(--write-end) auto 0;
  padding: var(--write-block) var(--sp-1);
  overflow: hidden;
  color: var(--dim);
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
}
.composer textarea[data-placeholder-overlay]::placeholder { color: transparent; }
/* A hint, not content: the channel's emoji is dimmed with the text. */
.composer-placeholder .flat-emoji { opacity: 0.6; }
.composer textarea {
  display: block;
  width: calc(100% - var(--write-end));
  min-width: 0;
  min-height: var(--control-md);
  max-height: min(200px, 35dvh);
  padding: var(--write-block) var(--sp-1);
  overflow-y: auto;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
  resize: none;
}
.composer textarea::placeholder { color: var(--dim); }
.composer textarea:focus,
.composer textarea:focus-visible { outline: none; }
.composer-expanded .composer textarea { min-height: var(--composer-expanded-min, min(240px, 35dvh)); max-height: min(420px, 45dvh); }

.composer-tools { position: static; display: flex; grid-column: 2; grid-row: 2; align-items: center; min-width: 0; }
.composer-tools button { flex-shrink: 0; display: grid; place-items: center; width: var(--control-md); height: var(--control-md); border-radius: var(--radius-md); background: transparent; color: var(--dim); }
.composer-tools button:hover,
.composer-tools button[aria-expanded='true'] { background: var(--hover); color: var(--text); }
/* The expand toggle sits at the top-right of the writing area. */
.composer-tools > button:last-child { position: absolute; top: var(--sp-2); right: var(--sp-3); z-index: var(--z-raised); }
.composer-format {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--sp-1);
  width: 0;
  overflow: hidden;
  visibility: hidden;
  opacity: 0;
  scrollbar-width: none;
  transition: width var(--dur-base) var(--ease), opacity var(--dur-fast) var(--ease), visibility var(--dur-base);
}
.composer-format::-webkit-scrollbar { display: none; }
.composer-format button { scroll-margin-inline: var(--sp-1); }
.has-format .composer-format { width: clamp(40px, calc(100cqi - 390px), 200px); overflow-x: auto; visibility: visible; opacity: 1; }

.composer > :is(.attach-btn, .gif-btn, .emoji-btn, .send) {
  grid-row: 2;
  display: grid;
  place-items: center;
  width: var(--control-md);
  height: var(--control-md);
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: var(--bg-3);
  color: var(--text);
}
.composer > :is(.attach-btn, .emoji-btn) { font-size: var(--fs-lg); }
.composer > :is(.attach-btn, .gif-btn, .emoji-btn):hover { background: var(--hover); }
.composer > .attach-btn { grid-column: 1; }
.composer > .gif-btn { grid-column: 3; font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: 0.05em; }
.composer > .emoji-btn { grid-column: 4; }
/* Without a GIF button (threads) the emoji button takes its place. */
.composer:not(:has(> .gif-btn)) > .emoji-btn { grid-column: 3; }
.composer > .send {
  grid-column: 6;
  width: auto;
  min-width: 76px;
  padding: 0 var(--sp-4);
  border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 22%, var(--bg-2));
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}
.composer > .send:disabled { opacity: 0.5; cursor: default; }
/* Ready to send: the solid accent. */
.composer > .send:not(:disabled) { background: var(--accent); color: var(--on-accent); }

/* Status row: the send-key hint (only while you type) shares the action row; status and
   character count sit below. */
.composer-foot { display: contents; color: var(--dim); font-size: var(--fs-xs); }
.composer-enter { grid-column: 5; grid-row: 2; min-width: 0; overflow: hidden; color: var(--dim); font-size: var(--fs-xs); text-align: right; text-overflow: ellipsis; white-space: nowrap; }
.composer-status { grid-column: 1 / 6; grid-row: 3; min-width: 0; color: var(--dim); font-size: var(--fs-xs); overflow-wrap: anywhere; }
.composer-limit { grid-column: 6; grid-row: 3; font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.composer-limit.over { color: var(--danger); font-weight: var(--fw-bold); }
.composer-status:empty,
.composer-limit:empty { display: none; }
/* Narrow (a thread, a small window): the short hint; with the format bar open, none. */
@container (max-width: 560px) { .composer-enter-more { display: none; } .has-format .composer-enter { display: none; } }
/* Too narrow for the tools and Send on one row (a chat column squeezed by an open thread): the row wraps,
   Send last at the right, so nothing overlaps or runs past the column's edge. */
@media (min-width: 761px) {
  @container (max-width: 340px) {
    .composer { display: flex; flex-wrap: wrap; }
    .composer > .composer-writing-area { flex: 1 0 100%; }
    .composer > .attach-btn { order: 1; }
    .composer > .composer-tools { order: 2; }
    .composer > :is(.capture-btn-wrap, .gif-btn) { order: 3; }
    .composer > .emoji-btn { order: 4; }
    .composer > .ib-newbrief { order: 5; }
    .composer > .send { order: 6; margin-left: auto; }
    .composer-enter { display: none; }
    .composer-status, .composer-limit { order: 7; flex-basis: 100%; }
  }
}

/* In a thread the reply box is the same Composer, on the dock's surface, with its broadcast option below. */
.thread-composer-dock { background: var(--bg-1); }
.thread-broadcast { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2); color: var(--dim); font-size: var(--fs-xs); }
.thread-broadcast input { accent-color: var(--accent); }

/* Suggestions: @mentions and :emoji:, the composer's width, just above it. */
.mention-pop {
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  z-index: var(--z-popover);
  /* Whole rows: seven 32px rows and the list's padding. */
  max-height: min(calc(7 * 32px + 2 * var(--sp-1)), 35dvh);
  margin-bottom: var(--sp-2);
  padding: var(--sp-1);
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-3);
  box-shadow: var(--shadow-2);
}
.mention-row { display: flex; align-items: center; gap: var(--sp-2); height: 32px; padding: 0 var(--sp-2); border-radius: var(--radius-md); font-size: var(--fs-md); cursor: pointer; }
.mention-row:is(.sel, :hover) { background: var(--accent); color: var(--on-accent); }
.mention-row .mu { color: var(--dim); font-size: var(--fs-sm); }
.mention-row .mention-broadcast { display: grid; place-items: center; width: 24px; height: 24px; }
.mention-row:is(.sel, :hover) .mu { color: color-mix(in srgb, var(--on-accent) 75%, transparent); }
.ac-emoji { display: inline-grid; place-items: center; width: 24px; font-size: var(--fs-xl); }
.ac-emoji .cemoji { width: 24px; height: auto; }
.ac-emoji .flat-emoji { margin: 0; }
/* A channel suggestion's mark: its own leading emoji, or # (or a speaker for voice), the size of a row's avatar. */
.ac-channel { display: inline-grid; place-items: center; flex: none; width: 24px; height: 24px; color: var(--dim); }
.ac-channel .flat-emoji { margin: 0; }

/* Phone "+" menu */
.plus-pop { position: absolute; bottom: calc(100% + var(--sp-2)); left: var(--sp-3); z-index: var(--z-popover); min-width: 180px; overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-2); box-shadow: var(--shadow-2); }
.plus-row { display: flex; align-items: center; gap: var(--sp-3); width: 100%; padding: var(--sp-3) var(--sp-4); font-size: var(--fs-md); text-align: left; }
.plus-row:hover { background: var(--hover); }
.plus-row i { width: 16px; color: var(--dim); text-align: center; }

@media (max-width: 760px) {
  .composer-dock { padding: var(--sp-1) var(--sp-2) var(--studio-composer-bottom, max(var(--sp-1), env(safe-area-inset-bottom))); }
  .composer { grid-template-columns: var(--control-touch) auto minmax(0, 1fr) auto; gap: var(--sp-1); padding: var(--sp-1) var(--sp-2); }
  .composer { --write-block: calc((var(--control-touch) - var(--fs-lg) * var(--lh-body)) / 2); --write-end: calc(var(--control-touch) + var(--sp-1)); }
  .composer textarea { min-height: var(--control-touch); }
  .composer > :is(.attach-btn, .send),
  .composer-tools button { width: var(--control-touch); height: var(--control-touch); }
  .composer > .send { grid-column: 4; width: auto; }
  .composer > :is(.gif-btn, .emoji-btn),
  .composer-enter { display: none; }
  .composer-tools > button:last-child { top: var(--sp-1); right: var(--sp-2); }
  .has-format .composer-format { width: clamp(44px, calc(100cqi - 210px), 240px); }
  .composer-status { grid-column: 1 / -1; }
  .composer-limit { grid-column: 1 / -1; grid-row: 4; }
  .composer-file { flex-basis: 240px; }
  .composer-file > button,
  .composer-reply > button { width: var(--control-touch); height: var(--control-touch); }
  .composer-error { max-height: 110px; overflow-y: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .typing-line .dots span { animation: none; }
}
/* The chat sidebar's list: places (Catch up, Threads, Notes), channel categories,
   Groups and People. One row for everything: 32px tall (44px on phones), a 24px icon
   column, the same 8px insets on both sides, and the same trail (counts, dots, marks)
   on the right. Unread is a bold name with a dot; only mentions get a count, and
   conversations (DMs, groups) count everything, since it's all addressed to you. */
.side-nav { display: flex; flex-direction: column; flex-shrink: 0; padding: var(--sp-2) var(--sp-2) 0; }
/* The phone's fold row for the places (hidden on wider screens, where the four rows always show). */
.side-nav > .side-nav-toggle { display: none; }
.side-nav-toggle .side-name { text-align: left; }
.side-nav-toggle .side-icon i { font-size: 11px; transition: transform var(--dur-fast) var(--ease); }
.side-nav.open .side-nav-toggle .side-icon i { transform: rotate(90deg); }
.chan-section { flex: 1; min-height: 0; overflow-y: auto; padding: var(--sp-2) var(--sp-2) var(--sp-5); }
.chan-group { margin-bottom: var(--sp-3); }
.chan-group:last-child { margin-bottom: 0; }

/* Section labels (categories, Groups, People) share the row's left inset. */
/* Section labels are small: --dim keeps them at AA contrast (--faint measured 3.7:1). */
.chan-label { display: flex; align-items: center; gap: var(--sp-2); min-height: 28px; padding: 0 var(--sp-2); color: var(--dim); font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: 0.04em; text-transform: uppercase; }
.side-add { display: grid; place-items: center; width: 24px; height: 24px; margin-left: auto; padding: 0; border: 0; border-radius: var(--radius-sm); background: none; color: var(--faint); font-size: var(--fs-xs); cursor: pointer; }
/* The glyph sits on the right of its box, so the plus lines up with the trail's counts and dots. */
.side-add { justify-items: end; padding-right: 2px; }
.side-add:focus-visible { background: var(--hover); color: var(--text); }
/* A section's name is its collapse toggle; the chevron turns when it's collapsed. */
.chan-toggle { display: flex; flex: 1; align-self: stretch; min-width: 0; align-items: center; gap: var(--sp-1); padding: 0; background: none; color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit; text-align: left; }
.chan-toggle > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chan-toggle:hover { color: var(--text); }
.chan-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--radius-sm); }
.chan-chevron { flex: none; width: 10px; font-size: 9px; transition: transform var(--dur-fast) var(--ease); }
.chan-toggle[aria-expanded='false'] .chan-chevron { transform: rotate(-90deg); }

.side-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  box-sizing: border-box;
  width: 100%;
  min-height: 32px;
  margin: 0;
  padding: 0 var(--sp-2);
  border: 0;
  border-radius: var(--radius-md);
  background: none;
  color: var(--dim);
  font: inherit;
  font-size: var(--fs-md);
  line-height: var(--lh-tight);
  text-align: left;
  cursor: pointer;
}
/* Hover only where there's a pointer to hover with: on touch, a tap would leave the row lit. */
@media (hover: hover) {
  .side-row:hover, .vc-member:hover { background: var(--hover); color: var(--text); }
  .side-add:hover { background: var(--hover); color: var(--text); }
}
.side-row.active { background: var(--active); color: var(--text); }
.side-row:focus-visible, .side-row > button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.side-icon { display: grid; flex: none; place-items: center; width: 24px; height: 24px; color: var(--faint); font-weight: var(--fw-semibold); }
.side-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Name styles are bold by default; in the list a name is bold only when it's unread. */
.side-row .side-name .dn { font-weight: inherit; }
/* A channel's leading emoji stands as its icon. */
.side-icon .flat-emoji { width: 18px; height: 18px; margin: 0; vertical-align: 0; }
.side-trail { display: flex; flex: none; align-items: center; gap: var(--sp-1); margin-left: auto; }
.side-trail:empty { display: none; }
.side-row.unread .side-name { color: var(--text); font-weight: var(--fw-semibold); }
/* Muted: quieter words and icon (colour, not row opacity, so a mention's count stays at full
   strength), and a small bell-slash in the trail so muted doesn't read as merely read. */
.side-row.muted:not(.unread) :is(.side-name, .side-icon) { color: var(--faint); }
.side-row.muted:not(.unread, .active, :hover, :focus-visible) .side-icon .flat-emoji { opacity: 0.55; }
.side-muted { color: var(--faint); font-size: var(--fs-xs); }
.side-row.in-voice .side-name { color: var(--online); font-weight: var(--fw-semibold); }
.side-row.chan[draggable='true'] { cursor: grab; }
.side-row.chan.drag-over { box-shadow: inset 0 2px 0 var(--accent); }

/* Trail marks: a mention count (red), the unread dot, a place's quiet total, voice. */
.side-row .badge { display: inline-grid; place-items: center; box-sizing: border-box; min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--radius-full); background: var(--danger); color: var(--on-danger); font-size: var(--fs-xs); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }
.unread-dot { width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--text); }
.side-count { margin-left: auto; color: var(--dim); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.in-voice-dot { width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--online); }
.side-row .dm-fav-star { color: var(--warning); font-size: var(--fs-xs); }

/* Group and person rows are two buttons (People.tsx): the padding moves onto them. */
.side-row:is(.person, .group) { gap: 0; padding: 0; }
.side-row:is(.person, .group) > button { display: flex; align-items: center; align-self: stretch; min-width: 0; padding: 0 var(--sp-2); border: 0; border-radius: inherit; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.side-row:is(.person, .group) > .person-open { flex: 1; gap: var(--sp-2); }
.side-row.person > .person-face { flex: none; padding-right: 0; }

/* The list fades out above the dock, so it reads as continuing; scrolled down, the top
   edge fades too. The bottom padding lets the last row scroll clear of the fade. */
.sidebar .chan-section { --fade-top: 0px; -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--fade-top), #000 calc(100% - var(--sp-5)), transparent); mask-image: linear-gradient(to bottom, transparent, #000 var(--fade-top), #000 calc(100% - var(--sp-5)), transparent); }
.sidebar .chan-section.is-scrolled { --fade-top: var(--sp-5); }

/* A narrow sidebar (tablet): your role tag gives way so your name and the panel's buttons don't collide. */
@media (min-width: 761px) and (max-width: 1100px) { .user-panel .name .role-tag { display: none; } }
@media (max-width: 760px) {
  .side-row, .chan-label { min-height: var(--control-touch); }
  /* What's new, Catch up, Threads and Notes fold under one row until it's opened. */
  .side-nav > .side-nav-toggle { display: flex; }
  /* Only chat's nav folds (Nautilus's rail shares .side-nav, and has no fold row). */
  .sidebar .side-nav:has(> .side-nav-toggle):not(.open) > .side-row:not(.side-nav-toggle) { display: none; }
  .side-add { width: var(--control-touch); height: var(--control-touch); }
  .user-panel .logout { display: grid; place-items: center; min-width: var(--control-touch); min-height: var(--control-touch); }
  /* One button on a phone (Preferences, which holds Theme and Log out), so your name and status fit. */
  .user-panel .logout.panel-wide-only { display: none; }
  .vc-member { min-height: var(--control-touch); }
  .chan-section { overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
}
/* Column headers: the sidebar's workspace head and the conversation header (the thread
   panel's head matches them in threads.css). All 56px with one bottom rule, so every
   column's header shares a baseline. The conversation header reads left to right: what
   this is (mark, name with its menu, topic), the calendar strip, then three or four
   actions (Threads, Pins, Search; Add people in a group). Nautilus's page header (.hr-pagehead,
   hr.css) is the same header. */
.ws-head, .main-head, .hr-pagehead {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--sp-2);
  box-sizing: border-box;
  height: 56px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 65%, transparent);
  background: var(--surface-head);
  -webkit-user-select: none;
  user-select: none;
}
.ws-head { padding: 0 var(--sp-3) 0 var(--sp-4); font-size: var(--fs-lg); font-weight: var(--fw-bold); }
.ws-head > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Feed and the tool switcher: a row under the drawer's head on a phone (one header). */
.ws-tools { display: none; }
.ws-gear { display: grid; flex: none; place-items: center; width: var(--control-md); height: var(--control-md); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); color: var(--dim); font-size: var(--fs-md); cursor: pointer; }

/* The header measures itself: in a narrow header (a tablet, or beside an open thread) the topic
   steps aside before any action is pushed out. */
.main-head { position: relative; padding: 0 var(--sp-3) 0 var(--sp-4); container: head / inline-size; }
body.kp-theater .main-head { display: none; }
.main-head .hash { display: grid; flex: none; place-items: center; min-width: 20px; height: 24px; color: var(--faint); font-size: var(--fs-lg); font-weight: var(--fw-semibold); }
.main-head .hash .flat-emoji { width: 20px; height: 20px; margin: 0; vertical-align: 0; }

/* The name: its menu (notifications; permissions, edit, delete for managers). */
/* The name keeps its full width (up to 40% of the header): it shrinks last. */
.desktop-channel-name { flex: 0 0 auto; min-width: 0; max-width: min(40%, 40ch); color: var(--text); font-size: var(--fs-lg); font-weight: var(--fw-bold); line-height: var(--lh-tight); }
b.desktop-channel-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.head-name { display: flex; align-items: center; gap: var(--sp-1); height: var(--control-md); margin-left: calc(-1 * var(--sp-1)); padding: 0 var(--sp-2) 0 var(--sp-1); border: 0; border-radius: var(--radius-md); background: none; font-family: inherit; text-align: left; cursor: pointer; }
.head-name > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.head-name > i { flex: none; color: var(--faint); font-size: 10px; }
.head-name > .head-muted { font-size: var(--fs-xs); }
.head-name:focus-visible { background: var(--hover); }

/* The topic takes whatever the calendar strip doesn't use, and keeps at least 40% of the
   header (up to 280px): when room runs short the strip drops its items first. A click shows
   all of it. The divider sits midway between the name and the topic (16px each side). */
.head-topic { flex: 1 1 0; min-width: min(40%, 280px); height: var(--control-md); padding: 0 var(--sp-2) 0 var(--sp-4); border: 0; border-left: 1px solid var(--line); border-radius: 0; background: none; color: var(--dim); font: inherit; font-size: var(--fs-sm); text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.head-topic[aria-expanded='true'] { color: var(--text); }
/* The calendar strip is as wide as what it shows (calendar.css drops items that don't fit),
   and sits with the actions on the right; without a topic it's pushed there. */
.main-head > .calendar-timeline { flex: 0 1 auto; min-width: var(--control-md); }
.main-head:not(:has(.head-topic)) > .calendar-timeline, .main-head:not(:has(.head-topic, .calendar-timeline)) > .head-actions { margin-left: auto; }
/* The calendar button matches the actions beside it, glyph size included. */
.main-head .cal-timeline-inner .cal-timeline-open { justify-content: center; box-sizing: border-box; width: var(--control-md); min-height: 0; height: var(--control-md); padding: 0; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); color: var(--text); font-size: var(--fs-md); }
/* A group's head count after its name: the same divider and inset as a topic. */
.main-head .head-people-count { height: var(--control-md); padding: 0 var(--sp-2) 0 var(--sp-4); border-left: 1px solid var(--line); border-radius: 0; }

.head-actions { display: flex; flex: none; align-items: center; gap: var(--sp-1); margin-left: var(--sp-2); }
.head-actions .icon-btn { display: grid; place-items: center; width: var(--control-md); height: var(--control-md); padding: 0; font-size: var(--fs-md); }

@media (hover: hover) {
  .head-name:hover { background: var(--hover); }
  .head-name:hover > i, .head-topic:hover { color: var(--text); }
  .ws-gear:hover { background: var(--hover); color: var(--text); }
}

/* Header panels (Popover.tsx): the topic in full; the people list adds its rows (people.css). */
.popover { position: fixed; z-index: var(--z-popover); max-width: min(480px, calc(100vw - var(--sp-4))); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); box-shadow: var(--shadow-2); }
.popover:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.topic-pop { padding: var(--sp-3) var(--sp-4); }
.topic-pop p { margin: 0; color: var(--text); font-size: var(--fs-md); line-height: var(--lh-body); white-space: pre-wrap; overflow-wrap: anywhere; -webkit-user-select: text; user-select: text; }

/* A calendar that can't be reached: a quiet dot on its button, not status text. */
/* The next event's time keeps its teal but leans toward the text colour, for AA contrast in every theme
   (pure teal measured 3.2:1 on light). */
.main-head .cal-timeline-next small { color: color-mix(in srgb, var(--teal, var(--accent)) 70%, var(--text)); }
.cal-timeline-open { position: relative; }
.cal-timeline-inner .cal-timeline-open > .cal-timeline-alert { display: block; position: absolute; top: 7px; right: 7px; width: 7px; height: 7px; border-radius: var(--radius-full); background: var(--warning); box-shadow: 0 0 0 2px var(--bg-2); }

@media (max-width: 760px) {
  .app-shell:has(> .app:not(.on-tool)) > .studio-mobile-header { display: none; }
  .ws-tools { display: flex; gap: var(--sp-2); padding: var(--sp-2); border-bottom: 1px solid color-mix(in srgb, var(--line) 65%, transparent); }
  .ws-tool { display: flex; flex: 1; justify-content: center; align-items: center; gap: var(--sp-2); height: var(--control-touch); padding: 0 var(--sp-3); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); color: var(--text); font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
  .ws-tool i { color: var(--dim); }
  .ws-gear, .main-head .cal-timeline-inner .cal-timeline-open { width: var(--control-touch); height: var(--control-touch); }
  /* The strip's one line is as tall as the touch-sized button, so the button isn't clipped. */
  .main-head .cal-timeline-inner { height: var(--control-touch); }
  .main-head { gap: var(--sp-1); padding: 0 var(--sp-2); }
  .main-head .desktop-channel-name, .head-topic, .head-actions :is(.head-pins, .head-search) { display: none; }
  /* A group's "N members" is the faces' own popover (the faces open it too): on a phone the faces are
     enough, so the name and every button fit. */
  .main-head .head-people-count { display: none; }
  /* The name keeps its width (up to 60%); the calendar strip gives way first. */
  .mobile-channel-title { display: flex; flex: 0 0 auto; max-width: 60%; align-items: center; gap: var(--sp-2); min-width: 0; min-height: var(--control-touch); padding: 0; border: 0; background: transparent; color: var(--text); font: inherit; font-size: var(--fs-lg); font-weight: var(--fw-bold); text-align: left; }
  .mobile-channel-title > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mobile-channel-title > i { flex: none; color: var(--dim); font-size: 11px; }
  .main-head :is(.icon-btn, .hamburger) { min-width: var(--control-touch); height: var(--control-touch); }
  .head-actions { margin-left: auto; gap: 0; }
}
@media (min-width: 761px) { .mobile-channel-title { display: none; } }
/* Light themes: the shared header rule at full line strength, so the baseline reads. */
[data-scheme='light'] :is(.ws-head, .main-head, .thread-dock-head, .hr-pagehead) { border-bottom-color: var(--line); }

/* Narrow headers (a tablet, or beside an open thread): the next event steps aside first, then the
   topic; very narrow, Pinned and Search move into the name's menu. Last in the file so they win
   over the base rules. */
@container head (max-width: 600px) { .main-head .cal-timeline-next { display: none; } }
@container head (max-width: 480px) { .head-topic { display: none; } }
/* Very narrow: Pinned and Search move into the name's menu, so the header never pushes an action out. */
@container head (max-width: 380px) { .head-actions :is(.head-pins, .head-search) { display: none; } }
/* People and Groups in the sidebar, and who's-in-this-conversation in the header
   (People.tsx). The rows themselves are the sidebar's (chat/sidebar.css); this file
   has what only people have: faces, notes, the offline fold, the participant list. */
/* The name is the row: it keeps its width (ellipsising only when it alone overflows); the note gives way first. */
.person-open .nm { flex: 0 0 auto; max-width: 100%; }
/* A status (or what they're doing) after the name, muted, cut short before the trail. */
.person-note { display: flex; flex: 0 100 auto; align-items: center; gap: var(--sp-1); min-width: 0; color: var(--faint); font-size: var(--fs-xs); }
.person-note > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Every activity icon in one box (fa-video is wider than 1em), so the gap to its label is always 4px. */
.person-note .member-activity i { flex: none; width: 1.25em; text-align: center; }
.person-note .member-activity { flex: none; display: inline-flex; align-items: center; gap: var(--sp-1); margin: 0; color: inherit; font-size: inherit; }
.person-trail { display: flex; flex: none; align-items: center; gap: var(--sp-1); margin-left: auto; }
.person-trail:empty { display: none; }
.person-trail .dm-fav-star { margin-left: 0; }
/* The face is its own target (the profile): a ring on hover says so. */
.person-face:hover .avatar, .person-face:focus-visible .avatar { box-shadow: 0 0 0 2px color-mix(in srgb, var(--text) 40%, transparent); }
/* Offline: face and words fade together (the dot keeps its colour, the badge stays). */
.dm-row.person.off { --av-fade: 0.5; }
.dm-row.person.off :is(.nm, .person-note) { opacity: 0.6; }
.dm-row.person.off:is(:hover, :focus-within, .active) { --av-fade: 1; }
.dm-row.person.off:is(:hover, :focus-within, .active) :is(.nm, .person-note) { opacity: 1; }
/* Everyone offline you've never talked to, folded under one line. */
.people-offline { display: flex; align-items: center; gap: var(--sp-2); width: 100%; min-height: 28px; padding: 0 var(--sp-2); border: 0; border-radius: var(--radius-sm); background: none; color: var(--faint); font: inherit; font-size: var(--fs-xs); font-weight: var(--fw-semibold); text-align: left; cursor: pointer; }
.people-offline:hover { color: var(--text); background: var(--hover); }
.people-offline i { width: 10px; font-size: 10px; }
.people-status { margin: 0; padding: var(--sp-1) var(--sp-2); color: var(--faint); font-size: var(--fs-xs); }
/* Find a person: phones only, where the drawer is long. */
.people-filter { display: none; }
/* "Unread above/below" pills over the list's top and bottom edges (UnreadEdge.tsx):
   the edges take no room, and the bottom pill sits in the list's faded strip. */
.unread-edge { position: relative; z-index: 3; display: flex; justify-content: center; height: 0; pointer-events: none; }
.unread-edge-pill { display: flex; align-items: center; gap: var(--sp-1); height: 24px; padding: 0 var(--sp-3); border: 0; border-radius: var(--radius-full); background: var(--accent); color: var(--on-accent); font: inherit; font-size: var(--fs-xs); font-weight: var(--fw-semibold); box-shadow: var(--shadow-2); pointer-events: auto; cursor: pointer; }
.unread-edge.above .unread-edge-pill { transform: translateY(var(--sp-1)); }
.unread-edge.below .unread-edge-pill { transform: translateY(calc(-100% - var(--sp-1))); }
/* The sidebar's bottom pill is a row of its own under the list (12 px above and below it), as in a call
   (voice/call.css): the list ends above it, so it never covers the last conversation. */
.sidebar .unread-edge.below:has(.unread-edge-pill) { height: auto; flex: none; padding: var(--sp-3) 0; }
.sidebar .unread-edge.below .unread-edge-pill { transform: none; }
.sidebar .unread-edge.below:has(.unread-edge-pill) + * { margin-top: 0; }
/* A bot's DM count (Calendar, Currents, Nautilus) is unread, not a mention: a quiet badge. */
.badge.quiet { background: color-mix(in srgb, var(--text) 16%, transparent); color: var(--text); }
.unread-edge-pill.mention { background: var(--danger); color: var(--on-danger); }

/* Header: the other person's face, or the group's faces, in place of the # mark. */
.head-people { display: flex; flex: none; align-items: center; padding: 0; border: 0; border-radius: var(--radius-full); background: none; cursor: pointer; }
/* A group's head count after its name: the same list as the faces. */
.head-people-count { flex: none; padding: var(--sp-1) var(--sp-2); border: 0; border-radius: var(--radius-sm); background: none; color: var(--dim); font: inherit; font-size: var(--fs-sm); white-space: nowrap; cursor: pointer; }
.head-people-count:hover, .head-people-count[aria-expanded='true'] { background: var(--hover); color: var(--text); }
.people-pop {
  position: fixed;
  z-index: var(--z-popover);
  display: flex;
  flex-direction: column;
  min-width: 220px;
  max-width: min(320px, calc(100vw - var(--sp-4)));
  max-height: min(420px, 70vh);
  overflow-y: auto;
  padding: var(--sp-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-2);
  box-shadow: var(--shadow-2);
}
.people-pop-row { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--control-md); padding: var(--sp-1) var(--sp-2); border: 0; border-radius: var(--radius-sm); background: none; color: var(--text); font: inherit; font-size: var(--fs-md); text-align: left; cursor: pointer; }
.people-pop-row:hover, .people-pop-row:focus-visible { background: var(--hover); }
.people-pop-row .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.people-pop-you, .people-pop-presence { color: var(--dim); font-size: var(--fs-xs); }
.people-pop-row.off { --av-fade: 0.5; }
.people-pop-row.off .nm { opacity: 0.6; }
@media (max-width: 760px) {
  .people-pop-row, .people-offline { min-height: var(--control-touch); }
  /* The pill stays slim; its tap target reaches 44px. */
  .unread-edge-pill { position: relative; }
  .unread-edge-pill::after { content: ''; position: absolute; inset: -10px 0; }
  .people-filter { display: flex; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-1); padding: 0 var(--sp-3); min-height: var(--control-touch); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); color: var(--dim); }
  .people-filter input { flex: 1; min-width: 0; border: 0; outline: 0; background: none; color: var(--text); font: inherit; font-size: 16px; }
  .people-filter:focus-within { border-color: var(--accent); }
}
