/**
 * Admin Dashboard Styles
 * Specific styles for admin interface
 */

/* ========== Admin Header ========== */
.admin-header {
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-light));
  color: white;
  padding: var(--space-xl) 0;
  box-shadow: var(--shadow-lg);
  border-bottom: 4px solid var(--color-accent-gold);
  position: relative;
}

.admin-header::before {
  content: '';
  position: absolute;
  bottom: -4px;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, var(--color-accent-red), var(--color-accent-gold), var(--color-primary));
}

.admin-nav {
  display: flex;
  gap: var(--space-md);
  align-items: center;
}

/* Language switcher in admin header */
.admin-header .language-switcher {
  position: static;
  background: transparent;
  padding: 0;
  box-shadow: none;
  gap: var(--space-xs);
}

.admin-header .lang-btn {
  padding: var(--space-xs) var(--space-md);
  border: 2px solid rgba(255, 255, 255, 0.3);
  background: transparent;
  color: white;
  font-size: var(--font-xs);
  font-weight: 600;
  border-radius: var(--border-radius-sm);
  cursor: pointer;
  transition: all var(--duration-normal) ease;
  text-transform: uppercase;
}

.admin-header .lang-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.5);
  transform: translateY(-2px);
}

.admin-header .lang-btn.active {
  background: var(--color-accent-gold);
  color: var(--color-primary);
  border-color: var(--color-accent-gold);
  font-weight: 700;
}

.admin-nav a {
  color: white;
  text-decoration: none;
  padding: var(--space-sm) var(--space-lg);
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: var(--border-radius-md);
  transition: all var(--duration-normal) ease;
  font-weight: 600;
  backdrop-filter: blur(10px);
  font-size: var(--font-sm);
  white-space: nowrap;
}

.admin-nav a:hover {
  border-color: var(--color-accent-gold);
  background: rgba(247, 198, 8, 0.2);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.logout-btn {
  padding: var(--space-sm) var(--space-lg);
  font-size: var(--font-sm);
  font-weight: 600;
  background: transparent;
  color: white;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: var(--border-radius-md);
  cursor: pointer;
  transition: all var(--duration-normal) ease;
  white-space: nowrap;
}

.logout-btn:hover {
  border-color: var(--color-accent-red);
  background: rgba(196, 30, 58, 0.2);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.logo-container {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
}

.logo-container h1 {
  color: white;
  font-size: var(--font-2xl);
  font-weight: 700;
  margin: 0;
}

.admin-header .container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-xl);
}

/* ========== Stats Grid ========== */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space-xl);
  margin-bottom: var(--space-3xl);
  animation: fadeIn var(--duration-normal) ease-out;
}

.stat-card {
  display: flex;
  align-items: center;
  gap: var(--space-xl);
  background: linear-gradient(135deg, var(--color-bg-primary), var(--color-bg-tertiary));
  padding: var(--space-2xl);
  border-radius: var(--border-radius-lg);
  box-shadow: var(--shadow-lg);
  transition: all var(--duration-normal) cubic-bezier(0.4, 0, 0.2, 1);
  border: 2px solid var(--color-border-light);
  position: relative;
  overflow: hidden;
}

.stat-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, var(--color-accent-red), var(--color-accent-gold));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--duration-normal) ease;
}

.stat-card:hover::before {
  transform: scaleX(1);
}

.stat-card:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-xl);
  border-color: var(--color-primary-light);
}

.stat-icon {
  width: 90px;
  height: 90px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-light));
  border-radius: var(--border-radius-lg);
  color: white;
  box-shadow: var(--shadow-md);
  transition: all var(--duration-normal) ease;
  flex-shrink: 0;
}

.stat-card:hover .stat-icon {
  transform: scale(1.1) rotate(5deg);
  box-shadow: 0 8px 20px rgba(26, 43, 74, 0.3);
}

/* Style Feather icons inside stat-icon */
.stat-icon svg,
.stat-icon [data-feather] {
  width: 48px;
  height: 48px;
  stroke-width: 2.5;
}

.stat-content {
  flex: 1;
}

.stat-content h3 {
  font-size: var(--font-3xl);
  margin: 0 0 var(--space-xs) 0;
  color: var(--color-primary);
  font-weight: 700;
  line-height: 1;
}

.stat-content p {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: var(--font-base);
  font-weight: 600;
}

/* ========== Action Buttons ========== */
.action-buttons {
  display: flex;
  gap: var(--space-md);
  margin-bottom: var(--space-2xl);
  flex-wrap: wrap;
}

.btn-secondary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-md) var(--space-xl);
  font-size: var(--font-base);
  font-weight: 600;
  background: white;
  color: var(--color-primary);
  border: 2px solid var(--color-primary);
  border-radius: var(--border-radius-md);
  cursor: pointer;
  transition: all var(--duration-normal) cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: var(--shadow-sm);
}

.btn-secondary:hover {
  background: var(--color-primary);
  color: white;
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.btn-secondary:active {
  transform: translateY(0);
}

.btn-secondary:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none !important;
}

.btn-danger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-md) var(--space-xl);
  font-size: var(--font-base);
  font-weight: 600;
  background: linear-gradient(135deg, var(--color-accent-red), var(--color-accent-red-dark));
  color: white;
  border: none;
  border-radius: var(--border-radius-md);
  cursor: pointer;
  transition: all var(--duration-normal) cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: var(--shadow-md);
  position: relative;
  overflow: hidden;
}

.btn-danger::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
  transform: translate(-50%, -50%);
  transition: width var(--duration-slow) ease, height var(--duration-slow) ease;
}

.btn-danger:hover::before {
  width: 300px;
  height: 300px;
}

.btn-danger:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.btn-danger:active {
  transform: translateY(0);
}

/* ========== Table Section ========== */
.table-section {
  background: linear-gradient(135deg, var(--color-bg-primary), var(--color-bg-tertiary));
  padding: var(--space-2xl);
  border-radius: var(--border-radius-lg);
  box-shadow: var(--shadow-xl);
  border: 2px solid var(--color-border-light);
  position: relative;
  overflow: hidden;
}

.table-section::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, var(--color-primary), var(--color-accent-gold));
}

.table-section h2 {
  margin-bottom: var(--space-xl);
  color: var(--color-primary);
  font-size: var(--font-2xl);
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.table-controls {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-xl);
  gap: var(--space-lg);
  flex-wrap: wrap;
}

.filter-input {
  flex: 1;
  min-width: 280px;
  padding: var(--space-md) var(--space-lg);
  font-size: var(--font-base);
  border: 2px solid var(--color-border-light);
  border-radius: var(--border-radius-md);
  transition: all var(--duration-normal) ease;
  background: white;
}

.filter-input:hover {
  border-color: var(--color-border-medium);
}

.filter-input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: var(--shadow-focus);
  transform: translateY(-1px);
}

.table-count {
  color: var(--color-text-primary);
  font-size: var(--font-base);
  font-weight: 600;
  padding: var(--space-sm) var(--space-lg);
  background: white;
  border-radius: var(--border-radius-full);
  border: 2px solid var(--color-border-light);
}

.table-container {
  overflow-x: auto;
  margin-bottom: var(--space-xl);
  background: white;
  border-radius: var(--border-radius-md);
  box-shadow: var(--shadow-md);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-sm);
}

thead {
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-light));
  position: sticky;
  top: 0;
  z-index: 10;
}

th {
  padding: var(--space-lg) var(--space-md);
  text-align: left;
  font-weight: 700;
  color: white;
  border-bottom: 3px solid var(--color-accent-gold);
  font-size: var(--font-sm);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

tbody tr {
  border-bottom: 1px solid var(--color-border-light);
  transition: all var(--duration-fast) ease;
  background: white;
}

tbody tr:nth-child(even) {
  background: var(--color-bg-secondary);
}

tbody tr:hover {
  background: linear-gradient(90deg, var(--color-bg-tertiary), white);
  transform: scale(1.01);
  box-shadow: var(--shadow-sm);
}

td {
  padding: var(--space-lg) var(--space-md);
  color: var(--color-text-primary);
  font-size: var(--font-sm);
  vertical-align: middle;
}

td:first-child {
  font-weight: 600;
  color: var(--color-primary);
}

/* Keep the Member ID on a single line (#75) */
.responsive-table td[data-label="Member ID"] {
  white-space: nowrap;
}

.empty-state {
  text-align: center;
  padding: var(--space-3xl);
  color: var(--color-text-muted);
  background: var(--color-bg-tertiary);
  border-radius: var(--border-radius-md);
  margin: var(--space-xl);
}

.empty-state::before {
  content: '📋';
  display: block;
  font-size: var(--font-3xl);
  margin-bottom: var(--space-md);
  opacity: 0.5;
}

.action-cell {
  display: flex;
  gap: var(--space-sm);
  align-items: center;
}

/* Terminated / scheduled-for-deletion marker (template#39) */
.badge-terminated {
  display: inline-block;
  margin-left: var(--space-sm);
  padding: 1px 8px;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #fff;
  background: var(--color-danger, #c0392b);
  border-radius: 10px;
  vertical-align: middle;
}

.btn-icon {
  padding: var(--space-sm);  /* compact: fit edit+terminate+delete without overflow (template#39 follow-up) */
  background: transparent;
  border: 2px solid transparent;
  font-size: var(--font-lg);
  cursor: pointer;
  border-radius: var(--border-radius-sm);
  transition: all var(--duration-fast) ease;
  color: var(--color-text-secondary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.btn-icon:hover {
  background: var(--color-bg-tertiary);
  border-color: var(--color-primary-light);
  color: var(--color-primary);
  transform: scale(1.1);
}

.btn-icon svg {
  width: var(--icon-size-md);
  height: var(--icon-size-md);
}

.btn-link {
  color: var(--color-primary);
  text-decoration: none;
  font-weight: 600;
  transition: all var(--duration-fast) ease;
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--border-radius-sm);
}

.btn-link:hover {
  background: var(--color-bg-tertiary);
  color: var(--color-accent-red);
  text-decoration: none;
  transform: translateX(4px);
}

/* ========== Pagination - Load More ========== */
.pagination-loadmore {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-lg);
  padding: var(--space-xl) 0;
  margin-top: var(--space-lg);
}

.employee-count-display {
  font-size: var(--font-size-sm);
  color: var(--color-text-secondary);
  text-align: center;
}

.employee-count-display strong {
  color: var(--color-text-primary);
  font-weight: 600;
}

#load-more-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-md) var(--space-xl);
  background: var(--color-bg-secondary);
  border: 2px solid var(--color-border-light);
  border-radius: var(--border-radius-md);
  color: var(--color-text-primary);
  font-weight: 600;
  cursor: pointer;
  transition: all var(--duration-fast);
}

#load-more-btn:hover {
  background: var(--color-primary);
  color: white;
  border-color: var(--color-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

#load-more-btn:active {
  transform: translateY(0);
}

#load-more-btn i {
  width: 18px;
  height: 18px;
}

.load-more-spinner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  color: var(--color-text-secondary);
  font-size: var(--font-size-sm);
}

.spinner-small {
  width: 24px;
  height: 24px;
  border: 3px solid var(--color-border-light);
  border-top-color: var(--color-primary);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

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

/* ========== Modals ========== */
.modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(26, 43, 74, 0.85);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-modal);
  padding: var(--space-xl);
  animation: fadeIn var(--duration-fast) ease-out;
}

.modal-content {
  background: var(--color-bg-primary);
  border-radius: var(--border-radius-lg);
  box-shadow: var(--shadow-xl);
  width: 100%;
  max-width: 700px;
  max-height: 90vh;
  overflow-y: auto;
  animation: slideUp var(--duration-normal) cubic-bezier(0.4, 0, 0.2, 1);
  border: 2px solid var(--color-border-light);
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(30px) scale(0.95);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-xl) var(--space-2xl);
  border-bottom: 3px solid var(--color-border-light);
  background: linear-gradient(135deg, var(--color-bg-primary), var(--color-bg-tertiary));
  position: relative;
}

.modal-header::before {
  content: '';
  position: absolute;
  bottom: -3px;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--color-accent-red), var(--color-accent-gold));
}

.modal-header h2 {
  margin: 0;
  color: var(--color-primary);
  font-size: var(--font-2xl);
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

.modal-close {
  background: transparent;
  border: 2px solid transparent;
  width: 40px;
  height: 40px;
  border-radius: var(--border-radius-sm);
  font-size: var(--font-2xl);
  cursor: pointer;
  color: var(--color-text-secondary);
  transition: all var(--duration-fast) ease;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-close:hover {
  color: var(--color-accent-red);
  background: var(--color-error-light);
  border-color: var(--color-accent-red);
  transform: rotate(90deg);
}

/* ========== Forms ========== */
form {
  padding: var(--space-2xl);
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-xl);
  margin-bottom: var(--space-2xl);
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.form-group label {
  font-weight: 600;
  color: var(--color-text-primary);
  font-size: var(--font-sm);
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.form-group label .required {
  color: var(--color-accent-red);
  font-size: var(--font-lg);
}

.form-group input,
.form-group select,
.form-group textarea {
  padding: var(--space-md) var(--space-lg);
  font-size: var(--font-base);
  border: 2px solid var(--color-border-light);
  border-radius: var(--border-radius-md);
  transition: all var(--duration-normal) ease;
  background: white;
}

.form-group input:hover,
.form-group select:hover,
.form-group textarea:hover {
  border-color: var(--color-border-medium);
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: var(--shadow-focus);
  transform: translateY(-1px);
}

.form-group input.error,
.form-group select.error,
.form-group textarea.error {
  border-color: var(--color-error);
  background: var(--color-error-light);
}

.field-help {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--font-sm);
}

.form-group .error-message {
  color: var(--color-error);
  font-size: var(--font-sm);
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  animation: shake var(--duration-fast) ease;
}

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px); }
  75% { transform: translateX(5px); }
}

.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-lg);
  padding-top: var(--space-2xl);
  border-top: 3px solid var(--color-border-light);
}

.form-actions button {
  flex-shrink: 0;
  white-space: nowrap;
}

.form-actions .btn-secondary {
  padding: var(--space-sm) var(--space-md);
  font-size: 14px;
}

/* ========== CSV Import ========== */
.csv-instructions {
  padding: 24px 32px;
  background: var(--color-bg-tertiary);
  border-left: 4px solid var(--color-primary);
  margin: 0 32px 24px 32px;
}

.csv-instructions h3 {
  margin-bottom: 12px;
  color: var(--color-primary);
}

.csv-instructions code {
  display: block;
  background: white;
  padding: 12px;
  border-radius: 4px;
  margin: 12px 0;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  overflow-x: auto;
}

.csv-instructions .note {
  margin-top: 12px;
  font-size: 14px;
  color: var(--color-text-secondary);
}

.csv-preview {
  margin: 24px 0;
  padding: 16px;
  background: var(--color-bg-tertiary);
  border-radius: var(--border-radius-sm);
}

.csv-preview pre {
  overflow-x: auto;
  font-size: 12px;
  font-family: 'Courier New', monospace;
}

.import-progress {
  padding: 32px;
}

.progress-bar {
  width: 100%;
  height: 40px;
  background: var(--color-bg-tertiary);
  border-radius: var(--border-radius-full);
  overflow: hidden;
  margin: var(--space-xl) 0;
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.1);
  border: 2px solid var(--color-border-light);
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--color-primary), var(--color-accent-gold), var(--color-accent-green));
  background-size: 200% 100%;
  animation: gradientShift 2s ease infinite;
  transition: width var(--duration-slow) cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 0 20px rgba(26, 43, 74, 0.3);
  position: relative;
}

.progress-fill::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
  animation: shimmer 1.5s infinite;
}

@keyframes gradientShift {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}

@keyframes shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

#progress-text {
  text-align: center;
  font-weight: 600;
  color: var(--color-text-primary);
}

.import-summary {
  background: var(--color-bg-tertiary);
  padding: 20px;
  border-radius: var(--border-radius-sm);
  margin-top: 20px;
}

.import-summary h4 {
  margin-bottom: 12px;
  color: var(--color-primary);
}

.import-summary p {
  margin: 8px 0;
}

.import-summary .success {
  color: var(--success-color);
}

.import-summary .warning {
  color: var(--accent-color);
}

.import-summary .error {
  color: var(--error-color);
}

.error-list {
  max-height: 200px;
  overflow-y: auto;
  padding-left: 20px;
  margin-top: 12px;
}

.error-list li {
  color: var(--error-color);
  margin: 8px 0;
  font-size: 14px;
}

/* ========== Toast Notifications ========== */
.toast-container {
  position: fixed;
  top: var(--space-2xl);
  right: var(--space-2xl);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  max-width: 400px;
}

.toast {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-lg) var(--space-xl);
  background: white;
  border-radius: var(--border-radius-md);
  box-shadow: var(--shadow-xl);
  border-left: 4px solid var(--color-primary);
  animation: slideInRight var(--duration-normal) cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  overflow: hidden;
}

.toast.success {
  border-left-color: var(--color-success);
}

.toast.error {
  border-left-color: var(--color-error);
}

.toast.warning {
  border-left-color: var(--color-warning);
}

.toast.info {
  border-left-color: var(--color-info);
}

@keyframes slideInRight {
  from {
    opacity: 0;
    transform: translateX(100%);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.toast-icon {
  width: var(--icon-size-xl);
  height: var(--icon-size-xl);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--color-bg-tertiary);
}

.toast.success .toast-icon {
  background: var(--color-success-light);
  color: var(--color-success);
}

.toast.error .toast-icon {
  background: var(--color-error-light);
  color: var(--color-error);
}

.toast.warning .toast-icon {
  background: var(--color-warning-light);
  color: var(--color-warning);
}

.toast.info .toast-icon {
  background: var(--color-info-light);
  color: var(--color-info);
}

.toast-content {
  flex: 1;
}

.toast-title {
  font-weight: 700;
  font-size: var(--font-base);
  color: var(--color-text-primary);
  margin-bottom: var(--space-xs);
}

.toast-message {
  font-size: var(--font-sm);
  color: var(--color-text-secondary);
  line-height: var(--line-height-normal);
  /* The bulk delete/resend summaries are multi-line (#110). Toast text is set
     with textContent, so newlines only survive if the CSS preserves them. */
  white-space: pre-line;
}

.toast-close {
  background: transparent;
  border: none;
  width: 32px;
  height: 32px;
  border-radius: var(--border-radius-sm);
  cursor: pointer;
  color: var(--color-text-secondary);
  transition: all var(--duration-fast) ease;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.toast-close:hover {
  background: var(--color-bg-tertiary);
  color: var(--color-text-primary);
}

.toast-progress {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 4px;
  background: currentColor;
  opacity: 0.3;
  animation: toastProgress 5s linear forwards;
}

@keyframes toastProgress {
  from {
    width: 100%;
  }
  to {
    width: 0%;
  }
}

/* ========== Checkbox Styling ========== */
.checkbox-cell input[type="checkbox"] {
  width: 20px;
  height: 20px;
  cursor: pointer;
  accent-color: var(--color-primary);
  border-radius: var(--border-radius-xs);
}

/* ========== Loading State for Buttons ========== */
.btn-primary.loading,
.btn-secondary.loading,
.btn-danger.loading {
  position: relative;
  color: transparent;
  pointer-events: none;
}

.btn-primary.loading::after,
.btn-secondary.loading::after,
.btn-danger.loading::after {
  content: '';
  position: absolute;
  width: 20px;
  height: 20px;
  top: 50%;
  left: 50%;
  margin-left: -10px;
  margin-top: -10px;
  border: 3px solid rgba(255, 255, 255, 0.3);
  border-top-color: white;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

.btn-secondary.loading::after {
  border-color: rgba(26, 43, 74, 0.3);
  border-top-color: var(--color-primary);
}

/* ========== Responsive Design ========== */

/* Tablet */
@media (max-width: 1024px) {
  .stats-grid {
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  }

  .action-buttons {
    gap: var(--space-sm);
  }
}

/* Mobile */
@media (max-width: 768px) {
  .admin-header {
    padding: var(--space-md) 0;
  }

  .admin-header .container {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-lg);
  }

  .logo-container {
    gap: var(--space-md);
  }

  .logo-container h1 {
    font-size: var(--font-xl);
  }

  .admin-nav {
    flex-wrap: wrap;
    gap: var(--space-sm);
    width: 100%;
  }

  .admin-nav a,
  .logout-btn {
    font-size: var(--font-xs);
    padding: var(--space-xs) var(--space-md);
  }

  .admin-header .lang-btn {
    padding: 6px var(--space-sm);
    font-size: 11px;
  }

  .form-grid {
    grid-template-columns: 1fr;
    gap: var(--space-md);
  }

  .stats-grid {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
  }

  .stat-card {
    padding: var(--space-lg);
  }

  .stat-icon {
    width: 70px;
    height: 70px;
  }

  .stat-icon svg,
  .stat-icon [data-feather] {
    width: 36px;
    height: 36px;
  }

  .table-section {
    padding: var(--space-lg);
  }

  /* Responsive card layout (#75): below 768px each row becomes a labelled
     card instead of a cramped horizontally-scrolling table. */
  .table-container {
    overflow-x: visible;
    font-size: var(--font-sm);
    box-shadow: none;
    background: transparent;
  }

  .responsive-table thead {
    /* visually hidden but kept for accessibility */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }

  .responsive-table,
  .responsive-table tbody,
  .responsive-table tr,
  .responsive-table td {
    display: block;
    width: 100%;
  }

  .responsive-table tr {
    margin-bottom: var(--space-md);
    padding: var(--space-sm) var(--space-md);
    border: 1px solid var(--color-border-light);
    border-radius: var(--border-radius-md);
    background: white;
    box-shadow: var(--shadow-sm);
  }

  .responsive-table tr:hover {
    transform: none;  /* no scale on cards */
  }

  .responsive-table td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-sm) 0;
    border-bottom: 1px solid var(--color-border-light);
    text-align: right;
  }

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

  /* Column label on the left of each cell */
  .responsive-table td::before {
    content: attr(data-label);
    font-weight: 700;
    text-transform: uppercase;
    font-size: var(--font-xs);
    letter-spacing: 0.5px;
    color: var(--color-text-secondary);
    text-align: left;
  }

  /* The row-select checkbox and the actions cell don't need a label */
  .responsive-table td.cell-select {
    justify-content: flex-end;
  }
  .responsive-table td.cell-select::before,
  .responsive-table td.cell-actions::before {
    content: "";
  }
  /* Action buttons must wrap, not overflow. The cell aligns to flex-end, so
     anything that does not fit pushes out to the LEFT — off-screen, where no
     amount of scrolling reaches it. On a phone the three buttons on an event
     row (Bewerken / Scanners / Archiveren) are wider than the card, and the
     first one was simply gone. */
  .responsive-table td.cell-actions {
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: var(--space-xs);
  }

  .row-actions {
    /* Overrides the nowrap that keeps these on one line on a desktop table. */
    white-space: normal;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--space-xs);
  }

  /* gap handles the spacing now; the sibling margin would double it. */
  .row-actions .btn + .btn {
    margin-left: 0;
  }

  /* Nothing in the toolbar may be wider than the toolbar. min-width on the
     event selector wins over the flex basis on a narrow screen and pushed the
     select, the count and the export button a few pixels past the card edge,
     where they were clipped. */
  .table-controls > * {
    max-width: 100%;
  }

  .filter-input {
    min-width: 0;
  }

  .modal {
    padding: var(--space-md);
  }

  .modal-content {
    max-width: 100%;
    max-height: 95vh;
  }

  .modal-header,
  form {
    padding: var(--space-lg);
  }

  .action-cell {
    flex-direction: row;
    justify-content: center;
  }

  .action-buttons {
    flex-direction: column;
  }

  .action-buttons button {
    width: 100%;
    justify-content: center;
  }

  .toast-container {
    top: var(--space-md);
    right: var(--space-md);
    left: var(--space-md);
    max-width: none;
  }

  .toast {
    padding: var(--space-md) var(--space-lg);
  }
}

/* Small mobile */
@media (max-width: 480px) {
  .stat-card {
    flex-direction: column;
    text-align: center;
  }

  .table-controls {
    flex-direction: column;
    align-items: stretch;
  }

  .filter-input {
    min-width: 100%;
  }

  .pagination {
    flex-direction: column;
    gap: var(--space-sm);
  }
}

/* ========== Events / scanners / attendance admin (template#67, #68) ========== */
.btn-small {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-xs) var(--space-md);
  font-size: var(--font-sm);
  font-weight: 600;
  background: white;
  color: var(--color-primary);
  border: 2px solid var(--color-primary);
  border-radius: var(--border-radius-sm);
  cursor: pointer;
  transition: all var(--duration-fast) ease;
}

.btn-small:hover {
  background: var(--color-primary);
  color: white;
}

/* Armed state of a two-click confirm button (#198) -- e.g. "resend attest",
   after the first click and before the second. No browser dialogs: the
   button itself carries the confirmation state instead. */
.btn-small.confirm-pending {
  background: var(--color-error);
  color: white;
  border-color: var(--color-error);
}

/* Generic inline error banner for a modal form (server-side / general
   failures) - kept separate from the required-field .error-message so a
   400 doesn't have to be pinned to a specific input. */
.form-error-banner {
  display: none;
  align-items: center;
  gap: var(--space-sm);
  margin-bottom: var(--space-lg);
  padding: var(--space-md) var(--space-lg);
  background: var(--color-error-light);
  border: 2px solid var(--color-error);
  border-radius: var(--border-radius-md);
  color: var(--color-error);
  font-weight: 600;
  font-size: var(--font-sm);
}

.form-error-banner.visible {
  display: flex;
}

/* Bulk action bar for attendance reassignment - shown only while at least
   one row is selected, same show/hide-via-style convention as the employee
   bulk action buttons in admin.js. */
.bulk-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
  padding: var(--space-md) var(--space-lg);
  background: var(--color-bg-tertiary);
  border: 2px solid var(--color-border-light);
  border-radius: var(--border-radius-md);
}

.bulk-bar-count {
  font-weight: 600;
  color: var(--color-text-primary);
}

.bulk-bar select {
  padding: var(--space-sm) var(--space-md);
  border: 2px solid var(--color-border-light);
  border-radius: var(--border-radius-sm);
  font-size: var(--font-sm);
}

/* Outcome banner for a bulk reassignment. Same layout as .form-error-banner
   but with success/warning/error variants, since the result is per-item and
   is not always a failure. */
.bulk-summary-banner {
  display: none;
  align-items: center;
  gap: var(--space-sm);
  margin-bottom: var(--space-lg);
  padding: var(--space-md) var(--space-lg);
  border-radius: var(--border-radius-md);
  font-weight: 600;
  font-size: var(--font-sm);
}

.bulk-summary-banner.visible {
  display: flex;
}

.bulk-summary-banner.success {
  background: var(--color-success-light);
  border: 2px solid var(--color-success);
  color: var(--color-success);
}

.bulk-summary-banner.warning {
  background: var(--color-warning-light);
  border: 2px solid var(--color-warning);
  color: var(--color-text-primary);
}

.bulk-summary-banner.error {
  background: var(--color-error-light);
  border: 2px solid var(--color-error);
  color: var(--color-error);
}

/* Attest engine (#58) send-time control, at the top of the Attendance
   section since that's where attesten conceptually belong. Reuses
   .form-error-banner / .bulk-summary-banner for inline feedback so a failed
   save reads the same way every other inline error does on this page. */
.attest-settings {
  margin-bottom: var(--space-xl);
  padding: var(--space-lg);
  background: var(--color-bg-tertiary);
  border: 2px solid var(--color-border-light);
  border-radius: var(--border-radius-md);
}

.attest-settings h3 {
  margin: 0 0 var(--space-md);
  color: var(--color-primary);
  font-size: var(--font-base);
  font-weight: 700;
}

.attest-settings-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-md);
}

.attest-settings-row input[type="time"] {
  padding: var(--space-sm) var(--space-md);
  border: 2px solid var(--color-border-light);
  border-radius: var(--border-radius-sm);
  font-size: var(--font-sm);
}

.attest-timezone-label {
  color: var(--color-text-secondary);
  font-size: var(--font-sm);
}

.attest-settings-help {
  margin: var(--space-md) 0 0;
  color: var(--color-text-muted);
  font-size: var(--font-sm);
}

.attest-settings #attest-settings-error,
.attest-settings #attest-settings-success {
  margin-top: var(--space-md);
  margin-bottom: 0;
}

/* Scanner secret display: shown once, unrecoverable afterwards */
.secret-body {
  padding: var(--space-2xl);
}

.secret-warning {
  color: var(--color-error);
  font-weight: 600;
  margin: 0 0 var(--space-lg) 0;
}

.secret-display {
  display: flex;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
}

.secret-display input {
  flex: 1;
  padding: var(--space-md) var(--space-lg);
  font-family: var(--font-family-mono);
  font-size: var(--font-base);
  border: 2px solid var(--color-border-light);
  border-radius: var(--border-radius-md);
  background: var(--color-bg-tertiary);
  color: var(--color-text-primary);
}

/* Badge marking a receipt-derived (not on-device) attendance timestamp */
.badge-source {
  display: inline-block;
  margin-left: var(--space-xs);
  padding: 1px 8px;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  background: var(--color-bg-tertiary);
  border: 1px solid var(--color-border-light);
  border-radius: 10px;
  vertical-align: middle;
  cursor: help;
}

/* Repeated scans on the attendance page (#196). Always shown once an action
   is selected -- .repeats-none is the "nothing to report" state, visible on
   purpose so the feature does not read as absent the way a count that only
   appeared for n > 0 did (the ACCG feedback this issue is from). */
.repeats-section {
  margin: 0 var(--space-xl) var(--space-xl);
}

.repeats-none {
  display: inline-block;
  color: var(--color-text-muted);
  font-size: var(--font-sm);
  padding: var(--space-sm) 0;
}

.repeats-toggle {
  display: inline-block;
  background: none;
  border: none;
  cursor: pointer;
  font-size: var(--font-sm);
}

.repeats-panel {
  margin-top: var(--space-sm);
}

/* Page navigation across Events / Scanners / Attendance (#87). The active
   page needs to be visually distinct or the nav reads as three identical
   links and gives no sense of place. */
.nav-link {
  padding: 0.4rem 0.85rem;
  border-radius: 4px;
  text-decoration: none;
  color: inherit;
}

.nav-link:hover {
  background: rgba(0, 0, 0, 0.06);
}

.nav-link.active {
  background: var(--color-primary, #1a2b4a);
  color: #fff;
  font-weight: 600;
}

/* Full-width message row inside a table body (#110). Used for the three
   states a blank table cannot distinguish: loading, empty, and failed. */
.table-message {
  padding: var(--space-xl);
  text-align: center;
  color: var(--color-text-secondary);
  font-size: var(--font-sm);
}

/* Archived events (#108): kept in the table for unarchiving, visually
   demoted so live events dominate the list. */
.event-archived td,
.scanner-revoked td {
  opacity: 0.55;
}

.badge-archived,
.badge-revoked {
  display: inline-block;
  padding: 1px 8px;
  margin-left: var(--space-xs);
  font-size: var(--font-xs);
  font-weight: 600;
  border-radius: var(--border-radius-full);
  background: var(--color-border-light);
  color: var(--color-text-secondary);
  vertical-align: middle;
}

/* Inherited (screen-default) attest send time reads quieter than an
   explicit per-event override (#108). */
/* The per-action filter sits under its heading rather than in a toolbar, so
   it does not inherit .table-controls' flex sizing and needs its own width. */
.dash-filter {
  width: 100%;
  min-width: 0;
  margin-bottom: var(--space-md);
}

.attest-inherited {
  color: var(--color-text-secondary);
  font-style: italic;
}

/* An action that issues no attest at all (#156). Deliberately not italic:
   "no attest is sent" must not read as another shade of "inherited default"
   — they are different facts, and the old cell showed a send time for both. */
.attest-none {
  color: var(--color-text-secondary);
  opacity: 0.7;
}

.row-actions {
  white-space: nowrap;
}

.row-actions .btn + .btn {
  margin-left: var(--space-xs);
}

/* 44px touch-target floor for row action icons on touch layouts (#115).
   Desktop keeps the compact 40px (a deliberate overflow fix, see .btn-icon);
   under 768px real estate is vertical anyway, so the bigger target costs
   nothing. */
@media (max-width: 768px) {
  .btn-icon {
    padding: 10px;
  }
}

/* Card-layout helpers shared by all responsive tables (#115): action cells
   and select-checkbox cells carry no data-label, so they get no leading
   label and align right like the employees table's originals. */

/* Event name in the events table links to that event's attendance (#113).
   Styled as an explicit link — an undecorated cell gives no hint it's the
   route to the page secretaries need most. */
.event-attendance-link {
  color: var(--color-primary);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.event-attendance-link:hover {
  color: var(--color-accent-gold);
}

/* Locatie can run long (venue + street + room), and a five-word address was
   part of what pushed the events table past 1280px (#266). Ellipsis with
   the full value in `title` instead of pushing the row wider. Scoped to the
   desktop table only -- the mobile card layout below 768px already gives
   each cell its own line, where truncating would just hide text a touch
   user has no hover to recover. */
@media (min-width: 769px) {
  .responsive-table td.cell-location {
    max-width: 220px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
}

/* ==========================================================================
   Events calendar (#132)

   Desktop: a seven-column month grid, fixed at six rows so paging between
   months does not make the page jump.

   Phone: the same DOM restyles into an agenda list — a 7-column grid at
   390px is unusable. Days without events are hidden rather than rendered as
   empty rows, so the list reads as "what is on this month".
   ========================================================================== */

.view-tabs {
  display: inline-flex;
  gap: 0;
  border: 2px solid var(--color-border-light);
  border-radius: var(--border-radius-md);
  overflow: hidden;
}

.view-tab {
  padding: var(--space-sm) var(--space-lg);
  background: white;
  border: none;
  cursor: pointer;
  font-weight: 600;
  font-size: var(--font-sm);
  color: var(--color-text-secondary);
}

.view-tab.active {
  background: var(--color-primary);
  color: white;
}

.calendar-header {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-lg);
  margin-bottom: var(--space-lg);
}

.calendar-header h3 {
  min-width: 12rem;
  text-align: center;
  color: var(--color-primary);
  font-size: var(--font-xl);
}

.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  background: var(--color-border-light);
  border: 1px solid var(--color-border-light);
  border-radius: var(--border-radius-md);
  overflow: hidden;
}

.calendar-weekday {
  background: var(--color-bg-tertiary);
  padding: var(--space-sm);
  text-align: center;
  font-size: var(--font-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-text-secondary);
}

.calendar-day {
  background: white;
  min-height: 6.5rem;
  padding: var(--space-sm);
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.calendar-day.out-of-month {
  background: var(--color-bg-secondary);
}

.calendar-day.out-of-month .calendar-daynum {
  opacity: 0.4;
}

.calendar-day.is-today {
  box-shadow: inset 0 0 0 2px var(--color-accent-gold);
}

.calendar-daynum {
  font-size: var(--font-xs);
  font-weight: 700;
  color: var(--color-text-secondary);
}

.calendar-event {
  display: block;
  padding: 2px var(--space-xs);
  border-radius: var(--border-radius-sm);
  background: var(--color-primary);
  color: white;
  font-size: var(--font-xs);
  font-weight: 600;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.calendar-event:hover {
  background: var(--color-accent-gold);
  color: var(--color-text-primary);
}

.calendar-event.archived {
  background: var(--color-border-light);
  color: var(--color-text-secondary);
}

/* The whole empty area of a day is the "create here" target. It carries no
   text, so it is exposed to assistive tech through its aria-label only. */
.calendar-newday {
  margin-top: auto;
  border: none;
  background: transparent;
  cursor: pointer;
  min-height: 1.5rem;
  border-radius: var(--border-radius-sm);
}

.calendar-newday:hover {
  background: var(--color-bg-tertiary);
}

.calendar-empty {
  display: none;
}

@media (max-width: 768px) {
  .calendar-grid {
    grid-template-columns: 1fr;
    gap: 0;
    background: transparent;
    border: none;
  }

  /* Weekday headers and empty days mean nothing in a list. */
  .calendar-weekday,
  .calendar-day:not(.has-events) {
    display: none;
  }

  .calendar-day {
    min-height: 0;
    flex-direction: row;
    align-items: center;
    gap: var(--space-md);
    border-bottom: 1px solid var(--color-border-light);
    padding: var(--space-md) var(--space-sm);
  }

  .calendar-day.out-of-month {
    background: white;
  }

  .calendar-daynum {
    min-width: 3.5rem;
    font-size: var(--font-sm);
  }

  .calendar-event {
    white-space: normal;
  }

  /* Creating an event by tapping blank space does not survive the collapse
     to a list — the New event button is right there instead. */
  .calendar-newday {
    display: none;
  }

  /* With every empty day hidden, a month with no events would render as
     nothing at all. Shown only when the month really is empty — the grid
     carries `is-empty` for exactly that case, otherwise this line would
     appear under every month regardless of content. */
  .calendar-grid.is-empty .calendar-empty {
    display: block;
    padding: var(--space-xl);
    text-align: center;
    color: var(--color-text-secondary);
  }
}

/* ==========================================================================
   Dashboard (#131)

   Both charts carry a single series, so there is no legend and no
   categorical palette — the panel heading names the series. Marks use the
   brand navy (14.1:1 on white). The brand gold is deliberately absent from
   data marks: at 1.6:1 it cannot carry meaning.
   ========================================================================== */

.dash-row {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: var(--space-xl);
  margin-top: var(--space-xl);
}

.dash-panel {
  min-width: 0; /* let the grid shrink the chart rather than overflow */
}

.chart-svg {
  width: 100%;
  height: auto;
}

.chart-grid {
  stroke: var(--color-border-light);
  stroke-width: 1;
}

.chart-axis {
  fill: var(--color-text-secondary);
  font-size: 11px;
}

.chart-value {
  fill: var(--color-text-primary);
  font-size: 11px;
  font-weight: 700;
}

.chart-bar path {
  fill: var(--color-primary);
}

.chart-bar:hover path {
  fill: var(--color-primary-light);
}

.chart-empty {
  padding: var(--space-xl);
  text-align: center;
  color: var(--color-text-secondary);
}

.rowchart {
  list-style: none;
  margin: 0;
  padding: 0;
}

.rowchart li {
  display: grid;
  /* Action names run long and share prefixes — two rows both reading
     "Militantenvergadering …" are indistinguishable, which defeats the point
     of filtering by name. Give the label room to reach the city that
     actually tells them apart, and let the bar take what is left. */
  grid-template-columns: minmax(10rem, 18rem) 1fr 3rem;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-xs) 0;
}

.rowchart-label {
  overflow: hidden;
  text-overflow: ellipsis;
  /* Two lines before truncating: the distinguishing part of an action name is
     the city at the end, and one line rarely reaches it. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  white-space: normal;
  overflow-wrap: anywhere;
  font-size: var(--font-sm);
  line-height: 1.3;
}

.rowchart-track {
  background: var(--color-bg-secondary);
  border-radius: var(--border-radius-sm);
  height: 1.25rem;
}

.rowchart-fill {
  display: block;
  height: 100%;
  background: var(--color-primary);
  border-radius: 0 4px 4px 0;
}

.rowchart-value {
  text-align: right;
  font-weight: 700;
  font-size: var(--font-sm);
}

.attention-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.attention-item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md) 0;
  border-bottom: 1px solid var(--color-border-light);
}

.attention-icon {
  font-size: var(--font-lg);
}

.attention-warning .attention-icon { color: var(--color-accent-gold-dark); }
.attention-serious .attention-icon { color: var(--color-accent-red); }

.attention-count {
  font-weight: 700;
}

.attention-clear {
  padding: var(--space-lg) 0;
  color: var(--color-text-secondary);
}

.upcoming-name { font-size: var(--font-lg); font-weight: 700; }
.upcoming-date { color: var(--color-text-secondary); }

/* Six KPIs (#138 added createdToday and last30Days to the original four),
   not the three the shared .stats-grid assumes — without this the grid's
   auto-fit would wrap unevenly and leave part of a row empty. Three columns
   reads as two logical rows: members/createdToday/events, then
   scans/last30Days/avgPerEvent. */
#dash-kpis {
  grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 1100px) {
  .dash-row {
    grid-template-columns: 1fr;
  }

  #dash-kpis {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 640px) {
  #dash-kpis {
    grid-template-columns: 1fr;
  }
}

/* A note inside a picker: informational or cautionary, never an error.
   These previously reused .form-error-banner, which painted an ordinary
   "this device will move" advisory in alarm red. */
.picker-note {
  margin: 0 0 var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--border-radius-md);
  font-size: var(--font-sm);
  color: var(--color-text-primary);
  background: var(--color-bg-secondary);
  border-left: 3px solid var(--color-border-medium);
}

.picker-note-warning {
  background: var(--color-warning-light);
  border-left-color: var(--color-accent-gold-dark);
}

/* ==========================================================================
   Scanner picker — "Scanners at this action" (#133)

   A scanner has exactly one assignment, so checking one that is currently at
   another action moves it. The current location is shown on every row so
   that is a visible choice rather than a silent theft of someone's device.
   ========================================================================== */

.scanner-picker {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  max-height: 22rem;
  overflow-y: auto;
}

.scanner-pick {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md);
  border: 1px solid var(--color-border-light);
  border-radius: var(--border-radius-md);
}

.scanner-pick input[type="checkbox"] {
  width: 20px;
  height: 20px;
}

.scanner-pick-name {
  font-weight: 600;
}

.scanner-pick-where {
  font-size: var(--font-sm);
  color: var(--color-text-secondary);
  text-align: right;
}

/* A device that would be taken from another action — the one case where
   saving has a side effect somewhere the operator is not looking. */
.scanner-pick.will-move {
  border-color: var(--color-accent-gold-dark);
  background: var(--color-warning-light);
}

.scanner-picker-empty {
  padding: var(--space-lg);
  text-align: center;
  color: var(--color-text-secondary);
}

/* ==========================================================================
   Assignment list — read-only, on the Scanners page's own table (#265)

   Assignment used to be writable from here too (the removed Assign modal,
   #159), which is why this class name survives even though the row/Remove
   styling that went with it does not. What's left is purely a redraw of
   what a device is booked for, inside its own table-cell.
   ========================================================================== */

.assignment-list-readonly {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  font-size: var(--font-sm);
}

.assignment-list-empty-inline {
  color: var(--color-text-secondary);
  font-size: var(--font-sm);
}

/* ==========================================================================
   Responsive navigation

   Six destinations + Logout does not fit one row on a 1280px laptop. The
   previous rules only wrapped below 768px, so everything between roughly
   769px and 1400px ran off the right edge.

   The numbers that drive this (measured with __nav-harness.html, Dutch
   labels — the widest of the three languages): the header .container caps at
   1200px; the logo block takes 296px and padding 48px, leaving ~840px for
   the nav. Full-size links + Logout need 936px — A SINGLE FULL-SIZE ROW CAN
   NEVER FIT, at any viewport. So above the breakpoint links are always
   compact (924px→776px via smaller padding/gap), which fits the 840px, and
   the language switcher wraps to its own small right-aligned row beneath.
   Below 1200px the panel itself may wrap to a second tidy row of links —
   wrapping, never overflowing, is the degradation for long translations or
   a seventh destination.

   At 1100px and below, links + Logout collapse behind a toggle. The language
   switcher stays OUT of the panel and visible beside the toggle at every
   width: switching language is how someone recovers from a screen shown in
   the wrong language, so it must never hide behind a menu labelled in that
   language.

   DOM order is [switcher, toggle, panel] (nav.js appends the panel last and
   inserts the toggle before it); the flex `order` below puts the panel first
   on desktop and last — full-width, under the toggle row — when collapsed.
   ========================================================================== */

.nav-panel {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  order: 1;
  /* Safety net above the breakpoint: wrap rather than overflow if a
     translation is long or a destination is added. */
  flex-wrap: wrap;
  justify-content: flex-end;
}

.admin-nav > .language-switcher {
  order: 2;
}

/* Hidden above the breakpoint; the panel is simply a flex row there. */
.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;   /* 44px is the touch-target floor (#115) */
  height: 44px;
  padding: 0 10px;
  background: transparent;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: var(--border-radius-md);
  cursor: pointer;
  order: 3;
  transition: border-color var(--duration-normal) ease;
}

.nav-toggle:hover,
.nav-toggle:focus-visible {
  border-color: var(--color-accent-gold);
}

.nav-toggle span {
  display: block;
  height: 2px;
  background: white;
  border-radius: 1px;
}

/* Compact links whenever the nav renders as a row (see the width math in
   the header comment — full-size never fits the 1200px container). min-width
   scopes this away from the collapsed panel, whose full-width rows keep
   comfortable touch targets. */
@media (min-width: 1101px) {
  .nav-panel .nav-link,
  .nav-panel .logout-btn {
    padding: var(--space-sm) var(--space-md);
  }

  .nav-panel {
    gap: var(--space-sm);
    /* Claim the row: all links + Logout on one line, the switcher wraps to
       its own small line below. max-width keeps the panel's own internal
       wrap as the fallback if the labels outgrow the container. */
    flex-shrink: 0;
    max-width: 100%;
  }

  .admin-nav {
    flex-wrap: wrap;
    justify-content: flex-end;
  }
}

@media (max-width: 1100px) {
  .admin-header .container {
    /* Keep the logo and the toggle on one line; the panel drops below. */
    flex-wrap: wrap;
    gap: var(--space-md);
  }

  .nav-toggle {
    display: flex;
  }

  .nav-panel {
    /* Not `display: none` in spirit — the panel must keep its flex layout
       when open so revealing it is a single class change, and screen
       readers reach it via aria-controls/aria-expanded on the toggle. */
    display: none;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: var(--space-sm);
    padding-top: var(--space-md);
    order: 4;
  }

  .admin-nav.nav-open .nav-panel {
    display: flex;
  }

  .admin-nav {
    /* The nav owns the full row so the panel can stack under the toggle. */
    flex-wrap: wrap;
    width: 100%;
    justify-content: flex-end;
    align-items: center;
  }

  .nav-panel .nav-link,
  .nav-panel .logout-btn {
    /* Full-width rows read as a menu rather than as stray buttons. */
    display: block;
    width: 100%;
    text-align: left;
  }
}

/* The 768px block below already shrinks type and padding; it now only needs
   to stop the header container forcing a column, which would put the toggle
   on its own line. */
@media (max-width: 768px) {
  .admin-header .container {
    flex-direction: row;
    align-items: center;
    flex-wrap: wrap;
  }
}

/* ---------- Date/time picker (#169) ---------- */
/* The field stays a text input in DD/MM/YYYY HH:MM — see datetime-picker.js
   for why a native control cannot be used. These styles dress the calendar
   button and the popup that opens beside it. */

.dtp-field {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 0.35rem;
}

/* The input keeps the form's own sizing; only the button is added beside it. */
.dtp-field > input {
  flex: 1 1 auto;
  min-width: 0;
}

.dtp-toggle {
  flex: 0 0 auto;
  padding: 0 0.6rem;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  background: var(--color-bg-secondary);
  border: 1px solid var(--color-border, #d5dbe1);
  border-radius: 4px;
  color: var(--color-text-secondary);
}

.dtp-toggle:hover { background: var(--color-bg-primary); }
.dtp-toggle:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 1px; }

.dtp-popup {
  position: absolute;
  top: calc(100% + 0.3rem);
  left: 0;
  z-index: 60; /* above the modal body, below nothing else on the page */
  width: max-content;
  padding: 0.7rem;
  background: var(--color-bg-primary);
  border: 1px solid var(--color-border, #d5dbe1);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
}

.dtp-popup[hidden] { display: none; }

.dtp-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.dtp-title {
  font-weight: 600;
  color: var(--color-text-primary);
  text-transform: capitalize; /* Intl yields lowercase month names in nl/fr */
}

.dtp-prev,
.dtp-next {
  padding: 0.1rem 0.5rem;
  font-size: 1.1rem;
  line-height: 1.4;
  cursor: pointer;
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  color: var(--color-text-secondary);
}

.dtp-prev:hover,
.dtp-next:hover { background: var(--color-bg-secondary); }

.dtp-grid {
  display: grid;
  grid-template-columns: repeat(7, 2.1rem);
  gap: 2px;
}

.dtp-weekday {
  padding: 0.2rem 0;
  font-size: 0.72rem;
  text-align: center;
  color: var(--color-text-muted);
  text-transform: uppercase;
}

.dtp-day {
  padding: 0.35rem 0;
  font: inherit;
  font-size: 0.86rem;
  font-variant-numeric: tabular-nums;
  text-align: center;
  cursor: pointer;
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  color: var(--color-text-primary);
}

.dtp-day:hover { background: var(--color-bg-secondary); }
.dtp-day:focus-visible { outline: 2px solid var(--color-primary); outline-offset: -2px; }
.dtp-out { color: var(--color-text-muted); }
/* Today is outlined, the selection is filled — so both can show at once. */
.dtp-today { border-color: var(--color-text-muted); }
.dtp-selected {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-text-inverse);
}
.dtp-selected:hover { background: var(--color-primary-light); }

.dtp-time {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin-top: 0.6rem;
}

.dtp-time select {
  padding: 0.3rem 0.4rem;
  font: inherit;
  font-variant-numeric: tabular-nums;
  border: 1px solid var(--color-border, #d5dbe1);
  border-radius: 4px;
}

.dtp-colon { color: var(--color-text-secondary); }

.dtp-actions {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.7rem;
}

.dtp-clear,
.dtp-done {
  padding: 0.3rem 0.7rem;
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
  border: 1px solid var(--color-border, #d5dbe1);
  border-radius: 4px;
  background: var(--color-bg-secondary);
  color: var(--color-text-secondary);
}

.dtp-done {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-text-inverse);
}

/* On a phone the popup would otherwise run off the right edge of a field
   sitting in the second column of the form grid. */
@media (max-width: 600px) {
  .dtp-popup { left: auto; right: 0; }
  .dtp-grid { grid-template-columns: repeat(7, 2.4rem); }
}
