/* ── Attachments tray (inside composer-inner, above the row) ── */
  .attachments-tray {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px 8px 0;
  }

  /* Link-preview tray — inline card showing OG snapshot for the first URL
     in the composer text. Same visual language as .att-card. */
  .link-preview-tray {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px 8px 0;
  }
  .link-preview-card {
    position: relative;
    display: flex; align-items: center; gap: 10px;
    padding: 8px 40px 8px 8px;
    background: var(--elevated);
    border-radius: var(--radius-m);
    overflow: hidden;
    cursor: pointer;
    transition: background var(--transition);
  }
  .link-preview-card:hover { background: var(--surface-hover, var(--glass)); }
  .link-preview-card-icon {
    position: relative;
    flex-shrink: 0;
    width: 44px; height: 44px;
    border-radius: var(--radius-s);
    background: var(--surface);
    color: var(--ink-muted);
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
  }
  .link-preview-card-icon img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover; display: block;
  }
  /* Favicons are tiny square icons — keep them centered at their natural
     size instead of stretching to cover the whole tile. */
  .link-preview-card-icon img.favicon {
    position: static;
    width: 22px; height: 22px;
    object-fit: contain;
  }
  .link-preview-card-meta {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; justify-content: center;
    gap: 2px;
  }
  .link-preview-card-name {
    font-size: var(--font-md); font-weight: 600; color: var(--ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .link-preview-card-title {
    font-size: var(--font-xs); color: var(--ink-ghost);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .link-preview-card-action {
    display: none;
    font-size: var(--font-xs); color: var(--ink-secondary);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .link-preview-card:hover .link-preview-card-title { display: none; }
  .link-preview-card:hover .link-preview-card-action { display: block; }
  /* Loading state has nothing to "go" to — keep it static. */
  .link-preview-card-loading { cursor: default; }
  .link-preview-card-loading:hover { background: var(--elevated); }
  .link-preview-card-remove {
    position: absolute; top: 50%; right: 12px;
    transform: translateY(-50%);
    width: 24px; height: 24px; border-radius: 50%;
    background: transparent; color: var(--ink-ghost);
    border: none; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: color var(--transition), background var(--transition);
  }
  .link-preview-card-remove:hover { color: var(--ink); background: var(--glass); }
  .link-preview-card-loading .link-preview-card-name,
  .link-preview-card-loading .link-preview-card-title {
    color: var(--ink-ghost);
  }

  /* External-link confirm modal — overrides the generic .modal-overlay /
     .modal so we can have a denser, single-purpose dialog without
     touching shared styles. */
  .link-confirm-overlay {
    display: none;
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.55);
    z-index: 100;
    align-items: center; justify-content: center;
  }
  .link-confirm-overlay.visible { display: flex; }
  .link-confirm-modal {
    position: relative;
    width: min(560px, calc(100vw - 32px));
    max-width: 560px;
    background: var(--deep);
    border: 1px solid var(--border);
    border-radius: var(--radius-l);
    padding: var(--space-lg);
    box-shadow: var(--shadow-l);
    display: flex; flex-direction: column;
    gap: var(--space-md);
  }
  .link-confirm-header {
    display: flex; align-items: center; justify-content: space-between;
  }
  .link-confirm-title {
    margin: 0;
    font-size: 18px; font-weight: 600; color: var(--ink);
  }
  .link-confirm-close {
    width: 32px; height: 32px;
    border: none; background: transparent; cursor: pointer;
    color: var(--ink-muted);
    display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-pill);
    transition: background var(--transition), color var(--transition);
  }
  .link-confirm-close:hover { background: var(--surface); color: var(--ink); }
  .link-confirm-body { display: flex; flex-direction: column; gap: 14px; }
  .link-confirm-prompt {
    font-size: var(--font-md); color: var(--ink-secondary); line-height: 1.5;
    word-break: break-all;
  }
  .link-confirm-prompt .link-confirm-url {
    color: var(--ink);
  }
  .link-confirm-remember {
    display: flex; align-items: center; gap: 10px;
    font-size: var(--font-sm); color: var(--ink-secondary);
    cursor: pointer; user-select: none;
  }
  .link-confirm-remember-cb {
    position: absolute;
    opacity: 0; pointer-events: none;
  }
  .link-confirm-remember-mark {
    width: 18px; height: 18px;
    border: 1.5px solid var(--border-mid);
    border-radius: 4px;
    flex-shrink: 0;
    background: transparent;
    transition: background var(--transition), border-color var(--transition);
    position: relative;
  }
  .link-confirm-remember-cb:checked + .link-confirm-remember-mark {
    background: var(--accent);
    border-color: var(--accent);
  }
  .link-confirm-remember-cb:checked + .link-confirm-remember-mark::after {
    content: '';
    position: absolute;
    left: 5px; top: 1px;
    width: 5px; height: 10px;
    border: solid white;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
  }
  .link-confirm-footer {
    display: flex; justify-content: flex-end;
  }
  .link-confirm-go {
    padding: 10px 22px;
    border: none;
    background: var(--accent);
    color: white;
    font-size: var(--font-md); font-weight: 600;
    border-radius: var(--radius-pill);
    cursor: pointer;
    transition: background var(--transition);
  }
  .link-confirm-go:hover { background: var(--accent-hover); }
  .att-card {
    position: relative;
    display: flex; align-items: center; gap: 10px;
    padding: 8px 40px 8px 8px;
    background: var(--elevated);
    border-radius: var(--radius-m);
    cursor: pointer;
    transition: background var(--transition);
    overflow: hidden;
  }
  .att-card:hover { background: var(--surface-hover, var(--glass)); }
  .att-card-icon {
    position: relative;
    flex-shrink: 0;
    width: 44px; height: 44px;
    border-radius: var(--radius-s);
    display: flex; align-items: center; justify-content: center;
    color: white;
    overflow: hidden;
    background: var(--accent);
  }
  /* Absolute positioning keeps the image filling the tile regardless of the
     flex sizing rules on the parent — flex children with percent heights
     don't always resolve, which showed as a tiny crop-to-top-left thumbnail
     instead of a 44×44 cover. */
  .att-card-icon img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover; display: block;
  }
  .att-card[data-kind="video"] .att-card-icon { background: var(--accent); }
  .att-card[data-kind="audio"] .att-card-icon { background: var(--pastel-rose); }
  .att-card[data-kind="file"] .att-card-icon { background: var(--pastel-indigo); }
  .att-card[data-kind="image"] .att-card-icon { background: var(--surface); color: var(--ink-muted); }
  .att-card-meta {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; justify-content: center;
    gap: 2px;
  }
  .att-card-name {
    font-size: var(--font-md); font-weight: 500; color: var(--ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .att-card-size {
    font-size: var(--font-xs); color: var(--ink-ghost);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .att-card-action {
    display: none;
    font-size: var(--font-xs); color: var(--ink-secondary);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .att-card:hover .att-card-action { display: block; }
  .att-card:hover .att-card-size { display: none; }
  .att-card-remove {
    position: absolute; top: 50%; right: 12px;
    transform: translateY(-50%);
    width: 24px; height: 24px; border-radius: 50%;
    background: transparent; color: var(--ink-ghost);
    border: none; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: color var(--transition), background var(--transition);
  }
  .att-card-remove:hover { color: var(--ink); background: var(--glass); }
  .att-card-progress {
    position: absolute; left: 0; bottom: 0;
    height: 2px;
    background: var(--accent);
    transition: width 0.12s linear;
    pointer-events: none;
  }
  .att-card.att-error { outline: 1px solid var(--coral); }
  .att-card.att-error .att-card-size { color: var(--coral); }

  .msg-attachments {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin-top: 6px; max-width: 100%;
    min-width: 0;
  }
  .msg-att-image {
    max-width: min(400px, 100%); max-height: 300px;
    width: auto; height: auto;
    border-radius: 8px; display: block; cursor: zoom-in;
    background: var(--surface);
    object-fit: contain;
    opacity: 0;
    transition: opacity var(--transition);
  }
  .msg-att-image.loaded { opacity: 1; }
  .msg-att-video-wrap {
    position: relative; display: block;
    max-width: min(420px, 100%); max-height: 320px;
    border-radius: 8px; overflow: hidden; background: #000;
  }
  .msg-att-video {
    width: 100%; height: 100%; display: block; object-fit: contain; background: #000;
    opacity: 0; transition: opacity var(--transition);
  }
  .msg-att-video-wrap.ready .msg-att-video { opacity: 1; }
  .msg-att-video-poster {
    position: absolute; inset: 0;
    background: #0d1218;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    z-index: 1;
    transition: opacity var(--transition);
  }
  .msg-att-video-poster svg { opacity: 0.85; transition: opacity var(--transition), transform var(--transition); }
  .msg-att-video-poster:hover svg { opacity: 1; transform: scale(1.08); }
  .msg-att-video-wrap.ready .msg-att-video-poster { opacity: 0; pointer-events: none; }
  .msg-att-video-fs {
    position: absolute; top: 8px; right: 8px;
    width: 32px; height: 32px; border-radius: 6px;
    background: rgba(0, 0, 0, 0.6); color: white;
    border: none; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    opacity: 0; transition: opacity var(--transition), background var(--transition);
  }
  .msg-att-video-wrap:hover .msg-att-video-fs { opacity: 1; }
  .msg-att-video-fs:hover { background: rgba(0, 0, 0, 0.85); }
  .msg-att-audio { width: min(360px, 100%); display: block; }
  .msg-att-file {
    display: flex; align-items: center; gap: 10px;
    width: min(360px, 100%); padding: 10px 12px;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: 8px; text-decoration: none; color: var(--ink);
    transition: background var(--transition);
  }
  .msg-att-file:hover { background: var(--elevated); }
  .msg-att-file-icon {
    flex-shrink: 0; width: 36px; height: 42px; border-radius: 4px;
    background: var(--accent); color: white;
    display: flex; align-items: center; justify-content: center;
    font-size: 10px; font-weight: 700; letter-spacing: 0.5px;
  }
  .msg-att-file-meta { flex: 1; min-width: 0; }
  .msg-att-file-name { font-size: var(--font-sm); color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .msg-att-file-size { font-size: var(--font-2xs); color: var(--ink-ghost); margin-top: 2px; }
  .msg-att-file-dl { color: var(--ink-ghost); flex-shrink: 0; }
  .msg-att-file:hover .msg-att-file-dl { color: var(--accent); }
  .msg-att-file-clickable { cursor: pointer; }
  .msg-att-file-btn {
    flex-shrink: 0; width: 32px; height: 32px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: none; border-radius: 6px;
    color: var(--ink-ghost); cursor: pointer; text-decoration: none;
    transition: background var(--transition), color var(--transition);
  }
  .msg-att-file-btn:hover { background: var(--surface); color: var(--accent); }

  /* ── File viewer modal ── */
  #kcFileViewer {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.78);
    backdrop-filter: blur(4px);
    z-index: 10001;
    display: none;
    align-items: center; justify-content: center;
    padding: 40px;
  }
  #kcFileViewer.visible { display: flex; }
  .fv-card {
    background: var(--surface);
    border-radius: 12px;
    width: min(900px, 100%); height: min(85vh, 1000px);
    display: flex; flex-direction: column;
    overflow: hidden;
    box-shadow: var(--shadow-l);
  }
  .fv-header {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
  }
  .fv-icon {
    flex-shrink: 0; width: 36px; height: 42px; border-radius: 4px;
    background: var(--accent); color: white;
    display: flex; align-items: center; justify-content: center;
    font-size: 10px; font-weight: 700; letter-spacing: 0.5px;
  }
  .fv-meta { flex: 1; min-width: 0; }
  .fv-name { font-size: var(--font-md); font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .fv-size { font-size: var(--font-xs); color: var(--ink-ghost); margin-top: 2px; }
  .fv-btn {
    flex-shrink: 0; width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: none; border-radius: 6px;
    color: var(--ink-secondary); cursor: pointer; text-decoration: none;
    transition: background var(--transition), color var(--transition);
  }
  .fv-btn:hover { background: var(--elevated); color: var(--ink); }
  .fv-body {
    flex: 1; min-height: 0; overflow: auto;
    background: var(--deep);
  }
  .fv-loading, .fv-error {
    padding: 40px; text-align: center; color: var(--ink-ghost); font-size: var(--font-md);
  }
  .fv-error { color: var(--coral); }
  .fv-pdf { width: 100%; height: 100%; border: none; display: block; background: #1e1e1e; }
  .fv-text {
    margin: 0; padding: 18px 22px;
    background: var(--deep);
    font-family: 'JetBrains Mono', SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--font-sm); line-height: 1.55;
    color: var(--ink);
    white-space: pre-wrap; word-wrap: break-word;
  }
  .fv-text > code { background: transparent; color: inherit; }
  .fv-md {
    padding: 22px 28px; max-width: 760px; margin: 0 auto;
    font-size: var(--font-md); line-height: 1.6; color: var(--ink);
  }
  .fv-md h1, .fv-md h2, .fv-md h3 { margin: 18px 0 10px; }
  .fv-md p, .fv-md ul, .fv-md ol { margin: 8px 0; }
  .fv-md code { background: var(--surface); padding: 1px 6px; border-radius: 4px; }
  .fv-md pre { background: var(--deep); padding: 12px; border-radius: 6px; overflow: auto; }
  .fv-csv-wrap { padding: 16px; overflow: auto; }
  .fv-csv {
    border-collapse: collapse; font-size: var(--font-sm);
    font-family: 'JetBrains Mono', SFMono-Regular, Menlo, Consolas, monospace;
    min-width: 100%;
  }
  .fv-csv th, .fv-csv td {
    padding: 6px 12px;
    border: 1px solid var(--border);
    text-align: left;
    white-space: nowrap;
    color: var(--ink);
  }
  .fv-csv thead th {
    background: var(--surface);
    font-weight: 600;
    position: sticky; top: 0;
    color: var(--ink);
  }
  .fv-csv tbody tr:nth-child(even) td { background: rgba(255,255,255,0.02); }

  /* ── Drag & drop overlay ── */
  #kcDropOverlay {
    position: fixed; inset: 0;
    background: rgba(15, 15, 26, 0.72);
    backdrop-filter: blur(4px);
    z-index: 10000;
    display: none;
    align-items: center; justify-content: center;
    pointer-events: none;
  }
  #kcDropOverlay.visible { display: flex; }
  #kcDropOverlay .drop-overlay-inner {
    border: 2px dashed var(--accent);
    border-radius: 16px;
    padding: 40px 56px;
    color: var(--ink);
    font-size: var(--font-lg); font-weight: 600;
    display: flex; flex-direction: column; align-items: center; gap: 14px;
    background: color-mix(in srgb, var(--accent) 10%, transparent);
  }
  #kcDropOverlay svg { color: var(--accent); opacity: 0.9; }

  /* ── Image lightbox ── */
  .kc-lightbox {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.92);
    z-index: 11000;
    display: none;
  }
  .kc-lightbox.visible {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
  }
  .kc-lightbox-topbar {
    position: absolute; top: 0; left: 0; right: 0;
    height: 64px;
    padding: 0 20px;
    display: flex; align-items: center; justify-content: space-between;
    color: var(--ink);
    z-index: 2;
  }
  .kc-lightbox-author { display: flex; align-items: center; gap: 10px; }
  .kc-lightbox-avatar {
    width: var(--avatar-md); height: var(--avatar-md); border-radius: var(--radius-full);
    display: flex; align-items: center; justify-content: center;
    color: white; font-weight: 600; font-size: var(--font-sm);
    flex-shrink: 0;
  }
  .kc-lb-name { font-size: var(--font-md); font-weight: 600; color: var(--ink); }
  .kc-lb-time { font-size: var(--font-2xs); color: var(--ink-muted); }
  .kc-lightbox-actions { display: flex; gap: 8px; }
  .kc-lightbox-actions > button,
  .kc-lightbox-actions > a {
    width: 40px; height: 40px;
    border-radius: 8px;
    background: var(--glass);
    color: var(--ink);
    border: none; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: background var(--transition);
    text-decoration: none;
  }
  .kc-lightbox-actions > button:hover,
  .kc-lightbox-actions > a:hover { background: var(--glass-active); }
  /* Stage = fixed viewport-sized container that owns gesture events.
     The image inside is sized by max-width/height (fit-to-viewport)
     and transformed via translate(tx, ty) scale(s) for pinch/pan. */
  .kc-lightbox-stage {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
    touch-action: none;          /* let our pointer handlers own gestures */
    user-select: none;
    -webkit-user-select: none;
  }
  .kc-lightbox-img {
    max-width: 95vw; max-height: calc(100vh - 140px);
    object-fit: contain;
    cursor: default;
    border-radius: 6px;
    transform-origin: 50% 50%;   /* center-origin scaling — pinch math relies on it */
    will-change: transform;
    -webkit-user-drag: none;
    user-drag: none;
  }
  .kc-lightbox-stage.kc-zooming .kc-lightbox-img,
  .kc-lightbox-stage.kc-panning .kc-lightbox-img { cursor: grabbing; }
  .kc-lightbox-stage.kc-zoomed   .kc-lightbox-img { cursor: grab; }
  /* Disable the CSS transition while a gesture is live; re-enable for
     snap-back / double-tap / programmatic toggles. */
  .kc-lightbox-stage:not(.kc-gesturing) .kc-lightbox-img {
    transition: transform 220ms cubic-bezier(0.22, 0.61, 0.36, 1);
  }
  /* When the image's natural size already fits at fit-mode (kcLightboxImgLoad
     measures and toggles this class on the lightbox), hide the magnifier
     button and drop the zoom cursor — there's nothing to enlarge. */
  .kc-lb-no-zoom .kc-lb-zoom-btn { display: none; }
  .kc-lightbox-nav {
    position: absolute; top: 50%; transform: translateY(-50%);
    width: 48px; height: 48px; border-radius: 50%;
    background: var(--glass);
    color: var(--ink);
    border: none; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: background var(--transition);
    z-index: 2;
  }
  .kc-lightbox-nav:hover { background: rgba(255, 255, 255, 0.20); }
  .kc-lightbox-nav.prev { left: 20px; }
  .kc-lightbox-nav.next { right: 20px; }
  .kc-lightbox-counter {
    position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%);
    font-size: var(--font-xs); color: var(--ink-muted);
    background: rgba(0, 0, 0, 0.6);
    padding: 5px 12px; border-radius: 12px;
  }

  /* ── DM sidebar items ── */
  .dm-item {
    display: flex; align-items: flex-start; gap: var(--space-sm);
    padding: 10px var(--space-sm); border-radius: var(--radius-s);
    cursor: pointer; transition: background var(--transition);
    margin-bottom: 1px;
    min-height: 56px;
  }
  .dm-item:hover { background: var(--surface); }
  .dm-item.active { background: var(--elevated); }
  .dm-avatar {
    width: var(--avatar-md); height: var(--avatar-md); border-radius: var(--radius-full);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--font-xs); font-weight: 700; color: white; flex-shrink: 0; position: relative;
  }
  .dm-avatar .dm-presence {
    position: absolute; bottom: -1px; right: -1px;
    width: 10px; height: 10px; border-radius: var(--radius-full);
    border: 2.5px solid var(--deep);
    z-index: 2;
  }

  /* Group DM composite avatar */
  .dm-group-avatar {
    position: relative; width: var(--avatar-md); height: var(--avatar-md); flex-shrink: 0;
  }
  .dm-group-avatar .dga-tile {
    position: absolute;
    border-radius: var(--radius-full);
    display: flex; align-items: center; justify-content: center;
    color: white; font-weight: 700;
    border: 1.5px solid var(--deep);
  }
  /* Use :nth-of-type instead of :first-child/:last-child — when the
     count badge is present, .dga-tile:last-child matches nothing
     (last child is .dga-count), leaving the second tile unpositioned
     and visually stacked over the first. */
  .dm-group-avatar .dga-tile:nth-of-type(1) {
    width: 22px; height: 22px; top: 0; left: 0; font-size: 9px; z-index: 1;
  }
  .dm-group-avatar .dga-tile:nth-of-type(2) {
    width: 22px; height: 22px; bottom: 0; right: 0; font-size: 9px; z-index: 2;
  }
  .dm-group-avatar .dga-count {
    position: absolute; bottom: -2px; right: -4px;
    background: var(--accent); color: white;
    font-size: 9px; font-weight: 700;
    padding: 1px 4px; border-radius: var(--radius-pill);
    border: 1.5px solid var(--deep);
    z-index: 3; min-width: 14px; text-align: center;
    line-height: 1.2;
  }

  /* Category header action button */
  .category-header-action {
    margin-left: auto;
    width: 18px; height: 18px;
    border-radius: var(--radius-s);
    background: transparent; border: none;
    display: flex; align-items: center; justify-content: center;
    color: var(--ink-muted); cursor: pointer;
    opacity: 0;
    transition: background var(--transition), color var(--transition), opacity var(--transition);
  }
  .category-header:hover .category-header-action { opacity: 1; }
  .category-header-action:hover { background: var(--surface); color: var(--ink); }
  .category-header .category-unread-badge {
    margin-left: auto;
    background: var(--accent);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    padding: 1px 7px;
    border-radius: 9px;
    line-height: 1.4;
    flex-shrink: 0;
  }
  /* When both the unread badge and the action button are present, the badge
     already ate `margin-left:auto`, so the action sits directly after it. */
  .category-header .category-unread-badge + .category-header-action { margin-left: var(--space-xs); }

  /* Group create modal */
  .group-modal-body { padding: var(--space-lg); display: flex; flex-direction: column; gap: var(--space-md); min-width: 480px; }
  .group-modal-name {
    width: 100%; background: var(--deep); border: 1px solid var(--border-mid);
    border-radius: var(--radius-m); padding: 10px var(--space-md);
    color: var(--ink); font-family: inherit; font-size: var(--font-md);
    transition: border-color var(--transition);
  }
  .group-modal-name:focus { outline: none; border-color: var(--accent); }

  /* Channel-edit modal — Discord-style overview layout: labelled
     fields stacked vertically, big topic textarea with a counter. */
  .channel-edit-body { gap: var(--space-lg); min-width: 0; }
  .ce-section-title {
    font-size: var(--font-lg);
    font-weight: 700;
    color: var(--ink);
    margin-bottom: -4px;
  }
  .ce-field {
    display: flex; flex-direction: column; gap: 6px;
    cursor: default;
  }
  .ce-label {
    font-size: var(--font-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ink-muted);
  }
  .ce-input {
    width: 100%;
    background: var(--deep);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-m);
    padding: 10px var(--space-md);
    color: var(--ink);
    font-family: inherit; font-size: var(--font-md);
    transition: border-color var(--transition);
  }
  .ce-input:focus { outline: none; border-color: var(--accent); }

  /* Custom select used for the slow-mode picker — replaces the native
     <select> chrome with a button + popup matching modal styling. */
  .kc-select { position: relative; }
  .kc-select-trigger {
    display: flex; align-items: center; gap: 10px;
    cursor: pointer; text-align: left;
  }
  .kc-select-trigger:focus { border-color: var(--accent); }
  .kc-select-label { flex: 1; min-width: 0; }
  .kc-select-chevron {
    flex-shrink: 0;
    color: var(--ink-muted);
    transition: transform var(--transition);
  }
  .kc-select.open .kc-select-trigger { border-color: var(--accent); }
  .kc-select.open .kc-select-chevron { transform: rotate(180deg); }
  .kc-select-menu {
    display: none;
    position: absolute; left: 0; right: 0; top: calc(100% + 4px);
    background: var(--raised);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-m);
    padding: 4px;
    max-height: 280px;
    overflow-y: auto;
    z-index: 200;
    box-shadow: var(--shadow-m);
  }
  .kc-select.open .kc-select-menu { display: block; }
  .kc-select-option {
    width: 100%;
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px;
    padding: 8px 12px;
    background: transparent;
    border: none;
    border-radius: var(--radius-s);
    color: var(--ink-secondary);
    font-family: inherit; font-size: var(--font-md);
    cursor: pointer; text-align: left;
    transition: background var(--transition), color var(--transition);
  }
  .kc-select-option:hover { background: var(--surface); color: var(--ink); }
  .kc-select-option.active { color: var(--ink); }
  .kc-select-check {
    flex-shrink: 0;
    width: 14px; height: 14px;
    color: var(--accent);
    display: inline-flex; align-items: center; justify-content: center;
  }
  .ce-topic-wrap { position: relative; }
  .ce-textarea {
    width: 100%;
    background: var(--deep);
    border: 1px solid var(--border-mid);
    border-radius: var(--radius-m);
    padding: 10px var(--space-md) 28px;
    color: var(--ink);
    font-family: inherit; font-size: var(--font-md);
    line-height: 1.5;
    resize: vertical;
    min-height: 140px;
    transition: border-color var(--transition);
  }
  .ce-textarea:focus { outline: none; border-color: var(--accent); }
  .ce-topic-counter {
    position: absolute;
    right: 10px; bottom: 6px;
    font-size: var(--font-xs);
    color: var(--ink-ghost);
    pointer-events: none;
    user-select: none;
  }
  .ce-private-row { margin: 0; }
  .cs-counter {
    margin-top: 6px;
    text-align: right;
    font-size: var(--font-xs);
    color: var(--ink-muted);
  }
  .cs-expiry { margin-top: 16px; }
  /* S6.1 — custom date+time row, shown when «Выбрать дату и время…» is
     picked from the expiry dropdown. Two equal-width inputs side-by-side. */
  .cs-custom-expiry {
    display: flex;
    gap: 8px;
    margin-top: 8px;
  }
  .cs-custom-expiry .cs-custom-field {
    flex: 1;
    min-width: 0;
    position: relative;
  }
  .cs-custom-expiry .cs-custom-input {
    width: 100%;
    text-align: left;
    cursor: pointer;
  }
  .cs-expiry-label,
  .cs-presets-label {
    font-size: var(--font-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--ink-muted);
    margin-bottom: 6px;
  }
  /* S1 — presets list under the status input. Hardcoded set in
     profile.js; S2.1 will swap in admin-edited workspace presets. */
  .cs-presets-label { margin-top: 14px; }
  .cs-presets {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .cs-preset-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-s);
    color: var(--ink);
    text-align: left;
    cursor: pointer;
    font: inherit;
    font-size: var(--font-sm);
  }
  .cs-preset-row:hover { background: var(--surface); border-color: var(--border); }
  .cs-preset-row-emoji { font-size: 16px; line-height: 1; }
  .cs-preset-row-text { font-weight: 500; }
  .cs-preset-row-meta { margin-left: auto; color: var(--ink-muted); font-size: var(--font-xs); }
  /* Emoji preview INSIDE the trigger button (so the icon swaps to
     the chosen emoji once one is picked). */
  .cs-emoji-preview { line-height: 1; }
  /* The expiry dropdown is reparented to <body> on open (escape the
     modal's overflow:hidden + backdrop-filter). Target by ID so the
     rules survive the move; selectors anchored at #csExpirySelect
     would silently stop matching. JS sets left/top + width on open. */
  #csExpiryMenu {
    position: fixed;
    top: auto; bottom: auto;
    left: auto; right: auto;
    z-index: 300;
    /* The custom-status modal is 440px wide; the trigger button is
       408px after .modal-content padding. Pin the menu to that exact
       width via CSS — JS's inline `style.width = rect.width + 'px'`
       wasn't applying for some users (timing? cache?). `min(...)`
       clamps when viewport is narrower than the modal. */
    width: min(408px, calc(100vw - 32px));
    max-width: calc(100vw - 32px);
    /* settings.css .kc-select-menu has `min-width: 100%`; once the
       menu is reparented to <body>, that 100% = viewport width and
       overrides our `width` clamp. Кill the min-width here. */
    min-width: 0;
    box-sizing: border-box;
    overflow-x: hidden;
  }
  #csExpiryMenu .kc-select-option { min-width: 0; }
  /* Dedicated class instead of `:first-child` so the rule survives
     even if extra wrappers/whitespace get added around the label. */
  .kc-select-option-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1;
  }
  #csExpirySelect.open .kc-select-chevron { transform: rotate(180deg); }

  /* Custom-status input with emoji-button on the left. */
  .cs-input-wrap { position: relative; }
  .cs-input-wrap .cs-input { padding-left: 40px; padding-right: 36px; }
  .cs-clear-btn {
    position: absolute;
    right: 8px; top: 50%;
    transform: translateY(-50%);
    width: 22px; height: 22px;
    display: inline-flex; align-items: center; justify-content: center;
    border: none; padding: 0; margin: 0;
    background: transparent;
    color: var(--ink-ghost);
    cursor: pointer;
    border-radius: var(--radius-full);
    transition: color var(--transition);
  }
  .cs-clear-btn:hover { color: var(--ink); }
  .cs-emoji-btn {
    position: absolute;
    left: 8px; top: 50%;
    transform: translateY(-50%);
    width: 28px; height: 28px;
    display: flex; align-items: center; justify-content: center;
    background: transparent; border: none; border-radius: 50%;
    color: var(--ink-muted); cursor: pointer;
    transition: color var(--transition), background var(--transition);
  }
  .cs-emoji-btn:hover { color: var(--ink); background: var(--surface); }
  .group-modal-section-title {
    font-size: var(--font-2xs); font-weight: 600; text-transform: uppercase;
    letter-spacing: 0.05em; color: var(--ink-muted); margin-bottom: -4px;
  }
  .group-modal-list {
    max-height: 340px; overflow-y: auto;
    display: flex; flex-direction: column; gap: 2px;
    margin: 0 calc(-1 * var(--space-xs));
    padding: var(--space-xs);
  }
  /* Two-list "Участники группы" modal — collapse the per-list scrolls
     so the body scrolls as one unit (was three concurrent scrollbars
     when both sections + the modal itself ran out of height). */
  #groupMembersModal .group-modal-body { overflow-y: auto; flex: 1; min-height: 0; }
  #groupMembersModal .group-modal-list { max-height: none; overflow-y: visible; }
  .group-modal-friend {
    display: flex; align-items: center; gap: var(--space-sm);
    padding: var(--space-sm); border-radius: var(--radius-s);
    cursor: pointer;
    transition: background var(--transition);
  }
  .group-modal-friend:hover { background: var(--surface); }
  .group-modal-friend.selected { background: var(--accent-soft); }
  .group-modal-friend.disabled { opacity: 0.4; cursor: not-allowed; }
  .group-modal-friend.disabled:hover { background: transparent; }
  .group-modal-friend .gmf-avatar {
    width: var(--avatar-md); height: var(--avatar-md); border-radius: var(--radius-full);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--font-xs); font-weight: 700; color: white; flex-shrink: 0;
  }
  .group-modal-friend .gmf-name { flex: 1; font-size: var(--font-md); color: var(--ink); }
  .group-modal-friend .gmf-check {
    width: 18px; height: 18px; border-radius: var(--radius-s);
    border: 2px solid var(--ink-ghost);
    display: flex; align-items: center; justify-content: center;
    color: white; transition: background var(--transition), border-color var(--transition);
  }
  .group-modal-friend.selected .gmf-check {
    background: var(--accent); border-color: var(--accent);
  }
  .group-modal-member { cursor: default; }
  .group-modal-member:hover { background: transparent; }
  .group-modal-member:hover .gmf-remove { opacity: 1; }
  .group-modal-friend .gmf-tag {
    display: inline-flex; align-items: center;
    margin-left: 8px; padding: 2px 8px;
    border-radius: var(--radius-pill);
    background: var(--glass); color: var(--ink-muted);
    font-size: var(--font-2xs); font-weight: 500; letter-spacing: 0.02em;
  }
  .group-modal-friend .gmf-remove {
    width: 28px; height: 28px; border-radius: var(--radius-full);
    display: flex; align-items: center; justify-content: center;
    background: transparent; border: none; padding: 0;
    color: var(--ink-muted); cursor: pointer;
    opacity: 0; transition: opacity var(--transition), background var(--transition), color var(--transition);
    flex-shrink: 0;
  }
  .group-modal-friend .gmf-remove:hover {
    background: var(--coral-soft); color: var(--coral);
  }
  .group-modal-footer {
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--space-md) var(--space-lg);
    border-top: 1px solid var(--border);
    background: var(--surface);
    border-radius: 0 0 var(--radius-xl) var(--radius-xl);
  }
  .group-modal-counter { font-size: var(--font-sm); color: var(--ink-muted); font-weight: 500; }
  .group-modal-counter.warn { color: var(--coral); }
  .group-modal-create {
    background: var(--accent); color: white; border: none;
    padding: 9px 18px; border-radius: var(--radius-m);
    font-family: inherit; font-size: var(--font-sm); font-weight: 600;
    cursor: pointer; transition: background var(--transition);
  }
  .group-modal-create:hover:not(:disabled) { background: var(--accent-hover); }
  .group-modal-create:disabled { background: var(--glass); color: var(--ink-muted); cursor: not-allowed; }

  /* Format-toolbar link modal */
  .fmt-link-field { display: flex; flex-direction: column; gap: 6px; }
  .fmt-link-field label {
    font-size: var(--font-sm); color: var(--ink-secondary); font-weight: 500;
  }
  .fmt-link-input-wrap { position: relative; }
  .fmt-link-input-wrap input {
    width: 100%; background: var(--deep); border: 1px solid var(--border-mid);
    border-radius: var(--radius-m); padding: 10px 36px 10px var(--space-md);
    color: var(--ink); font-family: inherit; font-size: var(--font-md);
    transition: border-color var(--transition);
    text-overflow: ellipsis;
  }
  .fmt-link-input-wrap input:focus { outline: none; border-color: var(--accent); }
  .fmt-link-clear {
    position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
    width: 22px; height: 22px; border-radius: var(--radius-full);
    display: flex; align-items: center; justify-content: center;
    background: transparent; border: none; color: var(--ink-muted);
    cursor: pointer; transition: background var(--transition), color var(--transition);
  }
  .fmt-link-clear:hover { background: var(--surface); color: var(--ink); }

  /* Group chat header — composite avatar + editable title + member chips */
  .chat-header-group-avatar { width: var(--avatar-md); height: var(--avatar-md); flex-shrink: 0; position: relative; }
  .chat-header-group-avatar .chga-tile {
    position: absolute; border-radius: var(--radius-full);
    display: flex; align-items: center; justify-content: center;
    color: white; font-weight: 700; font-size: 10px;
    border: 2px solid var(--surface);
  }
  .chat-header-group-avatar .chga-tile:first-child { width: 22px; height: 22px; top: 0; left: 0; z-index: 1; }
  .chat-header-group-avatar .chga-tile:last-child { width: 22px; height: 22px; bottom: 0; right: 0; z-index: 2; }
  .chat-title-editable { cursor: text; padding: 2px 6px; border-radius: var(--radius-s); border: 1px solid transparent; }
  .chat-title-editable:hover { background: var(--surface); }
  .chat-title-editable:focus { outline: none; background: var(--deep); border-color: var(--accent); }
  /* Group chat header — title on top, member count on a second line
     (Discord-style "N members"). The chat-title has 6px left padding
     for its hover/focus background; mirror that on the count so both
     lines share a left edge. */
  .chat-header-group-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .chat-header-group-info .chat-title { display: inline-block; align-self: flex-start; }
  .chat-header-group-info .chat-group-members { padding-left: 6px; }
  .chat-group-members { font-size: var(--font-xs); color: var(--ink-muted); }
  .dm-info { flex: 1; min-width: 0; }
  .dm-name { display: flex; align-items: center; gap: var(--space-xs); font-size: var(--font-sm); font-weight: 500; color: var(--ink-secondary); min-width: 0; }
  .dm-name > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dm-item.active .dm-name, .dm-item:hover .dm-name { color: var(--ink); }
  .dm-preview {
    font-size: var(--font-xs); color: var(--ink-secondary);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
    line-height: 1.4;
  }
  .dm-preview-thumbs {
    display: inline-flex;
    gap: 2px;
    margin-right: 4px;
    vertical-align: -3px;
  }
  .dm-preview-thumb {
    width: 18px; height: 18px;
    border-radius: 3px;
    object-fit: cover;
    flex-shrink: 0;
    background: var(--surface);
  }
  .dm-item.active .dm-preview, .dm-item:hover .dm-preview { color: var(--ink); }
  /* Telegram-style draft preview: red prefix, regular-toned body. */
  .dm-draft-prefix {
    color: var(--coral);
    font-weight: 600;
    margin-right: 2px;
  }
  .dm-typing { display: flex; align-items: center; gap: 6px; color: var(--ink-muted); font-size: var(--font-2xs); }
  .dm-typing-dots { display: inline-flex; gap: 2px; }
  .dm-typing-dots > span {
    width: 4px; height: 4px; border-radius: 50%; background: currentColor;
    animation: kc-typing-dot 1.2s infinite ease-in-out;
  }
  .dm-typing-dots > span:nth-child(2) { animation-delay: var(--transition); }
  .dm-typing-dots > span:nth-child(3) { animation-delay: 0.36s; }
  @keyframes kc-typing-dot {
    0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
    30% { opacity: 1; transform: translateY(-2px); }
  }
  .dm-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex-shrink: 0; min-height: 36px; }
  .dm-time { font-size: 10px; color: var(--ink-ghost); }
  .dm-unread-badge {
    background: var(--elevated);
    color: var(--ink);
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    padding: 1px 7px;
    border-radius: 9px;
    border: 1px solid var(--border-mid);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }
  .dm-preview-clip {
    display: inline-flex;
    align-items: center;
    margin-right: 3px;
    vertical-align: -2px;
    color: var(--ink-ghost);
    flex-shrink: 0;
  }
  .dm-item.active .dm-preview-clip, .dm-item:hover .dm-preview-clip { color: var(--ink-muted); }

  /* ── Media Picker (GIF + Emoji full panel) ── */
  .media-picker {
    position: fixed;
    width: 380px;
    height: 460px;
    background: var(--raised);
    border: 1px solid var(--border-mid);
    border-radius: 12px;
    box-shadow: var(--shadow-l);
    display: none;
    flex-direction: column;
    overflow: hidden;
    z-index: 400;
    animation: panelSlideIn var(--transition) ease-out;
  }
  .media-picker.mp-open { display: flex; }
  .mp-tabs { display: flex; padding: 10px 12px 0; gap: 2px; border-bottom: 1px solid var(--border); flex-shrink: 0; }
  .mp-tab {
    padding: 7px 16px; border-radius: 8px 8px 0 0; font-size: var(--font-sm); font-weight: 600;
    color: var(--ink-muted); background: none; border: none; cursor: pointer;
    transition: color var(--transition), background var(--transition);
  }
  .mp-tab:hover { color: var(--ink); }
  .mp-tab.active { color: var(--ink); background: var(--surface); }
  .mp-search { padding: 10px 12px; flex-shrink: 0; }
  .mp-search input {
    width: 100%; background: var(--surface); border: 1px solid var(--border-mid);
    border-radius: 8px; padding: 7px 12px; font-size: var(--font-sm); color: var(--ink);
    font-family: inherit; outline: none; box-sizing: border-box;
  }
  .mp-search input:focus { border-color: var(--accent); }
  .mp-body { flex: 1; overflow: hidden; display: flex; flex-direction: column; min-height: 0; }
  /* GIF */
  .gif-grid { flex: 1; overflow-y: auto; overflow-x: hidden; min-height: 0; scrollbar-width: thin; scrollbar-color: var(--float) transparent; }
  .gif-cols { columns: 2; column-gap: 4px; padding: 8px; }
  .gif-item { break-inside: avoid; margin-bottom: 4px; border-radius: 8px; overflow: hidden; cursor: pointer; background: var(--surface); }
  .gif-item img { width: 100%; height: auto; display: block; transition: opacity var(--transition); }
  .gif-item:hover img { opacity: .85; }
  .gif-empty { padding: 40px 20px; text-align: center; color: var(--ink-muted); font-size: var(--font-sm); }
  .gif-attribution { text-align: center; font-size: var(--font-2xs); color: var(--ink-ghost); padding: 6px; flex-shrink: 0; border-top: 1px solid var(--border); }
  /* Emoji */
  .ep-cat-bar {
    display: flex; padding: 6px 8px; gap: 2px; flex-shrink: 0;
    border-bottom: 1px solid var(--border); overflow-x: auto; scrollbar-width: none;
  }
  .ep-cat-bar::-webkit-scrollbar { display: none; }
  .ep-cat-btn {
    flex-shrink: 0; width: 32px; height: 30px; border-radius: 6px; border: none;
    background: none; cursor: pointer; font-size: var(--font-lg); display: flex;
    align-items: center; justify-content: center; transition: background var(--transition);
  }
  .ep-cat-btn:hover, .ep-cat-btn.ep-cat-active { background: var(--surface); }
  .ep-scroll { flex: 1; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--float) transparent; }
  .ep-section { padding: 0 8px 8px; }
  .ep-cat-label {
    font-size: var(--font-2xs); font-weight: 600; color: var(--ink-muted);
    text-transform: uppercase; letter-spacing: .5px; padding: 10px 0 4px;
  }
  .ep-grid { display: grid; grid-template-columns: repeat(9, 1fr); gap: 1px; }
  .ep-btn {
    width: 36px; height: 36px; border-radius: 6px; border: none; background: none;
    cursor: pointer; font-size: var(--font-xl); line-height: 1; display: flex;
    align-items: center; justify-content: center; transition: background var(--transition);
  }
  .ep-btn:hover { background: var(--surface); }
  /* GIF message */
  .msg-gif {
    max-width: 320px; max-height: 280px; border-radius: 10px;
    display: block; margin-top: 4px; margin-right: auto; cursor: default;
    /* Reserve a fixed-aspect box that doesn't reflow after decode — prevents Safari jitter
       caused by aspect-ratio: auto kicking in post-load. */
    aspect-ratio: 4 / 3;
    background: var(--surface);
    object-fit: contain;
    object-position: left center;
  }
  .msg-gif.kc-loaded { background: transparent; }
