/* ============================================================
   Common reusable components — design system layer.
   Loaded after feature-CSS so it can extend without overrides.

   Contents:
     1. .kc-spinner          — single loading indicator (5 sizes)
     2. .kc-skeleton         — shimmer placeholder for initial loads
     3. .kc-icon-close       — canonical close-X button (3 sizes)
     4. .kc-toast            — non-blocking notification (4 variants)
     5. .kc-pill             — unified badge/chip/role marker
     6. .kc-quick-switcher   — ⌘K modal for fast navigation
     7. .kc-icon             — DS icon (CSS mask, currentColor)
     8. .btn                 — primary / ghost / danger button family
   ============================================================ */

/* ── 7. DS icon — paints currentColor into a /icons/m/<name>.svg shape.
   Source: priv/static/icons/m/*.svg, extracted from @kui/icons (KUI DS).
   Helper: priv/static/js/kc-icon.js  →  kcIcon(name, opts).
   The mask trick lets one file render in any colour via the host's
   CSS `color` — no need for a per-colour copy. */
.kc-icon {
  display: inline-block;
  width: var(--kc-icon-size, 16px);
  height: var(--kc-icon-size, 16px);
  vertical-align: middle;
  flex-shrink: 0;
  background-color: currentColor;
  -webkit-mask-image: var(--kc-icon-url);
  mask-image: var(--kc-icon-url);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}

/* ── 1. Spinner ─────────────────────────────────────────── */
.kc-spinner {
  display: inline-block;
  /* DS path: Surface/loader/{accent,neutral}/default. Track stays at the
     dim white-overlay (--surface-loader-track-default) and the spinning
     arc is the DS accent blue. Light-mode picks up the same tokens via
     the rebased primitives. */
  border: 2px solid var(--surface-loader-track-default);
  border-top-color: var(--surface-loader-accent-default);
  border-radius: var(--radius-full);
  animation: kc-spin 800ms linear infinite;
  vertical-align: middle;
  flex-shrink: 0;
}
.kc-spinner--xs { width: 12px; height: 12px; border-width: 1.5px; }
.kc-spinner--sm { width: 16px; height: 16px; border-width: 2px; }
.kc-spinner--md { width: 20px; height: 20px; border-width: 2px; }
.kc-spinner--lg { width: 24px; height: 24px; border-width: 2.5px; }
.kc-spinner--xl { width: 32px; height: 32px; border-width: 3px; }

/* Centered block layout when used as a standalone loader. */
.kc-spinner--block {
  display: block;
  margin: var(--space-lg) auto;
}

@keyframes kc-spin {
  to { transform: rotate(360deg); }
}

/* ── 2. Skeleton ────────────────────────────────────────── */
.kc-skeleton {
  display: block;
  background: linear-gradient(
    90deg,
    var(--surface) 0%,
    var(--raised) 50%,
    var(--surface) 100%
  );
  background-size: 200% 100%;
  animation: kc-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--radius-s);
  pointer-events: none;
}
.kc-skeleton--circle { border-radius: var(--radius-full); }
.kc-skeleton--text   { height: 12px; }
.kc-skeleton--text-sm { height: 10px; }

@keyframes kc-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Preset: a single message row (avatar + 2 text lines).
   Use 5 of these in a column for the messages-list initial load. */
.kc-skeleton-message {
  display: flex;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  align-items: flex-start;
}
.kc-skeleton-message__av {
  width: var(--avatar-lg);
  height: var(--avatar-lg);
  border-radius: var(--radius-full);
  flex-shrink: 0;
  background: linear-gradient(90deg, var(--surface) 0%, var(--raised) 50%, var(--surface) 100%);
  background-size: 200% 100%;
  animation: kc-shimmer 1.4s ease-in-out infinite;
}
.kc-skeleton-message__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  /* Match the real .msg-text layout: 14px font @ 1.45 line-height ≈
     20px per line. Lines and gaps are sized so the skeleton occupies
     the same vertical footprint as a multi-line message — when real
     content swaps in there's no jarring jump. */
  gap: 8px;
  padding-top: 4px;
}
.kc-skeleton-message__header {
  width: 140px;
  height: 14px;
  border-radius: var(--radius-s);
  margin-bottom: 4px;
  background: linear-gradient(90deg, var(--surface) 0%, var(--raised) 50%, var(--surface) 100%);
  background-size: 200% 100%;
  animation: kc-shimmer 1.4s ease-in-out infinite;
}
.kc-skeleton-message__line {
  height: 16px;
  border-radius: var(--radius-s);
  background: linear-gradient(90deg, var(--surface) 0%, var(--raised) 50%, var(--surface) 100%);
  background-size: 200% 100%;
  animation: kc-shimmer 1.4s ease-in-out infinite;
}
.kc-skeleton-message__line--80 { width: 80%; }
.kc-skeleton-message__line--60 { width: 60%; }

/* Preset: a member/friend row (small avatar + 1 line). */
.kc-skeleton-row {
  display: flex;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  align-items: center;
}
.kc-skeleton-row__av {
  width: var(--avatar-sm);
  height: var(--avatar-sm);
  border-radius: var(--radius-full);
  flex-shrink: 0;
  background: linear-gradient(90deg, var(--surface) 0%, var(--raised) 50%, var(--surface) 100%);
  background-size: 200% 100%;
  animation: kc-shimmer 1.4s ease-in-out infinite;
}
.kc-skeleton-row__line {
  flex: 1;
  height: 12px;
  max-width: 240px;
  border-radius: var(--radius-s);
  background: linear-gradient(90deg, var(--surface) 0%, var(--raised) 50%, var(--surface) 100%);
  background-size: 200% 100%;
  animation: kc-shimmer 1.4s ease-in-out infinite;
}

/* ── 3. Close button (X) ────────────────────────────────── */
.kc-icon-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--size-icon-md);
  height: var(--size-icon-md);
  border: none;
  border-radius: var(--radius-s);
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: background var(--transition), color var(--transition);
}
.kc-icon-close:hover {
  background: var(--surface);
  color: var(--ink);
}
.kc-icon-close svg { width: 16px; height: 16px; }

/* Inline variant — sits inside reply/edit/attachment cards. */
.kc-icon-close--inline {
  width: var(--size-icon-sm);
  height: var(--size-icon-sm);
  border-radius: var(--radius-full);
  color: var(--ink-ghost);
}
.kc-icon-close--inline:hover {
  background: var(--glass-hover);
  color: var(--ink);
}
.kc-icon-close--inline svg { width: 14px; height: 14px; }

/* Large variant — lightbox / fullscreen overlays. */
.kc-icon-close--lg {
  width: var(--size-icon-xl);
  height: var(--size-icon-xl);
  border-radius: var(--radius-full);
  background: var(--glass);
}
.kc-icon-close--lg:hover { background: var(--glass-active); }
.kc-icon-close--lg svg { width: 20px; height: 20px; }

/* Legacy close-X aliases — visually equivalent to .kc-icon-close.
   Specific classes keep their positioning (position: absolute, etc.)
   from feature-CSS; we only normalize size/shape/colors/hover.
   Once JS-side migrates to .kc-icon-close, these can be deleted. */

/* Inline variants — replaces .kc-icon-close--inline (24×24, glass-hover). */
.cancel-edit, .cancel-reply,
.att-card-remove, .link-preview-card-remove {
  width: var(--size-icon-sm);
  height: var(--size-icon-sm);
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--ink-ghost);
  border: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  flex-shrink: 0;
  transition: background var(--transition), color var(--transition);
}
.cancel-edit:hover, .cancel-reply:hover,
.att-card-remove:hover, .link-preview-card-remove:hover {
  background: var(--glass-hover);
  color: var(--ink);
}

/* Default variants — replaces .kc-icon-close (28×28, surface hover). */
.thread-panel-close, .thread-panel-action,
.search-panel-close, .modal-close, .kc-modal-close,
.link-confirm-close {
  width: var(--size-icon-md);
  height: var(--size-icon-md);
  border-radius: var(--radius-s);
  background: transparent;
  color: var(--ink-muted);
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  flex-shrink: 0;
  transition: background var(--transition), color var(--transition);
}
.thread-panel-close:hover, .thread-panel-action:hover,
.search-panel-close:hover, .modal-close:hover, .kc-modal-close:hover,
.link-confirm-close:hover {
  background: var(--surface);
  color: var(--ink);
}

/* ── 4. Toast ───────────────────────────────────────────── */
.kc-toast-container {
  position: fixed;
  top: var(--space-lg);
  right: var(--space-lg);
  z-index: 10000;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  pointer-events: none;
  max-width: 360px;
}
.kc-toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  padding: var(--space-md) var(--space-md);
  background: var(--elevated);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-l);
  color: var(--ink);
  font-size: var(--font-md);
  line-height: var(--line-height-base);
  animation: kc-toast-in 200ms cubic-bezier(0.22, 0.61, 0.36, 1);
  min-width: 240px;
}
.kc-toast--info    { border-left-color: var(--info); }
.kc-toast--success { border-left-color: var(--success); }
.kc-toast--warning { border-left-color: var(--warning); }
.kc-toast--error   { border-left-color: var(--danger); }

.kc-toast.kc-toast--leaving {
  animation: kc-toast-out 160ms ease-in forwards;
}
@keyframes kc-toast-in {
  from { transform: translateX(120%); opacity: 0; }
  to   { transform: translateX(0);    opacity: 1; }
}
@keyframes kc-toast-out {
  from { transform: translateX(0);    opacity: 1; }
  to   { transform: translateX(120%); opacity: 0; }
}

.kc-toast__icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.kc-toast--info    .kc-toast__icon { color: var(--info); }
.kc-toast--success .kc-toast__icon { color: var(--success); }
.kc-toast--warning .kc-toast__icon { color: var(--warning); }
.kc-toast--error   .kc-toast__icon { color: var(--danger); }

.kc-toast__body { flex: 1; min-width: 0; }
.kc-toast__msg  { word-wrap: break-word; }
.kc-toast__action {
  margin-top: 6px;
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  font-weight: 600;
  font-size: var(--font-sm);
  cursor: pointer;
  font-family: inherit;
}
.kc-toast__action:hover { text-decoration: underline; }
.kc-toast__close {
  flex-shrink: 0;
  background: transparent;
  border: none;
  padding: 0;
  color: var(--ink-ghost);
  cursor: pointer;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-s);
  transition: color var(--transition), background var(--transition);
}
.kc-toast__close:hover { color: var(--ink); background: var(--glass); }

/* ── 5. Pill ────────────────────────────────────────────── */
.kc-pill {
  display: inline-flex;
  align-items: center;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  font-size: var(--font-2xs);
  font-weight: 600;
  line-height: var(--line-height-base);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--glass);
  color: var(--ink-secondary);
  white-space: nowrap;
}
/* Role variants — visually distinct so OWNER/ADMIN/MOD/STAFF/BOT
   are recognizable at a glance, not just by reading. Owner/Admin/Mod
   keep the solid status hues (DS Surface/{warning,accent,success}/
   default) because the role badge IS the brand colour — anything
   softer reads as "neutral tag". BOT stays on the neutral label
   surface (DS Surface/label/neutral/default) so it sits under the
   coloured badges in the visual hierarchy. */
.kc-pill--role-owner     { background: var(--warning); color: var(--color-white-100); }
.kc-pill--role-admin     { background: var(--accent);  color: var(--color-white-100); }
.kc-pill--role-moderator { background: var(--success); color: var(--color-white-100); }
.kc-pill--role-staff     { background: var(--pastel-indigo); color: var(--color-white-100); }
.kc-pill--role-bot       { background: var(--surface-label-neutral-default); color: var(--ink-muted); }

/* Numeric/state variants. */
.kc-pill--unread {
  background: var(--accent);
  color: var(--color-white-100);
  text-transform: none;
  letter-spacing: 0;
}
.kc-pill--count {
  background: var(--surface);
  color: var(--ink-secondary);
  text-transform: none;
  letter-spacing: 0;
}

/* "edited" marker — neutral, lowercase, no background. Used inline in
   message footers next to the timestamp. */
.kc-pill--edited {
  background: transparent;
  color: var(--ink-ghost);
  padding: 0;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 500;
  font-size: var(--font-2xs);
}

/* "draft" markers live in channel-list / DM-list now (Telegram-style):
   .channel-draft-mark — inline red text inside .channel-item
   .dm-draft-prefix    — red "Черновик:" prefix inside .dm-preview
   See channels.css and media.css. */

/* ── 6. Quick Switcher (⌘K) ─────────────────────────────── */
.kc-quick-switcher {
  position: fixed;
  inset: 0;
  z-index: 11000;
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding-top: 10vh;
}
.kc-quick-switcher.kc-quick-switcher--open { display: flex; }

.kqs-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  animation: kqs-fade var(--transition);
}
@keyframes kqs-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.kqs-modal {
  position: relative;
  width: min(560px, calc(100vw - 32px));
  max-height: 70vh;
  background: var(--elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-l);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: kqs-pop 160ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
@keyframes kqs-pop {
  from { opacity: 0; transform: translateY(-8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}

.kqs-input-wrap {
  position: relative;
  flex-shrink: 0;
  border-bottom: 1px solid var(--border);
}
.kqs-input-wrap svg {
  position: absolute;
  top: 50%; left: var(--space-md);
  transform: translateY(-50%);
  color: var(--ink-muted);
  pointer-events: none;
}
.kqs-input {
  width: 100%;
  background: transparent;
  border: none;
  color: var(--ink);
  font-family: inherit;
  font-size: var(--font-lg);
  padding: var(--space-md) var(--space-md) var(--space-md) 44px;
  outline: none;
}
.kqs-input::placeholder { color: var(--ink-muted); }

.kqs-results {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-sm) 0;
}
.kqs-section {
  padding: var(--space-sm) 0;
}
.kqs-section-header {
  padding: 4px var(--space-md);
  font-size: var(--font-2xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  font-weight: 600;
}

.kqs-result {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  cursor: pointer;
  transition: background var(--transition);
}
.kqs-result:hover,
.kqs-result.kqs-result--active {
  background: var(--surface);
}
.kqs-result__icon {
  flex-shrink: 0;
  width: var(--avatar-sm);
  height: var(--avatar-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  color: var(--ink-secondary);
  background: var(--surface);
}
.kqs-result.kqs-result--active .kqs-result__icon { color: var(--ink); }
.kqs-result__avatar {
  flex-shrink: 0;
  width: var(--avatar-sm);
  height: var(--avatar-sm);
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: var(--font-2xs);
  font-weight: 700;
}
.kqs-result__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.kqs-result__title {
  color: var(--ink);
  font-size: var(--font-md);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kqs-result__sub {
  color: var(--ink-muted);
  font-size: var(--font-xs);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kqs-result__hint {
  flex-shrink: 0;
  color: var(--ink-ghost);
  font-size: var(--font-2xs);
}

.kqs-empty {
  padding: var(--space-xl) var(--space-md);
  text-align: center;
  color: var(--ink-muted);
  font-size: var(--font-sm);
}

.kqs-footer {
  flex-shrink: 0;
  display: flex;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  border-top: 1px solid var(--border);
  background: var(--deep);
  font-size: var(--font-2xs);
  color: var(--ink-ghost);
}
.kqs-footer kbd {
  display: inline-block;
  padding: 1px 5px;
  background: var(--surface);
  border: 1px solid var(--border-mid);
  border-radius: 3px;
  font-family: 'SF Mono', Menlo, monospace;
  font-size: 10px;
  color: var(--ink-secondary);
  margin-right: 4px;
}

/* ── Forward DM picker ──────────────────────────────────────────────
   Telegram-style modal opened from the "Переслать" hover-action. Two
   states inside one container: the conversation list, then a confirm
   step with optional pre-comment. The shared .modal-overlay / .modal
   styles drive the backdrop + transition. */

.forward-picker {
  flex-direction: column;
  width: 480px;
  max-width: 92vw;
  max-height: 78vh;
  padding: 0;
  overflow: hidden;
}

.forward-picker-header {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-md);
  border-bottom: 1px solid var(--border-mid);
}

.forward-picker-title {
  flex: 1;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.forward-picker-back,
.forward-picker-close {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  border-radius: var(--radius-full);
  color: var(--ink-secondary);
  cursor: pointer;
  flex-shrink: 0;
}
.forward-picker-back:hover,
.forward-picker-close:hover {
  background: var(--glass-hover);
  color: var(--ink);
}

.forward-picker-search {
  flex: 1;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 0 var(--space-md);
  height: 36px;
  background: var(--surface);
  border: 1px solid var(--border-mid);
  border-radius: var(--radius-full);
  color: var(--ink-secondary);
}
.forward-picker-search input {
  flex: 1;
  background: transparent;
  border: 0;
  outline: none;
  color: var(--ink);
  font-size: var(--font-md);
}
.forward-picker-search input::placeholder { color: var(--ink-muted); }

.forward-picker-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-xs) 0 var(--space-md);
}

.forward-picker-section {
  padding: var(--space-md) var(--space-lg) var(--space-xs);
  font-size: var(--font-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
}

.forward-picker-list { display: flex; flex-direction: column; }

.forward-picker-row {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: 8px var(--space-lg);
  cursor: pointer;
  user-select: none;
}
.forward-picker-row:hover { background: var(--glass-hover); }

.forward-picker-row-av {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--font-md);
  font-weight: 600;
  color: #fff;
  flex-shrink: 0;
}

.forward-picker-row-text { flex: 1; min-width: 0; }
.forward-picker-row-name {
  font-size: var(--font-md);
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.forward-picker-row-group-marker {
  color: var(--ink-muted);
  font-weight: 400;
  font-size: var(--font-xs);
}
.forward-picker-row-subtitle {
  font-size: var(--font-xs);
  color: var(--ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.forward-picker-empty {
  padding: var(--space-xl) var(--space-lg);
  text-align: center;
  color: var(--ink-muted);
  font-size: var(--font-sm);
}

.forward-picker-source-preview {
  margin: var(--space-md) var(--space-lg) 0;
  padding: 8px 12px;
  border-left: 3px solid var(--accent);
  background: var(--surface);
  border-radius: 0 var(--radius-m) var(--radius-m) 0;
}
.forward-picker-source-author {
  font-size: var(--font-sm);
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 2px;
}
.forward-picker-source-body {
  font-size: var(--font-sm);
  color: var(--ink-secondary);
  max-height: 90px;
  overflow: hidden;
  white-space: pre-wrap;
  word-break: break-word;
}

.forward-picker-comment {
  display: block;
  width: calc(100% - var(--space-lg) - var(--space-lg));
  margin: var(--space-md) var(--space-lg) 0;
  padding: 8px 12px;
  background: var(--surface);
  border: 1px solid var(--border-mid);
  border-radius: var(--radius-m);
  color: var(--ink);
  font: inherit;
  resize: vertical;
  min-height: 56px;
  max-height: 200px;
  outline: none;
}
.forward-picker-comment:focus { border-color: var(--accent); }

.forward-picker-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-sm);
  padding: var(--space-md) var(--space-lg);
  margin-top: var(--space-md);
  border-top: 1px solid var(--border-mid);
}

/* ── 8. Button family ───────────────────────────────────────
   Canonical `.btn-*` definitions consumed by `modal_keyboard_contract_test.exs`
   as behavioural markers (Enter activates `.btn-primary`, Esc/backdrop trigger
   `.btn-ghost`, etc.). Maps to DS path `Surface/button/<intent>/<state>` so a
   future React import lands on the same tokens.

   Variants:
     • `.btn-primary`   — accent fill, white text. Enter-target in modals.
     • `.btn-ghost`     — neutral surface, secondary text. Esc-target.
     • `.btn-danger`    — alert fill, white text. Destructive confirms.
     • `.btn-cancel-del`/`.btn-confirm-del` — alias classes used by delete
       confirms (legacy names — match `.btn-ghost`/`.btn-danger` behaviour).

   Layout (padding, radius, font) is shared on the bare `.btn` reset.
*/
.btn {
  padding: 8px 16px;
  border-radius: var(--radius-m);
  border: 0;
  font-size: var(--font-md);
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
  line-height: var(--line-height-tight);
}
.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn-primary {
  background: var(--surface-button-accent-default);
  color: var(--on-accent);
}
.btn-primary:hover:not(:disabled) {
  background: var(--surface-button-accent-hovered);
}

.btn-ghost,
.btn-cancel-del {
  background: var(--elevated);
  color: var(--ink-secondary);
}
.btn-ghost:hover:not(:disabled),
.btn-cancel-del:hover:not(:disabled) {
  background: var(--float);
  color: var(--ink);
}

.btn-danger,
.btn-confirm-del {
  background: var(--surface-button-alert-default);
  color: var(--on-accent);
}
.btn-danger:hover:not(:disabled),
.btn-confirm-del:hover:not(:disabled) {
  background: var(--surface-button-alert-hovered);
}

/* `.btn-cancel-del` / `.btn-confirm-del` are used throughout the
   .delete-confirm modals (kcConfirm, leave-server, delete-message,
   disconnect-calendar — 4 sites) WITHOUT the bare `.btn` class. The
   colour rules above were applied but the layout (padding, radius,
   font, transition) was inherited from the browser default — the
   buttons rendered as raw UA chips with a stark outline focus ring
   and no padding. Repeat the .btn reset here so the alias classes
   are self-contained regardless of whether `.btn` is also present
   on the element. */
.btn-cancel-del,
.btn-confirm-del {
  padding: 8px 16px;
  border-radius: var(--radius-m);
  border: 0;
  font-size: var(--font-md);
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
  line-height: var(--line-height-tight);
}
.btn-cancel-del:disabled,
.btn-confirm-del:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ── 9. App cold-start splash ───────────────────────────────
   Centered logo + product name, painted from app.html before
   `#app` becomes visible. Bootstrap toggles `.hidden` once the
   first render is wired (servers / DMs / relationships landed).
   Without this, users see a half-built sidebar floating over a
   black void while WebSocket and renderChannels catch up. */
.kc-app-loading {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
  background: var(--void);
  color: var(--on-accent);
  transition: opacity var(--transition-slow);
}
.kc-app-loading.hidden {
  opacity: 0;
  pointer-events: none;
}
.kc-app-loading-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  color: var(--accent);
}
.kc-app-loading-logo svg {
  width: 100%;
  height: auto;
}
.kc-app-loading-title {
  font-size: var(--font-xl);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ink);
  user-select: none;
  -webkit-user-select: none;
}

/* 11. Checkbox — replaces native macOS look across the SPA.
   Applied via the type selector (`input[type="checkbox"]`) so existing
   inline checkboxes pick it up automatically. `.kc-toggle-input` is
   the visually-hidden checkbox behind .toggle pills (notifications,
   all-day event toggle) — left untouched. */
input[type="checkbox"]:not(.kc-toggle-input) {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border: 1.5px solid var(--surface-checkbox-neutral-default);
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  position: relative;
  transition: background var(--transition), border-color var(--transition);
  vertical-align: middle;
}
input[type="checkbox"]:not(.kc-toggle-input):hover {
  border-color: var(--surface-checkbox-neutral-hovered);
}
input[type="checkbox"]:not(.kc-toggle-input):checked {
  background: var(--surface-checkbox-accent-default);
  border-color: var(--surface-checkbox-accent-default);
}
input[type="checkbox"]:not(.kc-toggle-input):checked:hover {
  background: var(--surface-checkbox-accent-hovered);
  border-color: var(--surface-checkbox-accent-hovered);
}
input[type="checkbox"]:not(.kc-toggle-input):checked::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 5px;
  width: 4px;
  height: 8px;
  border: solid var(--color-white-100);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
input[type="checkbox"]:not(.kc-toggle-input):disabled {
  cursor: not-allowed;
  opacity: 0.5;
}
input[type="checkbox"]:not(.kc-toggle-input):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* 12. Bot accounts (P2.11) — APP badge next to bot-authored
   messages. Slack uses a small uppercase pill rendered in accent
   tint; we follow the same idiom so the affordance reads
   instantly to anyone who's used Slack apps. */
.kc-bot-badge {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  padding: 1px 5px;
  border-radius: 3px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--font-2xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  vertical-align: middle;
  user-select: none;
}

/* ── Channel-type picker (create-channel modal): text / voice ── */
.ch-type-picker {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
}
.ch-type-opt {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 10px 12px;
  border-radius: var(--radius-m);
  background: var(--surface);
  border: 1px solid var(--border-mid);
  color: var(--ink);
  cursor: pointer;
  text-align: left;
  transition: background var(--transition), border-color var(--transition);
}
.ch-type-opt:hover { background: var(--raised); }
.ch-type-opt.is-active { background: var(--accent-soft); border-color: var(--accent); }
.ch-type-opt-ico { display: flex; flex-shrink: 0; color: var(--ink-muted); }
.ch-type-opt.is-active .ch-type-opt-ico { color: var(--accent); }
.ch-type-opt-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ch-type-opt-name { font-size: var(--font-sm); font-weight: 600; }
.ch-type-opt-desc { font-size: var(--font-xs); color: var(--ink-muted); }
