/* ═══════════════════════════════════════════════════════════════════════
   KNOWLEDGE BASE MODULE
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── QUICK ENTRY (diary-style, single-row) ─── */
.quick-entry {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  margin-top: var(--space-4);
  margin-bottom: 22px;
  transition: all 0.25s cubic-bezier(0.32, 0.72, 0, 1);
  /* NO overflow:hidden — lets tag dropdown escape the box */
  box-shadow: 0 1px 3px rgba(0,0,0,0.05);
  position: relative;
}
.quick-entry:focus-within,
.quick-entry.expanded {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft), 0 4px 14px rgba(0,0,0,0.08);
}
.quick-entry-row {
  display: flex; align-items: flex-end;
  gap: 8px;
  padding: 8px 8px 8px 14px;
}
.quick-textarea {
  flex: 1;
  background: transparent;
  border: none;
  color: var(--text-primary);
  font-family: var(--body);
  /* iOS zooms automatically on inputs <16px when focused — keep this at 16px
     so the page doesn't zoom in when the user taps the entry box. */
  font-size: var(--text-xl);
  line-height: 1.5;
  resize: none;
  outline: none;
  padding: 10px 0;
  min-height: 24px;
  max-height: 200px;
  overflow-y: auto;
}
.quick-textarea::placeholder { color: var(--text-muted); }
.quick-action {
  width: 36px; height: 36px;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  display: grid; place-items: center;
  transition: transform 0.08s, background 0.15s, color 0.15s, opacity 0.15s;
  flex-shrink: 0;
  background: transparent;
  border: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.quick-action:hover:not(:disabled) { background: var(--bg-elevated); color: var(--text-primary); }
.quick-action:active:not(:disabled) { transform: scale(0.92); background: var(--bg-elevated); }
.quick-action:disabled { opacity: 0.4; cursor: wait; }
.quick-action svg { width: 18px; height: 18px; stroke-width: 2; }
.quick-action.recording {
  color: var(--danger); background: var(--danger-soft);
  animation: kb-pulse 1.4s ease-in-out infinite;
}
@keyframes kb-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,86,112,0.4); }
  50% { box-shadow: 0 0 0 6px rgba(255,86,112,0); }
}

.quick-send {
  width: 42px; height: 42px;
  border-radius: var(--radius-md);
  background: var(--accent);
  color: var(--bg-base);
  display: grid; place-items: center;
  transition: transform 0.08s, opacity 0.15s, box-shadow 0.15s;
  flex-shrink: 0;
  opacity: 0.4;
  pointer-events: none;
  border: none;
  cursor: pointer;
  position: relative;
  -webkit-tap-highlight-color: transparent;
}
.quick-entry.has-content .quick-send {
  opacity: 1;
  pointer-events: auto;
  box-shadow: 0 2px 8px var(--accent-glow);
}
.quick-send:hover:not(.is-loading) {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px var(--accent-glow);
}
.quick-send:active:not(.is-loading) {
  transform: scale(0.9);
  box-shadow: 0 1px 3px var(--accent-glow);
}
.quick-send svg { width: 20px; height: 20px; stroke-width: 2.5; }

/* Loading state — show spinner, hide arrow icon */
.quick-send.is-loading {
  pointer-events: none;
  cursor: wait;
}
.quick-send.is-loading svg { visibility: hidden; }
.quick-send.is-loading::after {
  content: '';
  position: absolute;
  width: 16px; height: 16px;
  border-radius: var(--radius-full);
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: kb-quicksend-spin 0.7s linear infinite;
}
@keyframes kb-quicksend-spin { to { transform: rotate(360deg); } }

/* Photo strip */
.quick-photos {
  display: flex; gap: 8px; flex-wrap: wrap;
  padding: 0 14px 12px;
}
.quick-photos:empty { display: none; }
.photo-thumb-wrap {
  position: relative;
  flex-shrink: 0;
  width: 64px; height: 64px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
}
.photo-thumb-wrap img { width: 100%; height: 100%; object-fit: cover; }
.photo-thumb-remove {
  position: absolute; top: 3px; right: 3px;
  width: 18px; height: 18px;
  border-radius: var(--radius-full);
  background: rgba(0,0,0,0.7);
  color: white;
  display: grid; place-items: center;
  cursor: pointer;
}
.photo-thumb-remove svg { width: 11px; height: 11px; stroke-width: 2.5; }

/* Tag bar — hidden until expanded or has content */
.quick-tags {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px;
  padding: 4px 14px 12px;
  font-size: var(--text-base);
}
.quick-entry:not(:focus-within):not(.has-content) .quick-tags { display: none; }

/* Labels inside composer */
.entry-tag-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px 5px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  font-size: var(--text-base); font-weight: 500;
  color: var(--text-primary);
  cursor: default;
  white-space: nowrap;
}
.entry-tag-chip .tag-dot { width: 8px; height: 8px; border-radius: var(--radius-full); flex-shrink: 0; }
.entry-tag-chip .tag-x {
  display: grid; place-items: center;
  width: 18px; height: 18px;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-muted);
  margin-left: 2px; margin-right: -4px;
  cursor: pointer;
  transition: all 0.12s;
  border: none; padding: 0;
}
.entry-tag-chip .tag-x:hover { background: var(--bg-hover); color: var(--danger); }
.entry-tag-chip .tag-x svg { width: 12px; height: 12px; stroke-width: 2.5; }
.entry-tag-input {
  flex: 1; min-width: 80px;
  background: transparent;
  border: none; outline: none;
  padding: 4px 0;
  font-size: var(--text-md); font-family: var(--body);
  color: var(--text-primary);
}
.entry-tag-input::placeholder { color: var(--text-muted); }

/* ─── TAG SUGGESTIONS DROPDOWN ─── */
.tag-input-wrap { position: relative; }

.tag-suggestions {
  background: var(--bg-surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  max-height: 220px; overflow-y: auto;
  z-index: 500;
  box-shadow: 0 8px 32px rgba(0,0,0,0.28), 0 2px 8px rgba(0,0,0,0.12);
  display: none;
}
.tag-suggestions.show { display: block; }

/* Quick entry dropdown — fixed to viewport so it escapes overflow:hidden parents */
#quickTagSuggestions {
  position: fixed;
  min-width: 200px;
}

.tag-suggestion {
  padding: 10px 14px; cursor: pointer; font-size: var(--text-base);
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  transition: background 0.1s;
  border-bottom: 1px solid var(--border);
}
.tag-suggestion:last-child { border-bottom: none; }
.tag-suggestion:hover, .tag-suggestion.active { background: var(--bg-elevated); }
.tag-suggestion-left { display: flex; align-items: center; gap: 8px; }
.tag-suggestion-dot { width: 8px; height: 8px; border-radius: var(--radius-full); flex-shrink: 0; }
.tag-suggestion-name { color: var(--text-primary); font-weight: 500; }
.tag-suggestion-name-hash { color: var(--text-muted); margin-right: 1px; }
.tag-suggestion-count {
  font-size: var(--text-xs); color: var(--text-muted);
  background: var(--bg-elevated); padding: 1px 6px; border-radius: var(--radius-pill);
}
.tag-suggestion-new { color: var(--accent); font-weight: 500; }

/* ─── ENTRY CARDS (current month list) ─── */
.entries-list { display: flex; flex-direction: column; gap: 8px; }

.entry-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, transform 0.12s, box-shadow 0.12s;
  position: relative;
  overflow: hidden;
}
.entry-card::before {
  content: "";
  position: absolute;
  left: 0; top: 12px; bottom: 12px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}
.entry-card:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(0,0,0,0.10);
}
.entry-card:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.entry-card-top {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 6px;
}
.entry-card-meta { display: flex; align-items: center; gap: 8px; }
.entry-card-date {
  font-size: var(--text-sm); font-weight: 600;
  color: var(--accent);
}
.entry-card-site {
  font-size: var(--text-xs); color: var(--text-muted);
  background: var(--bg-elevated);
  padding: 1px 7px; border-radius: var(--radius-pill);
  font-weight: 500;
}
.entry-card-tags { display: flex; gap: 4px; flex-wrap: wrap; }
.entry-tag {
  font-size: var(--text-xs);
  padding: 1px 7px;
  border-radius: var(--radius-pill);
  font-weight: 500;
  color: white;
  background: var(--accent);
}
.entry-card-text {
  font-size: var(--text-md);
  color: var(--text-secondary);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.entry-card-photos { display: flex; gap: 6px; margin-top: 10px; }
.entry-card-photo {
  width: 48px; height: 48px;
  border-radius: var(--radius-md);
  object-fit: cover;
  border: 1px solid var(--border);
}
.entry-card-photo-more {
  width: 48px; height: 48px;
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  display: grid; place-items: center;
  font-size: var(--text-sm); font-weight: 600;
  color: var(--text-muted);
}

/* Empty state */
.empty-state {
  text-align: center;
  padding: 48px 24px;
  color: var(--text-muted);
}
.empty-state-icon {
  width: 56px; height: 56px;
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  display: grid; place-items: center;
  margin: 0 auto 16px;
  color: var(--text-muted);
}
.empty-state-icon svg { width: 26px; height: 26px; stroke-width: 1.5; }
.empty-state-title {
  font-family: var(--display);
  font-size: var(--text-2xl);
  color: var(--text-secondary);
  margin-bottom: 4px;
  font-weight: 500;
}
.empty-state-sub { font-size: var(--text-base); }

/* ─── KB SEARCH BAR ─── */
.kb-search-row { margin-bottom: 12px; display: flex; gap: 8px; align-items: center; }
.kb-search-wrap {
  flex: 1;
  position: relative;
  display: flex; align-items: center;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.kb-manage-tags-btn {
  width: 40px; height: 40px;
  display: grid; place-items: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-muted);
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.12s, color 0.12s;
}
.kb-manage-tags-btn:hover { background: var(--accent-soft); color: var(--accent); }
.kb-manage-tags-btn svg { width: 16px; height: 16px; }

/* Tag manager modal */
/* ═══════════════════════════════════════════════════════════════════════
   UNIFIED LIBRARY PANEL — 2-tab modal opened from the KB app-bar.
   Hosts info blocks and document search tags in one place.
   ═══════════════════════════════════════════════════════════════════════ */
.kb-lib-panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.kb-lib-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 12px;
  padding: 4px;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
}
.kb-lib-tab {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 12px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.kb-lib-tab:hover { color: var(--text-primary); }
.kb-lib-tab.is-active {
  background: var(--bg-surface);
  color: var(--accent);
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.kb-lib-tab-icon { font-size: 14px; line-height: 1; }
.kb-lib-tab-label { white-space: nowrap; }
@media (max-width: 480px) {
  .kb-lib-tab-label { display: none; }
  .kb-lib-tab { padding: 10px; }
  .kb-lib-tab-icon { font-size: 18px; }
}
.kb-lib-body { min-height: 0; }
.kb-lib-loading,
.kb-lib-empty {
  padding: 30px 10px;
  text-align: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
}
.kb-lib-filter {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  margin-bottom: 12px;
}
.kb-lib-filter-label {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  font-weight: 500;
}
.kb-lib-allswitch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
}
.kb-lib-allswitch input { margin: 0; cursor: pointer; }
.kb-lib-list { display: flex; flex-direction: column; gap: 4px; }
.kb-lib-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  transition: border-color 0.12s, background 0.12s;
}
.kb-lib-row:hover {
  border-color: var(--accent);
  background: var(--bg-elevated);
}
.kb-lib-row-main { flex: 1; min-width: 0; }
.kb-lib-row-title {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kb-lib-row-sub {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kb-lib-tag-dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}
.kb-lib-scope {
  font-size: 10px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 999px;
  white-space: nowrap;
  flex-shrink: 0;
}
.kb-lib-scope--org  { background: var(--bg-elevated); color: var(--text-muted); }
.kb-lib-scope--site { background: var(--purple-soft); color: var(--purple); }
.kb-lib-scope--dept { background: var(--accent-soft); color: var(--accent); }
.kb-lib-group { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.kb-lib-group-label {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.kb-lib-chips { display: flex; flex-direction: column; gap: 4px; }
.kb-lib-chip-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.kb-lib-chip-row > .kb-tag-chip { flex-shrink: 0; }
.kb-lib-chip-row > .kb-lib-scope { margin-left: auto; }

/* Tag manager — dept-aware filter pill at top */
.kb-tag-mgr-filter {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  margin-bottom: 10px;
}
.kb-tag-mgr-filter-label {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  font-weight: 500;
}
.kb-tag-mgr-allswitch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
}
.kb-tag-mgr-allswitch input { margin: 0; cursor: pointer; }
/* Per-row scope chip — colour-coded by scope */
.kb-tag-mgr-scope {
  font-size: 10px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 999px;
  white-space: nowrap;
  flex-shrink: 0;
  text-transform: none;
  letter-spacing: 0.01em;
}
.kb-tag-mgr-scope--org  { background: var(--bg-elevated); color: var(--text-muted); }
.kb-tag-mgr-scope--site { background: var(--purple-soft); color: var(--purple); }
.kb-tag-mgr-scope--dept { background: var(--accent-soft); color: var(--accent); }

.kb-tag-mgr-list { display: flex; flex-direction: column; }
.kb-tag-mgr-row {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
}
.kb-tag-mgr-row:last-child { border-bottom: none; }
.kb-tag-mgr-dot { width: 10px; height: 10px; border-radius: var(--radius-full); flex-shrink: 0; }
.kb-tag-mgr-name { flex: 1; font-size: var(--text-md); font-weight: 500; color: var(--text-primary); }
.kb-tag-mgr-count { font-size: var(--text-sm); color: var(--text-muted); white-space: nowrap; }
.kb-tag-mgr-rename, .kb-tag-mgr-delete {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
  flex-shrink: 0;
}
.kb-tag-mgr-rename:hover { background: var(--accent-soft); color: var(--accent); }
.kb-tag-mgr-delete:hover { background: rgba(220,38,38,0.1); color: rgb(220,38,38); border-color: rgba(220,38,38,0.3); }
.kb-tag-mgr-rename svg, .kb-tag-mgr-delete svg { width: 13px; height: 13px; }
.kb-search-wrap:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.kb-search-icon {
  width: 16px; height: 16px;
  color: var(--text-muted);
  margin: 0 10px 0 14px;
  flex-shrink: 0;
}
.kb-search-input {
  flex: 1;
  background: transparent;
  border: none; outline: none;
  font-family: var(--body);
  font-size: var(--text-md);
  color: var(--text-primary);
  padding: 11px 0;
}
.kb-search-input::placeholder { color: var(--text-muted); }
.kb-search-clear {
  width: 32px; height: 32px;
  border-radius: var(--radius-md);
  display: grid; place-items: center;
  color: var(--text-muted);
  background: transparent; border: none;
  cursor: pointer; margin-right: 4px;
  transition: all 0.15s;
}
.kb-search-clear:hover { background: var(--bg-elevated); color: var(--text-primary); }
.kb-search-clear svg { width: 14px; height: 14px; stroke-width: 2.5; }

/* ─── KB TABS (Inbox / Folders / + new) ─── */
/* ─── KB TABS — independent chips with primary "+" on right ─── */
.kb-tabs {
  display: flex;
  gap: 10px;
  margin-bottom: 14px;
  align-items: center;
  flex-wrap: nowrap;
}
.kb-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 9px 14px;
  border-radius: var(--radius-md);
  font-family: var(--body);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-secondary);
  background: var(--bg-elevated);
  /* Use the stronger border + a subtle shadow so each chip reads as its
     own object on dark theme — without this they blur together. */
  border: 1px solid var(--border-strong);
  box-shadow: 0 1px 2px rgba(0,0,0,0.18);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s;
  -webkit-tap-highlight-color: transparent;
  white-space: nowrap;
}
.kb-tab:hover {
  color: var(--text-primary);
  border-color: color-mix(in srgb, var(--accent) 35%, var(--border));
}
.kb-tab.active {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 50%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent),
              0 1px 2px rgba(0,0,0,0.18);
}
.kb-tab svg { width: 15px; height: 15px; stroke-width: 2; }
.kb-tab-count {
  background: var(--bg-base);
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 700;
  padding: 1px 7px;
  border-radius: var(--radius-md);
  min-width: 20px;
  text-align: center;
  line-height: 1.5;
}
.kb-tab.active .kb-tab-count {
  background: var(--accent);
  color: var(--bg-base);
}

/* Spacer pushes the primary + button to the far right */
.kb-tabs-spacer {
  flex: 1 1 auto;
  min-width: 8px;
}

/* Primary + button — turquoise filled, opens action sheet (Doc / Folder).
   Sized a touch larger than the chips so the eye reads it as the primary
   action, with a soft glow to anchor it as a CTA. */
.kb-tabs-add {
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  width: 42px;
  height: 42px;
  background: var(--accent);
  color: var(--bg-base);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  cursor: pointer;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 14%, transparent),
              0 2px 8px rgba(0,0,0,0.25);
  transition: opacity 0.12s, transform 0.06s, box-shadow 0.15s;
  -webkit-tap-highlight-color: transparent;
}
.kb-tabs-add:hover {
  opacity: 0.92;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent),
              0 4px 12px rgba(0,0,0,0.3);
}
.kb-tabs-add:active { transform: scale(0.94); }
.kb-tabs-add svg { width: 20px; height: 20px; }

/* ─── BREADCRUMB ─── */
.kb-breadcrumb {
  display: flex; align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.kb-crumb {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 10px;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-family: var(--body);
  font-size: var(--text-sm); font-weight: 500;
  background: var(--bg-surface);
  border: 1px solid var(--border); cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.kb-crumb:hover { background: var(--bg-elevated); border-color: var(--border-strong); color: var(--text-primary); }
.kb-crumb svg { width: 13px; height: 13px; stroke-width: 2; }
.kb-crumb-current {
  color: var(--text-primary);
  background: var(--bg-elevated);
  cursor: default;
}
.kb-crumb-current:hover { background: var(--bg-elevated); }
.kb-crumb-sep { color: var(--text-muted); font-size: var(--text-sm); }

/* ─── FOLDER TITLE BAR (slim, Mac Finder style) ─── */
.kb-folder-titlebar {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 4px 4px 14px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.kb-folder-titlebar-info { flex: 1; min-width: 0; }
.kb-folder-titlebar-name {
  font-family: -apple-system, BlinkMacSystemFont, var(--body), "Helvetica Neue", sans-serif;
  font-size: var(--text-3xl); font-weight: 700;
  letter-spacing: 0;
  color: var(--text-primary);
  line-height: 1.15;
  margin-bottom: 2px;
}
.kb-folder-titlebar-desc {
  font-size: var(--text-base);
  color: var(--text-secondary);
  line-height: 1.5;
  margin-top: 4px;
}
.kb-folder-titlebar-tags {
  display: flex; flex-wrap: wrap; gap: 5px;
  margin-top: 8px;
}
.kb-folder-titlebar-actions {
  display: flex; gap: 4px;
  flex-shrink: 0;
  align-items: center;
  align-self: center;
}

/* ─── FOLDER ACTION BUTTONS (used in title bar) ─── */
.kb-folder-action {
  width: 32px; height: 32px;
  border-radius: var(--radius-md);
  color: var(--text-muted);
  display: grid; place-items: center;
  background: transparent;
  border: none; cursor: pointer;
  transition: all 0.12s;
}
.kb-folder-action:hover { background: var(--bg-elevated); color: var(--text-primary); }
.kb-folder-action.danger:hover { background: var(--danger-soft); color: var(--danger); }
.kb-folder-action svg { width: 15px; height: 15px; stroke-width: 2; }

/* ─── FOLDER LIST + CARDS ─── */
.kb-folder-list {
  display: flex; flex-direction: column;
  gap: 8px;
  margin-bottom: 14px;
}
.kb-folder-card {
  display: flex; align-items: center; gap: 12px;
  position: relative;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px 14px 12px 14px;
  text-align: left;
  cursor: pointer;
  font-family: var(--body);
  width: 100%;
  transition: all 0.15s cubic-bezier(0.32,0.72,0,1);
}
.kb-folder-card:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(0,0,0,0.10);
}
.kb-folder-card:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.kb-folder-card-icon {
  width: 36px; height: 36px;
  border-radius: var(--radius-md);
  background: var(--accent-soft);
  color: var(--accent);
  display: grid; place-items: center;
  flex-shrink: 0;
}
.kb-folder-card-icon svg { width: 18px; height: 18px; stroke-width: 2; }
.kb-folder-card-info { flex: 1; min-width: 0; }
/* Title row: folder name + dept-visibility pill on one line.
   The name shrinks/truncates so the pill is never pushed off-screen on
   narrow phones — keeping dept context always visible. */
.kb-folder-card-titlerow {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 2px;
  min-width: 0;
}
.kb-folder-card-titlerow .kb-folder-card-name {
  flex: 1;
  min-width: 0;
  margin-bottom: 0;
}
.kb-folder-card-titlerow .kb-visibility-pill {
  flex-shrink: 0;
}
.kb-folder-card-name {
  font-family: -apple-system, BlinkMacSystemFont, var(--body), "Helvetica Neue", sans-serif;
  font-weight: 600; font-size: var(--text-md);
  letter-spacing: 0;
  color: var(--text-primary);
  margin-bottom: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kb-folder-card-meta {
  font-size: var(--text-xs); color: var(--text-muted);
}
.kb-folder-card-tags {
  display: flex; gap: 4px; flex-wrap: wrap;
  margin-top: 6px;
}
.kb-folder-card-arrow { display: none; }

/* ─── ENTRY CARD EXTRAS (move button, tags row) ─── */
.entry-card-actions {
  display: flex; gap: 4px;
}
.entry-card-move {
  width: 28px; height: 28px;
  border-radius: var(--radius-md);
  color: var(--text-muted);
  display: grid; place-items: center;
  background: transparent;
  border: none; cursor: pointer;
  transition: all 0.12s;
}
.entry-card-move:hover { background: var(--bg-elevated); color: var(--accent); }
.entry-card-move svg { width: 14px; height: 14px; stroke-width: 2; }
.entry-card-tags-row {
  display: flex; gap: 4px; flex-wrap: wrap;
  margin-top: 6px;
}

/* ─── Instruction loader (shown while fetching from server) ─────── */
.kb-instr-loader {
  position: fixed; inset: 0;
  background: var(--bg-base);
  z-index: 285; /* above the reader overlay so the transition is clean */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  opacity: 0;
  transition: opacity 0.16s ease;
  pointer-events: auto;
}
.kb-instr-loader.open { opacity: 1; }
.kb-instr-loader-spinner {
  width: 40px;
  height: 40px;
  color: var(--accent);
  animation: kbInstrLoaderSpin 0.9s linear infinite;
}
.kb-instr-loader-spinner svg { width: 100%; height: 100%; display: block; }
.kb-instr-loader-label {
  font-family: var(--body);
  font-size: var(--text-base);
  color: var(--text-muted);
  letter-spacing: 0.3px;
}
@keyframes kbInstrLoaderSpin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* ═══════════════════════════════════════════════════════════════════════
   NOTE READER (full-screen overlay)
   ═══════════════════════════════════════════════════════════════════════ */
.kb-reader-overlay {
  position: fixed; inset: 0;
  background: var(--bg-base);
  z-index: 280;
  display: flex; flex-direction: column;
  /* Backdrop is opaque from frame 1 — no opacity transition on the
     overlay itself. Fading the whole element makes it semi-transparent
     during the open animation, which lets the underlying page bleed
     through and reads as a flash/flicker. We animate the content
     children instead so the surface stays solid throughout. */
  pointer-events: none;
}
.kb-reader-overlay.open {
  pointer-events: auto;
}

/* Content entrance: header, body, and any sticky nav slide up subtly
   from opacity 0. The motion is short and lightweight so the open
   feels instant but not jarring. */
.kb-reader-overlay > .kb-reader-header,
.kb-reader-overlay > .kb-reader-body,
.kb-reader-overlay > .kb-instr-nav {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.18s ease, transform 0.22s cubic-bezier(0.32, 0.72, 0, 1);
  will-change: opacity, transform;
}
.kb-reader-overlay.open > .kb-reader-header,
.kb-reader-overlay.open > .kb-reader-body,
.kb-reader-overlay.open > .kb-instr-nav {
  opacity: 1;
  transform: translateY(0);
}

.kb-reader-header {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-surface);
  flex-shrink: 0;
  /* Full-screen reader overlay → clear the status bar robustly (see --safe-top). */
  padding-top: var(--safe-top);
}
.kb-reader-back {
  /* Same 40×40 footprint as the photo-viewer close button so reader
     headers feel like a tap-friendly set on mobile. */
  width: 40px; height: 40px;
  border-radius: var(--radius-md);
  display: grid; place-items: center;
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  cursor: pointer;
  flex-shrink: 0;
  transition: all 0.12s;
}
.kb-reader-back:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.kb-reader-back:active { transform: scale(0.94); }
.kb-reader-back svg { width: 22px; height: 22px; stroke-width: 2; }
.kb-reader-header-spacer { flex: 1; }

#kbReaderActions,
#kbInstrActions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}

/* Reading aids (refs / start-over / collapse) — a contextual group that yields
   space BEFORE the pinned action trio. min-width:0 + overflow-x lets it shrink
   and scroll horizontally on a narrow phone rather than push the trio (and the
   Close button) off the right edge. Scrollbar is hidden — it's a tiny set. */
.kb-reader-aids {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  flex-shrink: 1;
  overflow-x: auto;
  scrollbar-width: none;
}
.kb-reader-aids::-webkit-scrollbar { display: none; }
.kb-reader-aids:empty { display: none; }

.kb-reader-action {
  /* Matches .kb-reader-back — 40×40 tappable target with 20px icon. */
  width: 40px; height: 40px;
  border-radius: var(--radius-md);
  display: grid; place-items: center;
  color: var(--text-secondary);
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 0.12s;
}
.kb-reader-action:hover { background: var(--bg-elevated); color: var(--text-primary); }
.kb-reader-action:active:not(:disabled) { transform: scale(0.94); }
.kb-reader-action.danger:hover { background: var(--danger-soft); color: var(--danger); }
.kb-reader-action.is-active {
  background: var(--accent-soft);
  color: var(--accent);
}
.kb-reader-action svg { width: 20px; height: 20px; stroke-width: 2; }
.kb-reader-action.kb-disabled-btn {
  opacity: 0.4;
  cursor: not-allowed;
}
.kb-reader-action.kb-disabled-btn:hover {
  background: transparent;
  color: var(--text-secondary);
}

.kb-reader-body {
  flex: 1;
  overflow-y: auto;
  padding: 24px 18px 80px;
  padding-bottom: max(80px, env(safe-area-inset-bottom));
}
.kb-reader-content {
  max-width: 720px;
  margin: 0 auto;
}

/* Meta row (date + site + folder) */
.kb-reader-meta {
  display: flex; flex-wrap: wrap; gap: 8px;
  align-items: center;
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-bottom: 14px;
}
.kb-reader-meta-item {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px;
  background: var(--bg-elevated);
  /* Hairline frame so the date/site/folder pills read as distinct chips
     on the reader canvas rather than dissolving into it (Prompt 33). */
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
}
.kb-reader-meta-item svg { width: 12px; height: 12px; stroke-width: 2; }
.kb-reader-meta-item-link {
  cursor: pointer;
  transition: all 0.12s;
}
.kb-reader-meta-item-link:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
.kb-reader-meta-edited {
  color: var(--text-muted);
  font-size: var(--text-xs);
}

/* Title (or first line if no explicit title) */
.kb-reader-title {
  /* Apple Notes look — system UI font (SF Pro on Apple, Segoe on Windows).
     DM Sans is the loaded fallback; weight 700 + zero tracking matches Notes. */
  font-family: -apple-system, BlinkMacSystemFont, var(--body), "Helvetica Neue", sans-serif;
  font-size: var(--text-3xl); font-weight: 700;
  letter-spacing: 0;
  color: var(--text-primary);
  line-height: 1.2;
  margin-bottom: 14px;
}

/* Labels row */
.kb-reader-tags {
  display: flex; flex-wrap: wrap; gap: 5px;
  margin-bottom: 18px;
}

/* Body text — preserve line breaks */
.kb-reader-text {
  font-size: var(--text-xl);
  line-height: 1.7;
  color: var(--text-primary);
  white-space: pre-wrap;
  word-wrap: break-word;
}
.kb-reader-text:empty { display: none; }

/* Photo blocks — document-style, not gallery-style.
   Each photo is full-width with caption below; tap to open lightbox for zoom. */
.kb-reader-photos {
  display: flex; flex-direction: column;
  gap: 22px;
  margin-top: 26px;
}
.kb-reader-photo-block {
  margin: 0;
  cursor: zoom-in;
}
.kb-reader-photo-frame {
  display: block;
  width: 100%;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-strong, var(--border));
  overflow: hidden;
  transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
  /* Reasonable cap on photo height so portrait shots don't dominate the screen */
  max-height: 70vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.kb-reader-photo-block:hover .kb-reader-photo-frame {
  border-color: var(--accent);
  box-shadow: 0 4px 16px rgba(0,0,0,0.18);
}
.kb-reader-photo-frame img {
  /* width:auto (NOT 100%) so the <img> box hugs the VISIBLE image instead of
     stretching to the full column and letterboxing portrait shots. The shared
     annotation overlay sizes itself to the <img> box (getBoundingClientRect),
     so a stretched box made marks render larger — and offset — versus the
     height-capped annotation editor (.kb-annot-img, css/04). Matching the
     editor's sizing here makes annotations look identical in edit and view.
     max-width:100% still lets large landscape photos fill the column. */
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 70vh;
  object-fit: contain;
  display: block;
  background: var(--bg-elevated); /* light bg matching checklist step photos */
}
/* step photo loading state */

/* ═══════════════════════════════════════════════════════════════════════
   PHOTO LIGHTBOX (full-screen photo viewer)
   ═══════════════════════════════════════════════════════════════════════ */
.kb-lightbox {
  position: fixed; inset: 0;
  background: #000;
  z-index: 500;
  display: flex; flex-direction: column;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s ease;
}
.kb-lightbox.open {
  opacity: 1;
  pointer-events: auto;
}

/* Top bar — counter + date + close */
.kb-lightbox-top {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 2;
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 18px;
  /* Full-screen lightbox → clear the status bar robustly (see --safe-top). */
  padding-top: var(--safe-top);
  background: linear-gradient(to bottom, rgba(0,0,0,0.65), rgba(0,0,0,0));
  pointer-events: none; /* text is non-interactive; only buttons need clicks */
}
.kb-lightbox-info {
  display: flex; flex-direction: column;
  gap: 2px;
  color: rgba(255,255,255,0.95);
  pointer-events: auto;
}
.kb-lightbox-counter {
  font-family: var(--display);
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: -0.01em;
}
.kb-lightbox-date {
  font-size: var(--text-sm);
  color: rgba(255,255,255,0.65);
  font-weight: 400;
}
.kb-lightbox-close {
  width: 40px; height: 40px;
  /* 10px matches the app's standard button/card radius. The previous
     12px on a 40px button read as a chunky rounded square — Radek's
     feedback that lightbox buttons "didn't match the style of the
     app." */
  border-radius: var(--radius-md);
  display: grid; place-items: center;
  background: rgba(255,255,255,0.1);
  color: white;
  border: none;
  cursor: pointer;
  pointer-events: auto;
  transition: all 0.15s;
  -webkit-tap-highlight-color: transparent;
}
.kb-lightbox-close:hover { background: rgba(255,255,255,0.18); }
.kb-lightbox-close:active { transform: scale(0.92); }
.kb-lightbox-close svg { width: 18px; height: 18px; stroke-width: 2.2; }

/* Photo stage — fills the screen, photo centred */
.kb-lightbox-stage {
  flex: 1;
  display: flex;
  align-items: center; justify-content: center;
  overflow: hidden;
  position: relative;
  touch-action: none; /* we handle all gestures manually when zoomed */
}
.kb-lightbox-img-wrap {
  max-width: 100%;
  max-height: 100%;
  display: flex;
  align-items: center; justify-content: center;
  transition: transform 0.32s cubic-bezier(0.32, 0.72, 0, 1), opacity 0.18s ease;
  transform-origin: center center;
  will-change: transform;
}
.kb-lightbox-img-wrap.is-animating {
  transition: transform 0.32s cubic-bezier(0.32, 0.72, 0, 1), opacity 0.18s ease;
}
.kb-lightbox-img-wrap.no-transition { transition: none; }
.kb-lightbox-img-wrap.swipe-left { transform: translateX(-110%); opacity: 0; }
.kb-lightbox-img-wrap.swipe-right { transform: translateX(110%); opacity: 0; }
.kb-lightbox-img-wrap.swipe-down { transform: translateY(40%); opacity: 0; }
.kb-lightbox img {
  max-width: 100vw;
  max-height: calc(100vh - 100px);
  max-height: calc(100dvh - 100px);
  object-fit: contain;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}

/* Side arrow buttons (shown on desktop and mobile alike) */
.kb-lightbox-nav {
  position: absolute;
  top: 50%; transform: translateY(-50%);
  width: 48px; height: 48px;
  border-radius: var(--radius-full);
  display: grid; place-items: center;
  background: rgba(255,255,255,0.1);
  color: white;
  border: none;
  cursor: pointer;
  z-index: 3;
  opacity: 0.6;
  transition: all 0.18s;
  -webkit-tap-highlight-color: transparent;
}
.kb-lightbox-nav:hover { opacity: 1; background: rgba(255,255,255,0.2); }
.kb-lightbox-nav:active:not(:disabled) { transform: translateY(-50%) scale(0.92); }
.kb-lightbox-nav:disabled { opacity: 0.2; cursor: default; }
.kb-lightbox-nav svg { width: 22px; height: 22px; stroke-width: 2.2; }
.kb-lightbox-nav-prev { left: 16px; }
.kb-lightbox-nav-next { right: 16px; }

@media (max-width: 600px) {
  .kb-lightbox-nav { width: 40px; height: 40px; opacity: 0.5; }
  .kb-lightbox-nav-prev { left: 8px; }
  .kb-lightbox-nav-next { right: 8px; }
}

/* Caption + dot indicators below photo */
.kb-lightbox-bottom {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 2;
  padding: 16px 18px;
  padding-bottom: max(16px, env(safe-area-inset-bottom));
  background: linear-gradient(to top, rgba(0,0,0,0.65), rgba(0,0,0,0));
  display: flex; flex-direction: column; align-items: center;
  gap: 10px;
  pointer-events: none;
}
.kb-lightbox-caption {
  color: rgba(255,255,255,0.92);
  font-size: var(--text-md);
  line-height: 1.5;
  text-align: center;
  max-width: 720px;
  pointer-events: auto;
}
.kb-lightbox-caption:empty { display: none; }
.kb-lightbox-dots {
  display: flex; gap: 6px;
  pointer-events: auto;
}
.kb-lightbox-dot {
  width: 6px; height: 6px;
  border-radius: var(--radius-full);
  background: rgba(255,255,255,0.35);
  border: none;
  padding: 0;
  cursor: pointer;
  transition: all 0.15s;
}
.kb-lightbox-dot:hover { background: rgba(255,255,255,0.7); }
.kb-lightbox-dot.active {
  background: white;
  width: 18px;
  border-radius: var(--radius-sm);
}

/* Loading spinner over the stage */
.kb-lightbox-spinner {
  position: absolute;
  width: 36px; height: 36px;
  border-radius: var(--radius-full);
  border: 3px solid rgba(255,255,255,0.2);
  border-top-color: rgba(255,255,255,0.85);
  animation: kb-lightbox-spin 0.7s linear infinite;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s;
}
.kb-lightbox-spinner.show { opacity: 1; }
@keyframes kb-lightbox-spin { to { transform: rotate(360deg); } }

/* ─── EDIT MODE FORM (inside the reader) ─── */
.kb-edit-form {
  display: flex; flex-direction: column;
  gap: 16px;
  max-width: 720px;
  margin: 0 auto;
}
.kb-edit-field {}
.kb-edit-title {
  font-family: var(--display);
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: -0.02em;
  padding: 12px 14px;
}
.kb-edit-body {
  font-size: var(--text-xl);
  line-height: 1.7;
  min-height: 180px;
}
.kb-edit-photos {
  display: flex; flex-direction: column;
  gap: 10px;
  margin-bottom: 8px;
}
.kb-edit-photo-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px;
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  transition: border-color 0.15s, background 0.15s;
}
.kb-edit-photo-row:hover {
  border-color: var(--border-strong);
}
.kb-edit-photo-row:focus-within {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.kb-edit-photo-row.kb-edit-photo-pending {
  border-color: var(--accent);
  border-style: dashed;
}
.kb-edit-photo-thumb {
  position: relative;
  width: 88px; height: 88px;
  border-radius: var(--radius-md);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg-base);
  flex-shrink: 0;
}
.kb-edit-photo-thumb img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.kb-edit-photo-thumb.kb-edit-photo-new::after {
  content: 'NEW';
  position: absolute;
  top: 4px; left: 4px;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  background: var(--accent);
  color: var(--bg-base);
  padding: 1px 6px;
  border-radius: var(--radius-sm);
}

/* Right column: caption + edit button stacked */
.kb-edit-photo-right {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Caption input */
.kb-edit-photo-right {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.kb-edit-photo-edit-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  min-height: 44px;
  padding: 0 14px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-family: var(--body);
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.kb-edit-photo-edit-btn:hover,
.kb-edit-photo-edit-btn:active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.kb-edit-photo-edit-btn svg {
  width: 15px; height: 15px; flex-shrink: 0; pointer-events: none;
}
.kb-edit-photo-caption {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg-base);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--body);
  font-size: var(--text-base);
  line-height: 1.4;
  outline: none;
  transition: border-color 0.15s, background 0.15s;
  box-sizing: border-box;
}
.kb-edit-photo-caption:hover { border-color: var(--border-strong); }
.kb-edit-photo-caption:focus {
  border-color: var(--accent);
  background: var(--bg-surface);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.kb-edit-photo-caption::placeholder { color: var(--text-muted); }

/* Edit photo button */
.kb-edit-photo-edit-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 0 14px;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-family: var(--body);
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
  width: 100%;
}
.kb-edit-photo-edit-btn:hover,
.kb-edit-photo-edit-btn:active {
  background: var(--bg-surface);
  color: var(--accent);
  border-color: var(--accent);
}
.kb-edit-photo-edit-btn svg {
  width: 14px; height: 14px; flex-shrink: 0;
}

.kb-edit-photo-remove {
  position: absolute; top: 4px; right: 4px;
  width: 24px; height: 24px;
  border-radius: var(--radius-full);
  background: rgba(0,0,0,0.7);
  color: white;
  display: grid; place-items: center;
  cursor: pointer;
  border: none;
  transition: all 0.15s;
}
.kb-edit-photo-remove:hover {
  background: var(--danger);
  transform: scale(1.08);
}
.kb-edit-photo-remove svg { width: 12px; height: 12px; stroke-width: 2.6; }

.kb-edit-photo-uploading { position: relative; }
.kb-edit-photo-upload-overlay {
  position: absolute; inset: 0;
  background: rgba(0,0,0,0.5);
  display: grid; place-items: center;
  color: white;
  border-radius: var(--radius-md);
}
@keyframes spin { to { transform: rotate(360deg); } }

.kb-edit-add-photo {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px;
  background: var(--bg-elevated);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-family: var(--body);
  font-size: var(--text-base); font-weight: 500;
  cursor: pointer;
  transition: all 0.12s;
}
.kb-edit-add-photo:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  border-style: solid;
}
.kb-edit-add-photo svg { width: 14px; height: 14px; stroke-width: 2; }

/* Archive card — slightly de-emphasised vs an active note */
.entry-card-archived {
  opacity: 0.85;
  background: var(--bg-elevated);
}
.entry-card-archived::before {
  background: var(--text-muted);
}
.entry-card-archived:hover {
  opacity: 1;
}
.entry-card-restore,
.entry-card-purge {
  width: 28px; height: 28px;
  border-radius: var(--radius-md);
  display: grid; place-items: center;
  background: transparent;
  border: none;
  cursor: pointer;
  transition: all 0.12s;
  color: var(--text-muted);
}
.entry-card-restore:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
.entry-card-purge:hover {
  background: var(--danger-soft);
  color: var(--danger);
}
.entry-card-restore svg,
.entry-card-purge svg { width: 14px; height: 14px; stroke-width: 2; }

/* ═══════════════════════════════════════════════════════════════════════
   INSTRUCTIONS (Stage C)
   ═══════════════════════════════════════════════════════════════════════ */

/* "+ New" buttons row inside a folder */
.kb-folder-actions-row {
  display: flex; gap: 10px; flex-wrap: wrap;
  margin: 14px 0 18px;
}
.kb-folder-action-instr { color: var(--accent); }
.kb-folder-action-instr:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
}
.kb-folder-create-btn {
  flex: 1; min-width: 140px;
  display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 16px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--body);
  font-size: var(--text-md); font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
}
.kb-folder-create-btn:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.kb-folder-create-btn:active { transform: scale(0.985); }
.kb-folder-create-btn svg { width: 16px; height: 16px; stroke-width: 2; flex-shrink: 0; }
.kb-folder-create-btn-instr svg { color: var(--accent); }

/* Instruction card — distinctively different from note cards */
.kb-instr-list {
  display: flex; flex-direction: column;
  gap: 10px;
}
#kbQuickBand { margin-bottom: 14px; }
.kb-instr-card {
  position: relative;
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 16px 14px 18px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  font-family: var(--body);
  text-align: left;
  width: 100%;
  transition: all 0.15s cubic-bezier(0.32,0.72,0,1);
  overflow: hidden;
}
.kb-instr-card:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(0,0,0,0.12);
}
.kb-instr-card:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* Coloured strip on the left edge */
.kb-instr-card-strip {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: var(--accent);
  opacity: 0.85;
}
.kb-instr-card-icon {
  width: 38px; height: 38px;
  border-radius: var(--radius-md);
  background: var(--accent-soft);
  color: var(--accent);
  display: grid; place-items: center;
  flex-shrink: 0;
}
.kb-instr-card-icon svg { width: 18px; height: 18px; stroke-width: 2; }
.kb-instr-card-body { flex: 1; min-width: 0; }
.kb-instr-card-top {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 4px;
}
.kb-instr-ref {
  display: inline-flex;
  align-items: center;
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}
.kb-instr-card-meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.kb-instr-card-title {
  font-family: -apple-system, BlinkMacSystemFont, var(--body), "Helvetica Neue", sans-serif;
  font-size: var(--text-xl);
  font-weight: 700;
  letter-spacing: 0;
  color: var(--text-primary);
  margin-bottom: 3px;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.kb-instr-card-desc {
  font-size: var(--text-base);
  color: var(--text-secondary);
  line-height: 1.5;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  margin-bottom: 4px;
}
.kb-instr-card-tags {
  display: flex; flex-wrap: wrap; gap: 4px;
  margin-top: 4px;
}
/* Top header row on document cards: the title fills the width and starts at the
   very top of the card, with the visibility/department pill pinned to the
   top-right corner. The old right-chevron was removed, so the pill squeezes to
   the edge. A long title wraps to a second line beneath; the pill stays put. */
.kb-instr-card-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 3px;
}
.kb-instr-card-head .kb-instr-card-title {
  flex: 1 1 auto;
  min-width: 0;
  margin-bottom: 0;
}
.kb-instr-card-head .kb-visibility-pill {
  flex-shrink: 0;
  margin-top: 1px;
}
/* ⋯ menu column on document / file cards (holds the shared .kb-card-menu-btn) */
.kb-instr-card-actions {
  display: flex; gap: 4px;
  flex-shrink: 0;
}

/* ─── KB rows mode: browse cards double as shared .colb-row hosts ──────────
   The folder browse rows⇄cards toggle renders Documents/Files/Notes as
   .colb-row rows, but each row root keeps its .kb-instr-card / .entry-card
   class (+ data-id) so the existing click-to-open AND tree drag-and-drop
   wiring stays attached. The shared row kit (css/21, loaded after this file)
   already wins the box layout by source order; these higher-specificity rules
   just neutralise the card-only chrome the row kit doesn't set — the note's
   ::before accent strip and the card hover lift/shadow. */
.colb-row.entry-card::before { content: none; }
.colb-row.kb-instr-card:hover,
.colb-row.entry-card:hover { transform: none; box-shadow: none; }

/* Instruction reader specifics */
.kb-instr-overlay .kb-reader-title {
  margin-top: 6px;
}
/* Leave space at the bottom of the scroll area for the sticky nav bar */
.kb-instr-overlay .kb-reader-body { padding-bottom: 0; }
.kb-instr-overlay .kb-instr-reader-content { padding-bottom: 80px; }
.kb-instr-meta-row {
  display: flex; flex-wrap: wrap; gap: 8px;
  align-items: center;
  margin-bottom: 12px;
}
.kb-instr-ref-pill {
  display: inline-flex;
  align-items: center;
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  padding: 3px 9px;
  border-radius: var(--radius-sm);
  cursor: text;
  user-select: all;
  -webkit-user-select: all;
  flex-shrink: 0; /* keep the ref readable; the reading-aids group yields space instead */
}
.kb-instr-desc {
  font-size: var(--text-md);
  line-height: 1.6;
  color: var(--text-secondary);
  margin-bottom: 18px;
  padding: 12px 14px;
  background: var(--bg-elevated);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
}

/* Steps in read-only view */
/* Steps in read-only view — number is rendered explicitly (not via CSS counter)
   so we can continue numbering across collapsed sub-instructions. */
.kb-instr-steps {
  list-style: none;
  padding: 0;
  margin: 24px 0 0;
}
/* Document-mode step block list variant — each step block renders as
   its own <ul> wrapping a single <li>. The base 24px top margin then
   appears between EVERY consecutive step block, creating the big gap
   Radek flagged. Zero out the inter-block spacing so the chips stack
   naturally; the chip's own margin-bottom (4px) controls the visible
   gap. */
.kb-instr-steps-block-list {
  margin: 0;
}
.kb-instr-step {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* Chip/card style — each step has its own visual frame. Radek's
     preferred design. The only thing that needed tightening was the
     stack gap between consecutive steps, which is what margin-bottom
     controls. Padding stays compact inside each chip. */
  padding: 8px 12px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-bottom: 4px;
}
/* Header row: number circle + step title side by side */
.kb-instr-step-header {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.kb-instr-step-num {
  position: relative;
  width: 32px; height: 32px;
  border-radius: var(--radius-full);
  background: var(--accent);
  color: var(--bg-base);
  font-family: var(--display);
  font-size: var(--text-base);
  font-weight: 700;
  display: grid; place-items: center;
  flex-shrink: 0;
  margin-top: 0;
  border: 0;
  cursor: pointer;
  padding: 0;
  transition: all 0.15s cubic-bezier(0.32,0.72,0,1);
}
.kb-instr-step-num:hover { transform: scale(1.06); }
.kb-instr-step-num:active { transform: scale(0.95); }
.kb-instr-step-num-text,
.kb-instr-step-num-check,
.kb-instr-step-num-lock {
  grid-area: 1 / 1;
  transition: opacity 0.15s, transform 0.15s;
}
.kb-instr-step-num-check,
.kb-instr-step-num-lock {
  width: 16px; height: 16px;
  opacity: 0;
  transform: scale(0.7);
}
/* When the parent step is done, swap number for check */
.kb-instr-step.is-done .kb-instr-step-num {
  background: var(--success, #16a34a);
}
.kb-instr-step.is-done .kb-instr-step-num-text { opacity: 0; transform: scale(0.7); }
.kb-instr-step.is-done .kb-instr-step-num-check { opacity: 1; transform: scale(1); }

/* Locked steps — faded, lock icon shown */
.kb-instr-step.is-locked {
  opacity: 0.55;
}
.kb-instr-step.is-locked .kb-instr-step-num {
  background: var(--text-muted);
  cursor: not-allowed;
}
.kb-instr-step.is-locked .kb-instr-step-num-text { opacity: 0; transform: scale(0.7); }
.kb-instr-step.is-locked .kb-instr-step-num-lock { opacity: 1; transform: scale(1); }
.kb-instr-step.is-locked .kb-instr-step-num:hover { transform: none; }

/* Current step — subtle highlight */
.kb-instr-step.is-current {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Done step — green tint */
.kb-instr-step.is-done {
  background: rgba(22, 163, 74, 0.06);
  border-color: rgba(22, 163, 74, 0.3);
}
.kb-instr-step.is-done .kb-instr-step-text {
  color: var(--text-secondary);
  text-decoration: line-through;
  text-decoration-color: rgba(22, 163, 74, 0.6);
  text-decoration-thickness: 1.5px;
}

/* Shake animation when user taps a locked step */
@keyframes kb-instr-step-shake {
  0%, 100% { transform: translateX(0); }
  20%      { transform: translateX(-6px); }
  40%      { transform: translateX(6px); }
  60%      { transform: translateX(-3px); }
  80%      { transform: translateX(3px); }
}
.kb-instr-step-shake { animation: kb-instr-step-shake 0.42s ease; }

.kb-instr-step-body { flex: 1; min-width: 0; } /* kept for edit mode compat */
.kb-instr-step-text {
  font-size: var(--text-lg);
  line-height: 1.5;
  color: var(--text-primary);
  transition: color 0.18s, text-decoration-color 0.18s;
}
.kb-instr-step-info {
  margin-top: 8px;
  padding: 8px 12px;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  color: var(--text-secondary);
  line-height: 1.5;
  border-left: 3px solid var(--text-muted);
}

/* ─── Progress bar (inline, sits above the index/steps — not sticky) ─── */
.kb-instr-progress {
  margin: 24px 0 12px;
  padding: 12px 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.kb-instr-progress-text {
  font-family: var(--display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 8px;
  letter-spacing: -0.005em;
}
.kb-instr-progress-bar {
  height: 6px;
  background: var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.kb-instr-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  border-radius: var(--radius-sm);
  transition: width 0.3s cubic-bezier(0.32,0.72,0,1), background 0.3s;
}
.kb-instr-progress-fill.is-complete {
  background: var(--success, #16a34a);
}

/* ─── Index (jump-to dropdown) ─── */
.kb-instr-index {
  margin: 0 0 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  overflow: hidden;
}
.kb-instr-index-summary {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 14px;
  font-family: var(--display);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
  cursor: pointer;
  list-style: none;
}
.kb-instr-index-summary::-webkit-details-marker { display: none; }
.kb-instr-index-summary svg {
  width: 16px; height: 16px;
  color: var(--text-muted);
}
.kb-instr-index[open] .kb-instr-index-summary {
  border-bottom: 1px solid var(--border);
}
.kb-instr-index-list {
  list-style: none;
  margin: 0;
  padding: 4px 0;
  max-height: 320px;
  overflow-y: auto;
}
.kb-instr-index-list li { margin: 0; padding: 0; }
.kb-instr-index-item {
  display: flex; align-items: center; gap: 12px;
  width: 100%;
  padding: 8px 14px;
  background: transparent;
  border: 0;
  font-family: var(--body);
  font-size: var(--text-base);
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  transition: background 0.12s;
}
.kb-instr-index-item:hover { background: var(--bg-elevated); }
.kb-instr-index-num {
  display: inline-grid; place-items: center;
  width: 22px; height: 22px;
  border-radius: var(--radius-full);
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--display);
  font-size: var(--text-xs);
  font-weight: 700;
  flex-shrink: 0;
}
.kb-instr-index-text {
  flex: 1; min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ─── Edit mode: hide read-mode UI elements that don't apply ───── */
/* When the user enters edit mode, the bottom Mark done / Back nav bar must
   be removed — otherwise its click handlers fire against the now-empty
   step DOM and freeze the page. Same for the floating progress bar and
   jump-to index, which are read-mode interaction layers. */
.kb-reader-overlay.is-editing .kb-instr-nav,
.kb-reader-overlay.is-editing .kb-instr-progress,
.kb-reader-overlay.is-editing .kb-instr-index { display: none !important; }
/* Make sure the body can scroll all the way to the bottom edit controls
   (no sticky bar reserving space anymore). */
.kb-reader-overlay.is-editing .kb-reader-body { padding-bottom: 24px; }

/* ─── Document editor (Pages — type='document') ─────────────────── */
.kb-doc-editor {
  display: flex;
  flex-direction: column;
  gap: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  /* overflow: hidden removed — sticky toolbar needs the scroll
     context to propagate up to .kb-reader-body. With overflow:hidden
     the sticky was clipped instead of pinned and scrolled away. */
  background: var(--bg-surface);
}
/* Combined sticky wrap. The main toolbar and notice row sit inside
   it; the wrap is what's sticky, so both rows pin as one unit
   regardless of how the inner content wraps on small viewports.
   This avoids the height-math fragility of two separate sticky
   rows where the second has to guess the first's height. */
.kb-doc-toolbar-wrap {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 6;
  background: var(--bg-elevated);
  /* Full border + all-corner radius so the toolbar reads as a DISTINCT
     control panel floating above the document — not a strip that blends
     into the content cards directly below it (which also use
     --bg-elevated). Was: border-bottom + top-only radius + a near-
     invisible shadow, which blended on dark themes. */
  border: 1px solid var(--border-strong, var(--border));
  border-radius: 12px;
  /* A real gap below reinforces that the toolbar is separate from the
     first content block. */
  margin-bottom: 14px;
  /* DON'T use overflow:hidden here — iOS Safari drops sticky positioning
     when the sticky element clips its own content. The two inner rows
     round their own outer corners to match (see below), so the panel
     stays crisp without clipping the sticky wrap. */
  overflow: visible;
  /* Layered shadow gives a clear visual signal that the toolbar is
     layered ABOVE the document content as the user scrolls. */
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
  /* Compositor-layer hint — keeps sticky stable on iOS during focus-
     triggered scrolls. Without this iOS drops sticky temporarily when
     the on-screen keyboard opens, making the toolbar "jump back" to
     its inline position. */
  will-change: transform;
}

/* ─── MOBILE: keep toolbar sticky at TOP of content ──────────────────
   Word-style: toolbar sits above content and stays visible while the
   user scrolls down through the document.
   ───────────────────────────────────────────────────────────────────
   Mobile sticky reliability notes:
     1. .kb-reader-body (the scroll container) needs -webkit-overflow-
        scrolling: touch and contain: layout so iOS Safari treats it
        as a hard scroll boundary and respects sticky inside it.
     2. The sticky element MUST NOT have any ancestor with `transform`,
        `filter`, or `perspective` set — those create a new containing
        block and break sticky pinning. The reader overlay uses
        `position: fixed` which is fine; we just need to avoid
        compositor transforms on intermediate ancestors.
     3. On focusin (keyboard open), iOS sometimes drops sticky for
        one frame. We work around it by adding `will-change: transform`
        to the sticky element + listening for focusin in kb.js to
        force a reflow that re-establishes the sticky position.
*/
@media (max-width: 768px) {
  .kb-doc-toolbar-wrap {
    /* Higher z-index on mobile so it floats above any other inline UI
       as the page scrolls beneath it. */
    z-index: 50;
    /* Stronger compositor hint on mobile where the bug actually appears */
    will-change: transform;
  }
  /* Reinforce the scroll container's behaviour — iOS needs explicit
     -webkit-overflow-scrolling and contain hints to keep sticky stable. */
  .kb-reader-body {
    -webkit-overflow-scrolling: touch;
    /* contain: layout isolates the scroll area as a sticky context */
    contain: layout;
    /* Anchor the scroll position when content changes (e.g. keyboard
       opens / closes). Prevents iOS from arbitrarily resetting scroll
       which is what makes the toolbar appear to "jump back". */
    overflow-anchor: auto;
  }
  /* Toolbar rows can scroll horizontally on small screens so all buttons
     remain reachable without wrapping into multiple lines. */
  .kb-doc-toolbar,
  .kb-doc-toolbar-notices {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    flex-wrap: nowrap;
  }
  .kb-doc-toolbar::-webkit-scrollbar,
  .kb-doc-toolbar-notices::-webkit-scrollbar { display: none; }
}
.kb-doc-toolbar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 8px 10px;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
  /* Match the wrap's rounded top so the icon row fills the panel corners. */
  border-top-left-radius: 11px;
  border-top-right-radius: 11px;
}
/* Notice row — below the main toolbar in the shared sticky wrap.
   No individual sticky positioning since the wrap handles it. */
.kb-doc-toolbar-notices {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 5px;
  padding: 8px 10px;
  background: var(--bg-elevated);
  /* Match the wrap's rounded bottom so the notice row fills the panel corners. */
  border-bottom-left-radius: 11px;
  border-bottom-right-radius: 11px;
}
/* Mobile-friendly tap target — matches the 42×42 app-bar buttons up top.
   Below 44px is unsafe per Apple/Material guidelines; 42px ties visually
   to the top bar while still leaving the editor compact on desktop. */
.kb-doc-tb-btn {
  width: 42px; height: 42px;
  display: grid; place-items: center;
  background: transparent;
  /* Resting outline so each formatting key is a visible affordance, not
     an invisible transparent square (Prompt 33). --border-strong is the
     one border token that holds on the --bg-elevated toolbar in BOTH
     themes (light --border dissolves into the warm fill). */
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
}
.kb-doc-tb-btn:hover {
  background: var(--bg-surface);
  color: var(--accent);
  /* Accent outline on hover — a clear step up from the resting
     --border-strong (was --border, which read weaker than rest). */
  border-color: var(--accent);
}
.kb-doc-tb-btn:active { transform: scale(0.96); }
/* Active state — currently-applied formatting at cursor (bold, italic,
   heading, list). Filled accent so users can tell which buttons are on. */
.kb-doc-tb-btn.is-active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.kb-doc-tb-btn.is-active svg { color: var(--accent); }
/* SVG bumped to 20px to keep a comfortable ~48% icon-to-button ratio
   (matches the app bar's 22-in-42 proportions) */
.kb-doc-tb-btn svg { width: 20px; height: 20px; pointer-events: none; }
.kb-doc-tb-btn span { pointer-events: none; }

/* ─── Aa BUTTON (opens the text-formatting popover) ────────────────── */
.kb-doc-tb-aa-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 0 10px;
  min-width: 56px;
  width: auto !important;  /* overrides .kb-doc-tb-btn width:42px */
}
.kb-doc-tb-aa-label {
  font: 700 17px / 1 var(--font-display, serif);
  letter-spacing: 0.02em;
}
.kb-doc-tb-aa-chevron {
  width: 12px !important;
  height: 12px !important;
  opacity: 0.7;
  transition: transform 0.15s;
}
.kb-doc-tb-aa-btn.is-open .kb-doc-tb-aa-chevron {
  transform: rotate(180deg);
}
.kb-doc-tb-aa-btn.is-open {
  background: var(--accent-soft, rgba(0,216,230,0.10));
  color: var(--accent);
}

/* ─── "+ Add block" TRIGGER (Prompt 32) ─────────────────────────────────
   The one primary insert affordance in the slim toolbar. Labelled + accent-
   tinted so it reads as the obvious way to add content (vs. the neutral Aa /
   Photo keys). Auto width like the Aa button. Both themes via tokens. */
.kb-doc-tb-addblock {
  width: auto !important;              /* overrides .kb-doc-tb-btn width:42px */
  padding: 0 14px;
  gap: 6px;
  display: inline-flex;
  align-items: center;
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.kb-doc-tb-addblock svg { width: 18px; height: 18px; }
.kb-doc-tb-addblock span {
  font: 600 14px / 1 var(--body);
  white-space: nowrap;
}
.kb-doc-tb-addblock:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.kb-doc-tb-addblock:hover svg { color: #fff; }
.kb-doc-tb-addblock[aria-expanded="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.kb-doc-tb-addblock[aria-expanded="true"] svg { color: #fff; }
/* Keyboard focus ring — parity with its palette siblings (add-zone pill /
   palette item), which the base .kb-doc-tb-btn doesn't provide (§4). */
.kb-doc-tb-addblock:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* ─── INLINE "+ Add block" ZONE (between blocks / end of doc) ────────────
   Calm at rest (visible on touch — no hover-only reveal, §4) and brightens
   to accent on hover / keyboard focus. Slim so a long document stays clean. */
.kb-doc-add-zone {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 3px 2px;
  margin: 1px 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  opacity: 0.5;                        /* present but quiet at rest */
  transition: opacity 0.12s;
  -webkit-tap-highlight-color: transparent;
}
.kb-doc-add-zone:hover,
.kb-doc-add-zone:focus-visible { opacity: 1; outline: none; }
.kb-doc-add-zone-rule {
  flex: 1;
  height: 1px;
  background: var(--border-strong);
}
.kb-doc-add-zone-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--bg-surface);
  color: var(--text-secondary);
  font: 600 12px / 1 var(--body);
  white-space: nowrap;
}
.kb-doc-add-zone-pill svg { width: 13px; height: 13px; }
.kb-doc-add-zone:hover .kb-doc-add-zone-pill,
.kb-doc-add-zone:focus-visible .kb-doc-add-zone-pill {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
}
.kb-doc-add-zone:focus-visible .kb-doc-add-zone-pill {
  box-shadow: 0 0 0 2px var(--accent-soft);
}

/* ─── BLOCK PALETTE popover (desktop; mobile uses the shared action sheet) ─
   Labelled rows: icon tile + name + one-line description. --bg-surface panel
   + --border-strong so it lifts off the page in BOTH themes (the Prompt 27/33
   card-vs-canvas language — --bg-elevated would invert muddy under light). */
.kb-block-palette {
  background: var(--bg-surface);
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  box-shadow: 0 14px 38px rgba(0, 0, 0, 0.30);
  padding: 8px;
  max-width: 92vw;
  /* When the list is taller than the viewport JS caps its height + sets
     overflow-y; keep that scroll smooth and stop it chaining to the page
     behind (which would otherwise scroll the editor and close the popover). */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.kb-block-palette-title {
  font: 700 11px / 1 var(--body);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 6px 8px 8px;
}
/* Desktop: groups stacked, each an internal 2-column grid so the whole
   palette (icon + name + one-line desc cards) is visible at once — no
   scrolling wall. JS sets the popover width (~600px) to fit two columns. */
.kb-block-palette-groups {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.kb-block-palette-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px;
}
.kb-block-palette-item {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  text-align: left;
  padding: 7px 9px;
  border-radius: 10px;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-primary);
  cursor: pointer;
  transition: background 0.1s, border-color 0.1s;
}
.kb-block-palette-item:hover,
.kb-block-palette-item:focus-visible {
  background: var(--bg-elevated);
  border-color: var(--border-strong);
  outline: none;
}
.kb-block-palette-item:focus-visible { box-shadow: 0 0 0 2px var(--accent-soft); }
.kb-block-palette-icon {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-secondary);
}
.kb-block-palette-icon svg { width: 17px; height: 17px; }
.kb-block-palette-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.kb-block-palette-name {
  font: 600 14px / 1.2 var(--body);
  color: var(--text-primary);
}
.kb-block-palette-desc {
  font: 400 12px / 1.3 var(--body);
  color: var(--text-secondary);
}
/* Group headers between the popover rows (Most used / Callouts / More) —
   slimmer + smaller than the "Add a block" title so the hierarchy reads. */
.kb-block-palette-group {
  font: 600 10px / 1 var(--body);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 9px 9px 4px;
}

/* ─── MOBILE: the block palette rides the shared action sheet (opened with
   sheetClass:'kb-block-palette-sheet' + grouped `sections`). 14 roomy rows
   filled the whole phone screen, so the palette variant renders each group
   as a 2-column grid of compact CARDS (icon on top, name, 2-line-max desc) —
   roughly half the height, and the "Most used" four sit in the first two
   rows. Scoped, so no other action sheet in the app changes. Higher
   specificity (0,2,0) beats the css/08 base (0,1,0) regardless of file
   order. Cards are far taller than 44px tap-height. */
.kb-block-palette-sheet .kb-action-sheet-sec {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px;
}
.kb-block-palette-sheet .kb-action-sheet-sec-title { padding: 8px 4px 6px; }
.kb-block-palette-sheet .kb-action-sheet-item {
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
  padding: 10px 8px 9px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg-elevated);
}
.kb-block-palette-sheet .kb-action-sheet-item:hover,
.kb-block-palette-sheet .kb-action-sheet-item:active {
  background: var(--bg-elevated);
  border-color: var(--border-strong);
}
.kb-block-palette-sheet .kb-action-sheet-icon {
  width: 34px; height: 34px; border-radius: 9px;
}
.kb-block-palette-sheet .kb-action-sheet-icon svg { width: 18px; height: 18px; }
.kb-block-palette-sheet .kb-action-sheet-text { flex: 0 0 auto; width: 100%; }
.kb-block-palette-sheet .kb-action-sheet-name { font-size: var(--text-base); }
.kb-block-palette-sheet .kb-action-sheet-sub {
  font-size: var(--text-xs);
  line-height: 1.25;
  margin-top: 1px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.kb-block-palette-sheet .kb-action-sheet-title { padding-bottom: 4px; }

/* The shared .kb-modal-field-hint (colour + size live in css/08) is used
   inline on labels everywhere else; the Tags field renders it as its own
   line, so it just needs top spacing here (css/08 sets no margin). */
.kb-modal-field-hint { margin: 6px 0 0; }

/* ─── Aa POPOVER ────────────────────────────────────────────────────── */
.kb-doc-aa-popover {
  position: fixed;
  z-index: 9100;
  min-width: 320px;
  max-width: 360px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 12px 32px rgba(0,0,0,0.15), 0 2px 8px rgba(0,0,0,0.08);
  padding: 8px;
  display: none;
  flex-direction: column;
  gap: 8px;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.12s ease-out, transform 0.12s ease-out;
}
.kb-doc-aa-popover.is-open {
  display: flex;
  opacity: 1;
  transform: none;
}
.kb-doc-aa-popover[hidden] { display: none; }

.kb-doc-aa-divider {
  height: 1px;
  background: var(--border);
  margin: 0 -2px;
}

.kb-doc-aa-row {
  display: flex;
  align-items: center;
  gap: 4px;
}
.kb-doc-aa-row-inline {
  justify-content: space-around;
  padding: 2px;
}

/* Inline format buttons (B / I / U / S) */
.kb-doc-aa-btn {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  cursor: pointer;
  font-family: inherit;
  transition: background 0.12s, color 0.12s;
}
.kb-doc-aa-btn:hover {
  background: var(--bg-elevated);
}
.kb-doc-aa-btn.is-active {
  background: var(--accent-soft, rgba(0,216,230,0.10));
  color: var(--accent);
}
.kb-doc-aa-btn svg { width: 16px; height: 16px; }

/* Paragraph style rows */
.kb-doc-aa-row-paragraphs {
  flex-direction: column;
  gap: 2px;
  align-items: stretch;
}
.kb-doc-aa-paragraph-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  transition: background 0.12s;
}
.kb-doc-aa-paragraph-btn:hover {
  background: var(--bg-elevated);
}
.kb-doc-aa-paragraph-btn.is-active {
  background: var(--accent-soft, rgba(0,216,230,0.06));
}
.kb-doc-aa-check {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--accent);
  opacity: 0;
}
.kb-doc-aa-check svg { width: 14px; height: 14px; }
.kb-doc-aa-paragraph-btn.is-active .kb-doc-aa-check { opacity: 1; }

/* List buttons (bulleted / numbered) */
.kb-doc-aa-row-lists {
  gap: 4px;
}
.kb-doc-aa-list-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  padding: 8px 10px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  cursor: pointer;
  font: 500 13px / 1 var(--body);
  font-family: inherit;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.kb-doc-aa-list-btn:hover {
  background: var(--bg-elevated);
  border-color: var(--border);
}
.kb-doc-aa-list-btn.is-active {
  background: var(--accent-soft, rgba(0,216,230,0.10));
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}
.kb-doc-aa-list-btn svg { width: 16px; height: 16px; flex-shrink: 0; }

/* Colour swatches */
.kb-doc-aa-row-colors {
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
}
.kb-doc-aa-row-label {
  font: 600 11px / 1 var(--body);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.kb-doc-aa-color-swatches {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.kb-doc-aa-color-swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1.5px solid transparent;
  cursor: pointer;
  padding: 0;
  transition: transform 0.08s, border-color 0.12s, box-shadow 0.12s;
  flex-shrink: 0;
}
.kb-doc-aa-color-swatch:hover {
  transform: scale(1.12);
  border-color: var(--text-primary);
  box-shadow: 0 0 0 2px var(--bg-surface);
}
/* "Auto" swatch — checker-pattern so it reads as "default theme colour" */
.kb-doc-aa-color-swatch.is-default {
  background: conic-gradient(
    var(--text-primary) 0deg 90deg,
    var(--bg-elevated) 90deg 180deg,
    var(--text-primary) 180deg 270deg,
    var(--bg-elevated) 270deg 360deg
  );
  background-size: 50% 50%;
  background-repeat: no-repeat;
  background-position: 0 0;
  background: linear-gradient(135deg, var(--text-primary) 0% 45%, var(--bg-elevated) 50% 100%);
  border-color: var(--border);
}
.kb-doc-tb-divider {
  width: 1px;
  height: 26px;
  background: var(--border);
  margin: 0 4px;
  flex-shrink: 0;
}
/* Mobile toolbar: horizontally scrollable single row with finger-friendly
   44px tap targets. Matches the pattern used by Notion, Bear, etc. */
@media (max-width: 768px) {
  .kb-doc-toolbar {
    /* Vertical breathing room so the 44px buttons don't sit flush against the
       toolbar panel's rounded top/bottom edges (was 0 vertical → cramped,
       "touching the edges"). A touch more side padding + gap too. */
    padding: 6px 8px;
    gap: 3px;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .kb-doc-toolbar::-webkit-scrollbar { display: none; }
  .kb-doc-tb-btn {
    width: 44px; height: 44px;
    flex-shrink: 0;
  }
  .kb-doc-tb-btn svg { width: 18px; height: 18px; }
  .kb-doc-divider { flex-shrink: 0; }
  .kb-doc-toolbar-notices {
    padding: 6px 8px;
    gap: 4px;
  }
  .kb-doc-toolbar-notices .kb-instr-edit-add-callout-label {
    display: none;
  }
  .kb-doc-toolbar-notices .kb-instr-edit-add-callout-btn {
    padding: 4px 7px;
    font-size: var(--text-xs);
  }
  .kb-doc-toolbar-notices .kb-instr-edit-add-callout-btn svg {
    width: 12px; height: 12px;
  }
  .kb-doc-tb-divider {
    height: 22px;
    background: var(--text-muted);
    opacity: 0.35;
    margin: 0 3px;
  }
}
.kb-doc-blocks {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  background: var(--bg-base);
}
/* ── Document block card — outer div IS the card ── */
.kb-doc-block {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  background: var(--bg-elevated);
  /* Stronger edge so each editor block card lifts clearly off the
     --bg-base canvas (Prompt 33 — the light theme flattens --border
     to a near-invisible hairline; --border-strong holds in both). */
  border: 1px solid var(--border-strong, var(--border));
  border-radius: var(--radius-md);
  padding: 10px;
  margin-bottom: 6px;
  transition: border-color 0.15s;
}
.kb-doc-block:focus-within { border-color: var(--accent); }

/* Universal inner wrapper — takes all available width */
.kb-doc-block-inner {
  flex: 1;
  min-width: 0;
}

/* Right-side action column */
.kb-doc-block-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
  align-items: center;
}

/* Document callout edit wrapper — pure flex-row so actions stay on right.
   The callout colour (border-left, background) comes from kb-doc-callout-xxx variants. */
.kb-doc-block-callout-wrap {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 8px;
  padding: 12px 10px 12px 16px;
  border-radius: var(--radius-md);
  margin-bottom: 6px;
  border-left: 4px solid var(--accent);
  background: var(--accent-soft);
}
.kb-doc-block-callout-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* UNIFIED action button — identical style for ↑ ↓ AND × everywhere */
/* Block action buttons (up / down / delete) — sized at 38×38 for a
   compact but still tappable target. Slightly tighter than the app-bar
   42px so the action column doesn't dominate small text blocks. */
.kb-block-action-btn {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  background: var(--bg-elevated);
  /* The action column shares the block card's --bg-elevated fill, so a
     stronger edge is what actually separates the ↑/↓/× keys from the
     card behind them — a plain --border is invisible here (Prompt 33). */
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  /* Darker colour for better light-mode visibility — text-secondary
     reads clearly on var(--bg-elevated) without needing a heavier
     border. Radek's spec: "make arrows a bit more visible". */
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
  touch-action: manipulation;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
}
.kb-block-action-btn:hover {
  background: var(--bg-surface);
  color: var(--text-primary);
  border-color: var(--border-strong, var(--text-muted));
}
.kb-block-action-btn:active { transform: scale(0.96); }
.kb-block-action-btn:disabled { opacity: 0.25; cursor: default; pointer-events: none; }
/* Delete variant — red icon by default. */
.kb-block-action-btn.kb-block-action-btn-remove {
  color: #dc2626;
  border-color: color-mix(in srgb, #dc2626 25%, var(--border));
}
.kb-block-action-btn.kb-block-action-btn-remove:hover {
  background: color-mix(in srgb, #dc2626 10%, transparent);
  color: #dc2626;
  border-color: color-mix(in srgb, #dc2626 50%, transparent);
}
/* Inline variant — used when the action button sits IN-LINE with
   content (not in the right-hand action column). Same tap-friendly
   size as the column variants so mobile users hit it reliably.
   Used by all destructive inline deletes per Radek's safety request:
   "Delete button below arrow is not a good place — as soon somebody
   wants to move section up/down they could tap delete by accident." */
.kb-block-action-btn.kb-block-action-btn-inline {
  width: 38px;
  height: 38px;
  flex-shrink: 0;
}
.kb-block-action-btn svg {
  width: 20px;
  height: 20px;
  pointer-events: none;
  /* Slightly lighter stroke now that the icons are larger — keeps
     them clear without feeling heavy at 20px. */
  stroke-width: 2.2;
}
.kb-block-action-btn.kb-block-action-btn-remove svg { width: 20px; height: 20px; }
.kb-block-action-btn.kb-block-action-btn-inline svg { width: 20px; height: 20px; }

/* Bottom row inside a block — for inline content actions like
   [Label input][Info button][trash icon]. Flex row, label grows,
   button + trash stay natural width. Used by photo, video, callout,
   step, text blocks. */
.kb-doc-block-bottom-row {
  display: flex;
  align-items: stretch;
  gap: 6px;
  margin-top: 8px;
}
.kb-doc-block-bottom-row > input[type="text"] {
  flex: 1;
  min-width: 0;
}
/* Text-block-specific bottom row — only contains the inline trash.
   Right-align so the trash sits at the end of the editable column,
   never crowding the text. */
.kb-doc-block-bottom-row-text {
  justify-content: flex-end;
  margin-top: 4px;
}

/* Editable area — transparent inside card, card provides the container */
.kb-doc-block-text { /* outer card handles styling */ }
.kb-doc-block-editable {
  flex: 1;
  min-height: 52px;
  padding: 4px 2px;
  background: transparent;
  border: none;
  border-radius: 0;
  font-family: var(--body);
  font-size: var(--text-xl);
  line-height: 1.55;
  color: var(--text-primary);
  outline: none;
  word-wrap: break-word;
  overflow-wrap: break-word;
  width: 100%;
}
.kb-doc-block-editable:focus { outline: none; }
.kb-doc-block-editable:empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
  pointer-events: none;
}
.kb-doc-block-editable h3 {
  font-family: var(--display);
  font-size: var(--text-2xl);
  font-weight: 700;
  margin: 8px 0 4px;
  color: var(--text-primary);
}
.kb-doc-block-editable ul,
.kb-doc-block-editable ol {
  list-style: none;
  padding: 0;
  margin: 6px 0 8px;
}
.kb-doc-block-editable ul > li {
  position: relative;
  padding-left: 1.4em;
  margin: 3px 0;
}
.kb-doc-block-editable ul > li::before {
  content: '•';
  position: absolute;
  left: 0.3em;
}
.kb-doc-block-editable ol {
  counter-reset: ol-counter;
}
.kb-doc-block-editable ol > li {
  position: relative;
  padding-left: 1.8em;
  margin: 3px 0;
  counter-increment: ol-counter;
}
.kb-doc-block-editable ol > li::before {
  content: counter(ol-counter) '.';
  position: absolute;
  left: 0;
  min-width: 1.4em;
  text-align: right;
}
.kb-doc-block-editable ul ul,
.kb-doc-block-editable ol ul {
  margin: 2px 0;
}
.kb-doc-block-editable ul ul > li { padding-left: 1.2em; }
.kb-doc-block-editable ul ul > li::before { left: 0.2em; content: '◦'; }
.kb-doc-block-editable strong { font-weight: 700; }
.kb-doc-block-editable em { font-style: italic; }
.kb-doc-block-editable a { color: var(--accent); text-decoration: underline; }

/* Photo block — outer card already has border/bg, just need column layout */
.kb-doc-block-photo {
  gap: 8px;
}
.kb-doc-block-photo-thumb {
  width: 100%;
  max-height: 240px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
}
.kb-doc-block-photo-thumb img {
  width: 100%;
  max-height: 240px;
  object-fit: contain;
  display: block;
}
.kb-doc-block-photo-loading {
  display: grid; place-items: center;
  height: 80px;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.kb-doc-block-caption {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg-base);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--body);
  font-size: var(--text-base);
  outline: none;
  transition: border-color 0.15s, background 0.15s;
  box-sizing: border-box;
  margin-top: 6px;
}
.kb-doc-block-caption:focus {
  border-color: var(--accent);
  background: var(--bg-surface);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.kb-doc-block-caption::placeholder { color: var(--text-muted); }
/* When the caption input sits inside the photo-buttons row (compact
   layout: row 1 = action buttons, row 2 = caption + info), it needs
   to match the button height so the row visually aligns. Drop the
   stand-alone margin-top (row gap handles spacing) and tighten the
   padding to match button metrics. */
.kb-instr-edit-photo-buttons-row > .kb-doc-block-caption {
  margin-top: 0;
  padding: 7px 10px;
  min-height: 34px;
  border-width: 1.5px;
}
.kb-doc-block-remove {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  color: var(--text-muted);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s, background 0.12s, color 0.12s;
}
.kb-doc-block:hover .kb-doc-block-remove { opacity: 1; }
.kb-doc-block-remove:hover {
  background: rgba(220, 38, 38, 0.1);
  color: rgb(220, 38, 38);
}
.kb-doc-block-remove svg { width: 13px; height: 13px; }
@media (hover: none) {
  /* On touch devices, always show the remove button */
  .kb-doc-block-remove { opacity: 1; }
}

/* The block ↑ / ↓ / × action column (.kb-block-action-btn) is always
   visible at rest on every breakpoint — no hover reveal to unhide. */

/* ─── QR Code modal ─────────────────────────────────────────────── */
.kb-qr-modal { display: flex; flex-direction: column; gap: 16px; }
.kb-qr-access-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 16px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.kb-qr-access-title { font-size: var(--text-lg); font-weight: 600; color: var(--text-primary); }
.kb-qr-access-sub { font-size: var(--text-sm); color: var(--text-muted); margin-top: 2px; }
/* Toggle switch */
.kb-qr-toggle { position: relative; flex-shrink: 0; cursor: pointer; }
.kb-qr-toggle input { opacity: 0; width: 0; height: 0; position: absolute; }
.kb-qr-toggle-track {
  display: block; width: 44px; height: 26px;
  background: var(--border); border-radius: var(--radius-pill);
  transition: background 0.2s;
}
.kb-qr-toggle-track::after {
  content: ''; position: absolute;
  top: 3px; left: 3px;
  width: 20px; height: 20px;
  background: #fff; border-radius: var(--radius-full);
  transition: transform 0.2s;
}
.kb-qr-toggle input:checked + .kb-qr-toggle-track { background: var(--accent); }
.kb-qr-toggle input:checked + .kb-qr-toggle-track::after { transform: translateX(18px); }
/* QR code display */
.kb-qr-code-area { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.kb-qr-label { font-size: var(--text-base); color: var(--text-secondary); text-align: center; }
.kb-qr-canvas-wrap {
  background: #fff; padding: 16px; border-radius: var(--radius-md);
  border: 1px solid var(--border);
  display: inline-flex; align-items: center; justify-content: center;
}
.kb-qr-url {
  font-size: var(--text-xs); color: var(--text-muted); word-break: break-all;
  text-align: center; max-width: 280px;
}
.kb-qr-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.kb-qr-private-msg {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px; border-radius: var(--radius-md);
  background: var(--bg-elevated); border: 1px solid var(--border);
  font-size: var(--text-base); color: var(--text-muted);
}
.kb-qr-private-msg svg { width: 16px; height: 16px; flex-shrink: 0; }

/* Photo block — Annotate + Remove buttons grouped in top-right */
/* Photo action buttons — same pill style as checklist/procedure step photos */
.kb-doc-block-photo-actions { display: none; } /* legacy - no longer used */

/* ─── Document reader (rendered Page output) ─────────────────────── */
.kb-doc-content {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 8px 0;
}
/* ─── Info-grid block (viewer + editor) ─── */
.kb-doc-info-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin: 12px 0;
}
.kb-doc-info-grid-tile {
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 6px);
}
.kb-doc-info-grid-label {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}
.kb-doc-info-grid-value {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
  display: flex;
  align-items: center;
  gap: 6px;
  word-break: break-word;
}
.kb-doc-info-grid-icon { font-size: 18px; flex-shrink: 0; line-height: 1; }
@media (max-width: 480px) {
  .kb-doc-info-grid { grid-template-columns: 1fr; }
}

/* Info-grid editor */
.kb-doc-info-grid-editor {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin: 8px 0;
}
.kb-doc-info-grid-editor-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.kb-doc-info-grid-add {
  background: transparent;
  border: 1px dashed var(--border-strong);
  color: var(--accent);
  font-weight: 600;
  font-size: var(--text-xs);
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-transform: none;
  letter-spacing: 0;
}
.kb-doc-info-grid-add:hover { border-color: var(--accent); }
/* Editor row is a mini "tile preview" matching the rendered viewer
   tile shape — label on top, icon + value below. Removes the mental
   mapping the old single-line row required. */
.kb-doc-info-grid-editor-row {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-top: 8px;
}
.kb-doc-info-grid-editor-row:first-of-type { margin-top: 0; }

.kb-doc-info-grid-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
/* Reserve room on the label row for the absolutely-positioned 🗑 */
.kb-doc-info-grid-field:first-of-type input { padding-right: 38px; }
.kb-doc-info-grid-field-eyebrow {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.kb-doc-info-grid-editor-row input {
  width: 100%;
  padding: 8px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 13px;
  color: var(--text-primary);
  min-width: 0;
  box-sizing: border-box;
}
.kb-doc-info-grid-editor-row input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.kb-doc-info-grid-value-row {
  display: grid;
  /* Was 44px + 28px + 1fr (icon-input + emoji-button + value). Now
     just 44px + 1fr — single icon-picker button replaces the previous
     two elements. */
  grid-template-columns: 44px 1fr;
  gap: 6px;
  align-items: center;
}

/* Single icon-picker button — empty state shows a + glyph, set state
   shows the picked emoji at a readable size. Replaces the old icon
   text-input + smiley button combo which confused users (was the
   fork/knife placeholder a real value or a hint?). One button, two
   visual states. */
.kb-doc-info-grid-icon-pick {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  background: var(--bg-elevated);
  border: 1.5px dashed color-mix(in srgb, var(--accent) 35%, var(--border));
  border-radius: var(--radius-md);
  color: color-mix(in srgb, var(--accent) 70%, var(--text-muted));
  cursor: pointer;
  padding: 0;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.kb-doc-info-grid-icon-pick:hover {
  background: color-mix(in srgb, var(--accent) 10%, var(--bg-elevated));
  border-color: var(--accent);
  color: var(--accent);
}
.kb-doc-info-grid-icon-pick:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.kb-doc-info-grid-icon-pick-content {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  font-size: 22px;
  line-height: 1;
}
/* When an emoji is picked, drop the dashed-border "empty" look and
   give the emoji proper visual weight. */
.kb-doc-info-grid-icon-pick.has-icon {
  border-style: solid;
  border-color: var(--border);
  background: var(--bg-surface);
}
.kb-doc-info-grid-icon-pick.has-icon .kb-doc-info-grid-icon-pick-content {
  font-size: 24px;
}

/* Trash icons (per-row + block-level) — red by default so the user
   immediately reads them as destructive, matching the rest of the
   app's danger-coloured destructive controls. Uses the canonical
   trash SVG with the two vertical interior lines. */
.kb-doc-info-grid-row-del {
  position: absolute;
  top: 6px;
  right: 6px;
  display: grid;
  place-items: center;
  /* Bumped from 26→32 (with svg 14→18) so the per-row delete reads as
     a proper tap target on touch devices. Still sits in the corner. */
  width: 32px; height: 32px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--danger);
  cursor: pointer;
  z-index: 1;
  transition: background 0.12s ease, color 0.12s ease;
}
.kb-doc-info-grid-row-del svg {
  width: 18px;
  height: 18px;
}
.kb-doc-info-grid-row-del:hover {
  background: var(--danger-soft);
}

/* (Block-level Remove for info-grid moved to the canonical
   .kb-doc-block-actions column on the right side of the block
   wrapper — same as photo/video/text. .kb-doc-info-grid-block-del
   and .kb-doc-info-grid-header-actions rules removed.) */

/* ─── Doc generator modal body ─── */
.docgen-body {
  display: flex;
  flex-direction: column;
  padding: 4px 0 12px;
}
.docgen-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 6px;
}
.docgen-textarea {
  width: 100%;
  padding: 12px 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--text-primary);
  resize: vertical;
  min-height: 110px;
  line-height: 1.4;
  box-sizing: border-box;
}
.docgen-textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.docgen-hint {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 6px;
}
.docgen-examples {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.docgen-example-chip {
  display: inline-flex;
  align-items: center;
  padding: 7px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
  text-align: left;
  line-height: 1.3;
}
.docgen-example-chip:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.docgen-status {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: var(--radius-md);
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: 600;
}
.docgen-spinner svg {
  width: 18px; height: 18px;
  animation: kbSpin 0.9s linear infinite;
}
@keyframes kbSpin { to { transform: rotate(360deg); } }
.docgen-error {
  margin-top: 14px;
  padding: 12px 14px;
  background: rgba(220, 38, 38, 0.08);
  border: 1px solid rgba(220, 38, 38, 0.3);
  border-radius: var(--radius-md);
  color: #dc2626;
  font-size: var(--text-sm);
}
[data-theme="dark"] .docgen-error {
  background: rgba(248, 113, 113, 0.10);
  color: #fca5a5;
}

/* The status + error boxes are toggled via the [hidden] attribute, but the
   class rules above set `display`, which ties specificity with `[hidden]`
   and — being later in source order — would otherwise win, leaving the
   "Working…" spinner permanently on screen. Make `hidden` actually hide. */
.docgen-status[hidden],
.docgen-error[hidden] { display: none; }

/* ─── Doc-generator: attached photos ─── */
.docgen-photos {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.docgen-photo-add {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  width: 64px; height: 64px;
  flex-shrink: 0;
  background: var(--bg-elevated);
  border: 1px dashed var(--border-strong, var(--border));
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: 11px; font-weight: 600;
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.docgen-photo-add svg { width: 20px; height: 20px; }
.docgen-photo-add:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
}
.docgen-photo-tile {
  position: relative;
  width: 64px; height: 64px;
  flex-shrink: 0;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
}
.docgen-photo-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.docgen-photo-tile.is-uploading img { opacity: 0.4; }
.docgen-photo-remove {
  position: absolute; top: 3px; right: 3px;
  width: 20px; height: 20px;
  display: grid; place-items: center;
  padding: 0;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  border: 0; border-radius: 50%;
  cursor: pointer;
}
.docgen-photo-remove svg { width: 12px; height: 12px; }
.docgen-photo-spin {
  position: absolute; inset: 0; margin: auto;
  width: 22px; height: 22px;
  border: 2px solid var(--accent-soft);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: kbSpin 0.8s linear infinite;
}

/* ─── AI FAB (KB-only floating action button) ─── */
.float-ai-fab {
  position: fixed;
  bottom: max(24px, calc(env(safe-area-inset-bottom) + 16px));
  right: 18px;
  width: 56px; height: 56px;
  border-radius: var(--radius-lg);
  background: var(--accent);
  color: #07090d;
  border: 0;
  box-shadow: 0 6px 20px color-mix(in srgb, var(--accent) 35%, transparent);
  z-index: 40;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: transform 0.12s, box-shadow 0.12s, filter 0.12s;
  -webkit-tap-highlight-color: transparent;
}
[data-theme="light"] .float-ai-fab { color: #ffffff; }
.float-ai-fab:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 28px color-mix(in srgb, var(--accent) 45%, transparent);
  filter: brightness(1.05);
}
.float-ai-fab:active { transform: translateY(0) scale(0.96); }
.float-ai-fab svg { width: 26px; height: 26px; stroke-width: 2; }
@media (min-width: 1024px) {
  .float-ai-fab { bottom: 32px; right: 32px; }
}

/* ─── Settings: subsection title (used under "Knowledge Base") ─── */
.settings-subsection-title {
  font-size: var(--text-md);
  font-weight: 700;
  color: var(--text-primary);
  margin-top: 8px;
  margin-bottom: 6px;
  letter-spacing: -0.01em;
}

/* ─── Reusable-label management (Settings → Knowledge Base) ─── */
.settings-chip-lib-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 12px;
}
.settings-chip-lib-filter {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  margin-bottom: 12px;
}
.settings-chip-lib-filter-label {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  font-weight: 500;
}
.settings-chip-lib-allswitch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
}
.settings-chip-lib-allswitch input { margin: 0; cursor: pointer; }
.settings-chip-lib-scope--org   { color: var(--text-muted); }
.settings-chip-lib-scope--site  { color: var(--purple); }
.settings-chip-lib-scope--dept  { color: var(--accent); font-weight: 600; }
.settings-chip-lib-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.settings-chip-lib-loading,
.settings-chip-lib-empty {
  text-align: center;
  padding: 24px 8px;
  color: var(--text-muted);
  font-size: var(--text-sm);
}
.settings-chip-lib-group { display: flex; flex-direction: column; gap: 6px; }
.settings-chip-lib-group-label {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.settings-chip-lib-rows { display: flex; flex-direction: column; gap: 4px; }
.settings-chip-lib-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  background: var(--bg-elevated);
  border-radius: var(--radius-sm);
}
.settings-chip-lib-row > .kb-tag-chip { flex-shrink: 0; }
.settings-chip-lib-scope {
  flex: 1;
  font-size: var(--text-xs);
  color: var(--text-muted);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.settings-chip-lib-row-del {
  display: grid;
  place-items: center;
  width: 26px; height: 26px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  flex-shrink: 0;
}
.settings-chip-lib-row-del:hover { background: var(--danger-soft); color: var(--danger); }

/* ─── Compact iOS-style switch ─── */
.ah-switch {
  display: inline-block;
  position: relative;
  flex-shrink: 0;
  width: 44px; height: 26px;
  cursor: pointer;
}
.ah-switch input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}
.ah-switch-track {
  position: absolute;
  inset: 0;
  background: var(--border-strong);
  border-radius: 999px;
  transition: background 0.18s ease;
}
.ah-switch-thumb {
  position: absolute;
  top: 2px; left: 2px;
  width: 22px; height: 22px;
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0,0,0,0.18);
  transition: transform 0.18s ease;
}
.ah-switch input:checked + .ah-switch-track { background: var(--accent); }
.ah-switch input:checked + .ah-switch-track .ah-switch-thumb {
  transform: translateX(18px);
}
.ah-switch input:focus-visible + .ah-switch-track {
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* ─── AI toggle row inside the settings card ─── */
.settings-ai-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 14px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.settings-ai-toggle-text { flex: 1; min-width: 0; }
.settings-ai-toggle-name {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 2px;
}
.settings-ai-toggle-desc {
  font-size: var(--text-xs);
  color: var(--text-muted);
  line-height: 1.4;
}

/* ─── AI Integration settings ─── */
.settings-ai-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
  margin-top: 12px;
}

/* Settings → Chats — one row per group chat (name + meta + Edit/Remove). */
.chat-mng-row { display: flex; align-items: center; gap: 10px; padding: 12px 0; border-bottom: 1px solid var(--border); }
.chat-mng-row:last-child { border-bottom: none; }
.chat-mng-main { flex: 1 1 auto; min-width: 0; }
.chat-mng-name { font: 600 var(--text-base)/1.3 var(--body); color: var(--text-primary); }
.chat-mng-sub { font: 500 var(--text-sm)/1.4 var(--body); color: var(--text-secondary); margin-top: 2px; }
.chat-mng-tag { flex: none; padding: 3px 9px; border-radius: 999px; font: 700 var(--text-xs)/1.4 var(--body);
  color: var(--c, var(--accent)); background: color-mix(in srgb, var(--c, var(--accent)) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--c, var(--accent)) 45%, transparent); }
.chat-mng-tag-stale { color: #d97706; background: color-mix(in srgb, #d97706 14%, transparent);
  border-color: color-mix(in srgb, #d97706 40%, transparent); white-space: nowrap; }
.chat-mng-row.is-stale { background: color-mix(in srgb, #d97706 6%, transparent); margin: 0 -8px; padding-left: 8px; padding-right: 8px; border-radius: var(--radius-md); border-bottom-color: transparent; }
.chat-mng-btn { flex: none; padding: 7px 14px; border-radius: var(--radius-md); cursor: pointer;
  background: var(--bg-elevated); border: 1px solid var(--border); color: var(--text-primary);
  font: 600 var(--text-sm)/1 var(--body); }
.chat-mng-btn:hover { background: var(--bg-hover); }
.chat-mng-btn.is-danger { color: #f87171; border-color: color-mix(in srgb, #f87171 40%, var(--border)); }
.chat-mng-btn.is-danger:hover { background: color-mix(in srgb, #f87171 14%, transparent); }
.chat-mng-btn:disabled { opacity: .5; cursor: default; }
.chat-mng-toggle { display: flex; align-items: center; gap: 14px; cursor: pointer; margin: 0; }
.chat-mng-toggle-text { flex: 1 1 auto; min-width: 0; }
.chat-mng-toggle-t { display: block; font: 600 var(--text-base)/1.3 var(--body); color: var(--text-primary); }
.chat-mng-toggle-s { display: block; font: 500 var(--text-sm)/1.4 var(--body); color: var(--text-secondary); margin-top: 2px; }

/* Tidy up inactive chats */
.chat-tidy-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.chat-tidy-row .eng-access-select { flex: 1 1 auto; }
.chat-tidy-found { font: 600 var(--text-sm)/1.4 var(--body); color: var(--text-secondary); margin: 14px 0 8px; }
.chat-tidy-item { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--border); cursor: pointer; }
.chat-tidy-item:last-of-type { border-bottom: none; }
.chat-tidy-cb { width: 18px; height: 18px; flex: none; accent-color: var(--accent); }
.chat-tidy-name { flex: 1 1 auto; min-width: 0; font: 600 var(--text-base)/1.3 var(--body); color: var(--text-primary); }
.chat-tidy-ago { flex: none; font: 500 var(--text-xs)/1.4 var(--body); color: var(--text-muted, var(--text-secondary)); }
.settings-ai-btn.is-danger-soft { color: #f87171; border-color: color-mix(in srgb, #f87171 40%, var(--border)); }
.settings-ai-btn.is-danger-soft:hover { background: color-mix(in srgb, #f87171 12%, transparent); }
.settings-ai-field { display: flex; flex-direction: column; gap: 8px; }
.settings-ai-label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
}
.settings-ai-hint {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.settings-ai-hint code {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  background: var(--bg-elevated);
  padding: 1px 6px;
  border-radius: var(--radius-xs);
  font-size: 11px;
}
.settings-ai-row {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.settings-ai-input {
  flex: 1 1 240px;
  min-width: 0;
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 13px;
  color: var(--text-primary);
}
.settings-ai-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.settings-ai-btn {
  padding: 9px 14px;
  background: var(--bg-elevated);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, border-color 0.12s;
}
.settings-ai-btn:hover { border-color: var(--accent); }
.settings-ai-btn.primary {
  background: var(--accent);
  color: #07090d;
  border-color: var(--accent);
}
[data-theme="light"] .settings-ai-btn.primary { color: #ffffff; }
.settings-ai-btn.primary:hover { opacity: 0.9; }
.settings-ai-btn.danger { color: #ef4444; border-color: rgba(239,68,68,0.35); }
.settings-ai-btn.danger:hover { background: rgba(239,68,68,0.08); border-color: #ef4444; }
.settings-ai-status {
  font-size: var(--text-xs);
  min-height: 18px;
  color: var(--text-muted);
}

/* ─── Settings: Asset Register — Service types ─── */
.settings-svc-toolbar {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}
.settings-svc-toolbar .settings-ai-btn { min-height: 44px; }
.callout-modal-overlay[data-svc-tidy] .callout-modal-close {
  width: 44px;
  height: 44px;
}
.callout-modal-overlay[data-svc-tidy] .callout-btn { min-height: 44px; }
.settings-svc-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.settings-svc-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--bg-base);
  border-radius: var(--radius-sm);
}
.settings-svc-row:hover { background: var(--bg-elevated); }
.settings-svc-info {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.settings-svc-name {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-primary);
}
.settings-svc-badge {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 99px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  white-space: nowrap;
}
.settings-svc-interval {
  font-size: var(--text-sm);
  color: var(--text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}
.settings-svc-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

/* ─── Reusable-label picker popover ─── */
.ahcl-popover-wrap {
  position: fixed;
  top: 0; left: 0;
  z-index: 9999;
  opacity: 0;
  transform: translateY(-4px) scale(0.98);
  transform-origin: top right;
  transition: opacity 0.14s, transform 0.14s;
  pointer-events: none;
}
.ahcl-popover-wrap.is-open {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.ahcl-popover {
  width: 360px;
  max-width: calc(100vw - 16px);
  max-height: 70vh;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.22);
  display: flex;
  flex-direction: column;
}
.ahcl-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.ahcl-title {
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--text-primary);
}
.ahcl-close {
  display: grid; place-items: center;
  width: 24px; height: 24px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
}
.ahcl-close:hover { background: var(--bg-elevated); color: var(--text-primary); }
.ahcl-body {
  padding: 10px 14px 14px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.ahcl-group { margin-bottom: 12px; }
.ahcl-group:last-child { margin-bottom: 0; }
.ahcl-group-label {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 6px;
}
.ahcl-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.ahcl-chip-btn {
  cursor: pointer;
  transition: transform 0.08s, filter 0.12s;
  font-family: inherit;
}
.ahcl-chip-btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
.ahcl-chip-btn:active { transform: translateY(0); }
.ahcl-empty {
  padding: 24px 8px;
  text-align: center;
  color: var(--text-muted);
}
.ahcl-empty p { margin: 0 0 6px; font-size: var(--text-sm); }
.ahcl-empty-hint { font-size: var(--text-xs); opacity: 0.7; }

/* Save-to-library dialog body */
.ahcl-save-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 4px 0;
}
.ahcl-save-preview-wrap {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
}
.ahcl-save-label {
  font-size: 10px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.ahcl-save-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.ahcl-save-field-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.ahcl-save-field-hint {
  font-size: var(--text-xs);
  color: var(--text-muted);
  line-height: 1.4;
  margin-top: 4px;
}
.ahcl-save-field input,
.ahcl-save-field select {
  padding: 8px 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 13px;
  color: var(--text-primary);
  width: 100%;
  box-sizing: border-box;
}
.ahcl-save-field input:focus,
.ahcl-save-field select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}

/* ─── Emoji picker popover ─── */
.ahep-popover-wrap {
  position: fixed;
  top: 0; left: 0;
  z-index: 9999;
  opacity: 0;
  transform: translateY(-4px) scale(0.98);
  transform-origin: top right;
  transition: opacity 0.12s, transform 0.12s;
  pointer-events: none;
}
.ahep-popover-wrap.is-open {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.ahep-popover {
  width: 280px;
  max-width: calc(100vw - 16px);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.18);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.ahep-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
}
.ahep-label {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.ahep-close {
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
}
.ahep-close:hover { background: var(--bg-elevated); color: var(--text-primary); }
.ahep-tabs {
  display: flex;
  gap: 2px;
  padding: 6px 8px;
  background: var(--bg-elevated);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}
.ahep-tab {
  display: grid;
  place-items: center;
  flex: 1 0 auto;
  min-width: 36px;
  height: 32px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 16px;
  transition: background 0.12s;
}
.ahep-tab:hover { background: var(--bg-surface); }
.ahep-tab.is-active {
  background: var(--accent-soft);
  box-shadow: inset 0 -2px 0 var(--accent);
}
.ahep-tab-icon { line-height: 1; }
.ahep-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 2px;
  padding: 8px;
  max-height: 220px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.ahep-emoji {
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  font-size: 18px;
  cursor: pointer;
  transition: background 0.08s, transform 0.08s;
  line-height: 1;
  padding: 0;
}
.ahep-emoji:hover {
  background: var(--accent-soft);
  transform: scale(1.15);
}
.ahep-emoji:active { transform: scale(1); }
@media (max-width: 420px) {
  .ahep-popover { width: calc(100vw - 16px); }
  .ahep-grid { grid-template-columns: repeat(7, 1fr); }
}

/* Emoji trigger button — used inside info-grid + tags editors */
.ahep-trigger {
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.ahep-trigger:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

/* ─── Tags block (viewer + editor) ─── */
.kb-doc-tags-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 10px 0;
}
.kb-tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 10px;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  line-height: 1.4;
}
/* Icon prefix inside a chip — rendered slightly larger than the
   text so emojis read at a comfortable size against the small
   12px label. Sits left of the text via the chip's flex gap. */
.kb-tag-chip-icon {
  font-size: 13px;
  line-height: 1;
}
.kb-tag-chip.red     { background: #fef2f2; color: #991b1b; border: 1px solid #fecaca; }
.kb-tag-chip.amber   { background: #fffbeb; color: #92400e; border: 1px solid #fde68a; }
.kb-tag-chip.green   { background: #f0fdf4; color: #166534; border: 1px solid #bbf7d0; }
.kb-tag-chip.blue    { background: #eff6ff; color: #1e40af; border: 1px solid #bfdbfe; }
.kb-tag-chip.neutral { background: var(--bg-elevated); color: var(--text-secondary); border: 1px solid var(--border); }
/* Dark-mode tinted variants so the chips read on dark surfaces */
[data-theme="dark"] .kb-tag-chip.red     { background: rgba(220,38,38,0.12); color: #fca5a5; border-color: rgba(220,38,38,0.3); }
[data-theme="dark"] .kb-tag-chip.amber   { background: rgba(245,158,11,0.14); color: #fcd34d; border-color: rgba(245,158,11,0.3); }
[data-theme="dark"] .kb-tag-chip.green   { background: rgba(16,185,129,0.14); color: #6ee7b7; border-color: rgba(16,185,129,0.3); }
[data-theme="dark"] .kb-tag-chip.blue    { background: rgba(59,130,246,0.14); color: #93c5fd; border-color: rgba(59,130,246,0.3); }

/* Tags editor */
.kb-doc-tags-editor {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin: 8px 0;
}
.kb-doc-tags-editor-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.kb-doc-tags-add {
  background: transparent;
  border: 1px dashed var(--border-strong);
  color: var(--accent);
  font-weight: 600;
  font-size: var(--text-xs);
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-transform: none;
  letter-spacing: 0;
}
.kb-doc-tags-add:hover { border-color: var(--accent); }
/* Labels row layout — all action buttons standardised at 32px for
   visual consistency across the row.
   [emoji-pick 32] [text 1fr] [color-pick 32] [trash 32]
   The block-level Remove button now lives on the parent wrapper
   (kb-doc-block-actions column), not inside the editor. */
.kb-doc-tags-editor-row {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) 32px 32px;
  gap: 6px;
  align-items: center;
}
.kb-doc-tags-editor-header-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}
.kb-doc-tags-library-btn {
  background: transparent;
  border: 1px dashed var(--border-strong);
  color: var(--accent);
  font-weight: 600;
  font-size: var(--text-xs);
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-transform: none;
  letter-spacing: 0;
  font-family: inherit;
}
.kb-doc-tags-library-btn:hover { border-color: var(--accent); background: var(--accent-soft); }

/* Emoji insert button — leading +-icon button. Tapping it opens the
   emoji picker, which inserts the chosen emoji at the cursor inside
   the text input. The + signals "tap to add (anything)" — replaces
   the old 😊 which read as "you can only add a smiley". */
.kb-doc-tags-emoji-pick {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  background: var(--bg-elevated);
  border: 1.5px dashed color-mix(in srgb, var(--accent) 35%, var(--border));
  border-radius: var(--radius-sm);
  color: color-mix(in srgb, var(--accent) 70%, var(--text-muted));
  cursor: pointer;
  padding: 0;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.kb-doc-tags-emoji-pick:hover {
  background: color-mix(in srgb, var(--accent) 10%, var(--bg-elevated));
  border-color: var(--accent);
  color: var(--accent);
}
.kb-doc-tags-emoji-pick svg { width: 16px; height: 16px; }
.kb-doc-tags-emoji-pick-content {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  font-size: 18px;
  line-height: 1;
}
/* Filled state — solid border, no dashed accent. Mirrors the
   info-grid icon picker's has-icon style for consistency. */
.kb-doc-tags-emoji-pick.has-icon {
  border-style: solid;
  border-color: var(--border);
  background: var(--bg-surface);
}
.kb-doc-tags-emoji-pick.has-icon .kb-doc-tags-emoji-pick-content {
  font-size: 20px;
}

/* Colour picker — single button showing only the colour. Tap opens
   a 5-swatch popover positioned below the trigger. Hidden input
   (inside the same .kb-doc-tags-color-wrap) holds the value.
   32×32 matches the neighbouring row actions; the border was thinned
   from 2px to 1.5px so it doesn't visually balloon at the smaller size. */
.kb-doc-tags-color-wrap {
  position: relative;
  width: 32px;
  height: 32px;
}
.kb-doc-tags-color-pick {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1.5px solid var(--border-strong);
  background: var(--bg-elevated);
  cursor: pointer;
  padding: 0;
  transition: transform 0.06s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}
.kb-doc-tags-color-pick:hover { transform: scale(1.05); }
.kb-doc-tags-color-pick:active { transform: scale(0.95); }
/* Per-colour fills — mirror the kb-tag-chip palette so the picker
   visually matches the rendered chip. */
.kb-doc-tags-color-pick.has-color-red     { background: #fecaca; border-color: #ef4444; }
.kb-doc-tags-color-pick.has-color-amber   { background: #fde68a; border-color: #f59e0b; }
.kb-doc-tags-color-pick.has-color-green   { background: #bbf7d0; border-color: #16a34a; }
.kb-doc-tags-color-pick.has-color-blue    { background: #bfdbfe; border-color: #3b82f6; }
.kb-doc-tags-color-pick.has-color-neutral { background: var(--bg-elevated); border-color: var(--border-strong); }

/* Colour popover — small white card with 5 colour swatches in a row.
   Anchored under the trigger button via absolute positioning inside
   .kb-doc-tags-color-wrap (no portal needed since the block content
   has no will-change ancestor — unlike the toolbar Aa popover). */
.kb-doc-tags-color-pop {
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 30;
  display: flex;
  gap: 6px;
  padding: 8px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 20px rgba(0,0,0,0.15), 0 2px 6px rgba(0,0,0,0.08);
}
.kb-doc-tags-color-pop[hidden] { display: none; }
.kb-doc-tags-color-swatch {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid var(--border-strong);
  cursor: pointer;
  padding: 0;
  transition: transform 0.06s ease, box-shadow 0.12s ease;
}
.kb-doc-tags-color-swatch:hover { transform: scale(1.10); }
.kb-doc-tags-color-swatch.is-selected {
  box-shadow: 0 0 0 3px var(--accent);
}
.kb-doc-tags-color-swatch.has-color-red     { background: #fecaca; border-color: #ef4444; }
.kb-doc-tags-color-swatch.has-color-amber   { background: #fde68a; border-color: #f59e0b; }
.kb-doc-tags-color-swatch.has-color-green   { background: #bbf7d0; border-color: #16a34a; }
.kb-doc-tags-color-swatch.has-color-blue    { background: #bfdbfe; border-color: #3b82f6; }
.kb-doc-tags-color-swatch.has-color-neutral { background: var(--bg-elevated); border-color: var(--border-strong); }

/* Text input — fills the remaining space, no padding for an overlaid
   button now that the emoji picker lives in its own column. */
.kb-doc-tags-text-input {
  width: 100%;
  padding: 7px 9px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 13px;
  color: var(--text-primary);
  min-width: 0;
}
.kb-doc-tags-text-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}

/* Per-row trash — red default, canonical SVG with 2 vertical lines,
   bigger 32×32 tap target. Matches the info-grid per-row delete. */
.kb-doc-tags-row-del {
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  color: var(--danger);
  cursor: pointer;
  transition: background 0.12s ease;
}
.kb-doc-tags-row-del svg { width: 18px; height: 18px; }
.kb-doc-tags-row-del:hover { background: var(--danger-soft); }

.kb-doc-block-render-text {
  font-family: var(--body);
  font-size: var(--text-lg);
  line-height: 1.6;
  color: var(--text-primary);
  word-wrap: break-word;
  overflow-wrap: break-word;
}
.kb-doc-block-render-text h3 {
  font-family: var(--display);
  font-size: var(--text-2xl);
  font-weight: 700;
  margin: 10px 0 6px;
  color: var(--text-primary);
}
.kb-doc-block-render-text ul,
.kb-doc-block-render-text ol {
  list-style: none;
  padding: 0;
  margin: 6px 0 10px;
}
/* Hanging indent — wrapped lines align with text, not bullet */
.kb-doc-block-render-text ul > li {
  position: relative;
  padding-left: 1.4em;
  margin: 3px 0;
}
.kb-doc-block-render-text ul > li::before {
  content: '•';
  position: absolute;
  left: 0.3em;
  color: currentColor;
}
/* Ordered list */
.kb-doc-block-render-text ol {
  counter-reset: ol-counter;
}
.kb-doc-block-render-text ol > li {
  position: relative;
  padding-left: 1.8em;
  margin: 3px 0;
  counter-increment: ol-counter;
}
.kb-doc-block-render-text ol > li::before {
  content: counter(ol-counter) '.';
  position: absolute;
  left: 0;
  min-width: 1.4em;
  text-align: right;
  color: currentColor;
}
/* Nested lists — same pattern, slightly less indent */
.kb-doc-block-render-text ul ul,
.kb-doc-block-render-text ol ul {
  margin: 2px 0;
}
.kb-doc-block-render-text ul ul > li,
.kb-doc-block-render-text ol ul > li {
  padding-left: 1.2em;
}
.kb-doc-block-render-text ul ul > li::before { left: 0.2em; content: '◦'; }
.kb-doc-block-render-text strong { font-weight: 700; }
.kb-doc-block-render-text em { font-style: italic; }
.kb-doc-block-render-text a {
  color: var(--accent);
  text-decoration: underline;
}
.kb-doc-block-render-text p { margin: 0 0 8px; }

.kb-doc-block-render-photo {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.kb-doc-render-photo {
  position: relative;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  max-height: 400px;
}
/* Video-block wrapper. Same role as .kb-doc-render-photo: provides the
   positioned coordinate space for absolute children (caption chip, etc).
   Needed because AngelHubVideo.renderPlaceholder rewrites the inner
   .kb-doc-render-video slot's innerHTML; the chip lives outside that
   slot but inside this wrap, so it survives hydration. */
.kb-doc-render-video-wrap {
  position: relative;
  border-radius: var(--radius-md);
  overflow: hidden;
}
/* Video thumbnail variant — wrapper shrinks to 80x80 inline-block so
   the video placeholder renders as a small square in viewer mode.
   When user taps the placeholder, AngelHubVideo replaces it with the
   <video> player element; the player isn't constrained so the player
   itself can be its natural size (player container grows via the
   .ahv-player selector which has its own width: 100% inside the
   wrap). For now the simple approach: limit just the placeholder to
   80x80; if the user taps, the player takes over the natural full
   width via the .has-player class.
   Tap-to-expand UX rationale: same as photo thumbnails — tiny visual
   reminder in the doc, click to access the full content. */
.kb-doc-block-render-video-thumb .kb-doc-render-video-wrap {
  display: inline-block;
  width: 80px;
  height: 80px;
}
.kb-doc-block-render-video-thumb .kb-doc-render-video {
  width: 80px;
  height: 80px;
}
.kb-doc-block-render-video-thumb .ahv-placeholder {
  width: 80px;
  height: 80px;
  cursor: pointer;
  position: relative;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  transition: transform 0.12s;
}
.kb-doc-block-render-video-thumb .ahv-placeholder:hover { transform: scale(1.04); }
.kb-doc-block-render-video-thumb .ahv-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Smaller play overlay — original is sized for full-width placeholders.
   On an 80x80 thumb the play icon needs to scale down accordingly. */
.kb-doc-block-render-video-thumb .ahv-play-overlay {
  width: 32px;
  height: 32px;
}
.kb-doc-block-render-video-thumb .ahv-play-overlay svg {
  width: 18px;
  height: 18px;
}
.kb-doc-block-render-video-thumb .ahv-duration-badge {
  font-size: var(--text-xs);
  padding: 1px 4px;
}
/* Caption chip restyled as bottom strip when video is in thumb mode —
   matches the callout/step thumbnail caption treatment. */
.kb-doc-block-render-video-thumb .kb-info-photo-caption-chip {
  left: 0;
  right: 0;
  bottom: 0;
  max-width: 100%;
  padding: 3px 6px;
  background: rgba(0, 0, 0, 0.72);
  border-radius: 0;
  font-size: var(--text-xs);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* When the user taps the thumb to play, AngelHubVideo replaces the
   placeholder with .ahv-player. Let the player expand to a usable
   size — break out of the 80x80 constraint by overriding the wrap. */
.kb-doc-block-render-video-thumb .ahv-player {
  width: 100%;
  min-width: 280px;
  height: auto;
}
.kb-doc-block-render-video-thumb:has(.ahv-player) .kb-doc-render-video-wrap,
.kb-doc-block-render-video-thumb:has(.ahv-player) .kb-doc-render-video {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
}
.kb-doc-render-photo img {
  width: 100%;
  max-height: 400px;
  object-fit: contain;
  display: block;
  cursor: zoom-in;
}
/* Thumbnail variant for plain photo blocks — clean 80x80 square at
   the start of the block. Matches the callout/step thumbnail pattern
   for visual consistency. Plain photo blocks have no body text to
   wrap around, so the thumbnail just sits inline-block; tap opens
   the lightbox via the existing hydration chain. */
.kb-doc-block-render-photo-thumb {
  /* Thumbnail on the left, info (i) button pushed to the TOP-RIGHT so it lines
     up with the notice/callout card's (i). Without this flex layout the
     absolutely-positioned button escaped to the document's top-right corner. */
  display: flex;
  flex-direction: row; /* override the column from .kb-doc-block-render-photo */
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}
.kb-doc-block-render-photo-thumb > .kb-doc-render-info-btn {
  position: static;
  top: auto;
  right: auto;
  flex-shrink: 0;
}
.kb-doc-render-photo-thumb {
  position: relative;
  display: inline-block;
  width: 80px;
  height: 80px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  cursor: zoom-in;
  transition: transform 0.12s;
}
.kb-doc-render-photo-thumb:hover { transform: scale(1.04); }
.kb-doc-render-photo-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.kb-doc-render-photo-thumb .kb-instr-step-photo-loading {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
/* Caption chip restyled the same way as callout/step thumbs — bottom
   strip over the photo rather than the default floating pill. */
.kb-doc-render-photo-thumb .kb-info-photo-caption-chip {
  left: 0;
  right: 0;
  bottom: 0;
  max-width: 100%;
  padding: 3px 6px;
  background: rgba(0, 0, 0, 0.72);
  border-radius: 0;
  font-size: var(--text-xs);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Info (i) overlay button on document photo blocks. Visually identical
   to the notice card and table info buttons — same SVG glyph, same
   size, same muted-grey colour, no backdrop pill. Sits at the top-
   right of the photo. Position is the only thing that differs from
   table/notice cards (where it sits in a cell or header); the icon
   itself is the same component. Radek's feedback: "we have different
   type info icon — can we have same colour icon everywhere" — this is
   that fix. */
.kb-doc-render-info-btn {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  /* iOS-style frosted glass — same pattern as task photo thumb actions.
     Without a background the icon disappears on busy or grey-toned
     photos (concrete walls, metal panels, the back of a fuse box).
     The blur and saturate boost make it pop on any background while
     still feeling native. */
  background: rgba(0, 0, 0, 0.55);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
  backdrop-filter: blur(12px) saturate(160%);
  border: 0.5px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-full);
  color: #fff;
  padding: 0;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  transition: background 0.12s, transform 0.06s;
  z-index: 2;
}
.kb-doc-render-info-btn:hover { background: var(--accent); border-color: rgba(255, 255, 255, 0.3); }
.kb-doc-render-info-btn:active { transform: scale(0.92); }
.kb-doc-render-info-btn svg { width: 16px; height: 16px; pointer-events: none; display: block; }
.kb-doc-render-caption {
  margin: 8px 0 0;
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--text-secondary);
}

/* ─── Callout blocks (warning / important / tip / info) ─────────── */
/* Shared structure for both editor + reader. Each variant only changes
   the colour palette (left stripe + tinted background + icon colour). */
.kb-doc-block-callout,
.kb-doc-callout-render {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px 12px 16px;
  border-left: 4px solid var(--accent);
  background: var(--accent-soft);
  border-radius: var(--radius-md);
}
.kb-doc-callout-header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--display);
  font-size: var(--text-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.kb-doc-callout-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.kb-doc-callout-icon svg {
  width: 16px;
  height: 16px;
}
.kb-doc-callout-body {
  font-family: var(--body);
  font-size: var(--text-md);
  line-height: 1.55;
  color: var(--text-primary);
  word-wrap: break-word;
  overflow-wrap: break-word;
}
/* Toggle button (Show as full / Show as thumbnail) — sits alongside
   the trash icon in the photo cluster's button row. Same metrics as
   the trash button for visual rhythm. Uses muted text colour rather
   than red since it's not destructive. */
.kb-instr-edit-photo-btn-size {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s, transform 0.06s;
  -webkit-tap-highlight-color: transparent;
}
.kb-instr-edit-photo-btn-size:hover {
  background: var(--bg-surface);
  color: var(--text-primary);
  border-color: var(--border-strong, var(--text-muted));
}
.kb-instr-edit-photo-btn-size:active { transform: scale(0.94); }
.kb-instr-edit-photo-btn-size svg { width: 20px; height: 20px; }

/* Callout photo — same display style as step photos: max-height
   capped so it doesn't dominate the screen, object-fit contain so
   the whole image is visible regardless of aspect ratio, and the
   image gets its own subtle background. Radek's spec: "should be
   displayed the same way like for task" (step) photos. */
.kb-doc-callout-photo {
  margin: 8px 0;
}
.kb-doc-callout-photo img {
  width: 100%;
  max-height: 320px;
  object-fit: contain;
  display: block;
  cursor: zoom-in;
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
}
/* Callout thumbnail variant — small square floated left inside the
   notice body, body text wraps around it. Per Radek's spec for
   space-efficient steps where a tiny visual is enough. Tap still
   opens the lightbox (handler attached by renderImgIntoSlot_). */
.kb-doc-callout-photo-thumb-wrap {
  float: left;
  margin: 2px 10px 6px 0;
  width: 80px;
}
.kb-doc-callout-photo-thumb {
  position: relative;
  width: 80px;
  height: 80px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: zoom-in;
  transition: transform 0.12s;
}
.kb-doc-callout-photo-thumb:hover { transform: scale(1.04); }
.kb-doc-callout-photo-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.kb-doc-callout-photo-thumb .kb-instr-step-photo-loading {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
/* Body needs to know to flow around the floated thumb. */
.kb-doc-callout-body::after {
  content: '';
  display: block;
  clear: both;
}
.kb-instr-step-photo-thumb-wrap {
  flex-shrink: 0;
  width: 64px;
  margin-right: 10px;
}
.kb-instr-step-photo-thumb {
  position: relative;
  width: 64px;
  height: 64px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: zoom-in;
  transition: transform 0.12s;
}
.kb-instr-step-photo-thumb:hover { transform: scale(1.04); }
.kb-instr-step-photo-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.kb-instr-step-photo-thumb .kb-instr-step-photo-loading {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
/* Tint the photo backdrop with a very faint version of each notice's
   accent colour, so when the photo is letterboxed (portrait image
   in a landscape slot, or vice versa) the visible empty area feels
   like part of the notice rather than a neutral box stuck inside.
   Kept much paler (5% / 10%) than the notice body's own 8% / 14-16%
   tint so the photo stays the visual focus — the colour whispers,
   not announces. */
.kb-doc-callout-warning   .kb-doc-callout-photo img { background: rgba(220, 38, 38, 0.05); }
.kb-doc-callout-important .kb-doc-callout-photo img { background: rgba(217, 119, 6, 0.05); }
.kb-doc-callout-tip       .kb-doc-callout-photo img { background: rgba(22, 163, 74, 0.05); }
.kb-doc-callout-info      .kb-doc-callout-photo img { background: rgba(37, 99, 235, 0.05); }
[data-theme="dark"] .kb-doc-callout-warning   .kb-doc-callout-photo img { background: rgba(220, 38, 38, 0.10); }
[data-theme="dark"] .kb-doc-callout-important .kb-doc-callout-photo img { background: rgba(217, 119, 6, 0.10); }
[data-theme="dark"] .kb-doc-callout-tip       .kb-doc-callout-photo img { background: rgba(22, 163, 74, 0.10); }
[data-theme="dark"] .kb-doc-callout-info      .kb-doc-callout-photo img { background: rgba(37, 99, 235, 0.10); }
.kb-doc-callout-photo .kb-instr-step-photo-loading {
  font-size: var(--text-sm);
  color: var(--text-muted);
  padding: 20px;
  text-align: center;
}
.kb-doc-callout-photo-caption {
  margin: 6px 2px 8px;
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--text-secondary);
  font-style: italic;
}
.kb-doc-callout-body p { margin: 0 0 6px; }
.kb-doc-callout-body p:last-child { margin-bottom: 0; }
.kb-doc-callout-body strong { font-weight: 700; }
.kb-doc-callout-body em { font-style: italic; }
.kb-doc-callout-body ul,
.kb-doc-callout-body ol { padding-left: 20px; margin: 4px 0; }

/* In the editor, the body is a contenteditable div — needs distinct visual
   to indicate it's editable */
.kb-doc-block-callout .kb-doc-callout-body {
  outline: none;
  min-height: 22px;
  padding: 4px 6px;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.4);
}
[data-theme="dark"] .kb-doc-block-callout .kb-doc-callout-body {
  background: rgba(0, 0, 0, 0.15);
}
.kb-doc-block-callout .kb-doc-callout-body:focus {
  background: var(--bg-surface);
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.05);
}
.kb-doc-block-callout .kb-doc-callout-body:empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
  font-style: italic;
  pointer-events: none;
}

/* Variant: WARNING — red */
.kb-doc-callout-warning {
  border-left-color: rgb(220, 38, 38);
  background: rgba(220, 38, 38, 0.08);
}
[data-theme="dark"] .kb-doc-callout-warning {
  background: rgba(220, 38, 38, 0.14);
}
.kb-doc-callout-warning .kb-doc-callout-header { color: rgb(185, 28, 28); }
[data-theme="dark"] .kb-doc-callout-warning .kb-doc-callout-header { color: rgb(252, 165, 165); }
.kb-doc-callout-warning .kb-doc-callout-icon svg { color: rgb(220, 38, 38); }
[data-theme="dark"] .kb-doc-callout-warning .kb-doc-callout-icon svg { color: rgb(252, 165, 165); }

/* Variant: IMPORTANT — amber */
.kb-doc-callout-important {
  border-left-color: rgb(217, 119, 6);
  background: rgba(217, 119, 6, 0.08);
}
[data-theme="dark"] .kb-doc-callout-important {
  background: rgba(217, 119, 6, 0.16);
}
.kb-doc-callout-important .kb-doc-callout-header { color: rgb(180, 83, 9); }
[data-theme="dark"] .kb-doc-callout-important .kb-doc-callout-header { color: rgb(252, 211, 77); }
.kb-doc-callout-important .kb-doc-callout-icon svg { color: rgb(217, 119, 6); }
[data-theme="dark"] .kb-doc-callout-important .kb-doc-callout-icon svg { color: rgb(252, 211, 77); }

/* Variant: TIP — green */
.kb-doc-callout-tip {
  border-left-color: rgb(22, 163, 74);
  background: rgba(22, 163, 74, 0.08);
}
[data-theme="dark"] .kb-doc-callout-tip {
  background: rgba(22, 163, 74, 0.16);
}
.kb-doc-callout-tip .kb-doc-callout-header { color: rgb(21, 128, 61); }
[data-theme="dark"] .kb-doc-callout-tip .kb-doc-callout-header { color: rgb(134, 239, 172); }
.kb-doc-callout-tip .kb-doc-callout-icon svg { color: rgb(22, 163, 74); }
[data-theme="dark"] .kb-doc-callout-tip .kb-doc-callout-icon svg { color: rgb(134, 239, 172); }

/* Variant: INFO — blue */
.kb-doc-callout-info {
  border-left-color: rgb(37, 99, 235);
  background: rgba(37, 99, 235, 0.08);
}
[data-theme="dark"] .kb-doc-callout-info {
  background: rgba(37, 99, 235, 0.16);
}
.kb-doc-callout-info .kb-doc-callout-header { color: rgb(29, 78, 216); }
[data-theme="dark"] .kb-doc-callout-info .kb-doc-callout-header { color: rgb(147, 197, 253); }
.kb-doc-callout-info .kb-doc-callout-icon svg { color: rgb(37, 99, 235); }
[data-theme="dark"] .kb-doc-callout-info .kb-doc-callout-icon svg { color: rgb(147, 197, 253); }

/* Toolbar: tint each callout button with its variant colour */
.kb-doc-tb-btn-warning   svg { color: rgb(220, 38, 38); }
.kb-doc-tb-btn-important svg { color: rgb(217, 119, 6); }
.kb-doc-tb-btn-tip       svg { color: rgb(22, 163, 74); }
.kb-doc-tb-btn-info      svg { color: rgb(37, 99, 235); }
[data-theme="dark"] .kb-doc-tb-btn-warning   svg { color: rgb(252, 165, 165); }
[data-theme="dark"] .kb-doc-tb-btn-important svg { color: rgb(252, 211, 77); }
[data-theme="dark"] .kb-doc-tb-btn-tip       svg { color: rgb(134, 239, 172); }
[data-theme="dark"] .kb-doc-tb-btn-info      svg { color: rgb(147, 197, 253); }

/* ─── Table block (editor + reader) ──────────────────────────────── */
.kb-doc-block-table {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  position: relative;
}
.kb-doc-table-header-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.kb-doc-table-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  cursor: pointer;
  user-select: none;
}
.kb-doc-table-toggle input[type="checkbox"] {
  margin: 0;
  width: 14px;
  height: 14px;
  cursor: pointer;
  accent-color: var(--accent);
}
.kb-doc-table-remove-block {
  position: static;
  opacity: 1;
}
.kb-doc-table-scroll {
  width: 100%;
  overflow-x: auto;
  border-radius: var(--radius-md);
  /* iOS momentum scrolling */
  -webkit-overflow-scrolling: touch;
}
.kb-doc-table {
  border-collapse: separate;
  border-spacing: 0;
  /* width:100% means table fills container. table-layout: fixed honours
     each cell's explicit width; the trailing .kb-doc-table-filler cell
     has NO width so it absorbs all remaining space. Result: data columns
     are strict, table edges look full-width. */
  width: 100%;
  font-family: var(--body);
  font-size: var(--text-md);
  background: var(--bg-base);
  table-layout: fixed;
}
.kb-doc-table td {
  border: 1px solid var(--border);
  padding: 0;
  vertical-align: top;
  /* Widths are applied inline per-cell from the column metadata. The user's
     drag-to-resize sets explicit pixel widths on each cell. */
  position: relative;
}
.kb-doc-table-cell {
  outline: none;
  padding: 8px 10px;
  min-height: 22px;
  /* 16px to prevent iOS auto-zoom on focus (the global rule is overridden
     by element-specific styles, so re-state it here explicitly). */
  font-size: var(--text-xl);
  line-height: 1.4;
  color: var(--text-primary);
  word-wrap: break-word;
  overflow-wrap: break-word;
  word-break: break-word; /* break very long unbroken strings */
  white-space: pre-wrap;
  max-width: 100%;
}
.kb-doc-table-cell:focus {
  background: var(--accent-soft);
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.kb-doc-table-cell:empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
  font-style: italic;
  pointer-events: none;
}
/* Header row treatment when hasHeader is on.
   Editor: col-opts row is tr:nth-child(1), so header data row is tr:nth-child(2).
   Reader: header is in <thead>, body starts at row 1 — uses thead th selector instead. */
.kb-doc-table-has-header:not(.kb-doc-table-readonly) tbody tr:nth-child(2) td:not(:last-child) {
  background: var(--bg-elevated);
}
.kb-doc-table-has-header:not(.kb-doc-table-readonly) tbody tr:nth-child(2) .kb-doc-table-cell {
  font-weight: 600;
  color: var(--text-primary);
}
.kb-doc-table-readonly.kb-doc-table-has-header thead th {
  background: var(--bg-elevated);
  font-weight: 600;
  color: var(--text-primary);
}

/* Column options row (sits above the data) — width-cycle button + mobile toggle */
.kb-doc-table-col-opts td {
  border: none !important;
  background: var(--bg-elevated) !important;
  padding: 6px 4px !important;
  vertical-align: middle;
  text-align: center;
  border-bottom: 1px solid var(--border) !important;
}
.kb-doc-table-col-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
}
/* Width-cycle button removed — drag handle replaces it. */

.kb-doc-table-mobile-toggle {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  padding: 4px;
  border-radius: var(--radius-sm);
  position: relative;
  transition: background 0.12s;
}
.kb-doc-table-mobile-toggle:hover {
  background: var(--bg-base);
}
.kb-doc-table-mobile-toggle input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.kb-doc-table-mobile-toggle svg {
  width: 14px;
  height: 14px;
  color: var(--text-muted);
  transition: color 0.12s;
}
.kb-doc-table-mobile-toggle input:checked ~ svg {
  color: var(--accent);
}
.kb-doc-table-mobile-toggle input:not(:checked) ~ svg {
  /* When unchecked, draw a strikethrough line via opacity reduction */
  opacity: 0.4;
}

/* Width preset classes removed — widths are now applied inline as
   pixel values via drag-to-resize. The min/max inline styles override
   any old CSS. */

/* Drag handle on the right edge of each column (first row only).
   Sized for touch — at least 14px wide hitbox. */
.kb-doc-table-data-cell { position: relative; }
.kb-doc-table-resize-handle {
  position: absolute;
  top: 0;
  right: -7px; /* overlap the cell border so drag is on the boundary */
  width: 14px;
  height: 100%;
  cursor: col-resize;
  z-index: 2;
  /* Visual indicator: a vertical bar centered in the hit area */
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: none; /* prevent native touch scrolling during drag */
}
.kb-doc-table-resize-handle::before {
  content: '';
  display: block;
  width: 2px;
  height: 60%;
  background: var(--border);
  border-radius: var(--radius-xs);
  transition: background 0.12s, width 0.12s, height 0.12s;
}
.kb-doc-table-resize-handle:hover::before {
  background: var(--accent);
  width: 4px;
  height: 80%;
}
.kb-doc-table-resize-handle.is-dragging::before {
  background: var(--accent);
  width: 4px;
  height: 100%;
}
/* Body class set during a drag — disables text selection and tweaks cursor */
body.kb-table-resizing,
body.kb-table-resizing * {
  cursor: col-resize !important;
  user-select: none !important;
  -webkit-user-select: none !important;
}

/* Width label in the col-opts row — small px readout */
.kb-doc-table-width-label {
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-family: var(--body);
  font-variant-numeric: tabular-nums;
}
.kb-doc-table-width-input {
  width: 48px;
  font-size: var(--text-xs);
  font-family: var(--body);
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 2px 4px;
  text-align: center;
  outline: none;
  -moz-appearance: textfield;
}
.kb-doc-table-width-input::-webkit-outer-spin-button,
.kb-doc-table-width-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.kb-doc-table-width-input:focus {
  border-color: var(--accent);
  color: var(--text-primary);
}

/* Per-row INFO icon button in the editor */
/* Editor: per-row info button when the row HAS info (comment or photo).
   Solid cyan circle with the (i) icon — same visual as reader for consistency. */
.kb-doc-table-info-btn {
  width: 32px;
  height: 32px;
  display: inline-grid;
  place-items: center;
  background: none;
  border: 0;
  /* Accent colour — same family as other info icons. Was muted grey
     which made the icon feel decorative; accent signals interactivity. */
  color: var(--accent);
  cursor: pointer;
  transition: color 0.12s;
  padding: 0;
  line-height: 0;
}
.kb-doc-table-info-btn.is-active { color: var(--accent); }
.kb-doc-table-info-btn:hover { color: var(--accent); }
.kb-doc-table-info-btn:active { opacity: 0.7; }
.kb-doc-table-info-btn svg { width: 32px; height: 32px; pointer-events: none; display: block; }

/* Editor: "+ Info" pill button shown when row has NO info yet.
   Matches the photo-block "+ Info" pill exactly so the editor reads
   consistently across block types — same padding, radius, weight. */
.kb-doc-table-add-info-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  min-height: 40px;
  background: var(--bg-elevated);
  border: 1.5px dashed var(--border);
  border-radius: var(--radius-md);
  color: var(--text-muted);
  cursor: pointer;
  font-family: var(--body);
  font-size: var(--text-base);
  font-weight: 600;
  transition: background 0.12s, border-color 0.12s, border-style 0.12s, color 0.12s;
  margin-right: 2px;
  white-space: nowrap;
}
.kb-doc-table-add-info-btn:hover,
.kb-doc-table-add-info-btn:active {
  background: var(--accent-soft);
  border-color: var(--accent);
  border-style: solid;
  color: var(--accent);
}
.kb-doc-table-add-info-btn svg {
  width: 14px;
  height: 14px;
  pointer-events: none;
  flex-shrink: 0;
}
.kb-doc-table-add-info-btn span { pointer-events: none; }

/* Reader-side: per-row info button (always solid since it only shows when there IS info) */
.kb-doc-table-info-col {
  /* Use !important on positioning rules because the generic .kb-doc-table-readonly td
     rule below has equal specificity and would otherwise override these.
     Width matches the 26px button + comfortable padding. Vertical padding
     is intentionally small (4px) so a row with the icon stays the same
     height as a text-only row — no more visible row-height jumps. */
  width: 38px !important;
  min-width: 38px !important;
  padding: 4px 4px !important;
  text-align: center !important;
  vertical-align: middle !important;
}

/* Filler column at end of every table — has NO width so it absorbs all
   remaining horizontal space. This makes the table visually fill the
   container (no "cut off" appearance) without affecting the strict
   widths of actual data columns. Borders + background are removed so
   the filler looks like blank space. */
.kb-doc-table-filler,
.kb-doc-table .kb-doc-table-filler,
.kb-doc-table-readonly .kb-doc-table-filler {
  border: none !important;
  background: transparent !important;
  padding: 0 !important;
  /* width auto → soaks up everything left over */
  width: auto !important;
  min-width: 0 !important;
  max-width: none !important;
}
.kb-doc-table-info-btn-reader {
  /* Sized to match the notice-card info button (.kb-doc-callout-info-btn)
     so the same (i) glyph appears at the same size everywhere it's used
     in a document. Previously this was 32×32 which made any table row
     with an info icon noticeably taller than its sibling rows — the
     compact size keeps row heights consistent. */
  width: 26px;
  height: 26px;
  display: inline-grid;
  place-items: center;
  background: none;
  border: 0;
  /* Accent colour — info icons across the app use the same accent
     treatment for visual consistency. */
  color: var(--accent);
  cursor: pointer;
  transition: color 0.12s, opacity 0.12s;
  padding: 0;
  line-height: 0;
  opacity: 0.85;
}
.kb-doc-table-info-btn-reader:hover { color: var(--accent); opacity: 1; }
.kb-doc-table-info-btn-reader:active { opacity: 0.6; }
.kb-doc-table-info-btn-reader svg {
  width: 22px; height: 22px;
  pointer-events: none; display: block;
}

/* Photo stack inside the row info modal (editor + reader).
   Vertical layout: each photo as its own card. */
.kb-table-info-photos-stack,
.kb-table-info-viewer-stack {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 8px;
}
/* Info photo rows now use checklist pill button layout */
.kb-table-info-photo-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 4px 0;
}
.kb-table-info-photo-thumb { display: none; } /* superseded by kb-instr-edit-photo-thumb */
.kb-table-info-photo-loading {
  display: grid; place-items: center;
  height: 80px; font-size: var(--text-sm); color: var(--text-muted);
}
/* Old overlay actions — no longer used */
.kb-table-info-photo-actions { display: none; }
.kb-table-info-photo-action  { display: none; }
/* Reader-side photo cards in the viewer modal — slightly different sizing */
.kb-table-info-viewer-photo {
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  min-height: 100px;
}
.kb-table-info-viewer-photo img {
  width: 100%;
  max-height: 300px;
  object-fit: contain;
  display: block;
  cursor: zoom-in;
}

/* "X columns hidden on mobile" notice — only visible on small screens via media query */
.kb-doc-table-hidden-badge {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: var(--text-xs);
  color: var(--text-muted);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 8px 12px;
  margin-bottom: 8px;
}
.kb-doc-table-show-all-btn {
  font-family: var(--body);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  padding: 4px 10px;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
}
/* When all columns are forced visible */
.kb-doc-table-scroll.show-all-cols .kb-doc-table-mobile-hide {
  display: table-cell !important;
}
@media (max-width: 768px) {
  .kb-doc-table-hidden-badge { display: flex; }
  /* Hide columns marked mobile=false on narrow viewports */
  .kb-doc-table-readonly .kb-doc-table-mobile-hide { display: none; }
  /* On narrow viewports we let tables overflow horizontally instead of
     squeezing every column to fit. Without this, when columns total wider
     than the viewport, the browser shrinks them all to fit — and on a
     phone screen this can squash a column down to ~30px, where its header
     text wraps one letter per line. With width:auto + min-width:100% the
     table fills its container when columns are short, and grows wider
     when they demand it. The surrounding .kb-doc-table-scroll wrap (which
     has overflow-x:auto) then handles the swipe-to-see-more behaviour. */
  .kb-doc-table-readonly {
    width: auto;
    min-width: 100%;
  }
}

/* Row remove button column */
.kb-doc-table-row-actions {
  /* Wider than just the remove button — it now also holds the "+ Info"
     pill button (or the active info circle when row has info). */
  width: 110px !important;
  min-width: 110px !important;
  border: none !important;
  padding: 0 6px !important;
  background: transparent !important;
  vertical-align: middle;
  text-align: center;
  white-space: nowrap;
}
.kb-doc-table-row-remove,
.kb-doc-table-col-remove {
  width: 24px;
  height: 24px;
  display: inline-grid;
  place-items: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.kb-doc-table-row-remove:hover,
.kb-doc-table-col-remove:hover {
  background: rgba(220, 38, 38, 0.1);
  color: rgb(220, 38, 38);
  border-color: rgba(220, 38, 38, 0.3);
}
.kb-doc-table-row-remove svg,
.kb-doc-table-col-remove svg {
  width: 12px;
  height: 12px;
}
/* Column remove buttons row sits below the data, no border */
.kb-doc-table-col-actions td {
  border: none !important;
  background: transparent !important;
  padding: 4px 0 0 !important;
  text-align: center;
}
/* Add row / add column buttons */
.kb-doc-table-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.kb-doc-table-add-row,
.kb-doc-table-add-col {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 10px;
  font-size: var(--text-sm);
  font-family: var(--body);
  background: var(--bg-elevated);
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.kb-doc-table-add-row:hover,
.kb-doc-table-add-col:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  border-style: solid;
}
.kb-doc-table-add-row svg,
.kb-doc-table-add-col svg {
  width: 12px;
  height: 12px;
  pointer-events: none;
}

/* Reader view of tables — no edit affordances, just clean grid */
.kb-doc-table-render {
  margin: 4px 0;
}
.kb-doc-table-render .kb-doc-table-scroll {
  border: 1px solid var(--border);
}
.kb-doc-table-readonly {
  border-collapse: separate;
  border-spacing: 0;
  /* width:100% lets the table fill the reader content area. Each data
     column has an explicit pixel width (inline style), the trailing
     .kb-doc-table-filler has no width so it eats the remainder.
     If columns total wider than container → .kb-doc-table-scroll
     wrapper handles horizontal scroll instead. */
  width: 100%;
  table-layout: fixed;
  font-family: var(--body);
  font-size: var(--text-md);
  background: var(--bg-surface);
}
.kb-doc-table-readonly th,
.kb-doc-table-readonly td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  border-right: 1px solid var(--border);
  vertical-align: top;
  text-align: left;
  /* Widths set inline per-cell. */
  word-wrap: break-word;
  overflow-wrap: break-word;
  word-break: break-word;
  white-space: pre-wrap;
}
.kb-doc-table-readonly th:last-child,
.kb-doc-table-readonly td:last-child { border-right: none; }
.kb-doc-table-readonly tbody tr:last-child td { border-bottom: none; }
.kb-doc-table-readonly thead th {
  background: var(--bg-elevated);
  font-weight: 600;
  color: var(--text-primary);
  border-bottom: 2px solid var(--border-strong, var(--border));
}

/* ─── Instruction edit form: photo slot ────────────────────────── */
.kb-instr-edit-photo-row { margin: 6px 0 4px; }
/* CANONICAL FUNCTION CHIP (app-wide, 2026-06-25). "Add photo" / "+ Info"
   match the Tasks quick-action chip + the checklist add-check chip: a calm
   neutral tile that recedes, with colour ONLY on the icon. One look across
   KB, Checklists and anywhere the step block is consumed. */
.kb-instr-edit-photo-add {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  min-height: 34px;
  font-family: var(--body);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: border-color 0.12s, color 0.12s, background 0.12s, transform 0.1s;
}
.kb-instr-edit-photo-add:hover {
  border-color: var(--accent);
  color: var(--text-primary);
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
}
.kb-instr-edit-photo-add:active { transform: scale(0.97); }
.kb-instr-edit-photo-add svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--accent); }
/* Desktop photo drag-and-drop: a placed photo (the tile) is a drag handle;
   empty "Add photo" slots highlight as you drag a photo over them. */
.kb-instr-edit-photo-thumb.kb-photo-draggable { cursor: grab; }
.kb-instr-edit-photo-thumb.kb-photo-draggable:active,
.kb-instr-edit-photo-thumb.is-dragging { cursor: grabbing; opacity: 0.55; }
.kb-instr-edit-photo-add.is-drop-target {
  border-style: solid;
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.kb-instr-edit-photo-filled {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.kb-instr-edit-photo-top {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.kb-instr-edit-photo-thumb {
  width: 88px;
  height: 88px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  flex-shrink: 0;
}
.kb-instr-edit-photo-thumb img {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
}
.kb-instr-edit-photo-loading {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.kb-instr-edit-photo-buttons {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
  min-width: 0;
}
/* Each row inside the photo button cluster sits side-by-side with
   the thumbnail. Rows mix three kinds of content depending on the
   block type:

   Photo: Row 1 = [Edit][Change][🗑], Row 2 = [Label input][Info]
   Video: Row 1 = [Change][🗑],       Row 2 = [Caption input]

   Children behaviour:
   - .kb-instr-edit-photo-btn → flex:1 (share evenly)
   - input[type=text]         → flex:1 (grow to fill)
   - .kb-block-action-btn-inline (🗑) → fixed natural size
   - .kb-instr-edit-step-info-add / -active (Info) → fixed natural size
*/
.kb-instr-edit-photo-buttons-row {
  display: flex;
  gap: 6px;
  align-items: stretch;
  min-width: 0;
}
.kb-instr-edit-photo-buttons-row > .kb-instr-edit-photo-btn {
  flex: 1;
  min-width: 0;
}
/* Icon-only photo action buttons (Edit / Replace / Remove). Fixed
   38×38 square so an entire toolbar of them reads as one consistent
   row instead of mixed text+icon. Works in any container — both the
   newer step-block buttons-row layout AND the legacy kb.js photo
   slots that use the flat .kb-instr-edit-photo-buttons parent. */
.kb-instr-edit-photo-btn--icon {
  flex: 0 0 auto !important;
  width: 38px !important;
  height: 38px !important;
  min-width: 38px;
  padding: 0 !important;
  display: grid !important;
  place-items: center;
}
.kb-instr-edit-photo-btn--icon svg {
  width: 18px;
  height: 18px;
}
.kb-instr-edit-photo-buttons-row > input[type="text"] {
  flex: 1;
  min-width: 0;
}
.kb-instr-edit-photo-btn {
  font-family: var(--body);
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  /* 38px min-height for a compact but tappable button. Horizontal padding
     keeps the label readable. */
  padding: 0 14px;
  min-height: 38px;
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
  text-align: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* Truncate long labels gracefully on very narrow viewports */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  -webkit-tap-highlight-color: transparent;
}
.kb-instr-edit-photo-btn svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.kb-instr-edit-photo-btn:hover,
.kb-instr-edit-photo-btn:active {
  background: var(--bg-surface);
  color: var(--text-primary);
}
/* Info button variants — when info is attached, accent-tinted to
   indicate "active." When empty, dashed border to indicate "add." */
.kb-instr-edit-photo-btn-info {
  border-style: dashed;
}
.kb-instr-edit-photo-btn-info.has-info {
  border-style: solid;
  border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
  color: var(--accent);
}
.kb-instr-edit-photo-btn-info.has-info:hover {
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
/* Delete icon — small red square at the end of row 2. Visually
   obvious (red = destructive) and compact so it doesn't crowd the
   Info button next to it. Replaces the old "Remove" labelled chip
   per Radek's spec: "delete button can be just replaced by red
   delete icon — very easy to see by eye." */
.kb-instr-edit-photo-btn-delete {
  flex-shrink: 0;
  /* Float the red delete to the RIGHT end of its action row so it sits above the
     Info button in the row below (and away from the annotate/replace/size cluster,
     reducing mis-taps). Radek 2026-06-26. */
  margin-left: auto;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  background: var(--bg-elevated);
  border: 1.5px solid color-mix(in srgb, #dc2626 30%, var(--border));
  color: #dc2626;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, transform 0.06s;
  -webkit-tap-highlight-color: transparent;
}
.kb-instr-edit-photo-btn-delete:hover {
  background: color-mix(in srgb, #dc2626 10%, transparent);
  border-color: color-mix(in srgb, #dc2626 55%, transparent);
}
.kb-instr-edit-photo-btn-delete:active { transform: scale(0.94); }
.kb-instr-edit-photo-btn-delete svg { width: 16px; height: 16px; }
/* Old .danger variant kept for backwards compatibility (other
   places might still use it) — but unused on photo blocks now. */
.kb-instr-edit-photo-btn.danger:hover,
.kb-instr-edit-photo-btn.danger:active {
  background: rgba(220, 38, 38, 0.1);
  color: rgb(220, 38, 38);
  border-color: rgba(220, 38, 38, 0.3);
}
.kb-instr-edit-photo-caption {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg-base);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--body);
  font-size: var(--text-base);
  outline: none;
  transition: border-color 0.15s, background 0.15s;
  box-sizing: border-box;
}
.kb-instr-edit-photo-caption:focus {
  border-color: var(--accent);
  background: var(--bg-surface);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.kb-instr-edit-photo-caption::placeholder { color: var(--text-muted); }

/* ─── Reader: step photo (below text, full width) ─────────────── */
/* step-text-row no longer used — text is now a direct flex child of step-header */
.kb-instr-step-text-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  flex: 1;
  min-width: 0;
}
.kb-instr-step-text { flex: 1; min-width: 0; }
/* Info icon — right side of step header, with circle border */
.kb-instr-step-info-btn {
  flex-shrink: 0;
  /* Matches the rest of the app's info icons (notice cards, tables,
     photo blocks) — was 32×32 which made step rows look heavier than
     other contexts. Per Radek's spec: "same colour icon everywhere". */
  width: 26px; height: 26px;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  /* Accent colour rather than muted grey — info icons are interactive
     (tap to view info), and accent signals that throughout the app.
     Per Radek's spec: "info icons should match the section accent
     colour, same style as borders". */
  color: var(--accent);
  cursor: pointer;
  opacity: 0.85;
  transition: color 0.12s, opacity 0.12s;
  padding: 0;
}
.kb-instr-step-info-btn:hover { color: var(--accent); opacity: 1; }
.kb-instr-step-info-btn:active { opacity: 0.7; }
.kb-instr-step-info-btn svg { width: 22px; height: 22px; }

.kb-instr-step-photo {
  margin-top: 10px;
}
.kb-instr-step-photo img {
  width: 100%;
  max-height: 320px;
  object-fit: contain;
  display: block;
  cursor: zoom-in;
  border-radius: var(--radius-md);
  background: var(--bg-elevated); /* subtle bg only for the image itself */
}
.kb-reader-photo-caption {
  margin: 6px 2px 0;
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--text-secondary);
}

/* Info-popup caption chip — small elegant pill overlaid on the bottom-
   left of the photo. Used in the "More information" modal so the photo
   visual size stays identical whether or not a caption exists (no
   layout reflow). Sits over the photo with a semi-transparent dark
   backdrop and a subtle backdrop blur so it reads cleanly without
   fighting the image content. pointer-events:none so it never steals
   taps from the photo's click-to-zoom. */
.kb-info-photo-caption-chip {
  position: absolute;
  left: 10px;
  bottom: 10px;
  z-index: 2;
  pointer-events: none;
  max-width: calc(100% - 20px);
  padding: 5px 10px;
  /* Accent-tinted dark backdrop — was rgba(0,0,0,0.62) which read as
     plain grey and visually disconnected from the section accent
     borders + info icons. Now uses a dark accent tint so caption
     labels visually belong to the same family as the rest of the
     app's accent treatments. White text stays for legibility. */
  background: color-mix(in srgb, var(--accent) 35%, rgba(0, 0, 0, 0.75));
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: #fff;
  font-family: var(--ui);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1.3;
  border-radius: var(--radius-md);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}
/* When the caption chip is inside a thumbnail variant, hide it
   entirely. The thumbnail stays a clean 80x80 square; the user can
   see the caption by tapping to open the lightbox. Adding a strip
   to the thumbnail (as we tried first) made the thumbnail taller
   and visually heavier — Radek's feedback: "the thumbnail is much
   taller, should we just keep it 80x80, you have to zoom out the
   photo anyway." */
/* Caption-chip restyle when the chip lives inside a thumbnail
   variant. The standard chip is sized for full-size photos (10px
   padding, 12px font) which dominates an 80x80 thumb. Here we
   shrink it to fit: thin bottom strip, tight padding, smaller font,
   single line with ellipsis. The chip is inserted async by
   renderImgIntoSlot_ when the photo data arrives — it carries the
   real caption from the photo record (the block's _photoCache.caption
   is null in viewer mode, which is why our pre-emitted caption div
   was always empty). */
.kb-doc-callout-photo-thumb .kb-info-photo-caption-chip,
.kb-instr-step-photo-thumb .kb-info-photo-caption-chip {
  left: 0;
  right: 0;
  bottom: 0;
  max-width: 100%;
  padding: 3px 6px;
  background: rgba(0, 0, 0, 0.72);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  font-size: var(--text-xs);
  border-radius: 0;
  text-align: center;
  box-shadow: none;
  letter-spacing: 0.01em;
}
.kb-instr-step-photo-thumb .kb-info-photo-caption-chip {
  padding: 2px 4px;
  font-size: var(--text-xs);
}
.kb-instr-step-photo-loading {
  display: grid;
  place-items: center;
  height: 80px;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
/* Tappable retry shown when a photo load times out (reuses the loading
   placeholder's centred layout; resets default button chrome). */
.kb-photo-retry-btn {
  width: 100%;
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--accent);
  font-weight: 600;
  font-family: inherit;
  text-align: center;
  white-space: normal;
  line-height: 1.2;
  padding: 2px 6px;
}
.kb-photo-retry-btn:hover { text-decoration: underline; }

/* Info popup photo */
.kb-instr-info-popup-photo {
  margin: 0 0 12px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  max-height: 280px;
}
.kb-instr-info-popup-photo img {
  width: 100%;
  max-height: 280px;
  object-fit: contain;
  display: block;
}
.kb-instr-info-popup-text {
  font-size: var(--text-md);
  line-height: 1.55;
  color: var(--text-primary);
  white-space: pre-wrap;
}

/* ─── Instruction type picker (Checklist vs Procedure) ─── */
.kb-instr-type-picker {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
@media (max-width: 520px) {
  .kb-instr-type-picker { grid-template-columns: 1fr; }
}
.kb-instr-type-option {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  background: var(--bg-surface);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-md);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, transform 0.08s;
}
.kb-instr-type-option:hover {
  border-color: var(--border-strong, #c9c9c9);
  background: var(--bg-elevated);
}
.kb-instr-type-option:active { transform: scale(0.99); }
.kb-instr-type-option.is-active {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.kb-instr-type-option-icon {
  flex-shrink: 0;
  width: 36px; height: 36px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  color: var(--text-muted);
  transition: background 0.12s, color 0.12s;
}
.kb-instr-type-option-icon svg { width: 20px; height: 20px; }
.kb-instr-type-option.is-active .kb-instr-type-option-icon {
  background: var(--accent);
  color: #fff;
}
.kb-instr-type-option-body { flex: 1; min-width: 0; }
.kb-instr-type-option-title {
  font-family: var(--display, inherit);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 2px;
}
.kb-instr-type-option-desc {
  font-size: var(--text-xs);
  color: var(--text-muted);
  line-height: 1.35;
}
.kb-instr-type-option.is-active .kb-instr-type-option-title { color: var(--accent); }

/* ─── Reference ID toggle: shows/hides inline ref_id badges on subs and steps.
   Step numbers (1, 2, 3) ALWAYS stay visible — they're for progress, not
   identification. The toggle only controls the small monospace ref tags. ─── */
.kb-instr-ref-tag {
  display: none; /* hidden by default; shown when .show-refs is applied */
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  align-self: flex-start;
  margin-top: 1px;
  cursor: text;
  user-select: all;
  -webkit-user-select: all;
}
.kb-instr-reader-content.show-refs .kb-instr-ref-tag { display: inline-flex; align-items: center; }
/* Sub-instruction header ref tag — fits between title and step count */
.kb-instr-ref-tag-sub {
  margin: 0 4px;
}

/* Index: ref tag always visible (the index IS the reference layer) */
.kb-instr-index-ref {
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  background: var(--bg-elevated);
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  margin-left: auto;
  cursor: text;
  user-select: all;
  -webkit-user-select: all;
}

/* ─── Sticky next/prev nav bar ─── */
.kb-instr-nav {
  position: sticky;
  bottom: 0; left: 0; right: 0;
  display: flex; gap: 10px;
  padding: 12px 14px;
  background: var(--bg-base);
  border-top: 1px solid var(--border);
  z-index: 6;
}
.kb-instr-nav-btn {
  flex: 1;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--display);
  font-size: var(--text-md);
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s;
  touch-action: manipulation; /* prevents iOS double-tap zoom */
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}
.kb-instr-nav-btn:hover:not(:disabled) {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.kb-instr-nav-btn:active:not(:disabled) { transform: scale(0.985); }
.kb-instr-nav-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.kb-instr-nav-btn svg { width: 16px; height: 16px; flex-shrink: 0; }
.kb-instr-nav-btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: white;
}
.kb-instr-nav-btn-primary:hover:not(:disabled) {
  background: var(--accent);
  color: white;
  filter: brightness(1.05);
}

/* ─── PRINT MODE ─── */
@media print {
  /* Hide everything but the active instruction overlay */
  body.kb-instr-printing > *:not(.kb-instr-overlay):not(.kb-instr-overlay *) {
    display: none !important;
  }
  body.kb-instr-printing .kb-instr-overlay {
    position: static !important;
    background: white !important;
    box-shadow: none !important;
    width: auto !important;
    height: auto !important;
    overflow: visible !important;
  }
  body.kb-instr-printing .kb-reader-overlay {
    position: static !important;
    transform: none !important;
  }
  /* Hide chrome */
  body.kb-instr-printing .kb-reader-header,
  body.kb-instr-printing .kb-instr-progress,
  body.kb-instr-printing .kb-instr-index,
  body.kb-instr-printing .kb-instr-nav,
  body.kb-instr-printing .kb-reader-meta-item,
  body.kb-instr-printing .kb-instr-step-num-check,
  body.kb-instr-printing .kb-instr-step-num-lock {
    display: none !important;
  }
  /* Restore step numbers always (override hide-numbers) */
  body.kb-instr-printing .kb-instr-step-num-text {
    opacity: 1 !important;
    transform: none !important;
  }
  body.kb-instr-printing .kb-instr-step-num {
    background: white !important;
    color: black !important;
    border: 2px solid black !important;
  }
  body.kb-instr-printing .kb-instr-step {
    background: white !important;
    border: 1px solid #ccc !important;
    box-shadow: none !important;
    page-break-inside: avoid;
  }
  body.kb-instr-printing .kb-instr-step.is-done .kb-instr-step-text {
    text-decoration: none !important;
    color: black !important;
  }
  body.kb-instr-printing .kb-instr-sub {
    page-break-inside: avoid;
    border: 1px solid #ccc !important;
    background: white !important;
    margin-top: 14px !important;
  }
  /* Force all subs open in print */
  body.kb-instr-printing .kb-instr-sub-body {
    display: block !important;
  }
  body.kb-instr-printing .kb-instr-sub-chevron { display: none !important; }
  body.kb-instr-printing .kb-instr-sub-count { display: none !important; }
  /* Title and ref ID are kept */
  body.kb-instr-printing .kb-reader-title,
  body.kb-instr-printing .kb-instr-ref-pill,
  body.kb-instr-printing .kb-instr-desc,
  body.kb-instr-printing .kb-instr-step-text,
  body.kb-instr-printing .kb-instr-step-info {
    color: black !important;
  }
  body.kb-instr-printing .kb-reader-tags { display: none !important; }
}

/* Sub-instruction collapsible sections (reader) */
.kb-instr-sub {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin: 18px 0 0;
  overflow: hidden;
}
.kb-instr-sub-header {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  padding: 14px 16px;
  background: transparent;
  border: 0;
  font-family: -apple-system, BlinkMacSystemFont, var(--body), "Helvetica Neue", sans-serif;
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  transition: background 0.12s;
}
.kb-instr-sub-header:hover { background: var(--bg-elevated); }
.kb-instr-sub-chevron {
  width: 16px; height: 16px;
  flex-shrink: 0;
  color: var(--text-muted);
  transition: transform 0.18s;
}
.kb-instr-sub.open .kb-instr-sub-chevron { transform: rotate(90deg); }
/* Section name hidden in viewer — names are for authoring only.
   Edit mode uses .kb-instr-edit-sub-title which is unaffected. */
.kb-instr-sub-title { display: none; }
.kb-instr-sub-count {
  font-family: var(--body);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-muted);
  flex-shrink: 0;
}
.kb-instr-sub-body {
  display: none;
  padding: 0 14px 14px;
}
.kb-instr-sub.open .kb-instr-sub-body { display: block; }
.kb-instr-sub-body .kb-instr-steps { margin-top: 6px; }
.kb-instr-sub-desc {
  padding: 10px 12px;
  font-size: var(--text-base);
  color: var(--text-secondary);
  line-height: 1.5;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  margin-bottom: 10px;
}

/* Edit-mode form */
.kb-instr-edit-form {
  display: flex; flex-direction: column;
  gap: 16px;
}

/* Sub-instruction card in editor */
.kb-instr-edit-sub {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  padding: 12px;
  margin-bottom: 12px;
}
.kb-instr-edit-sub-header {
  display: flex; gap: 10px;
  align-items: stretch;
  margin-bottom: 10px;
}
.kb-instr-edit-sub-title {
  flex: 1;
  font-weight: 600;
  font-size: var(--text-md);
}
.kb-instr-edit-sub-actions {
  display: flex; gap: 4px;
  flex-shrink: 0;
  align-items: center;
}
.kb-instr-edit-sub-steps {
  margin: 8px 0;
}
/* Add step / Add notice row */
.kb-instr-edit-add-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
}
.kb-instr-edit-add-step {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px;
  background: var(--bg-elevated);
  border: 1.5px dashed var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-family: var(--body);
  font-size: var(--text-base);
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s;
  align-self: flex-start;
}
.kb-instr-edit-add-step:hover {
  border-style: solid;
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
}
.kb-instr-edit-add-step svg { width: 14px; height: 14px; stroke-width: 2.4; }

/* Add notice row — holds the 4 callout type buttons */
.kb-instr-edit-add-callout-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 5px;
}
.kb-instr-edit-add-callout-label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
  margin-right: 2px;
}
/* Notice / add-block chips — visually unified with the PIG-ref chip
   (rectangular, color-mix(12%)/45% pattern) so the whole toolbar reads
   as one cohesive system. Per-type colour stays so a glance still tells
   you "Warning" from "Tip", just expressed through the shared chip style. */
.kb-instr-edit-add-callout-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 9px;
  border-radius: var(--radius-sm);
  font-family: var(--body);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: opacity 0.15s, transform 0.1s, background 0.12s, border-color 0.12s;
  border: 1px solid transparent;
  white-space: nowrap;
}
.kb-instr-edit-add-callout-btn:hover { opacity: 0.92; transform: scale(1.03); }
.kb-instr-edit-add-callout-btn:active { transform: scale(0.97); }
.kb-instr-edit-add-callout-btn svg { width: 12px; height: 12px; flex-shrink: 0; }

/* Per-type colour applied through the shared color-mix(12%) / 45% pattern */
.kb-callout-add-warning {
  background: color-mix(in srgb, #dc2626 12%, transparent);
  border-color: color-mix(in srgb, #dc2626 45%, transparent);
  color: #dc2626;
}
.kb-callout-add-important {
  background: color-mix(in srgb, #ea580c 12%, transparent);
  border-color: color-mix(in srgb, #ea580c 45%, transparent);
  color: #ea580c;
}
.kb-callout-add-tip {
  background: color-mix(in srgb, #16a34a 12%, transparent);
  border-color: color-mix(in srgb, #16a34a 45%, transparent);
  color: #16a34a;
}
.kb-callout-add-info {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--accent);
}
/* Text chip — neutral so it reads as a structural addition, not a notice variant.
   Uses the same border thickness + radius as the others; just monochrome. */
.kb-callout-add-text {
  background: var(--bg-elevated);
  border-color: var(--border);
  color: var(--text-secondary);
}
.kb-callout-add-text:hover {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--accent);
}

/* Compact inline label input — sits left of +Info button when a step has a photo */
.kb-instr-edit-step-label {
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  background: var(--bg-base);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--body);
  font-size: var(--text-base);
  outline: none;
  transition: border-color 0.15s, background 0.15s;
  box-sizing: border-box;
}
.kb-instr-edit-step-label:focus {
  border-color: var(--accent);
  background: var(--bg-surface);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.kb-instr-edit-step-label::placeholder { color: var(--text-muted); }

/* Callout block in the step editor */
.kb-instr-edit-callout {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 8px;
  border-radius: var(--radius-md);
  padding: 12px 10px 12px 16px;
  margin-bottom: 6px;
  border-left: 4px solid var(--accent);
}
.kb-instr-edit-callout-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.kb-instr-edit-callout-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}

.kb-instr-edit-callout-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.kb-instr-edit-callout-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}
.kb-instr-edit-callout-text {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 10px;
  border-radius: var(--radius-md);
  font-family: var(--body);
  font-size: var(--text-base);
  line-height: 1.5;
  resize: none;
  outline: none;
  min-height: 56px;
  transition: border-color 0.15s;
}
.kb-instr-edit-callout-text:focus { outline: 2px solid rgba(0,0,0,0.15); }

/* Colour variants for BOTH checklist callout (.kb-instr-edit-callout) and
   document callout (.kb-doc-block-callout-wrap) */
.kb-instr-edit-callout.kb-doc-callout-warning,
.kb-doc-block-callout-wrap.kb-doc-callout-warning {
  background: rgba(220,38,38,0.06); border-left-color: rgb(220,38,38);
}
.kb-instr-edit-callout.kb-doc-callout-important,
.kb-doc-block-callout-wrap.kb-doc-callout-important {
  background: rgba(234,88,12,0.06); border-left-color: rgb(234,88,12);
}
.kb-instr-edit-callout.kb-doc-callout-tip,
.kb-doc-block-callout-wrap.kb-doc-callout-tip {
  background: rgba(22,163,74,0.06); border-left-color: rgb(22,163,74);
}
.kb-instr-edit-callout.kb-doc-callout-info,
.kb-doc-block-callout-wrap.kb-doc-callout-info {
  background: var(--accent-soft); border-left-color: var(--accent);
}
/* Textarea colour variants for checklists */
.kb-instr-edit-callout.kb-doc-callout-warning   .kb-instr-edit-callout-text { background: rgba(220,38,38,0.06);  border: 1px solid rgba(220,38,38,0.2);  color: rgb(127,29,29); }
.kb-instr-edit-callout.kb-doc-callout-important .kb-instr-edit-callout-text { background: rgba(234,88,12,0.06);  border: 1px solid rgba(234,88,12,0.2);  color: rgb(124,45,18); }
.kb-instr-edit-callout.kb-doc-callout-tip       .kb-instr-edit-callout-text { background: rgba(22,163,74,0.06);  border: 1px solid rgba(22,163,74,0.2);  color: rgb(20,83,45); }
.kb-instr-edit-callout.kb-doc-callout-info      .kb-instr-edit-callout-text { background: var(--accent-soft);    border: 1px solid var(--accent);         color: var(--accent); }

/* Callout blocks in the checklist/procedure reader (in the <ol>) */
.kb-instr-callout-step {
  list-style: none;
  margin: 4px 0;
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  width: 100%;
  box-sizing: border-box;
}
/* When kb-doc-callout-render is on the same element as kb-instr-callout-step */
.kb-instr-callout-step.kb-doc-callout-render {
  width: 100%;
  box-sizing: border-box;
}

.kb-instr-edit-step {
  display: flex; gap: 10px;
  align-items: flex-start;
  padding: 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-bottom: 8px;
}
/* When the step is rendered inside a document block (.kb-doc-block,
   which is a flex container), the step needs flex:1 to grow to fill
   the available row width. Without this, the card stops at content
   width and leaves a large empty area to the right of the action
   column — visible on mobile and desktop. The legacy step-row case
   (no -block modifier) keeps its natural width because it isn't
   inside a flex parent. */
.kb-doc-block > .kb-instr-edit-step.kb-instr-edit-step-block {
  flex: 1;
  min-width: 0;
  margin-bottom: 0;
  /* The outer .kb-doc-block already provides the border + padding;
     drop the inner step's border so we don't get a double frame
     (otherwise the user sees the .kb-doc-block border AND the inner
     .kb-instr-edit-step border, stacked). */
  border: 0;
  background: transparent;
  padding: 0;
}
.kb-instr-edit-step:focus-within {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.kb-instr-edit-step-num {
  width: 28px; height: 28px;
  border-radius: var(--radius-full);
  background: var(--accent);
  color: var(--bg-base);
  font-family: var(--display);
  font-size: var(--text-base);
  font-weight: 700;
  display: grid; place-items: center;
  flex-shrink: 0;
  margin-top: 6px;
}
.kb-instr-edit-step-fields {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
  gap: 6px;
}
.kb-instr-edit-step-text { font-weight: 500; }

/* Step info row — replaces the old always-open textarea + photo button.
   Shows either a "+ Info" pill (no info yet) or an active cyan "Info added"
   pill (when comment/photos exist). Tapping opens the step info modal. */
.kb-instr-edit-step-info-row {
  display: flex;
  align-items: stretch;
  gap: 6px;
  margin-top: 4px;
}
/* When "Add step photo" sits inside the info-row alongside the Info
   button (the no-photo state), it needs to match the Info button's
   metrics so they look like siblings. */
.kb-instr-edit-step-info-row .kb-instr-edit-photo-add {
  flex: 1;
  justify-content: center;
  padding: 7px 10px;
  min-height: 34px;
  font-size: var(--text-base);
  font-weight: 600;
  border-width: 1.5px;
  border-radius: var(--radius-md);
}
.kb-instr-edit-step-info-row .kb-instr-edit-photo-add svg {
  width: 14px;
  height: 14px;
}
/* Inline variant of "Add photo" used by the step block in its bottom row.
   ICON-ONLY (Radek 2026-06-26): the "Add photo" label moved to aria-label/
   title so it's a compact square sitting as a sibling to the Info chip —
   the Info button keeps its label. The checklist's .cl-item-action-row keeps
   its own 38px override (more specific, still wins). */
.kb-instr-edit-photo-add-inline {
  flex: 0 0 auto;
  width: 34px;
  min-width: 34px;
  gap: 0;
  justify-content: center;
  padding: 0 !important;
  min-height: 34px;
  border-width: 1px;
  border-radius: var(--radius-md) !important;
}
.kb-instr-edit-step-info-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* Canonical function chip (see .kb-instr-edit-photo-add) — calm neutral,
     accent icon; was a 1.5px dashed muted ghost. */
  padding: 8px 12px;
  min-height: 34px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  font-family: var(--body);
  font-size: var(--text-sm);
  font-weight: 600;
  transition: background 0.12s, border-color 0.12s, color 0.12s, transform 0.1s;
  white-space: nowrap;
  flex-shrink: 0;
}
.kb-instr-edit-step-info-add:hover,
.kb-instr-edit-step-info-add:active {
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
  border-color: var(--accent);
  color: var(--text-primary);
}
.kb-instr-edit-step-info-add svg {
  width: 16px; height: 16px;
  pointer-events: none;
  flex-shrink: 0;
  color: var(--accent);
}
.kb-instr-edit-step-info-add span { pointer-events: none; }

.kb-instr-edit-step-info-active {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* "Info added" SIGNAL — keeps the accent so it reads as filled, but uses
     the canonical chip's metrics (app-wide pass, 2026-06-25). */
  padding: 8px 12px;
  min-height: 34px;
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  color: var(--accent);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  font-family: var(--body);
  font-size: var(--text-sm);
  font-weight: 600;
  transition: transform 0.12s;
  white-space: nowrap;
  flex-shrink: 0;
}
.kb-instr-edit-step-info-active:hover { transform: scale(1.02); }
.kb-instr-edit-step-info-active:active { transform: scale(0.98); }
.kb-instr-edit-step-info-active svg {
  width: 16px; height: 16px;
  pointer-events: none;
  flex-shrink: 0;
}
.kb-instr-edit-step-info-active span { pointer-events: none; }

/* Icon-only variant — used when info IS attached so the button
   doesn't repeat "Info added" text next to the icon. Sized to match
   the 38×38 photo action buttons so the whole row reads as one tidy
   toolbar. A small accent-coloured badge sits in the top-right when
   the info has photos attached, telling the user "this has N photos"
   without needing a verbose label. */
.kb-instr-edit-step-info-active--icon {
  position: relative;
  width: 38px;
  height: 38px;
  min-height: 38px;
  padding: 0;
  gap: 0;
}
.kb-instr-edit-step-info-active--icon svg {
  width: 18px;
  height: 18px;
}
.kb-instr-edit-step-info-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  background: var(--accent);
  color: #001317;
  border-radius: 999px;
  font: 700 10px / 16px var(--body);
  text-align: center;
  border: 1.5px solid var(--bg-base);
  pointer-events: none;
}
.kb-instr-edit-step-actions {
  display: flex; flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════════════════
   MODAL SYSTEM (reusable for folder create/edit, move note, tag picker)
   ═══════════════════════════════════════════════════════════════════════ */
.kb-modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 300;
  display: flex; align-items: flex-end; justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s ease;
}
[data-theme="light"] .kb-modal-overlay { background: rgba(15, 23, 42, 0.35); }
/* Nested modal sits above its parent so the picker visually stacks on top
   of the row-info editor (and similar nested flows). Pushed above the
   annotation editor's z-index (1300) so input/confirm modals invoked from
   inside the editor are actually visible. */
.kb-modal-overlay.kb-modal-nested { z-index: 1400; }
.kb-modal-overlay.open {
  opacity: 1;
  pointer-events: auto;
}

.kb-modal {
  background: var(--bg-surface);
  border-top-left-radius: 18px;
  border-top-right-radius: 18px;
  width: 100%;
  max-width: 560px;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  transform: translateY(100%);
  transition: transform 0.32s cubic-bezier(0.32, 0.72, 0, 1);
  box-shadow: 0 -8px 40px rgba(0, 0, 0, 0.35);
  border: 1px solid var(--border);
  border-bottom: none;
  padding-bottom: env(safe-area-inset-bottom);
}
.kb-modal-overlay.open .kb-modal { transform: translateY(0); }

@media (min-width: 600px) {
  .kb-modal-overlay {
    align-items: center;
  }
  .kb-modal {
    border-radius: var(--radius-lg);
    border-bottom: 1px solid var(--border);
    transform: translateY(20px) scale(0.96);
    max-height: 80vh;
  }
  .kb-modal-overlay.open .kb-modal {
    transform: translateY(0) scale(1);
  }
}

.kb-modal-handle {
  width: 36px; height: 4px;
  border-radius: var(--radius-pill);
  background: var(--border-strong);
  margin: 10px auto 0;
}
@media (min-width: 600px) { .kb-modal-handle { display: none; } }

.kb-modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
}
.kb-modal-title {
  font-family: var(--display);
  font-size: var(--text-2xl); font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text-primary);
}
.kb-modal-close {
  width: 32px; height: 32px;
  border-radius: var(--radius-md);
  display: grid; place-items: center;
  color: var(--text-muted);
  background: transparent;
  border: none; cursor: pointer;
  transition: all 0.15s;
}
.kb-modal-close:hover { background: var(--bg-elevated); color: var(--text-primary); }
.kb-modal-close svg { width: 16px; height: 16px; stroke-width: 2.2; }

.kb-modal-body {
  flex: 1;
  overflow-y: auto;
  padding: 18px 20px;
}

.kb-modal-footer {
  display: flex; gap: 8px;
  padding: 14px 20px 18px;
  border-top: 1px solid var(--border);
  justify-content: flex-end;
}

.kb-modal-field {
  margin-bottom: 14px;
}
/* New-instruction scope: read-only site/department display (non-managers) +
   the collapsible "Who can see this" section that hosts the shared audience
   picker. The accordion mechanics come from .asset-svc-section (css/13). */
.kb-scope-static { padding: 8px 0; font: 500 var(--text-sm) / 1.4 var(--body); color: var(--text-secondary); }
/* "Who can see this" reuses the SAME chrome as the New Project form:
   `.callout-form-section` (elevated card) + `.callout-form-section-head`
   (display header) — so KB and Projects look identical (css/12). */
.kb-modal-field-label {
  display: block;
  font-size: var(--text-xs); font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.kb-modal-input,
.kb-modal-textarea {
  width: 100%;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 11px 13px;
  color: var(--text-primary);
  font-family: var(--body);
  /* 16px is the iOS no-zoom threshold — keep all inputs at or above this. */
  font-size: var(--text-xl);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.kb-modal-input:focus,
.kb-modal-textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.kb-modal-textarea {
  resize: vertical;
  min-height: 70px;
  line-height: 1.5;
  font-family: var(--body);
}
.kb-modal-input::placeholder,
.kb-modal-textarea::placeholder { color: var(--text-muted); }

/* Folder field — a field-styled button (matches .kb-modal-input) that opens
   the SHARED drill-down folder picker on the New-instruction form. Pick an
   existing folder or create a new one, all in this one modal. */
.kb-folder-field {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 11px 13px;
  color: var(--text-primary);
  font-family: var(--body);
  /* match .kb-modal-input — 16px+ keeps iOS from zooming on focus */
  font-size: var(--text-xl);
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.kb-folder-field:hover { border-color: var(--accent); }
.kb-folder-field:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  outline: none;
}
.kb-folder-field-ico { width: 18px; height: 18px; flex-shrink: 0; color: var(--accent); }
.kb-folder-field-label {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kb-folder-field.is-empty .kb-folder-field-label { color: var(--text-muted); }
.kb-folder-field-chev { width: 18px; height: 18px; flex-shrink: 0; color: var(--text-muted); }

.kb-modal-btn {
  padding: 10px 18px;
  border-radius: var(--radius-md);
  font-family: var(--body);
  font-size: var(--text-md);
  font-weight: 500;
  cursor: pointer;
  border: none;
  transition: transform 0.08s, box-shadow 0.15s, background 0.15s, color 0.15s, opacity 0.15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  position: relative;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.kb-modal-btn:active:not(:disabled) {
  transform: scale(0.96);
}
.kb-modal-btn:disabled, .kb-modal-btn.is-loading {
  cursor: wait;
  opacity: 0.7;
  pointer-events: none;
}
.kb-modal-btn.is-loading .kb-modal-btn-label {
  visibility: hidden;
}
.kb-modal-btn.is-loading::after {
  content: '';
  position: absolute;
  width: 16px; height: 16px;
  border-radius: var(--radius-full);
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: kb-modal-spin 0.7s linear infinite;
}
@keyframes kb-modal-spin {
  to { transform: rotate(360deg); }
}

.kb-modal-btn-secondary {
  background: var(--bg-elevated);
  color: var(--text-primary);
  border: 1px solid var(--border);
}
.kb-modal-btn-secondary:hover { background: var(--bg-hover); }
.kb-modal-btn-secondary:active:not(:disabled) {
  background: var(--border);
}
.kb-modal-btn-primary {
  background: var(--accent);
  color: var(--bg-base);
  box-shadow: 0 2px 8px var(--accent-glow);
}
.kb-modal-btn-primary:hover { transform: translateY(-1px); box-shadow: 0 4px 12px var(--accent-glow); }
.kb-modal-btn-primary:active:not(:disabled) {
  transform: scale(0.96);
  box-shadow: 0 1px 4px var(--accent-glow);
}
.kb-modal-btn-danger {
  background: var(--danger-soft);
  color: var(--danger);
}
.kb-modal-btn-danger:hover { background: var(--danger); color: white; }
.kb-modal-btn-danger:active:not(:disabled) {
  transform: scale(0.96);
}

/* Generic disabled button (used for "permission denied" buttons) */
.kb-disabled-btn {
  opacity: 0.55;
  cursor: not-allowed;
  filter: grayscale(0.3);
}
.kb-disabled-btn:hover {
  background: inherit !important;
  color: inherit !important;
  transform: none !important;
}

/* ─── INLINE FIELD VALIDATION ─── */
.kb-modal-input.is-invalid,
.kb-modal-textarea.is-invalid,
.kb-modal-tag-row.is-invalid,
.kb-folder-field.is-invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(255, 86, 112, 0.12);
}
[data-theme="light"] .kb-modal-input.is-invalid,
[data-theme="light"] .kb-modal-textarea.is-invalid,
[data-theme="light"] .kb-modal-tag-row.is-invalid,
[data-theme="light"] .kb-folder-field.is-invalid {
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.12);
}
.kb-field-error {
  display: none;
  margin-top: 6px;
  padding: 0 2px;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--danger);
  align-items: center;
  gap: 5px;
}
.kb-field-error.show { display: flex; }
.kb-field-error svg { width: 13px; height: 13px; stroke-width: 2.4; flex-shrink: 0; }
.kb-modal-field.is-invalid .kb-field-error { display: flex; }

/* ─── MODAL ERROR BANNER (top of modal) ─── */
.kb-modal-error {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 12px 14px;
  margin: 0 0 16px;
  background: var(--danger-soft);
  border: 1px solid var(--danger);
  border-radius: var(--radius-md);
  color: var(--danger);
  font-size: var(--text-base);
  line-height: 1.5;
  animation: kb-error-shake 0.32s cubic-bezier(0.36,0.07,0.19,0.97) both;
}
.kb-modal-error-icon {
  flex-shrink: 0;
  width: 20px; height: 20px;
  display: grid; place-items: center;
}
.kb-modal-error-icon svg { width: 18px; height: 18px; stroke-width: 2.2; }
.kb-modal-error-text { flex: 1; min-width: 0; }
.kb-modal-error-title {
  font-weight: 600;
  margin-bottom: 2px;
}
.kb-modal-error-detail {
  color: var(--text-secondary);
  font-size: var(--text-sm);
}
.kb-modal-error-close {
  flex-shrink: 0;
  width: 24px; height: 24px;
  border-radius: var(--radius-md);
  display: grid; place-items: center;
  color: var(--danger);
  background: transparent;
  border: none;
  cursor: pointer;
  opacity: 0.7;
  transition: all 0.12s;
}
.kb-modal-error-close:hover { background: rgba(255,86,112,0.15); opacity: 1; }
.kb-modal-error-close svg { width: 13px; height: 13px; stroke-width: 2.5; }
@keyframes kb-error-shake {
  10%, 90% { transform: translate3d(-1px, 0, 0); }
  20%, 80% { transform: translate3d(2px, 0, 0); }
  30%, 50%, 70% { transform: translate3d(-3px, 0, 0); }
  40%, 60% { transform: translate3d(3px, 0, 0); }
}

/* Modal-scoped labels (reuse entry-tag-chip styling) */
.kb-modal-tag-row {
  display: flex; flex-wrap: wrap;
  gap: 6px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 8px 10px;
  align-items: center;
  min-height: 44px;
  position: relative;
}
.kb-modal-tag-row:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.kb-modal-tag-input {
  flex: 1; min-width: 100px;
  background: transparent;
  border: none; outline: none;
  color: var(--text-primary);
  font-family: var(--body);
  font-size: var(--text-md);
  padding: 4px 0;
}
.kb-modal-tag-input::placeholder { color: var(--text-muted); }

/* Pick-row list — SOLE remaining user: the doc editor's "Import from
   capture" chooser (kb.js openImportFromCapturePicker_). Every MOVE flow
   now rides the shared drill-down picker (openLinkedInstructionPicker_ →
   AngelHubUI.openPickerSheet), so the move-only states (.current,
   .is-disabled, -info/-path) are gone. Retire this block when the import
   chooser moves to the shared sheet too. */
.kb-folder-picker {
  display: flex; flex-direction: column;
  gap: 4px;
}
.kb-folder-pick-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  background: var(--bg-elevated);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-family: var(--body);
  font-size: var(--text-md);
  color: var(--text-primary);
  cursor: pointer;
  width: 100%;
  text-align: left;
  transition: all 0.12s;
  position: relative;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.kb-folder-pick-row:hover:not(.is-loading):not(.is-locked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
}
.kb-folder-pick-row:active:not(.is-loading):not(.is-locked) {
  transform: scale(0.985);
}
/* Selected row showing spinner while we save */
.kb-folder-pick-row.is-loading {
  cursor: wait;
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  pointer-events: none;
}
.kb-folder-pick-row.is-loading::after {
  content: '';
  position: absolute;
  right: 14px; top: 50%;
  width: 16px; height: 16px;
  margin-top: -8px;
  border-radius: var(--radius-full);
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: kb-pick-spin 0.7s linear infinite;
}
.kb-folder-pick-row.is-loading .kb-folder-pick-meta { display: none; }
@keyframes kb-pick-spin { to { transform: rotate(360deg); } }
/* Other rows fade while one row is being saved */
.kb-folder-pick-row.is-locked {
  opacity: 0.4;
  cursor: wait;
  pointer-events: none;
}
.kb-folder-pick-icon {
  width: 28px; height: 28px;
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--text-muted);
  display: grid; place-items: center;
  flex-shrink: 0;
}
.kb-folder-pick-row:hover .kb-folder-pick-icon {
  background: var(--accent);
  color: var(--bg-base);
}
.kb-folder-pick-icon svg { width: 14px; height: 14px; stroke-width: 2; }
.kb-folder-pick-name {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 500;
}
.kb-folder-pick-meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
  flex-shrink: 0;
}

/* Search input at the top of the Move picker */
.kb-pick-search-wrap {
  position: relative;
  margin-bottom: 14px;
}
.kb-pick-search-icon {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px;
  color: var(--text-muted);
  pointer-events: none;
}
.kb-pick-search {
  width: 100%; box-sizing: border-box;
  padding: 9px 12px 9px 34px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-family: var(--body); font-size: var(--text-md);
  color: var(--text-primary);
  outline: none;
  transition: border-color 0.15s;
}
.kb-pick-search::placeholder { color: var(--text-muted); }
.kb-pick-search:focus { border-color: var(--accent); }

/* Section labels and hints */
.kb-pick-moving-label {
  font-size: 13px; color: var(--text-muted);
  margin-bottom: 14px;
}
.kb-pick-moving-label span { color: var(--text-primary); font-weight: 500; }
.kb-pick-section { margin-bottom: 4px; }
.kb-pick-section + .kb-pick-section { margin-top: 18px; }
.kb-pick-section-head {
  font-size: 11px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 6px 2px;
}
.kb-pick-section-hint {
  font-size: 12px; color: var(--text-muted);
  margin: 0 2px 8px;
}
.kb-pick-no-results {
  padding: 10px 12px;
  font-size: 12px; color: var(--text-muted);
  text-align: center;
}
.kb-pick-empty-state {
  padding: 12px;
  font-size: 12px; color: var(--text-muted);
  text-align: center;
}


/* Mobile width pass (2026-06-25): tighten horizontal padding on mobile so content
   uses the screen width. Appended at end-of-file so it beats the base rules AND any
   wider-breakpoint (600/640/767px) blocks at equal specificity (later source wins).
   Desktop (>=600px) untouched. */
@media (max-width: 599px) {
  .kb-reader-body { padding: 24px 12px 80px; }
  /* Keep the mobile horizontal trim but DON'T clobber the safe-area top: the
     shorthand resets padding-top, so re-apply --safe-top (a bare shorthand here
     left the header behind the status bar on the PWA). */
  .kb-reader-header { padding: 14px 12px; padding-top: var(--safe-top); }
  .kb-lib-filter { padding: 10px 8px; }
  .kb-lib-row { padding: 10px 8px; }
  .kb-lib-loading,
  .kb-lib-empty { padding: 30px 6px; }
  .kb-qr-access-row { padding: 14px 12px; }
  .kb-doc-blocks { padding: 8px; }
  .kb-doc-block-callout-wrap { padding: 12px 8px 12px 12px; }
  /* In-page reader/editor (Prompt 31): let the reader host fill the phone
     screen — drop .main's own padding so there's no double inset and the
     content uses the FULL width AND scrolls all the way to the bottom, behind
     the floating chat FAB (Radek 2026-07-07: more screen on mobile; content
     should sit behind the fab, not stop above it). The reader header/body keep
     their own 12px inset, so this is edge-to-edge only at the .main level. */
  .main:has(> #module-view-kb.kb-hosting-reader) { padding: 0; }
  /* Edit mode's base rule reserves only 24px at the bottom (desktop-oriented);
     on a phone the last control (Add section) must clear the ~70px chat FAB, so
     give real scroll runway. Same specificity as the base rule, later source. */
  .kb-reader-overlay.is-editing .kb-reader-body { padding-bottom: 88px; }
}

/* ═══ Prompt 27 — card↔canvas separation, one polarity per canvas ═══════════
   The base card rules above lift folder/doc/note cards to --bg-elevated so they
   read as raised objects on the mobile single-pane's --bg-base canvas. On the
   desktop two-pane the .kb-tree-panel canvas is ITSELF --bg-elevated, so cards
   drop to --bg-surface with a firmer border — surface-on-elevated, matching the
   collection-browser .colb-row rows they sit beside. .colb-row rows-mode is
   excluded via :not() (it owns its own fill in css/21 — the KB rows-mode phase).
   Light mode (css/11) overrides both canvases to the white-card-on-warm-paper
   language, because --bg-elevated inverts to DARKER-than-base under light. */
.kb-tree-panel .kb-folder-card:not(.colb-row),
.kb-tree-panel .kb-instr-card:not(.colb-row),
.kb-tree-panel .entry-card:not(.colb-row) {
  background: var(--bg-surface);
  border-color: var(--border-strong);
}

/* ═══════════════════════════════════════════════════════════════════════
   READER — IN-PAGE HOST (pack Prompt 31)
   KB's own card / search / rows taps open a document IN-PAGE: the SAME reader
   overlay markup, re-positioned to flow inside the KB module body so the
   global app bar stays and Back restores the exact browse view. Only the
   overlay's full-screen positioning + the body lock change — the header /
   body / nav / block / editor styles are inherited UNCHANGED, so the reader
   and editor behave exactly as in the overlay, just in flow. Cross-module
   opens (tasks / chat / projects) and the ?doc= deep-link keep the overlay.
   ═══════════════════════════════════════════════════════════════════════ */

/* While a page reader is open, the shared .main region becomes a flex column
   so the reader takes the height remaining below the app bar AND the (maybe
   visible) context bar — no JS measurement. :has is already used elsewhere in
   this codebase; without it the reader degrades to a normal in-flow block that
   scrolls with .main (still usable). */
.main:has(> #module-view-kb.kb-hosting-reader) {
  display: flex;
  flex-direction: column;
}
#module-view-kb.kb-hosting-reader {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
/* The browse (action strip + list/tree) is HIDDEN, not destroyed — folder,
   search and scroll are preserved for Back with no re-render. */
#module-view-kb.kb-hosting-reader > .kb-actions-strip,
#module-view-kb.kb-hosting-reader > #kbBody {
  display: none;
}

/* The reader element: neutralise the full-screen fixed positioning so it fills
   the flex host in flow. .kb-reader-body keeps its own overflow, so the header
   pins to the top, the nav pins to the bottom and the edit toolbar sticks —
   identical to the overlay. No body lock is applied in this mode. */
.kb-reader-overlay.kb-reader-host-page {
  position: static;
  inset: auto;
  z-index: auto;
  flex: 1;
  min-height: 0;
  pointer-events: auto;
}
/* In-page there is no status bar to clear (the app bar already sits above
   .main), so drop the --safe-top header padding the full-screen overlay uses.
   (Overridden ≤599px below, where the app bar is HIDDEN and the reader header
   becomes the top surface — see the full-screen-on-mobile block.) */
.kb-reader-host-page .kb-reader-header {
  padding-top: 14px;
}

/* ═══ KB DOCUMENT = FULL-SCREEN ON MOBILE (Radek 2026-07-07) ═══════════════
   When a KB document is open in-page on a phone, the site/department context
   chips AND the global app bar are pure chrome: you've drilled into ONE
   document, so the scope switcher does nothing here, and the app-bar actions
   (search / library / +) belong to the browse you left behind. Hide both so
   the document — reader OR editor — uses the whole phone screen; the reader's
   own header (Back + id + edit/⋯) takes over as the top bar. Desktop and
   tablet (≥600px) keep their chrome untouched. CSS-only: both hides key off
   .kb-hosting-reader, so tapping Back (which removes the class) restores the
   app bar + context bar with no JS. The class is dropped on unmount + full
   re-render too (kb.js), so it never lingers to hide the bar on another
   module. */
@media (max-width: 599px) {
  /* 1 — Context chips: inside .main, drop them from the reader's flex column. */
  .main:has(> #module-view-kb.kb-hosting-reader) > .context-bar { display: none; }
  /* 2 — Global app bar: a flex sibling of .main inside .app-shell. Kept in the
         DOM (display:none, not removed) so any :has(#appBar) presence checks
         elsewhere stay true. */
  .app-shell:has(> .main > #module-view-kb.kb-hosting-reader) > .app-bar { display: none; }
  /* 3 — With the app bar gone, the reader header is the top surface: give it
         the notch clearance the full-screen overlay uses. Equal specificity to
         the padding-top:14px rule above → later source order wins here. */
  .kb-reader-host-page .kb-reader-header { padding-top: var(--safe-top); }
}
/* Impersonation: the orange banner already shifts .app-shell below the notch
   (its --banner-h includes the safe-area inset), so the reader header must NOT
   stack --safe-top on top — mirror the app bar's own 14px (css/09). Higher
   specificity + later source beats rule 3. */
body.has-impersonation-banner .kb-reader-host-page .kb-reader-header {
  padding-top: 14px;
}

/* ═══ Visible drag-and-drop (desktop) ═══════════════════════════════════
   The tree DnD engine (kb.js wireTreeDragAndDrop_) predates these rules —
   they make it DISCOVERABLE: a six-dot grip on card hover, a drop highlight
   on panel folder cards (twin of css/04 .kb-tree-row.is-drop-target — same
   accent language), and a one-time dismissible hint. The grab/grabbing
   cursor + drag-source fade already live in css/04 ("Drag visual feedback
   on right-panel cards") — not duplicated here. Desktop-only by design:
   the tree layout doesn't render <1024px and HTML5 DnD doesn't exist on
   touch — mobile moves stay ⋯ menu → shared picker. Rows-mode (.colb-row)
   keeps its dense look — no grip there. */
.kb-drag-grip {
  position: absolute;
  left: 6px; top: 50%;
  transform: translateY(-50%);
  width: 10px; height: 16px;
  color: var(--text-muted);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s;
}
.kb-drag-grip svg { width: 100%; height: 100%; display: block; }
.colb-row .kb-drag-grip { display: none; }
@media (hover: hover) and (min-width: 1024px) {
  .kb-tree-panel .kb-folder-card[draggable="true"]:not(.colb-row):hover .kb-drag-grip,
  .kb-tree-panel .kb-instr-card[draggable="true"]:not(.colb-row):hover .kb-drag-grip,
  .kb-tree-panel .entry-card[draggable="true"]:not(.colb-row):hover .kb-drag-grip { opacity: 0.75; }
}
/* Panel folder card as an ACTIVE drop target. */
.kb-tree-panel .kb-folder-card.is-drop-target {
  background: var(--accent-soft);
  border-color: var(--accent);
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* One-time "you can drag" hint above the tree layout. Hidden <1024px (no
   sidebar → nothing to drop on); dismissing it removes the node + sets the
   localStorage flag (kb.js DRAG_HINT_LS_KEY_). */
.kb-drag-hint {
  display: none;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
  padding: 9px 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: var(--text-sm);
}
@media (min-width: 1024px) {
  .kb-drag-hint { display: flex; }
}
.kb-drag-hint > svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--text-muted); }
.kb-drag-hint span { flex: 1; min-width: 0; }
.kb-drag-hint-close {
  flex-shrink: 0;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.1s, color 0.1s, border-color 0.1s;
  -webkit-tap-highlight-color: transparent;
}
.kb-drag-hint-close:hover {
  background: var(--bg-surface);
  color: var(--text-primary);
  border-color: var(--border);
}
.kb-drag-hint-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.kb-drag-hint-close svg { width: 15px; height: 15px; }

/* ── Doc-editor dictation mic (toolbar) — recording state ──────────────
   Same red-pulse language as the KB Capture mic (css/19 .kbcap-mic) so
   "the app is listening" reads identically everywhere. */
.kb-doc-tb-btn.kb-doc-tb-mic.recording {
  background: var(--danger, #ef4444);
  border-color: var(--danger, #ef4444);
  color: #fff;
  animation: kbDocMicPulse 1.3s ease-in-out infinite;
}
@keyframes kbDocMicPulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger, #ef4444) 55%, transparent); }
  50%      { box-shadow: 0 0 0 6px transparent; }
}

/* ─── Desktop KB DOCUMENT EDITOR — use the wider screen ───────────────────
   The reader canvas is capped at 720px (base) / 900px on desktop
   (css/04 .kb-reader-content @min-width:1024) for prose readability. That's
   right for READING, but while EDITING on desktop it forces a long up/down
   scroll in a column narrower than the screen. In edit mode only
   (.kb-reader-overlay.is-editing) and only on desktop (≥1024px) we widen the
   canvas a clear step beyond the 900px reading width and lay the
   Title / Description / Tags meta into a compact grid so they stop eating
   vertical space. The reading view (no .is-editing) and the note editor
   (.kb-edit-form, a different wrapper) are untouched. Appended at end-of-file
   so the equal-specificity .kb-instr-edit-form display override wins on source
   order (§4). */
@media (min-width: 1024px) {
  /* 0,3,0 specificity — beats BOTH the base .kb-reader-content{720px} and the
     css/04 desktop {900px} rule regardless of source order, and scoped to edit
     mode so reading keeps its 900px readable width. */
  .kb-reader-overlay.is-editing .kb-reader-content { max-width: 1040px; }

  /* Compact header: Title and Content span the full width; Description and
     Tags share a two-column row so the meta block is short. */
  .kb-instr-edit-form {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 20px;
    row-gap: 16px;
    align-items: start;
  }
  .kb-instr-edit-form > .kb-edit-field-title,
  .kb-instr-edit-form > .kb-edit-field-content { grid-column: 1 / -1; }
}

/* Inline "+ Add block" zone — lift it from a very-quiet rest state so it reads
   as a tappable affordance between blocks without going loud (still calm, still
   brightens to accent on hover/focus — §4). */
.kb-doc-add-zone { opacity: 0.72; }

/* Service-type references need the full row on phones; keeping the desktop
   three-column layout squeezed the legal hint into an unreadable sliver. */
@media (max-width: 599px) {
  .settings-svc-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
    gap: 8px 10px;
    padding-left: 8px;
    padding-right: 8px;
  }
  .settings-svc-info {
    grid-column: 1 / -1;
    display: block;
  }
  .settings-svc-interval {
    grid-column: 1;
    align-self: center;
  }
  .settings-svc-actions { grid-column: 2; }
  .settings-svc-actions .settings-ai-btn { min-height: 44px; }
}

/* Labels editor — the explicit authoring choices need room to read on phones,
   and every control in the row must meet the app's 44px tap-target floor. */
@media (max-width: 640px) {
  .kb-doc-tags-editor {
    padding-left: 10px;
    padding-right: 10px;
  }
  .kb-doc-tags-editor-header {
    align-items: stretch;
    flex-direction: column;
    gap: 8px;
  }
  .kb-doc-tags-editor-header-actions {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
    width: 100%;
  }
  .kb-doc-tags-library-btn,
  .kb-doc-tags-add {
    min-height: 44px;
    padding: 7px 6px;
    line-height: 1.25;
    white-space: normal;
  }
  .kb-doc-tags-editor-row {
    grid-template-columns: 44px minmax(0, 1fr) 44px 44px;
  }
  .kb-doc-tags-emoji-pick,
  .kb-doc-tags-color-wrap,
  .kb-doc-tags-color-pick,
  .kb-doc-tags-row-del {
    width: 44px;
    height: 44px;
  }
  .kb-doc-tags-text-input {
    min-height: 44px;
    font-size: 16px;
  }
}
