/*
 * BaseLock App Components
 * Buttons, forms, cards, tables, modals, badges, empty states, skeletons.
 * All colors via app-tokens.css variables — no hardcoded hex.
 */

/* ─── Reduced-motion preference ─────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   BUTTONS
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--bl-space-2);
  padding: 0.5rem 1rem;
  border-radius: var(--bl-radius-md);
  font-family: var(--bl-font);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.4;
  cursor: pointer;
  border: 1px solid transparent;
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease,
              box-shadow 0.12s ease;
  -webkit-user-select: none;
  user-select: none;
}

.bl-btn:focus-visible {
  outline: 2px solid var(--bl-primary);
  outline-offset: 2px;
}

.bl-btn:disabled,
.bl-btn[aria-disabled="true"] {
  background-color: var(--bl-surface-alt);
  color: var(--bl-text-muted);
  cursor: not-allowed;
  border-color: var(--bl-border);
  box-shadow: none;
  opacity: 0.75;
  pointer-events: none;
}

@media (forced-colors: active) {
  .bl-btn:disabled,
  .bl-btn[aria-disabled="true"] {
    color: GrayText;
    border-color: GrayText;
  }
}

/* Sizes */
.bl-btn--sm {
  font-size: 0.8125rem;
  padding: 0.3125rem 0.75rem;
  border-radius: var(--bl-radius-sm);
}

.bl-btn--lg {
  font-size: 1.0625rem;
  padding: 0.6875rem 1.375rem;
  border-radius: var(--bl-radius-lg);
}

/* Primary */
.bl-btn--primary {
  background: var(--bl-primary);
  color: #fff;
  border-color: var(--bl-primary);
  box-shadow: var(--bl-shadow-sm);
}

.bl-btn--primary:hover:not(:disabled) {
  background: var(--bl-primary-hover);
  border-color: var(--bl-primary-hover);
}

/* Secondary */
.bl-btn--secondary {
  background: var(--bl-surface);
  color: var(--bl-text);
  border-color: var(--bl-border);
  box-shadow: var(--bl-shadow-sm);
}

.bl-btn--secondary:hover:not(:disabled) {
  background: var(--bl-bg-secondary);
  border-color: var(--bl-text-muted);
}

/* Ghost */
.bl-btn--ghost {
  background: transparent;
  color: var(--bl-text-secondary);
  border-color: transparent;
}

.bl-btn--ghost:hover:not(:disabled) {
  background: var(--bl-bg-secondary);
  color: var(--bl-text);
}

/* Danger */
.bl-btn--danger {
  background: var(--bl-danger);
  color: #fff;
  border-color: var(--bl-danger);
}

.bl-btn--danger:hover:not(:disabled) {
  background: #dc2626;
  border-color: #dc2626;
}

/* Icon-only */
.bl-btn--icon {
  padding: 0.5rem;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--bl-radius-sm);
}

.bl-btn--icon.bl-btn--sm {
  width: 1.75rem;
  height: 1.75rem;
  padding: 0.25rem;
}

.bl-btn--icon.bl-btn--lg {
  width: 2.75rem;
  height: 2.75rem;
  padding: 0.6875rem;
}

/* Loading state */
.bl-btn.is-loading {
  position: relative;
  color: transparent;
  pointer-events: none;
}

.bl-btn.is-loading::after {
  content: '';
  position: absolute;
  width: 1rem;
  height: 1rem;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: bl-spin 0.6s linear infinite;
  color: inherit;
}

.bl-btn--primary.is-loading::after {
  border-color: rgb(255 255 255 / 0.5);
  border-top-color: transparent;
}

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

/* ═══════════════════════════════════════════════════════════════════════════
   FORMS
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-field {
  display: flex;
  flex-direction: column;
  gap: var(--bl-space-1);
}

.bl-label {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--bl-text);
  display: block;
}

.bl-label .required {
  color: var(--bl-danger);
  margin-left: 2px;
}

.bl-input {
  display: block;
  width: 100%;
  padding: 0.5625rem 0.75rem;
  background: var(--bl-surface-alt);
  border: 1px solid var(--bl-border);
  border-radius: var(--bl-radius-md);
  color: var(--bl-text);
  font-family: var(--bl-font);
  font-size: 0.9375rem;
  line-height: 1.5;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
  -webkit-appearance: none;
  appearance: none;
}

.bl-input::placeholder {
  color: var(--bl-text-muted);
}

.bl-input:hover:not(:disabled) {
  border-color: var(--bl-text-muted);
}

.bl-input:focus {
  outline: none;
  border-color: var(--bl-primary);
  box-shadow: 0 0 0 3px rgb(21 31 148 / 0.12);
}

html[data-theme="dark"] .bl-input:focus {
  box-shadow: 0 0 0 3px rgb(107 120 255 / 0.20);
}

.bl-input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: var(--bl-bg-tertiary);
}

/* Error state via :user-invalid (no error shown until user leaves field) */
.bl-input:user-invalid {
  border-color: var(--bl-danger);
}

.bl-input:user-invalid:focus {
  box-shadow: 0 0 0 3px rgb(239 68 68 / 0.15);
}

/* Select */
select.bl-input {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2394A3B8' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  padding-right: 2.25rem;
  cursor: pointer;
}

/* Textarea */
textarea.bl-input {
  resize: vertical;
  min-height: 80px;
}

.bl-hint {
  font-size: 0.8125rem;
  color: var(--bl-text-muted);
}

.bl-error {
  font-size: 0.8125rem;
  color: var(--bl-danger);
  display: none;
}

.bl-field.has-error .bl-error {
  display: block;
}

.bl-field.has-error .bl-input {
  border-color: var(--bl-danger);
}

/* ═══════════════════════════════════════════════════════════════════════════
   CARDS
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-card {
  background: var(--bl-surface);
  border: 1px solid var(--bl-border);
  border-radius: 10px;
  overflow: hidden;
}

.bl-card--elevated {
  box-shadow: var(--bl-shadow-sm);
  border-color: var(--bl-border);
}

.bl-card--flat {
  box-shadow: none;
  background: var(--bl-bg-secondary);
}

.bl-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bl-space-3);
  padding: 14px 20px;
  border-bottom: 1px solid var(--bl-border-light);
}

.bl-card__header h2,
.bl-card__header h3 {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--bl-text);
  letter-spacing: -0.005em;
}

.bl-card__header-actions {
  display: flex;
  align-items: center;
  gap: var(--bl-space-2);
  flex-shrink: 0;
}

.bl-card__body {
  padding: 20px;
}

.bl-card__footer {
  padding: var(--bl-space-4) var(--bl-space-6);
  border-top: 1px solid var(--bl-border-light);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--bl-space-2);
  background: var(--bl-bg-secondary);
}

/* ═══════════════════════════════════════════════════════════════════════════
   RESPONSIVE TABLES (plan §9)
   --
   Below 768 px, collapse data tables into stacked cards. Each row
   becomes its own card with the column header rendered above each
   value via the th's text content (cells inherit their label from
   the matching th in the same column). Works for any .bl-table
   without per-row data-label attributes by reading the thead text
   into custom properties on first paint.
   ═══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 768px) {
  .bl-table-wrap {
    overflow-x: visible;
  }
  .bl-table,
  .bl-table thead,
  .bl-table tbody,
  .bl-table tr,
  .bl-table th,
  .bl-table td {
    display: block;
    width: 100%;
  }
  .bl-table thead {
    /* Hide the header row; we surface column names per-cell via
       data-label below. */
    position: absolute;
    left: -10000px;
    top: -10000px;
  }
  .bl-table tbody tr {
    border: 1px solid var(--bl-border);
    border-radius: 10px;
    background: var(--bl-surface);
    margin-bottom: 12px;
    padding: 12px 14px;
  }
  .bl-table tbody td {
    border: none;
    padding: 6px 0;
    text-align: left;
  }
  .bl-table tbody td::before {
    content: attr(data-label);
    display: block;
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--bl-text-muted);
    margin-bottom: 2px;
  }
  .bl-table__action-col {
    padding-top: 8px;
  }
}

/* Page-header actions stack vertically on phones so a "Mark all
   read" / "Add a device" button doesn't sit cramped beside the h1. */
@media (max-width: 640px) {
  .bl-page-header__actions {
    width: 100%;
  }
  .bl-page-header__actions .bl-btn {
    width: 100%;
    justify-content: center;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   ACTIVITY LIST (dashboard "Recent activity" card)
   --
   Compact, divider-separated list of the latest 5 decisions on the
   home card. Each row: program name + device/when on the left,
   status chip on the right. Pairs with the "View all" link in the
   card header.
   ═══════════════════════════════════════════════════════════════════════════ */
.bl-activity-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.bl-activity-list__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--bl-border-light);
}
.bl-activity-list__item:last-child {
  border-bottom: none;
}
.bl-activity-list__main {
  min-width: 0;
  flex: 1;
}
.bl-activity-list__title {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--bl-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bl-activity-list__meta {
  font-size: 0.8125rem;
  color: var(--bl-text-muted);
  margin-top: 2px;
}
.bl-activity-list__status {
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════════════════════
   BANNER (§5 dunning)
   --
   Top-of-dashboard alert strip. Never a hard modal — a locked-out
   user can't pay you. Per the plan, the banner never shows
   decline_code / last4 / IP. Copy stays generic.
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-banner {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 20px;
  border-radius: 10px;
  border: 1px solid var(--bl-border);
  background: var(--bl-surface);
  margin-bottom: 20px;
}

.bl-banner--warning {
  background: var(--bl-warning-bg, #fffbeb);
  border-color: var(--bl-warning-border, #fde68a);
  color: var(--bl-warning-fg, #92400e);
}

.bl-banner__icon {
  font-size: 1.25rem;
  flex-shrink: 0;
}

.bl-banner__body {
  flex: 1;
  min-width: 0;
}

.bl-banner__title {
  margin: 0;
  font-weight: 600;
  font-size: 0.9375rem;
}

.bl-banner__copy {
  margin: 2px 0 0 0;
  font-size: 0.875rem;
  line-height: 1.4;
}

.bl-banner__actions {
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════════════════════
   CARD STATE UTILITY
   --
   Every dashboard card declares one of four explicit states via
   data-state="loading|empty|error|data" so the visual vocabulary stays
   consistent. Most cards opt into this incrementally; the health card
   (below) is the canonical reference renderer.
   ═══════════════════════════════════════════════════════════════════════════ */

[data-state="loading"] .bl-card-state__data,
[data-state="empty"]   .bl-card-state__data,
[data-state="error"]   .bl-card-state__data { display: none; }

[data-state="loading"] .bl-card-state__loading,
[data-state="empty"]   .bl-card-state__empty,
[data-state="error"]   .bl-card-state__error { display: block; }

[data-state="data"] .bl-card-state__loading,
[data-state="data"] .bl-card-state__empty,
[data-state="data"] .bl-card-state__error { display: none; }

/* ═══════════════════════════════════════════════════════════════════════════
   HEALTH CARD (§1)
   --
   Single hero pill at the top of /dashboard. Renders worst-of-three
   posture status. Uses shape + text + colour together for WCAG 1.4.1.
   Error state is neutral grey, never green — security products fail
   closed.
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-health__pill {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 14px 20px;
  border-radius: 999px;
  font-size: 1.0625rem;
  font-weight: 600;
  border: 1px solid var(--bl-border);
  background: var(--bl-surface-elevated, var(--bl-surface));
  color: var(--bl-text);
}

.bl-health__pill[data-status="green"] {
  background: var(--bl-success-bg, #ecfdf5);
  color: var(--bl-success-fg, #047857);
  border-color: var(--bl-success-border, #6ee7b7);
}

.bl-health__pill[data-status="yellow"] {
  background: var(--bl-warning-bg, #fffbeb);
  color: var(--bl-warning-fg, #92400e);
  border-color: var(--bl-warning-border, #fde68a);
}

.bl-health__pill[data-status="red"] {
  background: var(--bl-danger-bg, #fef2f2);
  color: var(--bl-danger-fg, #b91c1c);
  border-color: var(--bl-danger-border, #fca5a5);
}

.bl-health__pill[data-status="paused"] {
  background: var(--bl-bg-secondary);
  color: var(--bl-text-muted);
  border-color: var(--bl-border);
}

.bl-health__pill[data-status="no_devices"] {
  background: var(--bl-bg-secondary);
  color: var(--bl-text);
  border-color: var(--bl-border);
}

/* Error state: neutral grey, never green. */
.bl-health__pill[data-status="error"] {
  background: var(--bl-bg-secondary);
  color: var(--bl-text-muted);
  border-color: var(--bl-border);
}

.bl-health__icon {
  font-size: 1.25rem;
  display: inline-flex;
  align-items: center;
}

.bl-health__label {
  white-space: nowrap;
}

.bl-health__reason {
  margin: 12px 0 6px 0;
  color: var(--bl-text);
  font-size: 0.9375rem;
  line-height: 1.45;
}

.bl-health__timestamp {
  font-size: 0.8125rem;
  margin: 0 0 8px 0;
}

.bl-health__details {
  margin-top: 8px;
}

.bl-health__details summary {
  cursor: pointer;
  color: var(--bl-text-muted);
  font-size: 0.875rem;
  user-select: none;
}

.bl-health__details summary:focus-visible {
  outline: 2px solid var(--bl-focus-ring, #2563eb);
  outline-offset: 2px;
  border-radius: 4px;
}

.bl-health__signals {
  list-style: none;
  padding: 8px 0 0 0;
  margin: 0;
}

.bl-health__signals li {
  padding: 6px 0;
  font-size: 0.9375rem;
  line-height: 1.4;
}

.bl-health__signals li strong {
  font-weight: 600;
  text-transform: capitalize;
}

/* While the bootstrap call is in flight, hide the reason / timestamp /
   details so the card doesn't flicker with intermediate text. */
.bl-health[data-state="loading"] .bl-health__reason,
.bl-health[data-state="loading"] .bl-health__timestamp,
.bl-health[data-state="loading"] .bl-health__details { display: none; }

/* ═══════════════════════════════════════════════════════════════════════════
   STAT CARD
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-stat {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px 20px;
  background: var(--bl-surface);
  border: 1px solid var(--bl-border);
  border-radius: 10px;
  position: relative;
}

.bl-stat__icon {
  width: 28px;
  height: 28px;
  color: var(--bl-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.9375rem;
  background: transparent;
  position: absolute;
  top: 16px;
  right: 16px;
}

.bl-stat__label {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--bl-text-secondary);
  letter-spacing: 0.01em;
  text-transform: none;
  margin-top: 0;
}

.bl-stat__value {
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--bl-text);
  letter-spacing: -0.02em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.bl-stat__trend {
  font-size: 0.8125rem;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 4px;
}

.bl-stat__trend--up {
  color: var(--bl-success);
}

.bl-stat__trend--down {
  color: var(--bl-danger);
}

.bl-stat__subtext {
  font-size: 0.8125rem;
  color: var(--bl-text-muted);
}

/* ═══════════════════════════════════════════════════════════════════════════
   TABLE
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.bl-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.bl-table thead {
  position: sticky;
  top: 0;
  z-index: 1;
}

.bl-table th {
  padding: var(--bl-space-3) var(--bl-space-4);
  text-align: left;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--bl-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--bl-bg-secondary);
  border-bottom: 1px solid var(--bl-border);
  white-space: nowrap;
}

.bl-table th[aria-sort] {
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}

.bl-table th[aria-sort]:hover {
  color: var(--bl-text);
}

.bl-table th[aria-sort]::after {
  content: '\f0dc'; /* fa-sort */
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  margin-left: var(--bl-space-2);
  opacity: 0.4;
  font-size: 0.75rem;
}

.bl-table th[aria-sort="ascending"]::after {
  content: '\f0de'; /* fa-sort-up */
  opacity: 1;
}

.bl-table th[aria-sort="descending"]::after {
  content: '\f0dd'; /* fa-sort-down */
  opacity: 1;
}

.bl-table td {
  padding: var(--bl-space-3) var(--bl-space-4);
  color: var(--bl-text);
  border-bottom: 1px solid var(--bl-border-light);
  vertical-align: middle;
}

/* Zebra rows */
.bl-table tbody tr:nth-child(even) td {
  background: var(--bl-surface-alt);
}

.bl-table tbody tr:hover td {
  background: var(--bl-bg-tertiary);
}

.bl-table tbody tr:last-child td {
  border-bottom: none;
}

/* Checkbox column */
.bl-table .col-check {
  width: 40px;
  padding-left: var(--bl-space-4);
}

/* ═══════════════════════════════════════════════════════════════════════════
   MODAL (native <dialog>)
   ═══════════════════════════════════════════════════════════════════════════ */

dialog.bl-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
  padding: 0;
  border: 1px solid var(--bl-border);
  border-radius: var(--bl-radius-xl);
  background: var(--bl-surface);
  box-shadow: var(--bl-shadow-lg);
  width: min(90vw, 520px);
  max-height: 90vh;
  overflow: hidden;
  flex-direction: column;
}

/* Only show when [open] — without this the universal display:flex would defeat
   the UA `dialog:not([open]) { display: none }` rule. */
dialog.bl-modal:not([open]) {
  display: none;
}

dialog.bl-modal[open] {
  display: flex;
}

dialog.bl-modal--sm {
  width: min(90vw, 380px);
}

dialog.bl-modal--lg {
  width: min(95vw, 720px);
}

dialog.bl-modal::backdrop {
  background: rgb(0 0 0 / 0.5);
  backdrop-filter: blur(2px);
}

@media (prefers-reduced-motion: no-preference) {
  dialog.bl-modal[open] {
    animation: bl-modal-in 0.18s ease;
  }

  @keyframes bl-modal-in {
    from {
      opacity: 0;
      transform: translate(-50%, calc(-50% + 8px));
    }
    to {
      opacity: 1;
      transform: translate(-50%, -50%);
    }
  }
}

.bl-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bl-space-3);
  padding: var(--bl-space-5) var(--bl-space-6);
  border-bottom: 1px solid var(--bl-border-light);
  flex-shrink: 0;
}

.bl-modal__title {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--bl-text);
}

.bl-modal__close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border: none;
  background: transparent;
  color: var(--bl-text-muted);
  border-radius: var(--bl-radius-sm);
  cursor: pointer;
  font-size: 1rem;
  transition: background 0.12s ease, color 0.12s ease;
  flex-shrink: 0;
}

.bl-modal__close:hover {
  background: var(--bl-bg-secondary);
  color: var(--bl-text);
}

.bl-modal__close:focus-visible {
  outline: 2px solid var(--bl-primary);
  outline-offset: 2px;
}

.bl-modal__body {
  padding: var(--bl-space-6);
  overflow-y: auto;
  flex: 1;
}

.bl-modal__footer {
  padding: var(--bl-space-4) var(--bl-space-6);
  border-top: 1px solid var(--bl-border-light);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--bl-space-2);
  flex-shrink: 0;
  background: var(--bl-bg-secondary);
}

/* ═══════════════════════════════════════════════════════════════════════════
   BADGE
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
}

.bl-badge--neutral {
  background: var(--bl-bg-tertiary);
  color: var(--bl-text-secondary);
}

.bl-badge--primary {
  background: var(--bl-primary-soft);
  color: var(--bl-primary);
}

.bl-badge--success {
  background: rgb(16 185 129 / 0.12);
  color: var(--bl-success);
}

.bl-badge--warning {
  background: rgb(245 158 11 / 0.12);
  color: var(--bl-warning);
}

.bl-badge--danger {
  background: rgb(239 68 68 / 0.12);
  color: var(--bl-danger);
}

.bl-badge--info {
  background: rgb(59 130 246 / 0.12);
  color: var(--bl-info);
}

/* ═══════════════════════════════════════════════════════════════════════════
   EMPTY STATE
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--bl-space-3);
  padding: var(--bl-space-12) var(--bl-space-6);
  text-align: center;
}

.bl-empty__icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--bl-bg-tertiary);
  color: var(--bl-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.375rem;
}

.bl-empty__title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--bl-text);
  margin: 0;
}

.bl-empty__description {
  font-size: 0.9375rem;
  color: var(--bl-text-secondary);
  max-width: 340px;
  margin: 0;
  line-height: 1.6;
}

.bl-empty__action {
  margin-top: var(--bl-space-2);
}

/* ═══════════════════════════════════════════════════════════════════════════
   SKELETON / SHIMMER
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-skeleton {
  border-radius: var(--bl-radius-sm);
  background: var(--bl-border);
  position: relative;
  overflow: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  .bl-skeleton::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
      90deg,
      transparent 0%,
      rgb(255 255 255 / 0.15) 50%,
      transparent 100%
    );
    background-size: 200% 100%;
    animation: bl-shimmer 1.4s ease infinite;
  }

  html[data-theme="dark"] .bl-skeleton::after {
    background: linear-gradient(
      90deg,
      transparent 0%,
      rgb(255 255 255 / 0.06) 50%,
      transparent 100%
    );
    background-size: 200% 100%;
  }

  @keyframes bl-shimmer {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
  }
}

/* Skeleton size helpers */
.bl-skeleton--text {
  height: 1em;
  border-radius: 4px;
}

.bl-skeleton--title {
  height: 1.5em;
  border-radius: 4px;
}

.bl-skeleton--avatar {
  border-radius: 50%;
}

.bl-skeleton--btn {
  height: 2.25rem;
  border-radius: var(--bl-radius-md);
}

/* Skeleton row for tables */
.bl-skeleton-row {
  display: flex;
  gap: var(--bl-space-4);
  align-items: center;
  padding: var(--bl-space-3) var(--bl-space-4);
  border-bottom: 1px solid var(--bl-border-light);
}

/* ═══════════════════════════════════════════════════════════════════════════
   ALERT / TOAST
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--bl-space-3);
  padding: var(--bl-space-4) var(--bl-space-5);
  border-radius: var(--bl-radius-md);
  border: 1px solid transparent;
  font-size: 0.9375rem;
}

.bl-alert__icon {
  font-size: 1rem;
  flex-shrink: 0;
  margin-top: 1px;
}

.bl-alert__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.bl-alert__title {
  font-weight: 600;
}

.bl-alert--success {
  background: rgb(16 185 129 / 0.10);
  border-color: rgb(16 185 129 / 0.25);
  color: var(--bl-success);
}

.bl-alert--warning {
  background: rgb(245 158 11 / 0.10);
  border-color: rgb(245 158 11 / 0.25);
  color: var(--bl-warning);
}

.bl-alert--danger {
  background: rgb(239 68 68 / 0.10);
  border-color: rgb(239 68 68 / 0.25);
  color: var(--bl-danger);
}

.bl-alert--info {
  background: rgb(59 130 246 / 0.10);
  border-color: rgb(59 130 246 / 0.25);
  color: var(--bl-info);
}

/* ═══════════════════════════════════════════════════════════════════════════
   TABS
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--bl-border);
  overflow-x: auto;
  scrollbar-width: none;
}

.bl-tabs::-webkit-scrollbar {
  display: none;
}

.bl-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--bl-space-2);
  padding: var(--bl-space-3) var(--bl-space-5);
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--bl-text-secondary);
  border: none;
  background: transparent;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  cursor: pointer;
  white-space: nowrap;
  font-family: var(--bl-font);
  transition: color 0.12s ease, border-color 0.12s ease;
}

.bl-tab:hover {
  color: var(--bl-text);
}

.bl-tab:focus-visible {
  outline: 2px solid var(--bl-primary);
  outline-offset: -2px;
}

.bl-tab.is-active {
  color: var(--bl-primary);
  border-bottom-color: var(--bl-primary);
  font-weight: 600;
}

.bl-tab-panel {
  display: none;
}

.bl-tab-panel.is-active {
  display: block;
}

/* ═══════════════════════════════════════════════════════════════════════════
   DIVIDER
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-divider {
  border: none;
  border-top: 1px solid var(--bl-border-light);
  margin: var(--bl-space-4) 0;
}

/* ═══════════════════════════════════════════════════════════════════════════
   UTILITY
   ═══════════════════════════════════════════════════════════════════════════ */

/* Visually hidden (screen-reader accessible) */
.bl-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Grid helpers for stat cards */
.bl-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--bl-space-5);
}

/* Text utilities */
.bl-text-muted  { color: var(--bl-text-muted); }
.bl-text-danger { color: var(--bl-danger); }
.bl-text-success { color: var(--bl-success); }

/* ─── Sidebar user menu ──────────────────────────────────────────────────── */
.bl-user-menu { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: var(--bl-radius-md); }
.bl-user-menu__avatar { width: 32px; height: 32px; border-radius: 50%; background: var(--bl-primary); color: #fff; display: grid; place-items: center; font-weight: 600; font-size: 13px; flex-shrink: 0; }
.bl-user-menu__text { min-width: 0; flex: 1; }
.bl-user-menu__name { font-size: 13px; font-weight: 600; color: var(--bl-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bl-user-menu__email { font-size: 11px; color: var(--bl-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ─── Theme toggle ───────────────────────────────────────────────────────── */
.bl-theme-toggle { background: transparent; border: 1px solid var(--bl-border); border-radius: var(--bl-radius-md); padding: 8px 12px; color: var(--bl-text-secondary); cursor: pointer; width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px; }
.bl-theme-toggle:hover { background: var(--bl-surface-alt); }
.bl-theme-toggle .fa-moon { display: none; }
html[data-theme="dark"] .bl-theme-toggle .fa-sun { display: none; }
html[data-theme="dark"] .bl-theme-toggle .fa-moon { display: inline-block; }

/* ─── Sidebar error state ────────────────────────────────────────────────── */
.bl-sidebar-error { padding: 16px; color: var(--bl-danger); font-size: 13px; }

/* ─── Skip link (accessibility) ─────────────────────────────────────────── */
.skip-link { position: absolute; top: -40px; left: 8px; background: var(--bl-primary); color: #fff; padding: 8px 16px; border-radius: var(--bl-radius-sm); text-decoration: none; z-index: 1000; }

/* ─── Two-column grid (dashboard layout) ────────────────────────────────── */
.bl-grid-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
@media (max-width: 900px) { .bl-grid-2col { grid-template-columns: 1fr; } }

/* ─── List component (recent activity rows) ─────────────────────────────── */
.bl-list { list-style: none; margin: 0; padding: 0; }
.bl-list__item { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--bl-border-light); }
.bl-list__item:last-child { border-bottom: none; }
.bl-list__icon { width: 28px; height: 28px; color: var(--bl-text-muted); display: grid; place-items: center; flex-shrink: 0; font-size: 0.8125rem; background: transparent; }
.bl-list__primary { flex: 1; font-size: 0.875rem; color: var(--bl-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bl-list__secondary { font-size: 0.75rem; color: var(--bl-text-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.skip-link:focus { top: 8px; }

/* ─── Filter row (manage pages) ─────────────────────────────────────────── */
.bl-filter-row { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; }
.bl-field--inline { flex: 1; min-width: 180px; position: relative; }
.bl-field__icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--bl-text-muted); pointer-events: none; }
.bl-field--inline .bl-input { padding-left: 36px; }

/* ─── Bulk actions bar ───────────────────────────────────────────────────── */
.bl-bulk-actions { display: flex; align-items: center; gap: 12px; padding: 8px 12px; background: var(--bl-primary-soft); border-radius: var(--bl-radius-sm); margin-bottom: 12px; }

/* ─── Sort buttons inside table headers ─────────────────────────────────── */
.bl-sort-btn { background: transparent; border: 0; color: var(--bl-text); font: inherit; cursor: pointer; padding: 0; font-weight: 600; white-space: nowrap; }
.bl-sort-btn[aria-sort="ascending"]::after  { content: " \25B2"; font-size: 10px; }
.bl-sort-btn[aria-sort="descending"]::after { content: " \25BC"; font-size: 10px; }

/* ─── Visually hidden (alias for sr-only) ───────────────────────────────── */
.bl-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ─── Pagination nav ─────────────────────────────────────────────────────── */
.bl-pagination { display: flex; gap: 8px; justify-content: center; margin-top: 16px; flex-wrap: wrap; }

/* ─── Table action column ────────────────────────────────────────────────── */
.bl-table__action-col { width: 90px; text-align: right; }

/* ─── User avatars (inline) ──────────────────────────────────────────────── */
.bl-user-avatar-sm { width: 28px; height: 28px; border-radius: 50%; background: var(--bl-primary); color: #fff; display: grid; place-items: center; font-weight: 600; font-size: 12px; flex-shrink: 0; }
.bl-user-avatar-lg { width: 48px; height: 48px; border-radius: 50%; background: var(--bl-primary); color: #fff; display: grid; place-items: center; font-weight: 700; font-size: 20px; flex-shrink: 0; }

/* ─── List item component (team/members cards) ───────────────────────────── */
.bl-list-item { display: flex; align-items: center; gap: 16px; padding: 16px; border-radius: var(--bl-radius-md); border: 1px solid var(--bl-border); margin-bottom: 12px; background: var(--bl-surface); }
.bl-list-item__avatar { width: 40px; height: 40px; border-radius: 50%; background: var(--bl-primary-soft); color: var(--bl-primary); display: grid; place-items: center; flex-shrink: 0; }
.bl-list-item__body { flex: 1; min-width: 0; }
.bl-list-item__title { font-weight: 600; color: var(--bl-text); }
.bl-list-item__meta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; font-size: 13px; color: var(--bl-text-muted); }
.bl-list-item__meta > span { display: inline-flex; align-items: center; gap: 6px; }
.bl-list-item__actions { flex-shrink: 0; }

/* ─── Page header ────────────────────────────────────────────────────────── */
/* ─── Form field actions row ─────────────────────────────────────────────── */
.bl-field__actions { margin-top: 8px; }
/* NOTE: .bl-content + .bl-page-header are owned by app-shell.css */

/* ═══════════════════════════════════════════════════════════════════════════
   STEP BADGE  (used on new-device enrollment flow)
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-step-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--bl-primary);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 700;
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════════════════════
   TILE GRID  (OS picker on new-device page)
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--bl-space-4);
}

.bl-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--bl-space-2);
  padding: var(--bl-space-5) var(--bl-space-4);
  background: var(--bl-surface);
  border: 1px solid var(--bl-border);
  border-radius: var(--bl-radius-lg);
  text-decoration: none;
  color: var(--bl-text);
  transition: border-color 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
  cursor: pointer;
}

.bl-tile:hover {
  border-color: var(--bl-primary);
  box-shadow: var(--bl-shadow-md);
  background: var(--bl-primary-soft);
}

.bl-tile:focus-visible {
  outline: 2px solid var(--bl-primary);
  outline-offset: 2px;
}

.bl-tile__icon {
  font-size: 2rem;
  color: var(--bl-primary);
  display: block;
}

.bl-tile__label {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--bl-text);
}

.bl-tile__sub {
  font-size: 0.8125rem;
  color: var(--bl-text-muted);
  text-align: center;
}

/* ═══════════════════════════════════════════════════════════════════════════
   CODE BLOCK  (terminal-style pre blocks)
   ═══════════════════════════════════════════════════════════════════════════ */

.bl-code {
  background: var(--bl-bg-secondary);
  border: 1px solid var(--bl-border);
  border-radius: var(--bl-radius-md);
  padding: var(--bl-space-4) var(--bl-space-5);
  font-family: ui-monospace, 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
  font-size: 0.875rem;
  color: var(--bl-text);
  overflow-x: auto;
  margin: 0;
  white-space: pre;
  line-height: 1.6;
}

html[data-theme="dark"] .bl-code {
  background: #0d0f1f;
  border-color: var(--bl-border);
}
.bl-page-header h1 { margin: 0; font-size: 1.5rem; font-weight: 700; color: var(--bl-text); }
.bl-page-header p { margin: 0; font-size: 0.9375rem; color: var(--bl-text-secondary); }

/* ─── Settings-specific layout helpers ──────────────────────────────────── */
.bl-checkbox { display: flex; align-items: center; gap: 10px; padding: 8px 0; cursor: pointer; color: var(--bl-text); }
.bl-checkbox input { width: 16px; height: 16px; }
.bl-stack { display: flex; flex-direction: column; gap: 16px; }
.bl-field__actions { display: flex; gap: 12px; margin-top: 16px; flex-wrap: wrap; }
