/* ═══════════════════════════════════════════════════════════════════
   ROLES & PERMISSIONS — Settings UI (Session B)
   ─────────────────────────────────────────────────────────────────── */

/* Role cards in the Settings list */
.role-card {
  display: flex;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-bottom: 10px;
  overflow: hidden;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.role-card:hover {
  border-color: var(--accent-soft);
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
}
.role-card-strip {
  width: 4px;
  flex-shrink: 0;
}
.role-card-body {
  flex: 1;
  padding: 14px 16px;
  min-width: 0;
}
.role-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}
.role-card-name {
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--text-primary);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.role-card-pill {
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 2px 8px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  color: var(--text-muted);
}
.role-card-actions {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}
.role-card-btn {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.role-card-btn svg { width: 15px; height: 15px; }
.role-card-btn:hover {
  background: var(--bg-elevated);
  border-color: var(--border);
  color: var(--text-primary);
}
.role-card-btn-danger:hover {
  background: rgba(239, 68, 68, 0.08);
  border-color: rgba(239, 68, 68, 0.3);
  color: #ef4444;
}
.role-card-desc {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  margin-top: 4px;
  line-height: 1.45;
}
.role-card-meta {
  margin-top: 10px;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.role-card-meta-sep { opacity: 0.5; }

/* ─── ROLE EDITOR MODAL ──────────────────────────────────────────── */
.role-editor-backdrop {
  position: fixed;
  inset: 0;
  /* Strong, opaque overlay so the page behind doesn't bleed through.
     Light theme uses a softer overlay; both fully obscure content. */
  background: rgba(7, 9, 13, 0.82);
  z-index: 9000;
  display: flex;
  align-items: stretch;
  justify-content: stretch;
  animation: roleEditorFadeIn 0.18s ease-out;
}
[data-theme="light"] .role-editor-backdrop {
  background: rgba(20, 25, 35, 0.55);
}
@keyframes roleEditorFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.role-editor-panel {
  /* Full-screen on every viewport — this is important admin UI and
     deserves total focus, not a small dialog floating over Settings. */
  width: 100%;
  height: 100%;
  max-height: 100vh;
  /* Use --bg-surface, the actual defined card colour. The previous
     --bg-card was undefined and fell back to transparent, which is
     why you could see Settings text through the editor. */
  background: var(--bg-surface);
  /* Inner content gets a max-width container so it doesn't sprawl
     across ultrawide monitors. */
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: roleEditorSlideUp 0.22s ease-out;
  /* Respect iOS safe areas so the close button isn't under the notch */
  padding-top: env(safe-area-inset-top, 0);
  padding-bottom: env(safe-area-inset-bottom, 0);
}
@keyframes roleEditorSlideUp {
  from { transform: translateY(8px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
/* Constrain the inner content width on big screens for readability */
.role-editor-header,
.role-editor-footer {
  width: 100%;
  max-width: 880px;
  margin-left: auto;
  margin-right: auto;
  box-sizing: border-box;
}
.role-editor-body {
  width: 100%;
  max-width: 880px;
  margin-left: auto;
  margin-right: auto;
  box-sizing: border-box;
}
.role-editor-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
}
.role-editor-header h2 {
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--text-primary);
  margin: 0;
}
.role-editor-subtle {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-top: 2px;
}
.role-editor-close {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: var(--radius-md);
  color: var(--text-muted);
  cursor: pointer;
}
.role-editor-close:hover { background: var(--bg-elevated); color: var(--text-primary); }
.role-editor-close svg { width: 18px; height: 18px; }

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

.role-editor-identity {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 14px;
  margin-bottom: 16px;
}
.role-editor-identity-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 14px;
  margin-bottom: 12px;
}
.role-editor-field { display: flex; flex-direction: column; gap: 6px; }
.role-editor-label {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.role-editor-input {
  background: var(--bg-surface);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 9px 12px;
  font-size: var(--text-base);
  font-family: inherit;
  outline: none;
  transition: border-color 0.15s;
}
.role-editor-input:focus {
  border-color: var(--accent);
}
.role-editor-textarea {
  resize: vertical;
  min-height: 50px;
}
.role-editor-colours {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.role-editor-colour {
  width: 26px;
  height: 26px;
  border-radius: var(--radius-full);
  border: 3px solid transparent;
  cursor: pointer;
  padding: 0;
  transition: border-color 0.12s, transform 0.12s;
}
.role-editor-colour:hover { transform: scale(1.1); }
.role-editor-colour.is-selected { border-color: var(--text-primary); }

/* Filter row */
.role-editor-filter-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}
.role-editor-filter {
  flex: 1;
  display: flex;
  align-items: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0 10px;
  height: 36px;
  gap: 8px;
}
.role-editor-filter:focus-within { border-color: var(--accent); }
.role-editor-filter svg {
  width: 14px;
  height: 14px;
  color: var(--text-muted);
  flex-shrink: 0;
}
.role-editor-filter input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  color: var(--text-primary);
  font-size: var(--text-base);
  font-family: inherit;
  height: 100%;
}
#roleEditorFilterClear {
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 4px;
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-sm);
}
#roleEditorFilterClear:hover { color: var(--text-primary); background: var(--bg-surface); }
#roleEditorFilterClear svg { width: 12px; height: 12px; }
.role-editor-summary {
  font-size: var(--text-sm);
  color: var(--text-muted);
  white-space: nowrap;
}
/* Clear button is always rendered (surgical filter, no re-render) — [hidden]
   must win over its display:inline-flex author rule (§6). */
#roleEditorFilterClear[hidden] { display: none; }

/* Expand all / Collapse all */
.role-editor-expand-row {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}
.role-editor-expand-btn {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 5px 12px;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.role-editor-expand-btn:hover {
  background: var(--bg-elevated);
  border-color: var(--accent);
  color: var(--text-primary);
}

/* Empty state when a filter matches nothing */
.role-editor-modules-empty {
  text-align: center;
  padding: 40px 20px;
  color: var(--text-muted);
  font-size: var(--text-sm);
}
.role-editor-modules-empty[hidden] { display: none; }

/* Roles-list loading skeleton */
.ah-roles-skeleton {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Module sections */
.role-editor-modules {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.role-editor-module {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.role-editor-module-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  background: var(--bg-elevated);
  border: none;
  border-bottom: 1px solid transparent;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.role-editor-module-head[aria-expanded="true"] { border-bottom-color: var(--border); }
.role-editor-module-head:hover { background: var(--border); }
.role-editor-module-head:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.role-editor-module-headline {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.role-editor-module-chevron {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--text-muted);
  transition: transform 0.18s ease;
}
.role-editor-module-head[aria-expanded="true"] .role-editor-module-chevron { transform: rotate(90deg); }
.role-editor-module-title {
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
}
.role-editor-module-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.role-editor-module-count { white-space: nowrap; }
.role-editor-module-hr {
  color: var(--warning);
  font-weight: 600;
  white-space: nowrap;
}
.role-editor-module-hr[hidden] { display: none; }
.role-editor-module-body[hidden] { display: none; }
.role-editor-module[hidden] { display: none; }
.role-editor-module-bulkrow {
  display: flex;
  justify-content: flex-end;
  padding: 8px 14px 0;
}
.role-editor-module-bulk {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 3px 10px;
  font-size: var(--text-xs);
  color: var(--accent);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.role-editor-module-bulk:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
}

.role-editor-perms {
  display: flex;
  flex-direction: column;
}

.role-editor-perm {
  display: flex;
  gap: 12px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.12s;
}
.role-editor-perm:last-child { border-bottom: none; }
.role-editor-perm[hidden] { display: none; }
.role-editor-perm:hover { background: var(--bg-elevated); }
.role-editor-perm.is-checked { background: rgba(45, 212, 164, 0.04); }
.role-editor-checkbox {
  flex-shrink: 0;
  margin-top: 2px;
  width: 16px;
  height: 16px;
  cursor: pointer;
  accent-color: var(--accent);
}
.role-editor-perm-body {
  flex: 1;
  min-width: 0;
}
.role-editor-perm-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}
.role-editor-perm-label {
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--text-primary);
}
.role-editor-perm-desc {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-top: 3px;
  line-height: 1.45;
}

/* Risk badges */
.role-editor-risk-badge {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: var(--radius-pill);
  flex-shrink: 0;
}
.role-editor-risk-low {
  background: rgba(45, 212, 164, 0.12);
  color: #2dd4a4;
}
.role-editor-risk-medium {
  background: rgba(245, 158, 11, 0.12);
  color: #f59e0b;
}
.role-editor-risk-high {
  background: rgba(239, 68, 68, 0.12);
  color: #ef4444;
}

/* Footer */
.role-editor-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  background: var(--bg-elevated);
}
.role-editor-btn {
  padding: 9px 18px;
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, opacity 0.15s;
}
.role-editor-btn-cancel {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-secondary);
}
.role-editor-btn-cancel:hover {
  background: var(--bg-surface);
  color: var(--text-primary);
}
.role-editor-btn-save {
  background: var(--accent);
  border: 1px solid var(--accent);
  color: var(--bg-app, #0a0e14);
  font-weight: 600;
}
.role-editor-btn-save:hover { filter: brightness(1.08); }
.role-editor-btn-save:disabled { opacity: 0.6; cursor: not-allowed; }

/* Mobile: stack the identity row and filter row on narrow screens.
   The editor itself is already full-screen on every viewport. */
@media (max-width: 600px) {
  .role-editor-identity-row {
    grid-template-columns: 1fr;
  }
  .role-editor-filter-row {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }
  .role-editor-summary {
    text-align: right;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   USER SCOPE EDITOR — Stage 3
   ─────────────────────────────────────────────────────────────────── */

/* Section blocks within the editor body */
.scope-section { margin-bottom: 24px; }
.scope-section-title {
  font-size: var(--text-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin-bottom: 10px;
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.scope-section-subtle {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-muted);
  font-size: var(--text-xs);
}

/* Identity section uses the existing role-editor-identity card; keep
   it stacked one column instead of grid */
.scope-section .role-editor-identity {
  margin-bottom: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.scope-mini-note {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-muted);
  font-size: var(--text-xs);
  margin-left: 6px;
}
.scope-role-desc {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-top: 6px;
  line-height: 1.5;
  min-height: 1em;
}

/* Access mode radio cards — the one 3-way "what they can see" choice */
.scope-access-modes {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}
.scope-mode-card {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.scope-mode-card:hover { border-color: var(--accent-soft); }
.scope-mode-card.is-selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elevated));
}
.scope-mode-card input[type="radio"] {
  margin-top: 2px;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.scope-mode-title {
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-primary);
}
.scope-mode-desc {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-top: 3px;
  line-height: 1.5;
}
/* Custom pickers block — shown only in "Chosen sites & departments" mode.
   Explicit rule so [hidden] wins over any inherited display (§6 [hidden] trap). */
.scope-custom[hidden] { display: none; }
/* The explicit "All sites / All departments" option, set off from the
   specific rows below it. */
.scope-allrow {
  border-bottom: 1px solid var(--border);
  border-radius: 0;
  margin-bottom: 4px;
  padding-bottom: 10px;
}
.scope-all-note {
  color: var(--text-muted);
  font-weight: 400;
  font-size: var(--text-xs);
}

/* Helper buttons row */
.scope-helpers { margin-bottom: 14px; }
.scope-helper-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.scope-helper-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-family: inherit;
  padding: 7px 12px;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.scope-helper-btn:hover {
  background: var(--bg-elevated);
  border-color: var(--accent);
  color: var(--text-primary);
}
.scope-helper-btn svg { width: 13px; height: 13px; }

/* Pickers — sites + dept types live side-by-side on wide, stack on narrow */
.scope-pickers {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.scope-picker {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 14px;
}
.scope-picker-title {
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--text-primary);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 4px;
}
.scope-picker-meta {
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--text-muted);
}
.scope-picker-hint {
  font-size: var(--text-xs);
  color: var(--text-muted);
  line-height: 1.45;
  margin-bottom: 10px;
}
.scope-picker-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.scope-checkbox-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background 0.12s;
}
.scope-checkbox-row:hover { background: var(--bg-elevated); }
.scope-checkbox-row input[type="checkbox"] {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.scope-checkbox-label {
  font-size: var(--text-base);
  color: var(--text-primary);
}
/* Site sub-heading inside the "Belongs to" (team membership) picker, so a
   multi-site org can tell "Maintenance at The Pig" from "Maintenance at
   Pig in the Wall". First one has no top margin. */
.scope-checkbox-subhead {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 4px 10px 2px;
  margin-top: 8px;
}
.scope-checkbox-subhead:first-child { margin-top: 0; }

.scope-empty-hint, .scope-single-site-hint {
  font-size: var(--text-sm);
  color: var(--text-muted);
  padding: 12px;
  background: var(--bg-elevated);
  border-radius: var(--radius-md);
  line-height: 1.5;
}
.scope-single-site-hint strong { color: var(--text-primary); }

/* Preview box */
.scope-preview {
  padding: 14px 16px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  color: var(--text-primary);
  line-height: 1.55;
}
.scope-preview strong {
  color: var(--accent);
  font-weight: 600;
}
.scope-preview-warning {
  color: #f59e0b;
  font-weight: 500;
}

/* Popovers — templates picker + copy-from-user picker */
.scope-helper-popover-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(7, 9, 13, 0.7);
  z-index: 9100;       /* above the role/scope editor backdrop */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: roleEditorFadeIn 0.15s ease-out;
}
[data-theme="light"] .scope-helper-popover-backdrop {
  background: rgba(20, 25, 35, 0.45);
}
.scope-helper-popover {
  width: 100%;
  max-width: 480px;
  max-height: calc(100vh - 48px);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 20px 60px rgba(0,0,0,0.45);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: roleEditorSlideUp 0.18s ease-out;
}
.scope-helper-popover-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-primary);
}
.scope-helper-popover-body {
  padding: 12px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* User pick rows for copy-from */
.scope-userpick-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  transition: border-color 0.15s;
}
.scope-userpick-row:hover { border-color: var(--accent); }
.scope-userpick-avatar {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: var(--bg-surface);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  flex-shrink: 0;
}
.scope-userpick-info { flex: 1; min-width: 0; }
.scope-userpick-name {
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--text-primary);
}
.scope-userpick-meta { margin-top: 4px; }

/* Mobile: stack pickers */
@media (max-width: 600px) {
  .scope-pickers { grid-template-columns: 1fr; }
}

/* ═══════════════════════════════════════════════════════════════════
   IMPERSONATION BANNER — Owner viewing as another user
   ─────────────────────────────────────────────────────────────────── */

.impersonation-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 9500;            /* above everything except modals */
  background: linear-gradient(135deg, #f59e0b 0%, #ef4444 100%);
  color: #fff;
  font-size: var(--text-base);
  font-weight: 500;
  padding-top: env(safe-area-inset-top, 0);
  box-shadow: 0 2px 8px rgba(0,0,0,0.25);
  animation: impersonationSlideDown 0.25s ease-out;
}
@keyframes impersonationSlideDown {
  from { transform: translateY(-100%); }
  to { transform: translateY(0); }
}
.impersonation-banner-inner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  max-width: 1200px;
  margin: 0 auto;
}
.impersonation-banner-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  background: rgba(255,255,255,0.2);
  flex-shrink: 0;
}
.impersonation-banner-icon svg { width: 16px; height: 16px; color: #fff; }
.impersonation-banner-text {
  flex: 1;
  min-width: 0;
  line-height: 1.3;
}
.impersonation-banner-text strong { font-weight: 600; }
.impersonation-banner-subtle {
  opacity: 0.85;
  font-weight: 400;
  font-size: var(--text-sm);
  margin-left: 4px;
}
.impersonation-banner-stop {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255,255,255,0.18);
  border: 1px solid rgba(255,255,255,0.3);
  color: #fff;
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: 500;
  padding: 6px 12px;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background 0.15s;
  flex-shrink: 0;
}
.impersonation-banner-stop:hover { background: rgba(255,255,255,0.28); }
.impersonation-banner-stop svg { width: 13px; height: 13px; }

/* Push the rest of the page down when the banner is showing.
   ─────────────────────────────────────────────────────────────────
   --banner-h is a CSS variable that all full-viewport surfaces
   reference. When the banner mounts, body class gets set; --banner-h
   becomes 52px (or 48px on mobile). When unmounted, the variable
   isn't set, defaulting to 0 via fallback. This is cleaner than
   body padding because position:fixed elements don't respect padding;
   they DO respect explicit top values via the variable. */
body.has-impersonation-banner {
  --banner-h: 52px;
}
@supports (padding: env(safe-area-inset-top)) {
  body.has-impersonation-banner {
    --banner-h: calc(52px + env(safe-area-inset-top, 0));
  }
}

/* Apply the variable to every full-viewport fixed surface so they
   slide down out of the banner's way. Listing them explicitly is
   verbose but predictable — and it means we don't accidentally
   shift things that shouldn't be shifted. */
body.has-impersonation-banner .fullscreen-settings,
body.has-impersonation-banner .drawer,
body.has-impersonation-banner .role-editor-backdrop,
body.has-impersonation-banner .scope-helper-popover-backdrop,
body.has-impersonation-banner .app-shell {
  top: var(--banner-h, 0);
}
/* For app-shell which is position:relative, push it via margin-top
   instead — top doesn't apply to relative elements without a value. */
body.has-impersonation-banner .app-shell {
  top: auto;
  margin-top: var(--banner-h, 0);
  min-height: calc(100vh - var(--banner-h, 0));
}

/* Kill the DOUBLE safe-area inset on iPhones (Radek 2026-07-03): the shifted
   surfaces above already sit below the status bar via --banner-h (which
   contains env(safe-area-inset-top)), yet their own headers pad for the
   status bar AGAIN — stranding a tall dead strip under the banner. Collapse
   each to its non-notch padding while the banner shows. Desktop unaffected
   (env() is 0 there). Specificity (body.class + .class) also beats the
   mobile 599px re-declarations in css/02. */
body.has-impersonation-banner .app-bar { padding-top: 14px; }
body.has-impersonation-banner .drawer-header,
body.has-impersonation-banner .fs-settings-header { padding-top: 28px; }
body.has-impersonation-banner .role-editor-panel { padding-top: 0; }

/* Fixed-position floating buttons (back/hamburger on doc pages)
   need their top value adjusted explicitly — body padding doesn't
   reach them. The original position is max(18px, ...) — we add
   the banner height on top. */
body.has-impersonation-banner .float-btn {
  top: max(70px, calc(env(safe-area-inset-top, 0) + 66px));
}

/* Mobile: smaller banner height */
@media (max-width: 600px) {
  .impersonation-banner-inner { padding: 8px 12px; gap: 8px; }
  .impersonation-banner-icon { width: 28px; height: 28px; }
  .impersonation-banner-icon svg { width: 14px; height: 14px; }
  .impersonation-banner-stop { padding: 5px 10px; font-size: var(--text-xs); }
  body.has-impersonation-banner { --banner-h: 48px; }
  @supports (padding: env(safe-area-inset-top)) {
    body.has-impersonation-banner {
      --banner-h: calc(48px + env(safe-area-inset-top, 0));
    }
  }
  body.has-impersonation-banner .float-btn {
    top: max(66px, calc(env(safe-area-inset-top, 0) + 62px));
  }
}

/* ═══════════════════════════════════════════════════════════════════
   IMPERSONATION PICKER — list rows
   ─────────────────────────────────────────────────────────────────── */

.impersonation-pick-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.impersonation-pick-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  cursor: pointer;
  font-family: inherit;
  transition: border-color 0.15s, background 0.15s;
}
.impersonation-pick-row:hover {
  border-color: var(--accent);
  background: var(--bg-surface);
}
.impersonation-pick-avatar {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: var(--bg-surface);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-secondary);
  flex-shrink: 0;
}
.impersonation-pick-info { flex: 1; min-width: 0; }
.impersonation-pick-name {
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--text-primary);
}
.impersonation-pick-meta {
  margin-top: 4px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.impersonation-pick-scope {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.impersonation-pick-arrow {
  width: 16px;
  height: 16px;
  color: var(--text-muted);
  flex-shrink: 0;
}
.impersonation-pick-empty {
  padding: 20px;
  text-align: center;
  font-size: var(--text-base);
  color: var(--text-muted);
}

/* ═══════════════════════════════════════════════════════════════════
   AngelHubVideo — reusable video player styles (ui/video.js)
   ─────────────────────────────────────────────────────────────────
   Matches the existing photo-block aesthetic so video and photo
   feel consistent inside documents. Also self-contained: any
   module that includes ui/video.js gets these styles for free.
   ═══════════════════════════════════════════════════════════════ */

/* Placeholder — what you see in read mode before tapping play */
.ahv-placeholder {
  position: relative;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  max-height: 400px;
  cursor: pointer;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;            /* sensible default before thumbnail loads */
  border: 1px solid var(--border);
}
.ahv-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ahv-thumb-fallback {
  display: grid;
  place-items: center;
  color: var(--text-muted);
}
.ahv-thumb-fallback svg {
  width: 56px;
  height: 56px;
  opacity: 0.5;
}

/* Play button overlay — centred, semi-translucent dark disc with
   white triangle. Matches video-platform conventions (YouTube,
   Twitter) so the affordance reads instantly. */
.ahv-play-overlay {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 64px;
  height: 64px;
  border-radius: var(--radius-full);
  background: rgba(0, 0, 0, 0.55);
  border: none;
  color: white;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: transform 0.15s, background 0.15s;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.ahv-play-overlay:hover {
  background: rgba(0, 0, 0, 0.7);
  transform: scale(1.08);
}
.ahv-play-overlay svg {
  width: 28px;
  height: 28px;
  margin-left: 3px;                /* nudge the triangle visually centred */
}
.ahv-play-overlay:disabled {
  cursor: default;
  background: rgba(0, 0, 0, 0.4);
}

/* Duration badge — bottom-right corner pill */
.ahv-duration-badge {
  position: absolute;
  bottom: 8px;
  right: 8px;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  font-size: var(--text-sm);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  padding: 3px 7px;
  border-radius: var(--radius-sm);
  letter-spacing: 0.02em;
  pointer-events: none;
}

/* Spinner used while we resolve the video URL on first tap */
.ahv-spinner {
  width: 24px;
  height: 24px;
  border: 3px solid rgba(255,255,255,0.25);
  border-top-color: white;
  border-radius: var(--radius-full);
  animation: ahv-spin 0.8s linear infinite;
}
@keyframes ahv-spin { to { transform: rotate(360deg); } }

/* Player — shown after the user taps */
.ahv-player {
  border-radius: var(--radius-md);
  overflow: hidden;
  background: black;
  max-height: 400px;
}
.ahv-video {
  width: 100%;
  max-height: 400px;
  display: block;
  background: black;
}

/* Edit-mode block — mirrors .kb-instr-edit-photo-* styling so
   editors feel symmetrical between photo and video blocks */
.ahv-edit-block {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 8px 0;
}
.ahv-edit-thumb-wrap {
  position: relative;
  flex: 0 0 140px;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
}
.ahv-edit-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ahv-edit-buttons {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
  min-width: 0;
}
.ahv-edit-btn {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 6px 12px;
  font-size: var(--text-sm);
  color: var(--text-primary);
  cursor: pointer;
  transition: background 0.1s;
  text-align: center;
}
.ahv-edit-btn:hover { background: var(--bg-surface); }
.ahv-edit-btn.danger {
  color: var(--danger, #dc2626);
  border-color: var(--danger, #dc2626);
}
.ahv-edit-btn.danger:hover { background: rgba(220, 38, 38, 0.08); }

/* Error fallback when something goes wrong */
.ahv-error {
  padding: 20px;
  background: var(--bg-elevated);
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  color: var(--text-muted);
  font-size: var(--text-base);
  text-align: center;
}

/* ═══════════════════════════════════════════════════════════════════════
   UNIFIED APP-BAR — added Phase 2 (2026-05-15)
   Fixed top bar — direct flex child of .app-shell, never scrolls.
   Layout: [menu] [title-block] [search] [actions]
   Populated dynamically by Core.setAppBar({...}) on module navigation.
   ═══════════════════════════════════════════════════════════════════════ */

.app-bar {
  /* Direct flex child of .app-shell — always visible, never scrolls.
     position:relative so the mobile search overlay (absolute-positioned)
     is anchored to the bar rather than the viewport. */
  position: relative;
  flex-shrink: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 12px;
  /* Top padding grows with iOS safe-area-inset-top (notch/Dynamic Island).
     Longhand props — Safari silently drops a padding shorthand when
     calc()/max() appears in the first slot. */
  padding-top: calc(env(safe-area-inset-top) + 14px);
  padding-bottom: 12px;
  padding-left: 20px;
  padding-right: 20px;
  /* Opaque surface + delicate border — no blur/backdrop-filter.
     The bar lives in the DOM above .main, so there's nothing to
     recomposite; solid bg keeps it clean and fast. */
  background: var(--bg-base);
  border-bottom: 1px solid var(--border);
  box-shadow: none;
}

/* Hide old floating hamburger now that the app-bar has its own */
.app-shell .float-hamburger { display: none !important; }

/* Matches .quick-action from Knowledge Base: square, radius-md, transparent
   default with bg-elevated hover fill. Same press scale animation for tactile
   feedback. Keeps the top bar visually consistent with composer icons. */
/* GHOST icon buttons (app-wide bar standard, agreed 2026-06-10): bare glyph,
   no border/box at rest; affordance = the soft bg tint on hover/press. Matches
   M3 "standard" / Apple HIG "symbols without borders" / Primer "invisible".
   Accent is reserved for the ONE filled .primary action per bar + active
   states, so the primary CTA pops. Works in both themes via tokens. */
.app-bar-menu {
  flex-shrink: 0;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border-radius: var(--radius-md);
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, color 0.12s, transform 0.08s;
  -webkit-tap-highlight-color: transparent;
}
.app-bar-menu:hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.app-bar-menu:active { transform: scale(0.94); }
.app-bar-menu:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.app-bar-menu svg { width: 24px; height: 24px; stroke-width: 2; }
/* Flip the arrow when the drawer is open to signal "close" */
.app-shell.open .app-bar-menu .app-menu-icon { transform: scaleX(-1); }

.app-bar-title-block {
  display: flex; flex-direction: column; justify-content: center;
  min-width: 0; max-width: 30%; flex-shrink: 0;
  margin-right: 4px;
}
.app-bar-title {
  font-family: -apple-system, BlinkMacSystemFont, var(--body), "Helvetica Neue", sans-serif;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: 0;
  color: var(--text-primary);
  line-height: 1.1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.app-bar-context {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  font-weight: 500;
  margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  letter-spacing: 0.01em;
}

/* Search — same rectangular language as KB .quick-entry: radius-lg, 1px
   border, focus glow with accent + soft outer shadow */
.app-bar-search {
  flex: 1 1 auto;
  max-width: 520px;
  min-width: 0;
  position: relative;
  display: flex;
  align-items: center;
  height: 40px;
  padding: 0 14px;
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.app-bar-search:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.app-bar-search[hidden],
.app-bar-search-toggle[hidden],
.app-bar-context[hidden] { display: none !important; }
.app-bar-search-icon {
  width: 18px; height: 18px;
  color: var(--text-muted);
  flex-shrink: 0;
  margin-right: 10px;
  stroke-width: 2;
}
.app-bar-search-input {
  flex: 1;
  background: transparent;
  border: 0;
  outline: 0;
  font-family: var(--body);
  font-size: var(--text-sm);
  color: var(--text-primary);
  min-width: 0;
}
.app-bar-search-input::placeholder { color: var(--text-muted); }
.app-bar-search-input::-webkit-search-cancel-button { display: none; }
.app-bar-search-clear {
  flex-shrink: 0;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  margin-left: 6px;
  border-radius: var(--radius-sm);
  background: transparent;
  border: 0;
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.app-bar-search-clear:hover { background: var(--bg-elevated); color: var(--text-primary); }
.app-bar-search-clear svg { width: 13px; height: 13px; }

/* Cancel button — text button to the right of the input in takeover mode.
   Hidden by default; revealed via .app-bar.is-searching on mobile. Closes
   the search AND clears the filter (single tap to return to a clean bar). */
.app-bar-search-cancel {
  display: none;
  align-items: center;
  justify-content: center;
  height: 36px;
  padding: 0 4px 0 10px;
  background: transparent;
  border: 0;
  font-family: var(--body);
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--accent);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: opacity 0.12s;
}
.app-bar-search-cancel:hover { opacity: 0.8; }
.app-bar-search-cancel:active { opacity: 0.6; }
.app-bar-search-cancel[hidden] { display: none !important; }

/* All app-bar icon buttons share the .quick-action vocabulary: square 36px,
   radius-md, transparent default, bg-elevated hover, scale(0.92) on press */
.app-bar-search-toggle {
  display: none;
  flex-shrink: 0;
  width: 42px; height: 42px;
  border-radius: var(--radius-md);
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-secondary);
  cursor: pointer;
  align-items: center; justify-content: center;
  transition: background 0.12s, color 0.12s, transform 0.08s;
  -webkit-tap-highlight-color: transparent;
}
.app-bar-search-toggle:hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.app-bar-search-toggle:active { transform: scale(0.94); }
.app-bar-search-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.app-bar-search-toggle svg { width: 24px; height: 24px; stroke-width: 2; }

.app-bar-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  margin-left: auto;
}
/* Leading (left-of-title) action group — bell / incident on the dashboard, so
   the primary "+" sits alone on the right. No margin-left:auto → stays left.
   Empty on most screens → collapse so it adds no gap. */
.app-bar-left-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}
.app-bar-left-actions:empty { display: none; }
/* Thin accent separator between search area and action icon group */
.app-bar-actions:not(:empty)::before {
  content: '';
  display: block;
  width: 1px;
  height: 26px;
  background: color-mix(in srgb, var(--accent) 25%, transparent);
  margin-right: 4px;
  flex-shrink: 0;
}
.app-bar-action {
  flex-shrink: 0;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  border-radius: var(--radius-md);
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.12s, color 0.12s, transform 0.08s;
  -webkit-tap-highlight-color: transparent;
}
.app-bar-action:not(.primary):hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.app-bar-action:active { transform: scale(0.94); }
.app-bar-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.app-bar-action svg { width: 24px; height: 24px; stroke-width: 2; }
/* Compact action icons (20px) — for IN-PAGE detail views (Projects) that hoist
   their Share/Edit/Close into the app bar. Matches the 20px .kb-reader-action
   size every OVERLAY detail header uses (Tasks, Audits, Call-outs, KB reader,
   Checklists runner) so an opened project's top-bar icons read the same size as
   an opened checklist's. Opt-in via setAppBar({compactActions:true}); primary
   "+" (16px) and the app bar's own list/dashboard icons stay unchanged. */
.app-bar-actions.is-compact .app-bar-action:not(.primary) svg { width: 20px; height: 20px; }
.app-bar-action.primary {
  background: var(--accent);
  color: #07090d;
  border-color: var(--accent);
  padding: 0 16px;
  width: auto; height: 42px;
  font-family: var(--body);
  font-weight: 700;
  font-size: var(--text-sm);
  gap: 6px;
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-md);
}
.app-bar-action.primary:hover { background: var(--accent); color: #07090d; opacity: 0.88; }
.app-bar-action.primary:active { transform: scale(0.96); }
.app-bar-action.primary svg { width: 16px; height: 16px; }
[data-theme="light"] .app-bar-action.primary { color: #ffffff; }

/* When app-bar is present, suppress the legacy module page-header inside modules */
.app-shell:has(#appBar) .module-view .page-header,
.app-shell:has(#appBar) .module-view .tasks-page-header,
.app-shell:has(#appBar) .module-view .module-toolbar {
  /* gradual rollout — leave existing per-module headers visible for now;
     individual modules will opt out by adding .ah-hide-legacy-header */
}
.module-view.ah-hide-legacy-header .page-header,
.module-view.ah-hide-legacy-header .tasks-page-header,
.module-view.ah-hide-legacy-header .module-toolbar { display: none; }

/* Mobile (<= 640px) — title smaller, search collapses to icon. Don't
   reset the bar's padding shorthand here — that would clobber the
   safe-area-inset-top reservation set on the base rule (which is what
   keeps icons below the iPhone notch). Tighter side padding only. */
@media (max-width: 640px) {
  .app-bar { gap: 6px; padding-left: 12px; padding-right: 12px; }
  .app-bar-title { font-size: var(--text-lg); }
  .app-bar-context { display: none; }
  .app-bar-title-block { max-width: none; flex: 1 1 auto; }
  .app-bar-search { display: none; }
  .app-bar-search-toggle { display: flex; }
  /* ── Search-bar takeover (mobile) ──────────────────────────────────
     When the bar is in search mode, hide everything else and expand the
     input to fill the whole row. Cancel sits on the right. */
  .app-bar.is-searching .app-bar-menu,
  .app-bar.is-searching .app-bar-title-block,
  .app-bar.is-searching .app-bar-left-actions,
  .app-bar.is-searching .app-bar-search-toggle,
  .app-bar.is-searching .app-bar-actions { display: none !important; }
  .app-bar.is-searching .app-bar-search {
    display: flex;
    flex: 1 1 auto;
    max-width: none;
    height: 40px;
  }
  .app-bar.is-searching .app-bar-search-cancel {
    display: inline-flex;
    flex-shrink: 0;
  }
  /* On mobile the primary button collapses to icon-only — match the 42x42
     size of the other icon actions so the row reads as a tidy set instead
     of a slightly-smaller odd-one-out. */
  .app-bar-action.primary span { display: none; }
  .app-bar-action.primary { width: 42px; height: 42px; padding: 0; border-radius: var(--radius-md); justify-content: center; }
  .app-bar-action.primary svg { width: 22px; height: 22px; }
}

/* Tablet+ — search visible, toggle hidden */
@media (min-width: 641px) {
  .app-bar-search-toggle { display: none; }
}

/* 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) {
  .role-card-body { padding: 12px 12px; }
  .role-editor-header { padding: 18px 12px 14px; }
  .role-editor-body { padding: 18px 12px; }
  .role-editor-footer { padding: 14px 12px; }
  .scope-mode-card { padding: 12px 12px; }
  .scope-picker { padding: 10px; }
  .scope-preview { padding: 12px 12px; }
  .scope-helper-popover-head { padding: 12px 14px; }
  .scope-userpick-row { padding: 8px 10px; }
}

/* ── Prompt 45 — iOS-safe role-editor inputs (≥16px kills the zoom-on-focus)
   + a comfortable tap target on the new collapsible section headers.
   Appended at END per the §4 source-order law (a media query adds no
   specificity, so the ≤599px override must follow its base rule). ── */
@media (max-width: 599px) {
  .role-editor-input,
  .role-editor-textarea,
  .role-editor-filter input { font-size: 16px; }
  .role-editor-module-head { min-height: 44px; }
  .role-editor-expand-btn { padding: 8px 14px; }
}

