/* ==========================================================================
   GATE PASS — Components
   Gate Pass components: tight typography, restrained shadows,
   8-12px radius (no pill-heavy chrome), 8px spacing grid.
   ========================================================================== */

/* ============================================================
   TYPOGRAPHY HELPERS
   ============================================================ */
.section-title {
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
}
.section-subtitle {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}
.text-muted { color: var(--text-muted); font-size: var(--text-sm); }
/* Muted micro text for table meta cells (dates, counts) — replaces the
   repeated inline style="color:var(--text-muted);font-size:12px". */
.cell-meta { color: var(--text-muted); font-size: var(--text-xs); }
.eyebrow {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--text-muted);
}

/* ============================================================
   BUTTONS — accent (black primary), ghost, danger-ghost
   Monochrome system: "accent" is black, not gold. See tokens.css.
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 16px;
  height: 36px;
  border-radius: var(--radius-md);
  font-weight: var(--weight-medium);
  font-size: var(--text-sm);
  letter-spacing: -0.005em;
  transition:
    background var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast),
    opacity var(--duration-fast),
    transform var(--duration-fast);
  white-space: nowrap;
  border: 1px solid transparent;
}
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn:active:not(:disabled) { transform: translateY(0.5px); }
/* Keyboard focus ring — buttons had none (only inputs did), so tab focus
   was invisible. Matches the input/search/toggle focus treatment. */
.btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

/* Accent = the one primary CTA token. v89 unified btn--primary into this.
   Both used to resolve to black; merging removes the visual-token confusion
   between "primary" (navy) and "accent" (gold) that the original spec set
   up but never delivered on. */
.btn--accent {
  background: var(--color-accent-500);
  color: var(--accent-on);
  /* Neutral shadow — the button is black (gray-1000); the old gold-tinted
     shadow was vestigial from an abandoned gold-accent direction. */
  box-shadow: 0 1px 2px rgba(0,0,0,0.18), inset 0 1px 0 rgba(255,255,255,0.12);
}
.btn--accent:hover:not(:disabled) {
  background: var(--color-accent-600);
  box-shadow: 0 2px 6px rgba(0,0,0,0.22), inset 0 1px 0 rgba(255,255,255,0.12);
}

.btn--ghost {
  background: var(--surface-raised);
  color: var(--text-secondary);
  border-color: var(--surface-border);
  box-shadow: var(--shadow-xs);
}
.btn--ghost:hover:not(:disabled) {
  background: var(--surface-sunken);
  color: var(--text-primary);
  border-color: var(--surface-border-strong);
}

/* Solid-red .btn--danger removed (C4): destructive actions use one
   convention — .btn--danger-ghost (red outline) — gated by type-to-confirm
   modals. Reintroduce only with a deliberate reason. */

.btn--danger-ghost {
  background: transparent;
  color: var(--color-danger);
  border-color: var(--color-danger-border);
}
.btn--danger-ghost:hover:not(:disabled) {
  background: var(--color-danger-bg);
}

.btn--sm { height: 30px; padding: 0 12px; font-size: var(--text-xs); }
.btn--lg { height: 44px; padding: 0 20px; font-size: var(--text-md); }

/* Generic bordered surface card (admin join-code + pending-approvals blocks). */
.card {
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-lg);
  padding: 16px;
}

.btn .btn-icon { width: 16px; height: 16px; }

/* Icon-only square button */
.btn-icon-only {
  width: 36px; height: 36px;
  display: inline-flex;
  align-items: center; justify-content: center;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  border: 1px solid transparent;
  transition: all var(--duration-fast);
}
.btn-icon-only:hover {
  background: var(--surface-sunken);
  color: var(--text-primary);
  border-color: var(--surface-border);
}

/* ============================================================
   STAT CARDS — Operational metrics (no rainbow accents)
   ============================================================ */
.stat-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 20px;
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-xl);
  transition: box-shadow var(--duration-base);
}
.stat-card:hover { box-shadow: var(--shadow-sm); }

.stat-card__icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  margin-bottom: 4px;
}

.stat-card__label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.stat-card__value {
  font-size: var(--text-3xl);
  font-weight: var(--weight-bold);
  color: var(--text-primary);
  letter-spacing: -0.02em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.stat-card__hint {
  font-size: var(--text-xs);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 4px;
}
.stat-card__delta--up    { color: var(--color-success); }
.stat-card__delta--down  { color: var(--color-danger); }
.stat-card__delta--flat  { color: var(--text-muted); }

/* Status accents (used sparingly) */
.stat-card--success .stat-card__icon-wrap { background: var(--color-success-bg); color: var(--color-success); }
.stat-card--warning .stat-card__icon-wrap { background: var(--color-warning-bg); color: var(--color-warning); }
.stat-card--danger  .stat-card__icon-wrap { background: var(--color-danger-bg);  color: var(--color-danger); }
.stat-card--info    .stat-card__icon-wrap { background: var(--color-info-bg);    color: var(--color-info); }
.stat-card--brand   .stat-card__icon-wrap { background: var(--brand-light);      color: var(--brand); }
.stat-card--accent  .stat-card__icon-wrap { background: var(--accent-light);     color: var(--accent-hover); }

/* ============================================================
   LIST ITEMS
   ============================================================ */
.list-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 16px;
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  transition: border-color var(--duration-fast);
}
.list-item:hover { border-color: var(--surface-border-strong); }
.list-item--alert { border-left: 3px solid var(--color-warning); }

/* ============================================================
   TABLES — Linear/Stripe-grade
   ============================================================ */
.table-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-bottom: none;
  border-top-left-radius: var(--radius-xl);
  border-top-right-radius: var(--radius-xl);
}
.table-toolbar + .table-wrap {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  border-top: none;
}

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-xl);
  background: var(--surface-raised);
}
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.table th {
  text-align: left;
  padding: 10px 16px;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--surface-border);
  white-space: nowrap;
}
.table td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--surface-border);
  color: var(--text-primary);
  vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: none; }
.table tbody tr { transition: background var(--duration-fast); }
.table tbody tr:hover td { background: var(--surface-sunken); }
.table__actions { text-align: right; white-space: nowrap; }
.table tbody tr .row-hover-actions { opacity: 0; transition: opacity var(--duration-fast); }
.table tbody tr:hover .row-hover-actions { opacity: 1; }

.row--suspended td { opacity: 0.45; }
.row--suspended td:last-child { opacity: 1; }

/* Search input inside table toolbar */
.search-input {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  max-width: 320px;
  padding: 0 10px;
  height: 30px;
  /* Transparent border at rest so focus can wrap the WHOLE field in a black
     border with no layout shift. Sunken fill otherwise. */
  border: 1px solid transparent;
  background: var(--surface-sunken);
  border-radius: var(--radius-md);
}
.search-input:focus-within { border-color: var(--accent); box-shadow: none; }
.search-input svg { color: var(--text-muted); flex-shrink: 0; }
.search-input input {
  /* appearance:none kills the native type="search" chrome (the inset inner
     border/box that showed on mobile). No wrapper border either now. */
  -webkit-appearance: none;
  appearance: none;
  border: none; outline: none; box-shadow: none; background: transparent;
  font-size: var(--text-sm); flex: 1; padding: 0;
  color: var(--text-primary);
}
.search-input input::-webkit-search-decoration,
.search-input input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* Labeled inline date filter ("From [date]") — gives the bare date input a
   visible label so it isn't a mystery empty box. */
.filter-date {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}
.filter-date__label { flex-shrink: 0; font-weight: var(--weight-medium); }

/* ============================================================
   EMPTY STATES
   ============================================================ */
.empty {
  padding: 48px 24px;
  text-align: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
}
.empty--error {
  color: var(--color-danger);
  background: var(--color-danger-bg);
  border: 1px solid var(--color-danger-border);
  border-radius: var(--radius-md);
  padding: 16px;
}
.empty__icon {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 48px; height: 48px;
  border-radius: var(--radius-xl);
  background: var(--surface-sunken);
  color: var(--text-muted);
  margin-bottom: 12px;
}

/* ------------------------------------------------------------
   Rich empty-state. Use when an empty list deserves an action,
   not just a one-line label. Pattern: icon → headline →
   one-line subhead → primary CTA (optional).

     <div class="empty-state">
       <div class="empty-state__icon">SVG</div>
       <h3 class="empty-state__title">No visitors yet</h3>
       <p class="empty-state__sub">Register the people you'll invite over.</p>
       <button class="btn btn--accent">Add visitor</button>
     </div>
   ------------------------------------------------------------ */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 56px 24px;
  gap: 8px;
  color: var(--text-secondary);
}
.empty-state__icon {
  width: 56px;
  height: 56px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--surface-sunken);
  color: var(--text-muted);
  margin-bottom: 4px;
}
.empty-state__icon svg { width: 28px; height: 28px; }
.empty-state__title {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  letter-spacing: -0.018em;
}
.empty-state__sub {
  margin: 0;
  max-width: 38ch;
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--text-secondary);
}
.empty-state > .btn { margin-top: 8px; }

/* ============================================================
   FORM FIELDS
   ============================================================ */
.field { display: flex; flex-direction: column; gap: 6px; }
.field--inline { flex-direction: row; align-items: center; gap: 8px; }

.field__label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.field__input {
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  color: var(--text-primary);
  font-size: var(--text-sm);
  transition:
    border-color var(--duration-fast),
    box-shadow var(--duration-fast),
    background var(--duration-fast);
}
.field__input::placeholder { color: var(--text-muted); }
/* Radios + checkboxes use the brand near-black, not the browser default. */
input[type="radio"],
input[type="checkbox"] { accent-color: var(--text-primary); }

/* Resident dashboard "Notify security" — set apart at the bottom as a calm,
   always-available safety action (not competing with the primary CTA). */
.dash-notify-wrap { margin-top: 8px; padding-top: 16px; border-top: 1px solid var(--surface-border); }

/* ===== Resident mobile redesign (shared across resident screens) ===== */
.rd-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.rd-hi { margin: 0; font-size: var(--text-xl); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-tight); }
.rd-loc { display: flex; align-items: center; gap: 4px; margin: 4px 0 0; font-size: var(--text-xs); color: var(--text-secondary); }
.rd-owl { width: 38px; height: 38px; border-radius: var(--radius-full); background: var(--surface-sunken); color: var(--text-primary); display: flex; align-items: center; justify-content: center; flex: none; }

.rd-stats { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.rd-stat { background: var(--surface-sunken); border-radius: var(--radius-lg); padding: var(--space-4); }
.rd-stat__label { display: block; font-size: var(--text-xs); color: var(--text-secondary); }
.rd-stat__value { display: block; font-size: var(--text-2xl); font-weight: var(--weight-semibold); margin-top: 4px; }
.rd-stat__hint { display: block; font-size: var(--text-2xs); color: var(--text-muted); margin-top: 2px; }

.rd-section-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 6px; }
.rd-link { font-size: var(--text-xs); color: var(--text-secondary); background: none; border: 0; padding: 0; cursor: pointer; }
.rd-link:hover { color: var(--text-primary); }

.rd-list { display: flex; flex-direction: column; }
.rd-item { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--surface-border); }
.rd-item:last-child { border-bottom: 0; }
.rd-av { width: 36px; height: 36px; border-radius: var(--radius-full); background: var(--surface-sunken); color: var(--text-secondary); display: flex; align-items: center; justify-content: center; font-size: var(--text-xs); font-weight: var(--weight-medium); flex: none; }
.rd-item__main { flex: 1; min-width: 0; }
.rd-item__name { font-size: var(--text-sm); font-weight: var(--weight-medium); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rd-item__sub { font-size: var(--text-2xs); color: var(--text-muted); }
.rd-item__meta { font-size: var(--text-2xs); color: var(--text-muted); flex: none; }
.rd-item--tappable { cursor: pointer; }
.rd-item--tappable:hover { background: var(--surface-sunken); }
.rd-chevron { color: var(--text-muted); flex: none; }

.rd-tag { font-size: var(--text-2xs); padding: 3px 8px; border-radius: var(--radius-full); background: var(--surface-sunken); color: var(--text-secondary); flex: none; }
.rd-tag--delivery { background: var(--color-info-bg); color: var(--color-info); }

/* round add button + search field (visitors) */
.rd-add { width: 36px; height: 36px; border-radius: var(--radius-full); background: var(--accent); color: var(--accent-on); border: 0; display: flex; align-items: center; justify-content: center; cursor: pointer; flex: none; }
.rd-add:hover { background: var(--accent-hover); }
/* Transparent border at rest so focus can wrap the WHOLE field in a black
   border with no layout shift — matches .search-input. */
.rd-search { display: flex; align-items: center; gap: 8px; background: var(--surface-sunken); border: 1px solid transparent; border-radius: var(--radius-md); padding: 0 11px; color: var(--text-muted); }
.rd-search:focus-within { border-color: var(--accent); box-shadow: none; }
.rd-search input {
  /* appearance:none kills the native type="search" chrome (the inset inner
     border/glow that showed on mobile when tapped). */
  -webkit-appearance: none; appearance: none;
  border: 0; outline: none; box-shadow: none; background: transparent;
  flex: 1; height: 38px; font-size: var(--text-sm); color: var(--text-primary);
}
.rd-search input::-webkit-search-decoration,
.rd-search input::-webkit-search-cancel-button { -webkit-appearance: none; }
.rd-icon-btn { border: 0; background: transparent; color: var(--text-muted); padding: 6px; cursor: pointer; border-radius: var(--radius-sm); flex: none; }
.rd-icon-btn:hover { color: var(--color-danger); background: var(--surface-sunken); }

/* profile header (avatar + name) */
.rd-profile-head { text-align: center; }
.rd-avatar-lg { width: 64px; height: 64px; border-radius: var(--radius-full); background: var(--surface-sunken); color: var(--text-secondary); display: flex; align-items: center; justify-content: center; font-size: var(--text-xl); font-weight: var(--weight-medium); margin: 0 auto 8px; }
.rd-profile-name { margin: 0; font-size: var(--text-lg); font-weight: var(--weight-semibold); }
.rd-profile-sub { margin: 2px 0 0; font-size: var(--text-xs); color: var(--text-secondary); }

/* admin user cards (mobile-first, replaces the users table) */
.user-card { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--surface-border); }
.user-card:last-child { border-bottom: 0; }
.user-card.is-suspended { opacity: 0.55; }
.user-card .rd-item__main { flex: 1; min-width: 0; }
.role-pill { font-size: var(--text-2xs); padding: 3px 9px; border-radius: var(--radius-full); text-transform: capitalize; flex: none; }
.role-pill--resident { background: var(--surface-sunken); color: var(--text-secondary); }
.role-pill--security { background: var(--color-info-bg); color: var(--color-info); }
.role-pill--admin { background: transparent; color: var(--text-primary); border: 1px solid var(--surface-border-strong); }
.pending-zone { background: var(--color-warning-bg); border-color: var(--color-warning-border); }

/* audit log cards (replaces the logs table) */
.log-card { padding: 12px 0; border-bottom: 1px solid var(--surface-border); }
.log-card:last-child { border-bottom: 0; }
.log-card__top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.log-card__action { font-size: var(--text-sm); font-weight: var(--weight-medium); }
.log-card__reason { font-size: var(--text-xs); color: var(--text-secondary); margin-top: 4px; }
.log-card__meta { display: flex; gap: 10px; align-items: center; margin-top: 6px; font-size: var(--text-2xs); color: var(--text-muted); }

/* active pass card (passes) */
.rd-pass-card { border: 0.5px solid var(--surface-border); border-radius: var(--radius-lg); padding: 18px 16px; text-align: center; }
.rd-pass-name { margin: 10px 0 0; font-size: var(--text-base); font-weight: var(--weight-medium); }
.rd-pass-qr { width: 150px; height: 150px; margin: 12px auto; display: block; border-radius: var(--radius-sm); }
.rd-pass-code { margin: 0; font-family: var(--font-mono); font-size: var(--text-2xl); font-weight: var(--weight-semibold); letter-spacing: 3px; }
.rd-pass-actions { display: flex; gap: 8px; margin-top: 14px; }
/* One consistent modal footer everywhere: full-width, stacked action button(s)
   so the primary action is centred and positioning matches across all modals.
   (The canonical .danger-zone component lives further down and is shared by the
   profile self-delete and the edit-org modal.) */
.modal__body .row-end { flex-direction: column; align-items: stretch; }
.modal__body .row-end .btn { width: 100%; }

/* Read-only / disabled fields must LOOK non-editable so users don't try to
   change them (e.g. the org-owned Estate fields on the profile screen). */
.field__input:disabled,
.field__input[readonly] {
  background: var(--surface-sunken);
  color: var(--text-secondary);
  -webkit-text-fill-color: var(--text-secondary); /* iOS keeps disabled text legible */
  cursor: not-allowed;
  opacity: 1;
}
textarea.field__input {
  height: auto;
  padding: 10px 12px;
  resize: vertical;
  min-height: 80px;
  line-height: 1.5;
}
.field__input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: none;
}
.field__input[aria-invalid="true"] {
  border-color: var(--color-danger);
  box-shadow: 0 0 0 3px rgba(239,68,68,0.1);
}
.field__input--inline {
  height: 32px;
  width: auto;
  min-width: 128px;
  font-size: var(--text-sm);
  text-transform: capitalize;
}
.field__error { font-size: var(--text-xs); color: var(--color-danger); }
.field__hint  { font-size: var(--text-xs); color: var(--text-muted); }

/* Mobile overrides moved to the END of this file so they reliably
   win the cascade against the base rules. See the bottom of the file. */

/* ============================================================
   BADGES — 8px radius (NO full pills per spec)
   ============================================================ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.01em;
  text-transform: capitalize;
  white-space: nowrap;
  border: 1px solid transparent;
  line-height: 1.3;
}
.badge::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}
/* Status badge colors (neutral chip + colored dot) live in the dot-only
   block further down — these variants are intentionally not filled here.
   See ".badge--active" etc. in the v2 polish section. */

.badge--role::before { display: none; }
.badge--role {
  text-transform: none;
  padding: 3px 8px;
  background: var(--brand-light);
  color: var(--brand);
  border-color: rgba(24,36,66,0.12);
}

/* ============================================================
   MODAL
   ============================================================ */
.modal-backdrop {
  position: fixed; inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(15,23,42,0.55);
  backdrop-filter: blur(4px);
}
.modal {
  width: 100%; max-width: 480px;
  /* Cap to viewport so tall content (e.g. visitor pass with QR) gets an
     INTERNAL scrollbar instead of scrolling the page and burying the X. */
  max-height: calc(100dvh - 32px);
  display: flex;
  flex-direction: column;
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  outline: none;
  overflow: hidden;
  animation: fade-in var(--duration-base) var(--ease-out);
}
.modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--surface-border);
  flex-shrink: 0; /* never collapse — close button must stay reachable */
  background: var(--surface-raised);
}
.modal__title { font-size: var(--text-md); font-weight: var(--weight-semibold); }
.modal__close {
  width: 36px; height: 36px; /* 44pt safe area minus chrome — easy tap target */
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  font-size: var(--text-xl);
  color: var(--text-muted);
  line-height: 1;
  flex-shrink: 0;
}
.modal__close:hover { background: var(--surface-sunken); color: var(--text-primary); }
.modal__body {
  padding: 20px;
  /* Scroll the body within the modal, keep the header pinned. */
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* ============================================================
   KEBAB MENU — row-level overflow menu used in admin Users to
   collapse Suspend / Archive / Delete onto a single button.
   ============================================================ */
.kebab { position: relative; display: inline-block; }
.kebab__trigger {
  background: transparent;
  border: 1px solid transparent;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-secondary);
  cursor: pointer;
}
.kebab__trigger:hover {
  background: var(--surface-sunken);
  color: var(--text-primary);
  border-color: var(--surface-border);
}
.kebab__menu {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  min-width: 180px;
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 4px;
  z-index: var(--z-overlay);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.kebab__item {
  text-align: left;
  background: transparent;
  border: none;
  padding: 8px 12px;
  font-size: var(--text-sm);
  color: var(--text-primary);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.kebab__item:hover { background: var(--surface-sunken); }
.kebab__item--danger { color: #b91c1c; }
.kebab__item--danger:hover { background: #fef2f2; }

/* Archived row: muted background + struck-through name (sprint 2 polish). */
.row--archived { opacity: 0.55; }
.row--archived td strong { text-decoration: line-through; }

/* Danger zone — used in edit-org modal (and future settings panels) to
   visually quarantine destructive actions from the regular form footer.
   Pattern borrowed from GitHub / Vercel settings: subtle red border,
   small "Danger zone" label, the action button sits to the right of an
   explanation block. */
.danger-zone {
  margin-top: 20px;
  border: 1px solid #fca5a5;
  border-radius: var(--radius-md);
  background: #fff7f7;
}
.danger-zone__label {
  padding: 6px 12px;
  border-bottom: 1px solid #fca5a5;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #b91c1c;
  background: #fff0f0;
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.danger-zone__body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px;
}
.danger-zone__body strong {
  display: block;
  color: var(--text-primary);
  font-size: var(--text-sm);
  margin-bottom: 2px;
}
.danger-zone__body p {
  margin: 0;
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.4;
}
@media (max-width: 480px) {
  .danger-zone__body { flex-direction: column; align-items: stretch; }
  .danger-zone__body button { width: 100%; }
}

/* ============================================================
   ALERTS — semantic info / warning / danger blocks.
   Replaces the inline-styled .auth__error misuse for warnings
   and destructive context. Keep .auth__error for actual recoverable
   form errors only (red).
   ============================================================ */
.alert {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font-size: var(--text-sm);
  line-height: 1.5;
}
.alert strong { font-weight: var(--weight-semibold); }
.alert--info {
  background: #eff6ff;
  border-color: #bfdbfe;
  color: #1e3a8a;
}
.alert--warning {
  background: #fff8e1;
  border-color: #ffe7a3;
  color: #7a5b00;
}
.alert--danger {
  background: #fff0f0;
  border-color: #fca5a5;
  color: #7a1d1d;
}

/* ============================================================
   TOASTS
   ============================================================ */
.toast-root {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: var(--z-modal);
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: min(360px, calc(100vw - 32px));
}
.toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: var(--radius-md);
  background: var(--color-primary-900);
  color: white;
  box-shadow: var(--shadow-lg);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  cursor: pointer;
  border: 1px solid rgba(255,255,255,0.06);
  transition: opacity var(--duration-base), transform var(--duration-base) var(--ease-out);
}
.toast--leaving { opacity: 0; transform: translateX(8px); }
.toast--success { background: #14532d; border-color: rgba(34,197,94,0.3); }
.toast--error   { background: #7f1d1d; border-color: rgba(239,68,68,0.3); }
.toast--info    { background: #1e3a8a; border-color: rgba(59,130,246,0.3); }

/* ============================================================
   PANEL (analytics + section containers)
   ============================================================ */
.panel {
  padding: 20px;
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-xl);
}
.panel__title {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
}
.panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.panel__link {
  font-size: 12px;
  font-weight: var(--weight-medium);
  color: var(--brand);
  background: none;
  border: none;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--duration-fast);
}
.panel__link:hover { background: var(--brand-light); }

/* Two-column dashboard split */
.dash-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}
@media (min-width: 1024px) {
  .dash-split { grid-template-columns: 1fr 1fr; }
}

/* ============================================================
   REALTIME LIVE PILL
   ============================================================ */
.realtime-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: var(--radius-sm);
  color: #15803d;
  background: var(--color-success-bg);
  border: 1px solid var(--color-success-border);
}
.realtime-pill::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--color-success);
  animation: pulse-dot 2s ease-in-out infinite;
}

/* ============================================================
   USER AREA (header)
   ============================================================ */
.user-area {
  display: flex; align-items: center; gap: 10px;
}
.user-area__role {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  text-transform: capitalize;
  padding: 3px 8px;
  border-radius: var(--radius-sm);
  color: var(--brand);
  background: var(--brand-light);
  border: 1px solid rgba(24,36,66,0.12);
}
.user-area__email {
  color: var(--text-secondary);
  font-size: var(--text-sm);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.user-area__logout {
  height: 32px;
  padding: 0 12px;
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  border: 1px solid transparent;
  transition: all var(--duration-fast);
  white-space: nowrap;   /* never wrap "Sign out" to two lines */
  flex-shrink: 0;
}
.user-area__logout:hover {
  background: var(--surface-sunken);
  border-color: var(--surface-border);
  color: var(--text-primary);
}

/* ============================================================
   LAYOUT HELPERS
   ============================================================ */
.form { width: 100%; }
.stack      { display: flex; flex-direction: column; gap: 16px; }
.stack-sm   { display: flex; flex-direction: column; gap: 8px; }
.stack-lg   { display: flex; flex-direction: column; gap: 32px; }
.row        { display: flex; gap: 12px; flex-wrap: wrap; }
.row-between{ justify-content: space-between; }
.row-center { align-items: center; }
.row-end    { justify-content: flex-end; }
.flex-1     { flex: 1 1 0%; }

/* ============================================================
   ACTIVITY FEED (dashboard "what's happening right now")
   ============================================================ */
.activity-feed {
  display: flex;
  flex-direction: column;
  gap: 0;
  background: var(--surface-raised);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-xl);
  overflow: hidden;
}
.activity-row {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--surface-border);
  transition: background var(--duration-fast);
}
.activity-row:last-child { border-bottom: none; }
.activity-row:hover { background: var(--surface-sunken); }
.activity-row__icon {
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  flex-shrink: 0;
}
.activity-row__icon--success { background: var(--color-success-bg); color: var(--color-success); }
.activity-row__icon--danger  { background: var(--color-danger-bg);  color: var(--color-danger); }
.activity-row__icon--info    { background: var(--color-info-bg);    color: var(--color-info); }
.activity-row__main {
  font-size: var(--text-sm);
  color: var(--text-primary);
  min-width: 0;
}
.activity-row__sub {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-top: 2px;
}
.activity-row__when {
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ============================================================
   AUDIT LOG TABLE — compact, dense, debugging-optimized
   ============================================================ */
.table--logs th,
.table--logs td {
  padding: 8px 12px;
  font-size: 12.5px;
  line-height: 1.4;
}
.table--logs .log-time {
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  font-size: 12px;
  white-space: nowrap;
}
.table--logs .log-reason {
  color: var(--text-secondary);
}
.table--logs .log-ref code {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-muted);
}

/* Alerts strip — compact warning bar above the log table */
.alerts-strip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
  border-radius: var(--radius-md);
  font-size: 13px;
  color: #92400e;
}
.alerts-strip svg { color: var(--color-warning); flex-shrink: 0; }
.alerts-strip strong { font-weight: var(--weight-semibold); }
.alerts-strip span { color: #78350f; opacity: 0.9; }

/* ============================================================
   MOBILE OVERRIDES — at end of file so they win the cascade.
   Apple HIG: 44pt touch targets. iOS Safari: 16px+ inputs to avoid
   the focus-zoom that wrecks form UX.
   ============================================================ */
@media (max-width: 767px) {
  /* iOS focus-zoom guard: every input must be ≥16px to avoid auto-zoom */
  .field__input,
  textarea.field__input,
  .search-input input { font-size: 16px; }
  .field__input--code { font-size: 22px; }

  /* Touch targets */
  .btn            { height: 44px; padding: 0 18px; }
  .btn--sm        { height: 40px; padding: 0 14px; font-size: var(--text-sm); }
  .btn--lg        { height: 48px; padding: 0 20px; }
  .btn-icon-only  { width: 44px; height: 44px; }
  .user-area__logout { height: 40px; padding: 0 14px; }

  /* Touch targets: everything tappable hits the 44px floor on mobile
     (DESIGN.md §1.5 / Apple HIG). These were 32–40px — under the floor on
     the two most-tapped controls (kebab menu + inline role select). */
  .field__input--inline { height: 44px; }
  .table__actions .btn--sm { min-height: 44px; }
  .kebab__trigger { width: 44px; height: 44px; }
}

/* ==========================================================================
   MOBILE BOTTOM TAB BAR (v2 mobile-first nav — replaces hamburger drawer)
   ========================================================================== */
.bottom-nav {
  display: none; /* desktop hides it; mobile @media below shows it */
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: var(--z-bottom-nav);
  background: var(--surface-raised);
  border-top: 1px solid var(--surface-border);
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
  height: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom, 0px));
  align-items: stretch;
  justify-content: space-around;
}
.bottom-nav__item {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 44px;
  padding: 4px 2px;
  background: transparent;
  border: 0;
  text-decoration: none;
  color: var(--text-muted);
  font-family: inherit;
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--duration-fast) var(--ease-out);
}
.bottom-nav__item:hover { color: var(--text-primary); text-decoration: none; }
.bottom-nav__item[aria-current="page"] { color: var(--text-primary); }
.bottom-nav__item[aria-current="page"]::after {
  content: "";
  position: absolute;
  top: 0;
  height: 2px;
  width: 24px;
  background: var(--gray-1000);
  border-radius: 0 0 2px 2px;
}
.bottom-nav__item { position: relative; }
.bottom-nav__icon {
  width: 22px;
  height: 22px;
  display: block;
}
.bottom-nav__label {
  font-size: 10.5px;
  line-height: 1;
  white-space: nowrap;
}

/* When the tab bar is visible, give the main scroll area headroom so the
   last row isn't covered by the bar (and account for the safe area). */
@media (max-width: 1023px) {
  .bottom-nav { display: flex; }
  .app-main {
    padding-bottom: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom, 0px) + 16px) !important;
  }
  /* The actual scroll container is .container (it holds #screen-root). The
     padding on .app-main sits OUTSIDE that scroll area, so the last element
     could still slip under the fixed bar. Put headroom on the scroller too. */
  .container {
    padding-bottom: calc(var(--bottom-nav-height) + env(safe-area-inset-bottom, 0px) + 24px);
  }
  /* Hide the hamburger button — tab bar is the primary nav now. The "More"
     tab still triggers it programmatically for any overflow items. */
  .app-header__menu-btn { display: none !important; }
}

/* ==========================================================================
   v2 MOBILE POLISH — fixes from real-device screenshots
   ========================================================================== */

@media (max-width: 1023px) {
  /* Show a compact brand mark + current screen title on the left. The
     bottom bar highlights tabs, but OVERFLOW screens (Organizations, Audit
     Logs, Profile…) only light up "More" — so the title is the only thing
     telling the user which screen they're on. Slim, single-line, truncates. */
  .app-header__mark {
    display: inline-flex;
    align-items: center;
    width: 26px; height: 26px;
    flex-shrink: 0;
    color: var(--text-primary);
  }
  .app-header__mark svg { width: 26px; height: 26px; }
  .app-header__title {
    display: block;
    font-size: 16px;
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-tight);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
  }
  .app-header { padding-left: var(--space-4); gap: 8px; }

  /* "Sign out" was reading as plain text — give it a real button affordance. */
  .user-area__logout {
    border: 1px solid var(--surface-border);
    background: var(--surface-raised);
    color: var(--text-primary);
    border-radius: var(--radius-md);
    font-weight: var(--weight-medium);
    font-size: 13px;
  }
  .user-area__logout:hover { background: var(--surface-sunken); }

  /* Page-header rows ("Welcome back…" + CTA, "Passes" + Issue button, etc.)
     should ALWAYS stack on mobile — current behavior wraps inconsistently
     based on heading length, producing left- vs right-aligned CTAs.
     Targeting `.row-between` inside a section is broad but the only place
     it lives is at the top of each screen. */
  section > .row.row-between {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3);
  }
  section > .row.row-between .btn { align-self: flex-start; }
}

/* ==========================================================================
   v3 ADMIN-SCREEN POLISH (from admin screenshots)
   ========================================================================== */
@media (max-width: 1023px) {

  /* Admin Dashboard's page-header uses `<div class="stack">` wrapper (not
     `<section>`), so the section> selector didn't catch it. Match both. */
  .stack > .row.row-between,
  section > .row.row-between {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3);
  }
  .stack > .row.row-between .row,
  section > .row.row-between .row {
    flex-wrap: wrap;
    gap: var(--space-2);
  }
  .stack > .row.row-between .btn,
  section > .row.row-between .btn { flex: 1 1 auto; justify-content: center; }

  /* Stat-card grid: ensure 2-up on phones. The auto-fill min was being
     overridden somewhere — force explicit 2-column grid up to 640px. */
  .grid-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 10px !important;
  }
  .stat-card { padding: 14px; }
  .stat-card__value { font-size: 22px; }
  .stat-card__icon-wrap { width: 28px; height: 28px; margin-bottom: 2px; }

  /* Admin Users role <select> — compact inline control, but still on the
     44px touch floor (it's a primary tappable control on this screen). */
  .table .field__input--inline,
  .table select.field__input {
    height: 44px;
    padding: 0 28px 0 10px;
    font-size: 13px;
    min-width: 96px;
    width: auto;
  }
}

/* Analytics: detune the bar colors so they don't shout. Vercel-system means
   data viz keeps semantic color but at a lower saturation. */
.chart-bar--allow, .chart-legend-swatch--allow { background: #16a34a !important; }
.chart-bar--deny,  .chart-legend-swatch--deny  { background: #dc2626 !important; }

/* ==========================================================================
   v4 ADMIN POLISH (from screenshots: stretched icons, overflowing filters,
   rainbow stat icons, vibrant badges)
   ========================================================================== */

/* Force every SVG inside a button to keep its declared size — the v29
   `flex: 1 1 auto` made unsized SVGs stretch to fill the flex track,
   producing the giant Open-scanner QR pattern. */
.btn svg { flex: 0 0 auto; width: 16px; height: 16px; display: inline-block; }
.btn--sm svg { width: 14px; height: 14px; }
.btn--lg svg { width: 18px; height: 18px; }

/* Stat-card icons: drop the rainbow variants. All icons monochrome,
   matching TOTAL USERS / VISITORS. */
.stat-card .stat-card__icon-wrap,
.stat-card--success .stat-card__icon-wrap,
.stat-card--warning .stat-card__icon-wrap,
.stat-card--danger  .stat-card__icon-wrap,
.stat-card--info    .stat-card__icon-wrap,
.stat-card--brand   .stat-card__icon-wrap,
.stat-card--accent  .stat-card__icon-wrap {
  background: transparent;
  color: var(--text-primary);
  border: 0;
  width: 24px;
  height: 24px;
  margin-bottom: 6px;
}
.stat-card .stat-card__icon-wrap svg { width: 22px; height: 22px; }

/* Audit log ALLOW/DENY badges: keep the dot, drop the loud bg colors.
   Color survives in the dot + text — no fill. */
.badge--active,
.badge--revoked,
.badge--expired,
.badge--created,
.badge--pending {
  background: var(--surface-raised);
  border-color: var(--surface-border);
}
.badge--active  { color: var(--text-primary); }
.badge--active::before  { background: #16a34a; }
.badge--revoked { color: var(--text-primary); }
.badge--revoked::before { background: #dc2626; }
.badge--scanned { color: var(--text-muted); }
.badge--scanned::before { background: var(--gray-400); }
.badge--expired { color: var(--text-muted); }
.badge--expired::before { background: var(--gray-500); }
.badge--created { color: var(--text-primary); }
.badge--created::before { background: var(--blue-500); }
.badge--pending { color: var(--text-secondary); }
.badge--pending::before { background: var(--gray-500); }

/* Audit log filter toolbar: stack on mobile so it doesn't horizontally
   scroll. Search goes full-width, selects share row 2. */
@media (max-width: 767px) {
  .logs-toolbar,
  .audit-toolbar,
  section > .row.row-end,
  section > .row.row-wrap {
    flex-wrap: wrap;
    gap: var(--space-2);
  }
  .logs-toolbar .search-input,
  .logs-toolbar input[type="search"],
  .logs-toolbar > .field { flex: 1 1 100%; }
  .logs-toolbar select,
  .logs-toolbar .field--inline { flex: 1 1 calc(50% - 4px); min-width: 0; }
  /* Generic fallback: any inline field/select in a row should shrink */
  .row select.field__input,
  .row .field--inline { min-width: 0; }
}

/* Logs toolbar uses .table-toolbar — not .logs-toolbar. Override. */
@media (max-width: 767px) {
  .table-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
  }
  .table-toolbar .search-input { flex: 1 1 100%; }
  .table-toolbar select.field__input { flex: 1 1 calc(50% - 4px); min-width: 0; }
  /* "From" / "To" share a row — each takes half, label + compact picker. */
  .table-toolbar .filter-date { flex: 1 1 calc(50% - 4px); min-width: 0; }
  .table-toolbar .filter-date .field__input--inline { flex: 1 1 auto; width: auto; min-width: 0; }
}

/* ==========================================================================
   v5: TABLES BECOME CARDS ON MOBILE
   The Passes / Visitors tables had 5 columns that overflowed horizontally
   on a 375px viewport — actions (Show pass / Revoke) lived offscreen,
   requiring a swipe to reach. On mobile each row now renders as a stacked
   card with visitor + code/status on one line and actions on their own row.
   ========================================================================== */
@media (max-width: 767px) {
  .table-wrap {
    overflow-x: visible;       /* no more horizontal scroll-trap */
    border: 0;
    background: transparent;
    border-radius: 0;
  }
  .table {
    display: block;
    border-collapse: separate;
    border-spacing: 0;
  }
  .table thead { display: none; }   /* column headers don't make sense once stacked */
  .table tbody { display: flex; flex-direction: column; gap: 10px; }
  .table tr {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px;
    background: var(--surface-raised);
    border: 1px solid var(--surface-border);
    border-radius: var(--radius-lg);
  }
  .table tr:hover td { background: transparent; }
  .table td {
    display: block;
    padding: 0;
    border-bottom: 0;
  }
  /* In card mode `.table td` (0,1,1) was overriding `.hide-mobile` (0,1,0),
     so hidden columns leaked back in as stacked cells — including empty
     "—" placeholders (e.g. a blank visitor Purpose, empty audit Decision/
     Reason). Keep them hidden, and hide explicitly-empty cells too. */
  .table td.hide-mobile,
  .table td.cell-empty { display: none !important; }
  /* First td (visitor name) is the headline */
  .table td:first-child {
    font-size: 15px;
    font-weight: var(--weight-semibold);
  }
  /* Action row spans the card and right-aligns the buttons */
  .table td.table__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding-top: 4px;
    border-top: 1px dashed var(--surface-border);
  }
  .table td.table__actions .btn { flex: 1 1 calc(50% - 4px); justify-content: center; }
  /* Inline pass code + status badge: render side-by-side via flex on td#2-3 */
  .table td:nth-child(2),
  .table td:nth-child(3) {
    display: inline-flex;
    margin-right: 8px;
    vertical-align: middle;
  }
  /* Logs: the 2nd column is the Action (with an actor sub-line), not a chip.
     Keep it block so "by <actor>" sits UNDER the action, not jammed onto it. */
  .table--logs td:nth-child(2) { display: block; margin-right: 0; }

  /* Users table density (#6): default card stacks name / role / status /
     actions on 4 lines (~260px). Make it 2 lines — name on top, then role
     select + status badge + kebab inline on one meta row. Scoped to
     .table--users so the Passes/Logs card layout is untouched. */
  .table--users tr {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 10px;
    padding: 12px 14px;
  }
  .table--users td:first-child { flex: 1 1 100%; }   /* name owns row 1 */
  /* row 2: role select (td3) + status badge (td4) inline; td2 (Joined) is
     hide-mobile so it's already display:none. */
  .table--users td:nth-child(3),
  .table--users td:nth-child(4) {
    display: inline-flex;
    margin: 0;
    align-items: center;
  }
  .table--users td.table__actions {
    margin-left: auto;           /* push kebab to the right edge of row 2 */
    border-top: 0;
    padding-top: 0;
    flex: 0 0 auto;
  }
  .table--users td.table__actions .btn,
  .table--users td.table__actions .kebab { flex: 0 0 auto; }
}

/* Pass countdown sub-label under the status badge */
.pass-countdown {
  margin-top: 4px;
  font-size: var(--text-2xs);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

/* ==========================================================================
   L4: SAFE-AREA INSETS on more surfaces (landscape iPhone, edge displays)
   ========================================================================== */
.app-header {
  padding-left:  max(var(--space-4), env(safe-area-inset-left, 0px));
  padding-right: max(var(--space-4), env(safe-area-inset-right, 0px));
  padding-top:   env(safe-area-inset-top, 0px);
}
.app-main {
  padding-left:  env(safe-area-inset-left, 0px);
  padding-right: env(safe-area-inset-right, 0px);
}
.toast-container {
  padding-left:  max(12px, env(safe-area-inset-left, 0px));
  padding-right: max(12px, env(safe-area-inset-right, 0px));
  padding-bottom: max(12px, env(safe-area-inset-bottom, 0px));
}
.modal,
.modal__panel {
  padding-left:  max(16px, env(safe-area-inset-left, 0px));
  padding-right: max(16px, env(safe-area-inset-right, 0px));
}

/* Forgot-password "if an account exists…" info card */
.auth__info {
  display: flex;
  gap: 8px;
  padding: 12px 14px;
  background: var(--surface-sunken);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: 13px;
  line-height: 1.5;
}

/* ==========================================================================
   Password show/hide toggle
   ========================================================================== */
.pw-toggle { position: relative; display: block; }
.pw-toggle__btn {
  position: absolute;
  top: 50%;
  right: 4px;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
  -webkit-tap-highlight-color: transparent;
}
.pw-toggle__btn:hover { color: var(--text-primary); background: var(--surface-sunken); }
.pw-toggle__btn:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.pw-toggle__btn svg { width: 18px; height: 18px; display: block; }

/* Numbered step list used in auth flows (invite, recovery) */
.auth__steps {
  margin: 0;
  padding-left: 20px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-secondary);
}
.auth__steps li { margin-bottom: 6px; }
.auth__steps strong { color: var(--text-primary); }
.auth__code {
  display: block;
  margin: 0;
  padding: 12px 14px;
  background: var(--surface-sunken);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-primary);
  white-space: pre-wrap;
  word-break: break-all;
  overflow-x: auto;
}

/* Resident pass history — "Scanned 14:32 by Powell" sub-line under used pass status */
.pass-scan-info {
  margin-top: 4px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--text-2xs);
  color: var(--color-success);
  font-weight: var(--weight-medium);
}
.pass-scan-info svg { flex: 0 0 auto; }

/* Header user-area: org name pill (multi-tenancy v49+) */
.user-area__org {
  font-size: 12px;
  color: var(--text-secondary);
  font-weight: var(--weight-medium);
  padding: 4px 10px;
  background: var(--surface-sunken);
  border: 1px solid var(--surface-border);
  border-radius: var(--radius-sm);
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.user-area__org:empty { display: none; }
@media (max-width: 767px) {
  .user-area__org { max-width: 110px; font-size: var(--text-2xs); padding: 3px 8px; }
}
/* On mobile the header now carries a brand mark + screen title on the left,
   so the right side must stay slim. The role chip is redundant (the app is
   already role-scoped, and super-admin has the yellow banner) — hide it and
   keep just the org pill + Sign out. */
@media (max-width: 1023px) {
  .user-area { gap: 8px; }
  .user-area__role { display: none; }
}
