/* Motion51 App - Custom CSS
   Built on top of Pico CSS framework
   Mobile-first responsive design
*/

:root {
  /* Campaign color palette */
  --success: #22c55e;
  --warning: #eab308;
  --danger: #ef4444;
  --info: #3b82f6;
  --neutral: #6b7280;

  /* Extended campaign colors */
  --strong-support: #15803d;
  --lean-support: #4ade80;
  --undecided: #fbbf24;
  --lean-against: #fca5a5;
  --strong-against: #991b1b;
  --not-home: #9ca3af;
  --refused: #374151;
  --wrong-address: #fb923c;
  --moved: #f97316;
  --deceased: #000000;
  --no-answer: #64748b;
  --wrong-number: #a855f7;
  --do-not-call: #7f1d1d;

  /* Spacing */
  --spacing-xs: 0.25rem;
  --spacing-sm: 0.5rem;
  --spacing-md: 1rem;
  --spacing-lg: 1.5rem;
  --spacing-xl: 2rem;

  /* Touch target minimum */
  --touch-target: 48px;
}

/* ============================================
   Reset and Base Styles
   ============================================ */

body {
  font-family: 'Source Sans 3', system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Headings use Inter for a more designed feel. */
h1, h2, h3, h4, h5, h6,
.stat-card-number, .stat-value,
.dashboard-header h1, .welcome-banner h1 {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  letter-spacing: -0.01em;
}

/* Mobile-first: ensure readable text size */
@media (max-width: 768px) {
  body {
    font-size: 16px;
  }
}

/* ============================================
   Status Badges
   ============================================ */

.badge {
  display: inline-block;
  padding: 0.25rem 0.75rem;
  border-radius: 9999px;
  font-size: 0.875rem;
  font-weight: 600;
  white-space: nowrap;
}

.badge-active {
  background-color: rgba(34, 197, 94, 0.1);
  color: var(--success);
  border: 1px solid var(--success);
}

.badge-paused {
  background-color: rgba(234, 179, 8, 0.1);
  color: #ca8a04;
  border: 1px solid #ca8a04;
}

.badge-completed {
  background-color: rgba(59, 130, 246, 0.1);
  color: var(--info);
  border: 1px solid var(--info);
}

.badge-inactive {
  background-color: rgba(107, 114, 128, 0.1);
  color: var(--neutral);
  border: 1px solid var(--neutral);
}

/* Response type badges */
.badge-strong-support {
  background-color: rgba(21, 128, 61, 0.1);
  color: var(--strong-support);
}

.badge-lean-support {
  background-color: rgba(74, 222, 128, 0.1);
  color: var(--lean-support);
}

.badge-undecided {
  background-color: rgba(251, 191, 36, 0.1);
  color: var(--undecided);
}

.badge-lean-against {
  background-color: rgba(252, 165, 165, 0.1);
  color: var(--lean-against);
}

.badge-strong-against {
  background-color: rgba(153, 27, 27, 0.1);
  color: var(--strong-against);
}

.badge-not-home {
  background-color: rgba(156, 163, 175, 0.1);
  color: var(--not-home);
}

.badge-refused {
  background-color: rgba(55, 65, 81, 0.1);
  color: var(--refused);
}

.badge-wrong-address {
  background-color: rgba(251, 146, 60, 0.1);
  color: var(--wrong-address);
}

.badge-moved {
  background-color: rgba(249, 115, 22, 0.1);
  color: var(--moved);
}

.badge-deceased {
  background-color: rgba(0, 0, 0, 0.1);
  color: var(--deceased);
}

.badge-no-answer {
  background-color: rgba(100, 116, 139, 0.1);
  color: var(--no-answer);
}

.badge-wrong-number {
  background-color: rgba(168, 85, 247, 0.1);
  color: var(--wrong-number);
}

.badge-do-not-call {
  background-color: rgba(127, 29, 29, 0.1);
  color: var(--do-not-call);
  text-decoration: line-through;
}

/* ============================================
   Stats Grid and Cards
   ============================================ */

.stats-grid {
  display: grid;
  gap: var(--spacing-md);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin-bottom: var(--spacing-lg);
}

@media (min-width: 768px) {
  .stats-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

@media (max-width: 576px) {
  .stats-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.stat-card {
  background: var(--form-element-background-color);
  border: 1px solid transparent;
  border-radius: var(--border-radius);
  padding: var(--spacing-md);
  border-left: 4px solid #1e40af;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06), 0 4px 12px rgba(15, 23, 42, 0.04);
  transition: transform 0.2s, box-shadow 0.2s;
}

.stat-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 20px rgba(15, 23, 42, 0.10), 0 2px 6px rgba(15, 23, 42, 0.06);
}

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

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

.stat-card.danger {
  border-left-color: var(--danger);
}

.stat-card-number {
  display: block;
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1;
  margin-bottom: var(--spacing-sm);
  color: var(--form-element-valid-border-color);
}

.stat-card-label {
  display: block;
  font-size: 0.875rem;
  color: var(--neutral);
  font-weight: 500;
}

/* Animated number updates */
.stat-card-number.updating {
  animation: pulse 0.6s;
}

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

/* ============================================
   Map Container
   ============================================ */

.map-container {
  width: 100%;
  height: 250px;
  border: 1px solid var(--form-element-border-color);
  border-radius: var(--border-radius);
  overflow: hidden;
  margin-bottom: var(--spacing-lg);
  background-color: #f5f5f5;
}

@media (min-width: 768px) {
  .map-container {
    height: 400px;
  }
}

/* Leaflet overrides */
.map-container .leaflet-container {
  font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}

.map-container .leaflet-popup-content {
  font-size: 14px;
  line-height: 1.4;
}

.map-container .leaflet-popup-content-wrapper {
  border-radius: 6px;
}

/* 2026-05-15 (feedback #89): center Leaflet zoom + and - glyphs on EVERY
   map in the app, not just /admin/county-coverage. Root cause is that
   Leaflet's zoom buttons are <a role="button"> elements, and Pico CSS's
   heavy [role=button] rule adds padding, border, border-radius,
   font-size:1rem, line-height:var(--pico-line-height), and overrides
   Leaflet's intended monospace font. The combined effect: glyphs render
   in Source Sans 3 (which sits lower in its line-box than monospace) in
   a slightly-too-big button, so the + ends up near the bottom of its
   button and the - near the top — clustered against the dividing line.
   Reset to what Leaflet's own CSS expects. Global on purpose: every
   Leaflet map in this app (dashboard live-map, county-coverage, voter
   filter, turf detail, turf builder, etc.) has the same problem. */
.leaflet-bar a.leaflet-control-zoom-in,
.leaflet-bar a.leaflet-control-zoom-out {
  font: bold 18px 'Lucida Console', Monaco, monospace !important;
  line-height: 26px !important;
  padding: 0 !important;
  border: 0 none !important;
  border-bottom: 1px solid #ccc !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  text-decoration: none !important;
  text-align: center !important;
  text-indent: 0 !important;
  display: block !important;
  color: #333 !important;
  background: #fff !important;
}
/* Bottom button has no divider below it (leaflet's intended layout). */
.leaflet-bar a:last-child.leaflet-control-zoom-out,
.leaflet-bar .leaflet-control-zoom-out:last-child {
  border-bottom: 0 none !important;
}
/* Touch-mode (mobile-style) zoom controls are 30x30; bump the line-height
   and glyph size to match. */
.leaflet-touch .leaflet-bar a.leaflet-control-zoom-in,
.leaflet-touch .leaflet-bar a.leaflet-control-zoom-out {
  line-height: 30px !important;
  font-size: 22px !important;
}


/* ============================================
   Progress Bars
   ============================================ */

.progress-bar {
  width: 100%;
  height: 24px;
  background-color: var(--form-element-background-color);
  border: 1px solid var(--form-element-border-color);
  border-radius: 12px;
  overflow: hidden;
  margin-bottom: var(--spacing-md);
  position: relative;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--success), var(--info));
  border-radius: 12px;
  transition: width 0.3s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  font-weight: 600;
  color: white;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
  min-width: 24px;
}

.progress-fill.warning {
  background: linear-gradient(90deg, var(--warning), #f97316);
}

.progress-fill.danger {
  background: linear-gradient(90deg, var(--danger), #dc2626);
}

.progress-label {
  display: flex;
  justify-content: space-between;
  font-size: 0.875rem;
  margin-bottom: var(--spacing-xs);
  font-weight: 500;
}

/* ============================================
   Response Code Buttons
   ============================================ */

.response-btn {
  display: block;
  width: 100%;
  padding: var(--spacing-md) var(--spacing-lg);
  min-height: var(--touch-target);
  margin-bottom: var(--spacing-sm);
  border: none;
  border-radius: var(--border-radius);
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
  text-align: center;
  color: white;
}

@media (min-width: 768px) {
  .response-btn {
    margin-bottom: var(--spacing-md);
  }
}

.response-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.response-btn:not(:disabled):hover,
.response-btn:not(:disabled):focus {
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.response-btn:not(:disabled):active {
  transform: translateY(0);
}

.response-strong-support {
  background-color: var(--strong-support);
}

.response-lean-support {
  background-color: var(--lean-support);
  color: #1f2937;
}

.response-undecided {
  background-color: var(--warning);
  color: #1f2937;
}

.response-lean-against {
  background-color: var(--lean-against);
  color: #1f2937;
}

.response-strong-against {
  background-color: var(--strong-against);
}

.response-not-home {
  background-color: var(--not-home);
}

.response-refused {
  background-color: var(--refused);
}

.response-wrong-address {
  background-color: var(--wrong-address);
}

.response-moved {
  background-color: var(--moved);
}

.response-deceased {
  background-color: var(--deceased);
}

.response-no-answer {
  background-color: var(--no-answer);
}

.response-wrong-number {
  background-color: var(--wrong-number);
}

.response-do-not-call {
  background-color: var(--do-not-call);
  position: relative;
}

.response-do-not-call::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  background-color: rgba(255, 255, 255, 0.7);
  transform: translateY(-50%);
}

/* Grid layout for response buttons on desktop */
.response-grid {
  display: grid;
  gap: var(--spacing-sm);
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .response-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--spacing-md);
  }
}

/* ============================================
   Voter Card
   ============================================ */

.voter-card {
  background: var(--form-element-background-color);
  border: 1px solid var(--form-element-border-color);
  border-radius: var(--border-radius);
  padding: var(--spacing-lg);
  margin-bottom: var(--spacing-lg);
}

.voter-card.visited {
  opacity: 0.7;
  background-color: rgba(34, 197, 94, 0.05);
}

.voter-card.flagged {
  border-left: 4px solid var(--danger);
}

.voter-card-name {
  display: block;
  font-size: 1.5rem;
  font-weight: 700;
  margin-bottom: var(--spacing-sm);
}

.voter-card-address {
  display: block;
  font-size: 0.95rem;
  color: var(--neutral);
  margin-bottom: var(--spacing-md);
}

.voter-card-meta {
  display: flex;
  gap: var(--spacing-sm);
  flex-wrap: wrap;
  margin-bottom: var(--spacing-md);
}

.voter-card-meta .badge {
  margin: 0;
}

.voter-card-details {
  font-size: 0.875rem;
  color: var(--neutral);
}

.voter-card-details dt {
  font-weight: 600;
  display: inline;
}

.voter-card-details dd {
  display: inline;
  margin-right: var(--spacing-lg);
}

.voter-card-actions {
  display: flex;
  gap: var(--spacing-sm);
  margin-top: var(--spacing-md);
  flex-wrap: wrap;
}

.voter-card-actions button {
  flex: 1;
  min-width: 100px;
  padding: var(--spacing-sm) var(--spacing-md);
  font-size: 0.875rem;
}

/* ============================================
   Canvass Interface Layout
   ============================================ */

.canvass-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

.canvass-header {
  padding: var(--spacing-md);
  border-bottom: 1px solid var(--form-element-border-color);
  background: var(--form-element-background-color);
  flex-shrink: 0;
}

.canvass-content {
  flex: 1;
  overflow-y: auto;
  padding: var(--spacing-md);
}

.canvass-actions {
  flex-shrink: 0;
  padding: var(--spacing-md);
  border-top: 1px solid var(--form-element-border-color);
  background: var(--form-element-background-color);
  max-height: 50vh;
  overflow-y: auto;
}

@media (max-width: 768px) {
  .canvass-container {
    height: auto;
  }

  .canvass-content {
    min-height: calc(100vh - 200px);
  }
}

/* ============================================
   Offline Indicator
   ============================================ */

.offline-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  background-color: var(--warning);
  color: #1f2937;
  padding: var(--spacing-md);
  text-align: center;
  font-weight: 600;
  z-index: 1000;
  display: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.offline-banner.show {
  display: block;
}

.offline-banner::before {
  content: '⚠️ ';
  margin-right: var(--spacing-sm);
}

/* ============================================
   Sync Status Indicator
   ============================================ */

.sync-status {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-xs);
  font-size: 0.875rem;
  color: var(--neutral);
  padding: var(--spacing-sm);
  background-color: rgba(107, 114, 128, 0.1);
  border-radius: 6px;
}

.sync-status.syncing {
  color: var(--warning);
}

.sync-status.synced {
  color: var(--success);
}

.sync-status.error {
  color: var(--danger);
}

.sync-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: currentColor;
}

.sync-status.syncing .sync-status-dot {
  animation: blink 1.5s infinite;
}

@keyframes blink {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.4;
  }
}

/* ============================================
   Filter Form
   ============================================ */

.filter-form {
  display: grid;
  gap: var(--spacing-md);
  grid-template-columns: 1fr;
  margin-bottom: var(--spacing-lg);
  padding: var(--spacing-lg);
  background-color: var(--form-element-background-color);
  border: 1px solid var(--form-element-border-color);
  border-radius: var(--border-radius);
}

@media (min-width: 768px) {
  .filter-form {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--spacing-lg);
  }
}

.filter-form-row {
  display: flex;
  flex-direction: column;
}

.filter-form-row label {
  font-size: 0.875rem;
  font-weight: 600;
  margin-bottom: var(--spacing-xs);
}

.filter-form-row input,
.filter-form-row select {
  padding: var(--spacing-sm);
  border-radius: var(--border-radius);
}

.filter-form-actions {
  display: flex;
  gap: var(--spacing-sm);
  margin-top: var(--spacing-md);
}

@media (min-width: 768px) {
  .filter-form-actions {
    grid-column: 1 / -1;
    justify-content: flex-end;
  }
}

.filter-form-actions button {
  min-height: var(--touch-target);
  padding: var(--spacing-sm) var(--spacing-lg);
}

/* ============================================
   Table Responsive Wrapper
   ============================================ */

.table-responsive {
  overflow-x: auto;
  margin-bottom: var(--spacing-lg);
  -webkit-overflow-scrolling: touch;
}

.table-responsive table {
  min-width: 100%;
  width: 100%;
}

@media (max-width: 768px) {
  .table-responsive {
    border: 1px solid var(--form-element-border-color);
    border-radius: var(--border-radius);
  }

  .table-responsive table {
    font-size: 0.875rem;
  }

  .table-responsive th,
  .table-responsive td {
    padding: var(--spacing-sm);
  }
}

/* ============================================
   Activity Feed
   ============================================ */

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

.activity-feed-item {
  display: flex;
  gap: var(--spacing-md);
  padding: var(--spacing-md);
  border-left: 2px solid var(--form-element-border-color);
  margin-left: var(--spacing-md);
  position: relative;
}

.activity-feed-item::before {
  content: '';
  position: absolute;
  left: -7px;
  top: var(--spacing-md);
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background-color: var(--info);
  border: 2px solid white;
  box-shadow: 0 0 0 1px var(--form-element-border-color);
}

.activity-feed-item.success::before {
  background-color: var(--success);
}

.activity-feed-item.warning::before {
  background-color: var(--warning);
}

.activity-feed-item.error::before {
  background-color: var(--danger);
}

.activity-feed-item:last-child {
  border-left-color: transparent;
}

.activity-feed-time {
  font-size: 0.75rem;
  color: var(--neutral);
  white-space: nowrap;
}

.activity-feed-content {
  flex: 1;
}

.activity-feed-message {
  font-weight: 500;
  margin-bottom: var(--spacing-xs);
}

.activity-feed-detail {
  font-size: 0.875rem;
  color: var(--neutral);
}

/* ============================================
   Navigation Overrides
   ============================================ */

nav {
  padding: var(--spacing-md) 0;
}

/* Mobile hamburger menu */
@media (max-width: 576px) {
  nav ul {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background-color: var(--form-element-background-color);
    border-bottom: 1px solid var(--form-element-border-color);
    flex-direction: column;
    gap: 0;
    padding: var(--spacing-md) 0;
  }

  nav ul.show {
    display: flex;
  }

  nav ul li {
    padding: var(--spacing-md) var(--spacing-lg);
    border-bottom: 1px solid var(--form-element-border-color);
  }

  nav ul li:last-child {
    border-bottom: none;
  }

  nav ul li a {
    display: block;
    color: inherit;
    text-decoration: none;
    font-weight: 500;
  }
}

/* ============================================
   Flash Messages
   ============================================ */

.flash-messages {
  position: fixed;
  top: 60px;
  right: var(--spacing-md);
  z-index: 999;
  max-width: 400px;
  display: flex;
  flex-direction: column;
  gap: var(--spacing-md);
}

@media (max-width: 576px) {
  .flash-messages {
    left: var(--spacing-md);
    right: var(--spacing-md);
    max-width: none;
  }
}

.flash {
  padding: var(--spacing-md) var(--spacing-lg);
  border-radius: var(--border-radius);
  border-left: 4px solid;
  background-color: var(--form-element-background-color);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  animation: slideInRight 0.3s ease;
}

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

.flash.success {
  border-left-color: var(--success);
  color: var(--strong-support);
}

.flash.warning {
  border-left-color: var(--warning);
  color: #d97706;
}

/* ============================================================
   Flash message styling for Flask flash() messages (Batch 1 #19)
   Template uses <article class="flash-message flash-{{ category }}">
   so we style by class name, not chained selector.
   Categories: error, warning, success, info, message
   ============================================================ */
.flash-message {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0.7rem 1rem;
  margin: 0.75rem auto;
  max-width: 980px;
  border-radius: 8px;
  border-left: 4px solid;
  font-size: 0.92rem;
  line-height: 1.4;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06);
}
.flash-message::before {
  flex: none;
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.2;
}
.flash-message.flash-error,
.flash-message.flash-danger {
  background: #fee2e2;
  border-left-color: #dc2626;
  color: #991b1b;
}
.flash-message.flash-error::before,
.flash-message.flash-danger::before { content: '\26D4'; }
.flash-message.flash-warning {
  background: #fef3c7;
  border-left-color: #d97706;
  color: #92400e;
}
.flash-message.flash-warning::before { content: '\26A0'; }
.flash-message.flash-success {
  background: #dcfce7;
  border-left-color: #16a34a;
  color: #166534;
}
.flash-message.flash-success::before { content: '\2713'; }
.flash-message.flash-info,
.flash-message.flash-message {
  background: #dbeafe;
  border-left-color: #2563eb;
  color: #1e40af;
}
.flash-message.flash-info::before,
.flash-message.flash-message::before { content: '\2139'; }

.flash.error {
  border-left-color: var(--danger);
  color: #b91c1c;
}

.flash.info {
  border-left-color: var(--info);
  color: #1e40af;
}

.flash-close {
  position: absolute;
  top: var(--spacing-sm);
  right: var(--spacing-sm);
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  font-size: 1.25rem;
  opacity: 0.7;
  transition: opacity 0.2s;
}

.flash-close:hover {
  opacity: 1;
}

/* ============================================
   Form Helpers
   ============================================ */

.form-row {
  display: grid;
  gap: var(--spacing-md);
  grid-template-columns: 1fr;
  margin-bottom: var(--spacing-lg);
}

@media (min-width: 768px) {
  .form-row {
    grid-template-columns: repeat(2, 1fr);
  }
}

.form-row.full {
  grid-template-columns: 1fr;
}

.form-section {
  padding: var(--spacing-lg);
  border: 1px solid var(--form-element-border-color);
  border-radius: var(--border-radius);
  margin-bottom: var(--spacing-lg);
}

.form-section-title {
  font-size: 1.125rem;
  font-weight: 700;
  margin-bottom: var(--spacing-md);
  display: block;
}

/* ============================================
   Loading Spinner
   ============================================ */

.loading {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 3px solid rgba(0, 0, 0, 0.1);
  border-top-color: var(--info);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

.loading.lg {
  width: 40px;
  height: 40px;
  border-width: 4px;
}

.loading.sm {
  width: 16px;
  height: 16px;
  border-width: 2px;
}

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

.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--spacing-xl);
  gap: var(--spacing-md);
  color: var(--neutral);
}

/* ============================================
   Modal / Dialog Styles
   ============================================ */

dialog {
  border: 1px solid var(--form-element-border-color);
  border-radius: var(--border-radius);
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  max-width: 500px;
}

dialog::backdrop {
  background-color: rgba(0, 0, 0, 0.5);
}

dialog h2 {
  margin-top: 0;
  margin-bottom: var(--spacing-lg);
}

.dialog-content {
  margin-bottom: var(--spacing-lg);
}

.dialog-actions {
  display: flex;
  gap: var(--spacing-md);
  justify-content: flex-end;
}

.dialog-actions button {
  flex: 0 1 auto;
  min-height: var(--touch-target);
}

@media (max-width: 576px) {
  dialog {
    max-width: 90vw;
    width: 90vw;
  }

  .dialog-actions {
    flex-direction: column;
  }

  .dialog-actions button {
    width: 100%;
  }
}

/* ============================================
   Print Styles
   ============================================ */

@media print {
  nav,
  .offline-banner,
  .sync-status,
  .filter-form,
  .response-grid,
  .canvass-actions,
  button:not(.print-show),
  input:not(.print-show),
  .no-print {
    display: none !important;
  }

  body {
    background: white;
  }

  .stat-card,
  .voter-card,
  .activity-feed-item {
    border: 1px solid #ccc;
    break-inside: avoid;
    page-break-inside: avoid;
  }

  .stats-grid {
    margin-bottom: 2rem;
  }

  .table-responsive {
    border: none;
  }

  .table-responsive table {
    width: 100%;
  }
}

/* ============================================
   Utility Classes
   ============================================ */

.text-muted {
  color: var(--neutral);
}

.text-success {
  color: var(--success);
}

.text-warning {
  color: var(--warning);
}

.text-danger {
  color: var(--danger);
}

.text-info {
  color: var(--info);
}

.text-center {
  text-align: center;
}

.text-right {
  text-align: right;
}

.mb-0 {
  margin-bottom: 0;
}

.mb-1 {
  margin-bottom: var(--spacing-sm);
}

.mb-2 {
  margin-bottom: var(--spacing-md);
}

.mb-3 {
  margin-bottom: var(--spacing-lg);
}

.mt-0 {
  margin-top: 0;
}

.mt-1 {
  margin-top: var(--spacing-sm);
}

.mt-2 {
  margin-top: var(--spacing-md);
}

.mt-3 {
  margin-top: var(--spacing-lg);
}

.hidden {
  display: none;
}

.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flex-wrap {
  flex-wrap: wrap;
}

.gap-1 {
  gap: var(--spacing-sm);
}

.gap-2 {
  gap: var(--spacing-md);
}

.gap-3 {
  gap: var(--spacing-lg);
}

/* ============================================================
   GLOBAL BUTTON STYLES
   These override the per-template .btn-primary etc. that
   referenced Pico v1's --form-element-valid-border-color
   variable, which doesn't exist as a global in Pico v2 and
   was rendering buttons white-on-white (invisible).
   ============================================================ */
.btn-primary,
button.btn-primary,
a.btn-primary {
  display: inline-block;
  background-color: #1e40af !important;
  color: #ffffff !important;
  border: none !important;
  padding: 0.75rem 1.5rem;
  font-size: 1rem;
  font-weight: 600;
  min-height: 44px;
  border-radius: 6px;
  cursor: pointer;
  text-decoration: none;
  transition: background-color 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;
  box-shadow: 0 1px 2px rgba(30, 64, 175, 0.2);
}
.btn-primary:hover,
button.btn-primary:hover,
a.btn-primary:hover {
  background-color: #1e3a8a !important;
  color: #ffffff !important;
  box-shadow: 0 4px 10px rgba(30, 64, 175, 0.25);
  transform: translateY(-1px);
}

.btn-secondary,
button.btn-secondary,
a.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: #e5e7eb !important;
  color: #111827 !important;
  border: 1px solid #d1d5db !important;
  padding: 0.6rem 1.2rem;
  font-size: 0.95rem;
  font-weight: 600;
  min-height: 44px; /* 2026-05-25 (11B): mobile tap-target */
  border-radius: 6px;
  cursor: pointer;
  text-decoration: none;
  transition: background-color 0.2s ease;
}
.btn-secondary:hover,
button.btn-secondary:hover,
a.btn-secondary:hover {
  background-color: #d1d5db !important;
}

.btn-danger,
button.btn-danger,
a.btn-danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: #dc2626 !important;
  color: #ffffff !important;
  border: none !important;
  padding: 0.6rem 1.2rem;
  font-size: 0.95rem;
  font-weight: 600;
  min-height: 44px; /* 2026-05-25 (11B): mobile tap-target */
  border-radius: 6px;
  cursor: pointer;
  text-decoration: none;
}
.btn-danger:hover {
  background-color: #b91c1c !important;
}

.btn-small {
  display: inline-block;
  background-color: #e5e7eb !important;
  color: #111827 !important;
  border: 1px solid #d1d5db !important;
  padding: 0.35rem 0.75rem;
  font-size: 0.85rem;
  border-radius: 4px;
  cursor: pointer;
  text-decoration: none;
}
.btn-small.danger {
  background-color: #dc2626 !important;
  color: #ffffff !important;
  border-color: #dc2626 !important;
}

/* ============================================================
   PHASE A DESIGN UPGRADE (2026-04-13)
   Adds: brand color (deep blue #1e40af), branded nav,
   card shadows, theme toggle, Lucide icon sizing, dark-mode
   tuning for existing components.
   ============================================================ */

/* --- Brand color tokens ------------------------------------- */
:root {
  --brand: #1e40af;
  --brand-600: #1e3a8a;
  --brand-700: #172f67;
  --brand-50: #eff6ff;

  /* Elevation tokens — reused everywhere that needs a card look */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.05), 0 1px 3px rgba(15, 23, 42, 0.04);
  --shadow-md: 0 2px 4px rgba(15, 23, 42, 0.05), 0 4px 12px rgba(15, 23, 42, 0.06);
  --shadow-lg: 0 10px 15px -3px rgba(15, 23, 42, 0.08), 0 4px 6px -2px rgba(15, 23, 42, 0.05);
}

[data-theme="dark"] {
  --brand: #3b82f6;        /* lighter blue on dark for contrast */
  --brand-600: #2563eb;
  --brand-700: #1d4ed8;
  --brand-50: #1e293b;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 12px 24px rgba(0, 0, 0, 0.6);
}

/* --- Branded navigation bar --------------------------------- */
body > nav {
  background-color: var(--brand);
  color: #ffffff;
  padding: 0.75rem 1.25rem;
  box-shadow: var(--shadow-sm);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

body > nav ul {
  align-items: center;
}

body > nav a,
body > nav li,
body > nav strong {
  color: #ffffff !important;
}

body > nav a {
  text-decoration: none;
  font-weight: 500;
  padding: 0.5rem 0.75rem;
  border-radius: 6px;
  transition: background-color 0.15s ease;
}

body > nav a:hover {
  background-color: rgba(255, 255, 255, 0.12);
}

body > nav a[aria-current="page"] {
  background-color: rgba(255, 255, 255, 0.18);
  font-weight: 600;
}

body > nav strong {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: 700;
  letter-spacing: -0.01em;
  font-size: 1.05rem;
}

/* Mobile drawer uses solid brand color too */
@media (max-width: 576px) {
  body > nav ul {
    background-color: var(--brand);
  }
  body > nav ul li {
    border-bottom-color: rgba(255, 255, 255, 0.12);
  }
}

/* --- Theme toggle button ------------------------------------ */
.theme-toggle {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: #ffffff;
  width: 38px;
  height: 38px;
  padding: 0;
  border-radius: 8px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.theme-toggle:hover {
  background-color: rgba(255, 255, 255, 0.15);
  border-color: rgba(255, 255, 255, 0.5);
}

.theme-toggle .theme-icon-light,
.theme-toggle .theme-icon-dark {
  width: 18px;
  height: 18px;
}

/* Show moon in light mode (offering switch TO dark), sun in dark mode. */
[data-theme="light"] .theme-toggle .theme-icon-light { display: none; }
[data-theme="light"] .theme-toggle .theme-icon-dark  { display: inline-block; }
[data-theme="dark"]  .theme-toggle .theme-icon-light { display: inline-block; }
[data-theme="dark"]  .theme-toggle .theme-icon-dark  { display: none; }

/* --- Lucide icon sizing ------------------------------------- */
[data-lucide] {
  width: 18px;
  height: 18px;
  stroke-width: 2;
  vertical-align: -3px;
}

.quick-action-btn [data-lucide] {
  width: 22px;
  height: 22px;
  margin-right: 0.35rem;
}

/* --- Card & panel elevation upgrade ------------------------- */
.voter-card,
.assignment-card,
.filter-form,
.form-section,
.flash,
dialog {
  box-shadow: var(--shadow-md);
  border-color: transparent;
}

.voter-card:hover,
.assignment-card:hover {
  box-shadow: var(--shadow-lg);
}

/* Activity feed: quieter border, brand-colored dot */
.activity-feed-item::before {
  background-color: var(--brand);
}

/* --- Dark mode tuning for custom components ----------------- */

/* Stat cards look washed out on dark without a background lift */
[data-theme="dark"] .stat-card,
[data-theme="dark"] .voter-card,
[data-theme="dark"] .assignment-card,
[data-theme="dark"] .filter-form,
[data-theme="dark"] .form-section,
[data-theme="dark"] .flash {
  background-color: #1e293b;
  color: #e2e8f0;
}

[data-theme="dark"] .stat-card-label,
[data-theme="dark"] .voter-card-address,
[data-theme="dark"] .voter-card-details {
  color: #94a3b8;
}

[data-theme="dark"] .stat-card-number,
[data-theme="dark"] .stat-value {
  color: #f1f5f9;
}

/* Badges on dark need a stronger background — the 0.1 alpha disappears */
[data-theme="dark"] .badge {
  background-color: rgba(255, 255, 255, 0.08);
}
[data-theme="dark"] .badge-active          { background-color: rgba(34, 197, 94, 0.22); color: #86efac; border-color: #16a34a; }
[data-theme="dark"] .badge-paused          { background-color: rgba(234, 179, 8, 0.22); color: #fde68a; border-color: #ca8a04; }
[data-theme="dark"] .badge-completed       { background-color: rgba(59, 130, 246, 0.22); color: #93c5fd; border-color: #3b82f6; }
[data-theme="dark"] .badge-inactive        { background-color: rgba(148, 163, 184, 0.22); color: #cbd5e1; border-color: #64748b; }

[data-theme="dark"] .badge-strong-support  { color: #86efac; background-color: rgba(34, 197, 94, 0.18); }
[data-theme="dark"] .badge-lean-support    { color: #bbf7d0; background-color: rgba(74, 222, 128, 0.18); }
[data-theme="dark"] .badge-undecided       { color: #fde68a; background-color: rgba(251, 191, 36, 0.18); }
[data-theme="dark"] .badge-lean-against    { color: #fecaca; background-color: rgba(252, 165, 165, 0.18); }
[data-theme="dark"] .badge-strong-against  { color: #fca5a5; background-color: rgba(153, 27, 27, 0.28); }
[data-theme="dark"] .badge-not-home,
[data-theme="dark"] .badge-no-answer       { color: #cbd5e1; background-color: rgba(148, 163, 184, 0.18); }
[data-theme="dark"] .badge-refused         { color: #e5e7eb; background-color: rgba(55, 65, 81, 0.5); }

/* Response buttons: the light-colored ones need darker text flipped */
[data-theme="dark"] .response-lean-support,
[data-theme="dark"] .response-undecided,
[data-theme="dark"] .response-lean-against {
  color: #0f172a;
}

/* Flash messages */
[data-theme="dark"] .flash.success { color: #86efac; }
[data-theme="dark"] .flash.warning { color: #fde68a; }
[data-theme="dark"] .flash.error   { color: #fca5a5; }
[data-theme="dark"] .flash.info    { color: #93c5fd; }

/* Map container gets a proper background in dark mode */
[data-theme="dark"] .map-container {
  background-color: #0f172a;
}

/* Progress bar track */
[data-theme="dark"] .progress-bar {
  background-color: #0f172a;
}

/* Activity feed line */
[data-theme="dark"] .activity-feed-item {
  border-left-color: #334155;
}

/* Footer */
[data-theme="dark"] footer {
  color: #94a3b8;
}

/* Secondary buttons readable on dark */
[data-theme="dark"] .btn-secondary,
[data-theme="dark"] button.btn-secondary,
[data-theme="dark"] a.btn-secondary {
  background-color: #334155 !important;
  color: #f1f5f9 !important;
  border-color: #475569 !important;
}
[data-theme="dark"] .btn-secondary:hover {
  background-color: #475569 !important;
}

/* --- Small polish ------------------------------------------- */
a { color: var(--brand); }
a:hover { color: var(--brand-600); }
[data-theme="dark"] a { color: #93c5fd; }
[data-theme="dark"] a:hover { color: #bfdbfe; }

/* =========================================================
   PHASE B — Global print stylesheet (Phase B #20)
   Makes route lists, reports, and dashboards printer-friendly:
   hide nav/buttons, force light background, avoid page breaks
   inside cards. Individual pages can override if needed.
   ========================================================= */
@media print {
  /* Hide chrome that doesn't belong on paper */
  nav, .theme-toggle, .flash-messages,
  .quick-actions, .date-range-selector,
  button, .btn, .btn-primary, .btn-secondary,
  .quick-action-btn, a.primary-btn,
  .map-controls, .map-legend,
  summary .collapse-hint { display: none !important; }

  /* Always expand collapsibles for print */
  details > summary { list-style: none; }
  details > summary::-webkit-details-marker { display: none; }
  details:not([open]) > *:not(summary) { display: block !important; }

  /* Reset colors for toner-friendly output */
  body, main, article, section {
    background: #fff !important;
    color: #000 !important;
    box-shadow: none !important;
  }
  :root, [data-theme="dark"] {
    --card-background-color: #fff !important;
    --background-color: #fff !important;
    --color: #000 !important;
  }

  a { color: #000 !important; text-decoration: underline; }

  /* Keep logical groupings intact across pages */
  .stat-card, .activity-item, .turf-item, .queue-item,
  .assignment-card, .lb-row, .voter-card,
  details.collapsible-section { page-break-inside: avoid; }

  /* Tables get visible borders for legibility */
  table, th, td { border: 1px solid #666 !important; }
  th { background: #f3f4f6 !important; }

  /* Generous but not wasteful page margin */
  @page { margin: 0.5in; }
}

/* =========================================================
   PHASE C — Remaining Design Enhancements (2026-04-15)
   Adds: progress rings (#9), map plugin styles (#11),
   illustrated empty states (#12), skeleton loaders (#13),
   bottom response bar (#16), PWA install banner (#18),
   branded route-list print (#20).
   ========================================================= */

/* ---- #9 : Circular progress rings (turf detail) --------- */
.progress-ring {
  --ring-size: 110px;
  --ring-stroke: 10px;
  --ring-color: var(--brand, #1e40af);
  --ring-bg: #e2e8f0;
  width: var(--ring-size);
  height: var(--ring-size);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  flex-shrink: 0;
}
.progress-ring svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}
.progress-ring .ring-track {
  fill: none;
  stroke: var(--ring-bg);
  stroke-width: var(--ring-stroke);
}
.progress-ring .ring-fill {
  fill: none;
  stroke: var(--ring-color);
  stroke-width: var(--ring-stroke);
  stroke-linecap: round;
  transition: stroke-dashoffset 0.6s ease;
}
.progress-ring .ring-label {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  line-height: 1;
}
.progress-ring .ring-percent {
  font-family: 'Inter', sans-serif;
  font-size: 1.35rem;
  font-weight: 800;
  color: #0f172a;
}
.progress-ring .ring-sub {
  font-size: 0.68rem;
  color: var(--neutral);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-top: 0.2rem;
}
[data-theme="dark"] .progress-ring .ring-percent { color: #f1f5f9; }
[data-theme="dark"] .progress-ring { --ring-bg: #334155; }

/* Color variants for different progress states */
.progress-ring.state-complete { --ring-color: #15803d; }
.progress-ring.state-warning  { --ring-color: #ca8a04; }
.progress-ring.state-danger   { --ring-color: #b91c1c; }

/* Small variant for table cells and inline use */
.progress-ring.ring-sm {
  --ring-size: 56px;
  --ring-stroke: 7px;
}
.progress-ring.ring-sm .ring-percent { font-size: 0.78rem; }
.progress-ring.ring-sm .ring-sub { display: none; }

/* ---- #11 : Leaflet plugin controls (cluster + heatmap toggle) -- */
.map-layer-toggle {
  display: inline-flex;
  gap: 0.25rem;
  background: rgba(255, 255, 255, 0.98);
  border: 1px solid #cbd5e1;
  border-radius: 8px;
  padding: 0.25rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.map-layer-toggle button {
  background: transparent;
  border: none;
  padding: 0.4rem 0.75rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: #334155;
  border-radius: 6px;
  cursor: pointer;
  min-height: 32px;
}
.map-layer-toggle button.active {
  background: var(--brand, #1e40af);
  color: #ffffff;
}
[data-theme="dark"] .map-layer-toggle {
  background: #1e293b;
  border-color: #334155;
}
[data-theme="dark"] .map-layer-toggle button { color: #cbd5e1; }

/* Custom cluster bubble — override default marker-cluster styles.
 *
 * 2026-04-18 revision: the cluster's BACKGROUND COLOR is now driven by the
 * `.cluster-tier-*` modifier classes (set in iconCreateFunction) which
 * reflect what % of the cluster's voters have been knocked. The previous
 * size-based coloring (cluster-lg/md/sm) gave a misleading "greener = more
 * progress" impression at zoom-out because big clusters were always dark
 * green, even in areas that had not been canvassed yet.
 */
.marker-cluster-custom {
  background: rgba(100, 116, 139, 0.9); /* default / fallback */
  color: #ffffff;
  border-radius: 50%;
  border: 3px solid #ffffff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
  font-weight: 700;
  font-family: 'Inter', sans-serif;
  display: flex !important;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.marker-cluster-custom .mc-count { font-size: 0.95em; font-weight: 800; }
.marker-cluster-custom .mc-pct   { font-size: 0.68em; font-weight: 600; opacity: 0.92; margin-top: 2px; }

/* Progress tiers — color = % of voters in the cluster already knocked */
.marker-cluster-custom.cluster-tier-done { background: rgba(21, 128, 61, 0.92); }   /* 70%+ done   : dark green  */
.marker-cluster-custom.cluster-tier-mid  { background: rgba(101, 163, 13, 0.92); }  /* 40–69% done : light green */
.marker-cluster-custom.cluster-tier-low  { background: rgba(217, 119, 6, 0.92); }   /* 10–39% done : amber       */
.marker-cluster-custom.cluster-tier-none { background: rgba(100, 116, 139, 0.92); } /* < 10% done  : slate gray  */

/* Back-compat: the size-based classes are no longer emitted by the cluster
 * factory, but keep them defined so any cached template html in the wild
 * still renders a sensible neutral bubble rather than a transparent one. */
.marker-cluster-custom.cluster-lg,
.marker-cluster-custom.cluster-md,
.marker-cluster-custom.cluster-sm { background: rgba(100, 116, 139, 0.9); }

/* ---- #12 : Illustrated empty-state --------------------- */
/* (Builds on the existing .empty-state block used on the dashboard.)
   Replaces the plain Lucide icon with an SVG illustration so empty
   pages feel friendly rather than broken. */
.empty-state-illustration {
  max-width: 260px;
  width: 60%;
  margin: 0 auto 1rem;
  display: block;
}
.empty-state-illustration svg { width: 100%; height: auto; display: block; }
[data-theme="dark"] .empty-state-illustration { opacity: 0.85; }

/* ---- #13 : Skeleton loading states --------------------- */
@keyframes sk-shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
.skeleton,
.skeleton-line,
.skeleton-circle,
.skeleton-block {
  background: linear-gradient(90deg, #e2e8f0 0%, #f1f5f9 50%, #e2e8f0 100%);
  background-size: 200% 100%;
  animation: sk-shimmer 1.4s ease-in-out infinite;
  border-radius: 6px;
  display: block;
}
[data-theme="dark"] .skeleton,
[data-theme="dark"] .skeleton-line,
[data-theme="dark"] .skeleton-circle,
[data-theme="dark"] .skeleton-block {
  background: linear-gradient(90deg, #1e293b 0%, #334155 50%, #1e293b 100%);
  background-size: 200% 100%;
}
.skeleton-line       { height: 1rem; margin: 0.5rem 0; }
.skeleton-line.short { width: 40%; }
.skeleton-line.long  { width: 80%; }
.skeleton-line.full  { width: 100%; }
.skeleton-block      { height: 100px; }
.skeleton-circle     { border-radius: 50%; width: 40px; height: 40px; }
.skeleton-card {
  padding: 1.25rem;
  border: 1px solid var(--form-element-border-color);
  border-radius: var(--border-radius);
  background-color: var(--form-element-background-color);
}
.skeleton-stat-card {
  padding: 1.5rem;
  border-radius: 12px;
  background-color: var(--form-element-background-color);
  border: 1px solid var(--form-element-border-color);
}
.skeleton-stat-card .skeleton-line { margin: 0.35rem 0; }
.skeleton-row {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--form-element-border-color);
}
.skeleton-row:last-child { border-bottom: none; }
.skeleton-row .skeleton-body { flex: 1; }
.skeleton-hide { display: none !important; }

/* When JS is available, real content fades in on load */
.fade-in-loaded { animation: fadeIn 0.3s ease; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

/* ---- #16 : Bottom-fixed response bar (canvass, mobile) - */
.response-bar {
  display: none;  /* hidden on desktop by default; JS toggles on mobile */
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1050;
  background: #ffffff;
  border-top: 1px solid #e2e8f0;
  box-shadow: 0 -8px 24px -6px rgba(15, 23, 42, 0.18);
  padding: 0.5rem 0.5rem calc(0.5rem + env(safe-area-inset-bottom, 0px));
}
[data-theme="dark"] .response-bar {
  background: #0f172a;
  border-top-color: #1e293b;
}
.response-bar-inner {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.35rem;
}
.response-bar .rb-btn {
  min-height: 52px;
  border: none;
  border-radius: 10px;
  color: #ffffff;
  font-weight: 700;
  font-size: 0.78rem;
  padding: 0.4rem 0.35rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  line-height: 1.1;
  gap: 0.15rem;
  cursor: pointer;
  transition: transform 0.1s ease, filter 0.1s ease;
}
.response-bar .rb-btn:active { transform: scale(0.96); filter: brightness(0.9); }
.response-bar .rb-btn.rb-primary   { background: #15803d; }
.response-bar .rb-btn.rb-secondary { background: #65a30d; }
.response-bar .rb-btn.rb-neutral   { background: #ca8a04; color: #1f2937; }
.response-bar .rb-btn.rb-skip      { background: #64748b; }
.response-bar .rb-btn.rb-more      { background: #334155; }
.response-bar .rb-btn.selected {
  outline: 3px solid #fbbf24;
  outline-offset: -3px;
}
.response-bar [data-lucide] {
  width: 18px; height: 18px;
}

/* More-codes sheet (pops up over the page) */
.response-sheet-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.55);
  z-index: 1060;
  align-items: flex-end;
  justify-content: center;
}
.response-sheet-backdrop.open { display: flex; }
.response-sheet {
  background: #ffffff;
  width: 100%;
  max-width: 640px;
  border-radius: 16px 16px 0 0;
  padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -12px 40px -10px rgba(0, 0, 0, 0.5);
  animation: rs-slide-up 0.2s ease-out;
}
[data-theme="dark"] .response-sheet { background: #0f172a; color: #f1f5f9; }
@keyframes rs-slide-up {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}
.response-sheet-title {
  font-family: 'Inter', sans-serif;
  font-weight: 700;
  margin: 0 0 0.75rem;
  font-size: 1.1rem;
}
.response-sheet-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}
.response-sheet-grid .rb-btn {
  min-height: 54px;
  font-size: 0.88rem;
}
.response-sheet-close {
  width: 100%;
  padding: 0.75rem;
  background: #e2e8f0;
  color: #334155;
  border: none;
  border-radius: 10px;
  font-weight: 700;
  font-size: 0.95rem;
  cursor: pointer;
}
[data-theme="dark"] .response-sheet-close { background: #1e293b; color: #e2e8f0; }

/* Activate the bottom bar only on narrow screens */
@media (max-width: 720px) {
  .response-bar { display: block; }
  /* Give the canvass page extra bottom padding so the bar doesn't
     cover the last form field. */
  .canvass-container { padding-bottom: 140px; }
  /* Hide the old inline response-buttons grid only on mobile —
     desktop still gets the full grid. */
  .response-codes-inline { display: none; }
}

/* ---- #18 : PWA install banner ------------------------- */
.pwa-install-banner {
  position: fixed;
  left: 50%;
  bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  transform: translate(-50%, 200%);
  width: calc(100% - 2rem);
  max-width: 420px;
  background: #0f172a;
  color: #f1f5f9;
  border-radius: 14px;
  box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.4);
  z-index: 1100;
  transition: transform 0.25s ease;
  border: 1px solid #1e293b;
}
.pwa-install-banner.pwa-install-open { transform: translate(-50%, 0); }
.pwa-install-banner.pwa-install-closing { transform: translate(-50%, 200%); }
.pwa-install-inner {
  display: grid;
  grid-template-columns: 42px 1fr auto;
  grid-template-rows: auto auto;
  gap: 0.75rem;
  padding: 1rem 1.1rem;
  align-items: center;
}
.pwa-install-icon {
  grid-row: 1 / span 2;
  width: 42px; height: 42px;
  border-radius: 10px;
  background: #1e40af;
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pwa-install-icon svg { width: 22px; height: 22px; }
.pwa-install-text { grid-column: 2; }
.pwa-install-title {
  font-family: 'Inter', sans-serif;
  font-weight: 700;
  font-size: 0.95rem;
  margin-bottom: 0.2rem;
}
.pwa-install-body {
  font-size: 0.82rem;
  color: #cbd5e1;
  line-height: 1.4;
}
.pwa-install-actions {
  grid-column: 3;
  grid-row: 1 / span 2;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  align-self: center;
}
.pwa-install-btn {
  font-weight: 700;
  font-size: 0.82rem;
  padding: 0.5rem 0.9rem;
  border-radius: 8px;
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
}
.pwa-install-primary {
  background: #3b82f6;
  color: #ffffff;
}
.pwa-install-primary:hover { background: #2563eb; }
.pwa-install-secondary {
  background: transparent;
  color: #cbd5e1;
  border-color: #334155;
}
.pwa-install-secondary:hover { background: #1e293b; }

@media (max-width: 480px) {
  .pwa-install-inner {
    grid-template-columns: 42px 1fr;
    grid-template-rows: auto auto auto;
  }
  .pwa-install-actions {
    grid-column: 1 / span 2;
    grid-row: 3;
    flex-direction: row;
    justify-content: flex-end;
  }
}

/* ---- #20 : Branded route-list print stylesheet --------- */
/* Screen styles for route-list print preview page */
.route-list-print {
  background: #ffffff;
  color: #0f172a;
  font-family: 'Source Sans 3', system-ui, sans-serif;
  max-width: 820px;
  margin: 1rem auto;
  padding: 2rem;
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.08);
  border-radius: 8px;
}
.route-list-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  border-bottom: 3px solid #1e40af;
  padding-bottom: 1rem;
  margin-bottom: 1.25rem;
}
.route-list-brand {
  display: flex;
  gap: 0.8rem;
  align-items: center;
}
.route-list-brand-mark {
  width: 46px; height: 46px;
  border-radius: 10px;
  background: #1e40af;
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
}
.route-list-brand-mark svg { width: 26px; height: 26px; }
.route-list-brand-text h1 {
  font-family: 'Inter', sans-serif;
  margin: 0;
  font-size: 1.3rem;
  font-weight: 800;
  letter-spacing: -0.01em;
}
.route-list-brand-text p {
  margin: 0.15rem 0 0;
  color: #64748b;
  font-size: 0.88rem;
}
.route-list-meta {
  text-align: right;
  font-size: 0.82rem;
  color: #334155;
}
.route-list-meta strong { display: block; color: #0f172a; font-size: 1.05rem; margin-bottom: 0.15rem; }
.route-list-summary {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}
.route-list-summary .wl-stat {
  background: #f1f5f9;
  border: 1px solid #e2e8f0;
  padding: 0.75rem;
  border-radius: 8px;
  text-align: center;
}
.route-list-summary .wl-stat .wl-num {
  display: block;
  font-family: 'Inter', sans-serif;
  font-weight: 800;
  font-size: 1.4rem;
  color: #1e40af;
}
.route-list-summary .wl-stat small {
  display: block;
  font-size: 0.7rem;
  color: #64748b;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-top: 0.15rem;
}
.route-list-table {
  width: 100%;
  border-collapse: collapse;
  margin: 1rem 0;
  font-size: 0.88rem;
}
.route-list-table th {
  text-align: left;
  background: #1e40af;
  color: #ffffff;
  padding: 0.55rem 0.65rem;
  font-family: 'Inter', sans-serif;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
}
.route-list-table td {
  padding: 0.5rem 0.65rem;
  border-bottom: 1px solid #e2e8f0;
  vertical-align: top;
}
.route-list-table tbody tr:nth-child(even) { background: #f8fafc; }
.route-list-table .wl-response {
  display: inline-block;
  min-width: 20px;
  min-height: 20px;
  border: 2px solid #334155;
  border-radius: 4px;
  margin-right: 0.25rem;
  vertical-align: middle;
}
.route-list-footer {
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid #e2e8f0;
  display: flex;
  justify-content: space-between;
  font-size: 0.78rem;
  color: #64748b;
}
.route-list-print .no-print {
  text-align: center;
  margin-bottom: 1rem;
}
.route-list-print .no-print button {
  padding: 0.6rem 1.25rem;
  background: #1e40af;
  color: #ffffff;
  border: none;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
  margin-right: 0.5rem;
}

/* Actual print rules for the route list */
@media print {
  body { background: #ffffff !important; }
  .route-list-print {
    box-shadow: none !important;
    margin: 0 !important;
    padding: 0 !important;
    max-width: none !important;
  }
  .route-list-print .no-print,
  .route-list-print button { display: none !important; }
  .route-list-table { page-break-inside: auto; }
  .route-list-table tr { page-break-inside: avoid; page-break-after: auto; }
  .route-list-table thead { display: table-header-group; }
  .route-list-footer { page-break-inside: avoid; }
  @page {
    margin: 0.5in;
    @bottom-right { content: "Page " counter(page) " of " counter(pages); }
  }
}

/* ---- Turf overall progress summary + row ring layout (Phase C #9) ----- */
.turf-progress-summary {
  background: linear-gradient(135deg, #f8fafc 0%, #eff6ff 100%);
  border-left: 4px solid var(--brand, #1e40af);
}
[data-theme="dark"] .turf-progress-summary {
  background: linear-gradient(135deg, #1e293b 0%, #1e3a8a 100%);
}
.turf-progress-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2rem;
  align-items: center;
  padding: 0.5rem 0;
}
.turf-progress-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 1rem;
}
.turf-stat {
  padding: 0.75rem 0.5rem;
  background: #ffffff;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  text-align: center;
}
[data-theme="dark"] .turf-stat {
  background: #0f172a;
  border-color: #334155;
}
.turf-stat-value {
  font-family: 'Inter', sans-serif;
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--brand, #1e40af);
  line-height: 1.1;
}
[data-theme="dark"] .turf-stat-value { color: #93c5fd; }
.turf-stat-label {
  font-size: 0.7rem;
  color: var(--muted-color);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
  margin-top: 0.25rem;
}
@media (max-width: 640px) {
  .turf-progress-grid { grid-template-columns: 1fr; justify-items: center; }
}
.turf-row-progress {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.turf-row-progress-text {
  min-width: 55px;
}

/* Skeleton overlay for the map — sits above #map until tiles load. */
.skeleton-map {
  position: absolute;
  inset: 0;
  z-index: 450;
  background: #f8fafc;
  border-radius: inherit;
  transition: opacity 0.25s ease;
  pointer-events: none;
}
[data-theme="dark"] .skeleton-map { background: #0f172a; }
.map-wrapper { position: relative; }

/* =========================================================
   PHASE D — DESIGN SYSTEM OVERHAUL (2026-04-19)
   Implements 19 design picks from Design_Proposal_20_Suggestions.
   =========================================================
   S1 Palette:     Slate & Amber
   S2 Typography:  Source Serif 4 (headlines) + Inter (body/UI)
   S3 Logo:        Wordmark + ballot-check glyph (see base.html)
   S4 Buttons:     Subtle gradient + shadow
   S5 Badges:      Bold solid pills (white text, no outline)
   S6 Stat cards:  Big number + delta trend (Stripe-style)
   S7 Icons:       Lucide, stroke-width 1.75 (slightly finer)
   S8 Density:     Adaptive — relaxed mobile, dense desktop
   S9 Light/dark:  (no change, manual toggle kept)
   S10 Empty:      Narrative coach
   S11 Top nav:    Flat solid slate (no gradient)
   S12 Login:      Role chooser first
   S13 Dashboard:  Live-map control room
   S14 Volunteer:  Single-mission card
   S15 Canvass:    Map + list split
   S16 Survey:     Sticky bottom action buttons (extends existing)
   S17 Turf:       Card grid + progress bars
   S18 Reports:    Stat card + deltas
   S19 Offline:    Corner sync chip, always-on
   S20: (deferred — no pick)
   ========================================================= */

/* ============================================================
   S1 — NEW COLOR PALETTE: SLATE & AMBER
   Overrides the deep-blue brand tokens defined in Phase A.
   Cool slate primary (trust, civic) + warm amber accent (warmth,
   approachability). The slate is tuned to be distinctive from the
   old navy blue — cooler, more neutral, less "generic SaaS".
   ============================================================ */
:root {
  /* Primary — slate */
  --d-primary-50:  #f1f5f9;
  --d-primary-100: #e2e8f0;
  --d-primary-200: #cbd5e1;
  --d-primary-300: #94a3b8;
  --d-primary-400: #64748b;
  --d-primary-500: #475569;
  --d-primary-600: #334155;
  --d-primary-700: #1e293b;   /* main slate — top nav */
  --d-primary-800: #0f172a;   /* deep slate — headers */
  --d-primary-900: #020617;

  /* Accent — amber */
  --d-accent-50:  #fffbeb;
  --d-accent-100: #fef3c7;
  --d-accent-200: #fde68a;
  --d-accent-300: #fcd34d;
  --d-accent-400: #fbbf24;
  --d-accent-500: #f59e0b;    /* main amber — CTAs, highlights */
  --d-accent-600: #d97706;
  --d-accent-700: #b45309;

  /* Surface + text */
  --d-surface:        #ffffff;
  --d-surface-alt:    #f8fafc;
  --d-surface-muted:  #f1f5f9;
  --d-text:           #0f172a;
  --d-text-muted:     #475569;
  --d-text-faint:     #94a3b8;
  --d-border:         #e2e8f0;
  --d-border-strong:  #cbd5e1;

  /* Semantic */
  --d-success: #15803d;
  --d-warning: #b45309;
  --d-danger:  #b91c1c;
  --d-info:    #0369a1;

  /* Legacy --brand aliases now point at slate so existing
     components inherit the new palette without per-file edits. */
  --brand:      var(--d-primary-700);
  --brand-600:  var(--d-primary-600);
  --brand-700:  var(--d-primary-800);
  --brand-50:   var(--d-primary-50);

  /* Semantic aliases that used to be vibrant blues/greens — tuned
     down to a more professional slate-forward feel. */
  --info: var(--d-info);

  /* Touch targets keep the 48px floor from earlier phases. */
  --d-touch: 48px;

  /* Elevation tokens — slightly softer than Phase A */
  --d-shadow-1: 0 1px 2px rgba(15,23,42,.06), 0 1px 3px rgba(15,23,42,.04);
  --d-shadow-2: 0 2px 4px rgba(15,23,42,.06), 0 6px 14px rgba(15,23,42,.05);
  --d-shadow-3: 0 12px 20px -8px rgba(15,23,42,.14), 0 4px 8px -4px rgba(15,23,42,.08);
}

[data-theme="dark"] {
  --d-surface:        #0f172a;
  --d-surface-alt:    #1e293b;
  --d-surface-muted:  #334155;
  --d-text:           #f1f5f9;
  --d-text-muted:     #cbd5e1;
  --d-text-faint:     #64748b;
  --d-border:         #334155;
  --d-border-strong:  #475569;

  /* Keep accent amber vivid on dark */
  --d-accent-500: #fbbf24;
  --d-accent-600: #f59e0b;

  --brand:      var(--d-primary-200);
  --brand-600:  var(--d-primary-100);
  --brand-50:   var(--d-primary-700);

  --d-shadow-1: 0 1px 2px rgba(0,0,0,.5);
  --d-shadow-2: 0 6px 16px rgba(0,0,0,.55);
  --d-shadow-3: 0 16px 32px rgba(0,0,0,.6);
}

/* ============================================================
   S2 — TYPOGRAPHY: Source Serif 4 (headlines) + Inter (UI/body)
   Body goes to Inter (replacing Source Sans 3) for crisp UI reads,
   headings go to Source Serif 4 for a more considered, civic feel.
   Fonts are loaded in base.html.
   ============================================================ */
body {
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-feature-settings: 'cv11', 'ss01', 'ss03';  /* Inter refinements */
  color: var(--d-text);
}

h1, h2, h3,
.dashboard-header h1,
.welcome-banner h1,
.d-headline {
  font-family: 'Source Serif 4', 'Source Serif Pro', Georgia, 'Times New Roman', serif;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--d-text);
}

h4, h5, h6,
.stat-card-number, .stat-value,
.d-eyebrow {
  /* Smaller headings keep Inter for UI consistency */
  font-family: 'Inter', system-ui, sans-serif;
  letter-spacing: -0.005em;
}

/* An "eyebrow" micro-label style used above sections */
.d-eyebrow {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--d-text-muted);
  margin-bottom: 0.4rem;
}

/* ============================================================
   S4 — BUTTONS: Subtle gradient + shadow
   Overrides Phase A .btn-primary / .btn-secondary / .btn-danger
   to use gradient fills and a soft lift on hover. Uses
   !important to win over the earlier Phase A block.
   ============================================================ */
.btn-primary,
button.btn-primary,
a.btn-primary {
  background: linear-gradient(180deg, var(--d-primary-600) 0%, var(--d-primary-800) 100%) !important;
  color: #ffffff !important;
  border: 1px solid var(--d-primary-800) !important;
  box-shadow: 0 1px 0 rgba(255,255,255,0.12) inset,
              0 1px 2px rgba(15,23,42,0.18),
              0 4px 10px -2px rgba(15,23,42,0.15) !important;
  border-radius: 8px !important;
  padding: 0.7rem 1.3rem;
  font-weight: 600;
  transition: all 0.18s ease;
}
.btn-primary:hover,
button.btn-primary:hover,
a.btn-primary:hover {
  background: linear-gradient(180deg, var(--d-primary-500) 0%, var(--d-primary-700) 100%) !important;
  box-shadow: 0 1px 0 rgba(255,255,255,0.15) inset,
              0 3px 6px rgba(15,23,42,0.22),
              0 8px 20px -4px rgba(15,23,42,0.22) !important;
  transform: translateY(-1px);
}
.btn-primary:active {
  transform: translateY(0);
  box-shadow: 0 1px 2px rgba(15,23,42,0.15) inset !important;
}

/* Amber accent button — the "campaign CTA" style */
.btn-accent,
button.btn-accent,
a.btn-accent {
  display: inline-block;
  background: linear-gradient(180deg, var(--d-accent-400) 0%, var(--d-accent-600) 100%);
  color: #451a03;
  border: 1px solid var(--d-accent-700);
  padding: 0.7rem 1.3rem;
  font-weight: 700;
  border-radius: 8px;
  text-decoration: none;
  cursor: pointer;
  min-height: 44px;
  box-shadow: 0 1px 0 rgba(255,255,255,0.3) inset,
              0 1px 2px rgba(180,83,9,0.25),
              0 4px 10px -2px rgba(180,83,9,0.2);
  transition: all 0.18s ease;
}
.btn-accent:hover {
  background: linear-gradient(180deg, var(--d-accent-300) 0%, var(--d-accent-500) 100%);
  box-shadow: 0 1px 0 rgba(255,255,255,0.4) inset,
              0 3px 6px rgba(180,83,9,0.3),
              0 8px 18px -4px rgba(180,83,9,0.25);
  transform: translateY(-1px);
  color: #451a03;
  text-decoration: none;
}

.btn-secondary,
button.btn-secondary,
a.btn-secondary {
  background: linear-gradient(180deg, #ffffff 0%, var(--d-surface-muted) 100%) !important;
  color: var(--d-text) !important;
  border: 1px solid var(--d-border-strong) !important;
  box-shadow: 0 1px 2px rgba(15,23,42,0.06) !important;
  border-radius: 8px !important;
}
[data-theme="dark"] .btn-secondary {
  background: linear-gradient(180deg, var(--d-surface-alt) 0%, var(--d-primary-700) 100%) !important;
  color: var(--d-text) !important;
  border-color: var(--d-border) !important;
}

/* ============================================================
   S5 — BADGES: Bold solid pills (solid color, white text)
   Replaces the washed-out tinted pills with full-saturation pills
   for scan-ability. Opacity of 1.0; strong weight; no outline.
   ============================================================ */
.badge {
  border: none !important;
  font-weight: 700;
  letter-spacing: 0.01em;
  padding: 0.3rem 0.8rem;
  color: #ffffff !important;
  box-shadow: 0 1px 2px rgba(15,23,42,0.08);
}

.badge-active          { background-color: #15803d !important; }
.badge-paused          { background-color: #b45309 !important; }
.badge-completed       { background-color: #1e40af !important; }
.badge-inactive        { background-color: var(--d-primary-400) !important; }

.badge-strong-support  { background-color: #15803d !important; }
.badge-lean-support    { background-color: #65a30d !important; }
.badge-undecided       { background-color: #b45309 !important; }
.badge-lean-against    { background-color: #dc2626 !important; }
.badge-strong-against  { background-color: #7f1d1d !important; }
.badge-not-home        { background-color: var(--d-primary-400) !important; }
.badge-refused         { background-color: var(--d-primary-600) !important; }
.badge-wrong-address   { background-color: #ea580c !important; }
.badge-moved           { background-color: #c2410c !important; }
.badge-deceased        { background-color: #18181b !important; }
.badge-no-answer       { background-color: var(--d-primary-400) !important; }
.badge-wrong-number    { background-color: #7c3aed !important; }
.badge-do-not-call     { background-color: #7f1d1d !important; }

/* Dark-mode badges keep the same saturated pills (already white text). */
[data-theme="dark"] .badge { color: #ffffff !important; }

/* ============================================================
   S6 — STAT CARDS: Big number + delta (Stripe-style)
   Adds a delta indicator (Δ +12% vs prior) under each stat card
   number. Stat cards get a cleaner look with the left-border
   removed in favor of a subtle top accent bar.
   ============================================================ */
.stat-card {
  border-left: none !important;      /* kill the old left bar */
  border-top: 3px solid var(--d-primary-700);
  border-radius: 10px !important;
  padding: clamp(0.9rem, 2vw, 1.25rem) !important;
  background: var(--d-surface);
  box-shadow: var(--d-shadow-1);
  position: relative;
}
.stat-card.success { border-top-color: var(--d-success); }
.stat-card.warning { border-top-color: var(--d-accent-500); }
.stat-card.danger  { border-top-color: var(--d-danger); }
.stat-card.accent  { border-top-color: var(--d-accent-500); }

.stat-card-number {
  font-family: 'Inter', system-ui, sans-serif;
  font-size: clamp(1.6rem, 4.5vw, 2.4rem) !important;
  font-weight: 800 !important;
  line-height: 1 !important;
  color: var(--d-text) !important;
  letter-spacing: -0.02em;
  margin-bottom: 0.3rem !important;
}

.stat-card-label {
  font-size: 0.78rem !important;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600 !important;
  color: var(--d-text-muted) !important;
}

/* Delta indicator — trend arrow + pct change vs prior */
.stat-card-delta {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.78rem;
  font-weight: 600;
  margin-top: 0.5rem;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  background: var(--d-surface-muted);
  color: var(--d-text-muted);
  font-feature-settings: 'tnum';   /* tabular numerals */
}
.stat-card-delta.up    { background: rgba(21,128,61,0.12);  color: #15803d; }
.stat-card-delta.down  { background: rgba(185,28,28,0.12);  color: #b91c1c; }
.stat-card-delta.flat  { background: var(--d-surface-muted); color: var(--d-text-muted); }
.stat-card-delta svg,
.stat-card-delta [data-lucide] { width: 14px; height: 14px; }

/* Optional tiny sparkline — rendered as inline SVG from templates */
.stat-card-spark {
  margin-top: 0.5rem;
  height: 28px;
  display: block;
  width: 100%;
}
.stat-card-spark path { fill: none; stroke: var(--d-primary-500); stroke-width: 1.5; }
.stat-card.success .stat-card-spark path { stroke: var(--d-success); }
.stat-card.warning .stat-card-spark path { stroke: var(--d-accent-500); }
.stat-card.danger  .stat-card-spark path { stroke: var(--d-danger); }

/* ============================================================
   S7 — LUCIDE ICONS: refine stroke weight
   Slightly finer stroke (1.75 vs default 2) feels more modern.
   Sizes stay on the pre-existing Phase A default.
   ============================================================ */
[data-lucide] {
  stroke-width: 1.75;
}

/* ============================================================
   S8 — ADAPTIVE DENSITY: relaxed mobile, dense desktop
   Uses CSS clamp + a single --d-density var to scale spacing.
   Touch targets are preserved on mobile (44-48px minimum).
   ============================================================ */
:root { --d-density: 1; }   /* mobile default — relaxed */
@media (min-width: 1024px) {
  :root { --d-density: 0.75; }  /* desktop — denser */
}

main.container {
  padding-top: calc(1.25rem * var(--d-density));
  padding-bottom: calc(1.5rem * var(--d-density));
}

/* Tighter table rows on desktop, roomier on mobile */
table th, table td {
  padding-top: calc(0.7rem * var(--d-density));
  padding-bottom: calc(0.7rem * var(--d-density));
}

/* Denser form stacks on desktop */
.form-row, .form-section {
  gap: calc(0.75rem * var(--d-density));
}

/* ============================================================
   S10 — EMPTY STATES: Narrative coach
   Doubles as in-app training. Each empty state gets a heading,
   a short coaching blurb, and one clear next-step button.
   ============================================================ */
.empty-coach {
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 14px;
  padding: clamp(1.5rem, 4vw, 2.5rem);
  text-align: center;
  max-width: 640px;
  margin: 1.5rem auto;
  box-shadow: var(--d-shadow-1);
}
.empty-coach-icon {
  width: 56px;
  height: 56px;
  margin: 0 auto 1rem;
  border-radius: 14px;
  background: linear-gradient(135deg, var(--d-primary-50) 0%, var(--d-accent-100) 100%);
  color: var(--d-primary-700);
  display: flex;
  align-items: center;
  justify-content: center;
}
.empty-coach-icon [data-lucide] { width: 28px; height: 28px; }
.empty-coach h2, .empty-coach h3 {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 1.35rem;
  margin: 0 0 0.5rem;
}
.empty-coach-body {
  color: var(--d-text-muted);
  font-size: 0.98rem;
  line-height: 1.55;
  margin: 0 auto 1.2rem;
  max-width: 480px;
}
.empty-coach-steps {
  text-align: left;
  max-width: 440px;
  margin: 1rem auto 1.2rem;
  padding: 0;
  list-style: none;
  counter-reset: coachstep;
}
.empty-coach-steps li {
  position: relative;
  padding: 0.5rem 0 0.5rem 2.4rem;
  color: var(--d-text-muted);
  font-size: 0.93rem;
  line-height: 1.45;
  counter-increment: coachstep;
}
.empty-coach-steps li::before {
  content: counter(coachstep);
  position: absolute;
  left: 0;
  top: 0.45rem;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 999px;
  background: var(--d-primary-700);
  color: #ffffff;
  font-family: 'Inter', sans-serif;
  font-weight: 700;
  font-size: 0.8rem;
  display: flex;
  align-items: center;
  justify-content: center;
}
.empty-coach-actions {
  display: flex;
  justify-content: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

/* ============================================================
   S11 — TOP NAV: Flat solid slate (drop the Phase A gradient)
   Overrides the gradient rule in base.html <style> and the Phase A
   body > nav rule. Uses a solid slate background for a calmer,
   more civic look.
   ============================================================ */
body > nav {
  background: var(--d-primary-700) !important;
  background-image: none !important;
  box-shadow: 0 1px 0 rgba(255,255,255,0.05) inset,
              0 2px 6px rgba(15,23,42,0.12) !important;
  border-bottom: 1px solid var(--d-primary-800) !important;
}
body > nav strong {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 600;
  font-size: 1.1rem;
}
body > nav a[aria-current="page"] {
  background-color: var(--d-primary-500) !important;
  color: #ffffff !important;
}

/* Ballot-check logo glyph (used inside base.html nav <strong>) */
.d-logo {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: #ffffff;
  text-decoration: none;
}
.d-logo-mark {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: var(--d-accent-500);
  color: var(--d-primary-800);
  box-shadow: 0 1px 2px rgba(0,0,0,0.2), 0 1px 0 rgba(255,255,255,0.2) inset;
}
.d-logo-mark svg { width: 18px; height: 18px; }
.d-logo-text {
  font-family: 'Source Serif 4', Georgia, serif;
  font-weight: 600;
  letter-spacing: -0.01em;
  font-size: 1.1rem;
  color: #ffffff;
}

/* ============================================================
   S12 — LOGIN: Role chooser first
   Users pick "I'm canvassing" vs "I'm running the campaign"
   before seeing the credentials form. Implemented in login.html.
   ============================================================ */
.role-chooser {
  max-width: 720px;
  margin: 2rem auto;
}
.role-chooser h1 {
  text-align: center;
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: clamp(1.6rem, 4vw, 2.1rem);
  margin-bottom: 0.5rem;
}
.role-chooser-sub {
  text-align: center;
  color: var(--d-text-muted);
  margin-bottom: 2rem;
  font-size: 1rem;
}
.role-chooser-grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
}
@media (min-width: 640px) {
  .role-chooser-grid { grid-template-columns: 1fr 1fr; }
}
.role-card {
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 14px;
  padding: 1.5rem 1.25rem;
  text-align: center;
  text-decoration: none;
  color: var(--d-text);
  cursor: pointer;
  transition: all 0.2s ease;
  box-shadow: var(--d-shadow-1);
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 220px;
}
.role-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--d-shadow-3);
  border-color: var(--d-primary-300);
  color: var(--d-text);
  text-decoration: none;
}
.role-card-icon {
  width: 64px; height: 64px;
  border-radius: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1rem;
  background: linear-gradient(135deg, var(--d-primary-50) 0%, var(--d-accent-100) 100%);
  color: var(--d-primary-700);
}
.role-card-icon [data-lucide] { width: 30px; height: 30px; }
.role-card.is-admin .role-card-icon {
  background: linear-gradient(135deg, var(--d-primary-100) 0%, var(--d-primary-300) 100%);
}
.role-card.is-volunteer .role-card-icon {
  background: linear-gradient(135deg, var(--d-accent-100) 0%, var(--d-accent-300) 100%);
  color: var(--d-primary-800);
}
.role-card h2 {
  font-family: 'Source Serif 4', Georgia, serif;
  font-size: 1.2rem;
  margin: 0 0 0.4rem;
}
.role-card p {
  color: var(--d-text-muted);
  font-size: 0.9rem;
  margin: 0;
  line-height: 1.45;
}
.role-chooser-footer {
  text-align: center;
  margin-top: 1.5rem;
  font-size: 0.88rem;
  color: var(--d-text-muted);
}

/* The login form shown after a role is picked */
.role-login-form {
  max-width: 400px;
  margin: 1.5rem auto;
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 14px;
  padding: 1.75rem 1.5rem;
  box-shadow: var(--d-shadow-2);
}
.role-login-back {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--d-text-muted);
  text-decoration: none;
  font-size: 0.85rem;
  margin-bottom: 1rem;
}
.role-login-back:hover { color: var(--d-text); }

/* Visibility state toggled by JS on login.html */
.role-chooser[hidden],
.role-login-form[hidden] { display: none !important; }

/* ============================================================
   S13 — ADMIN DASHBOARD: Live-map control room (RADICAL)
   The map is the dashboard. KPI chips float above it. A left
   rail lists turfs with live progress. Collapses stacked on
   mobile (map on top, chips below, list below).
   ============================================================ */
.control-room {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  grid-template-areas:
    "chips"
    "map"
    "rail";
}
@media (min-width: 1024px) {
  .control-room {
    grid-template-columns: 320px 1fr;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "chips chips"
      "rail map";
    min-height: calc(100vh - 180px);
  }
}
.control-room-chips { grid-area: chips; }
.control-room-map   { grid-area: map; }
.control-room-rail  { grid-area: rail; }

.kpi-chips {
  display: grid;
  /* 2026-05-14 (#78): widened from 140px to 180px so 7-digit voter
     counts (4,064,093 etc.) don't wrap onto two lines inside a chip. */
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.6rem;
}
.kpi-chip {
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 12px;
  padding: 0.75rem 0.9rem;
  box-shadow: var(--d-shadow-1);
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.kpi-chip-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 700;
  color: var(--d-text-muted);
}
.kpi-chip-value {
  font-family: 'Inter', sans-serif;
  font-size: 1.4rem;
  font-weight: 800;
  line-height: 1;
  color: var(--d-text);
  letter-spacing: -0.02em;
  font-feature-settings: 'tnum';
  /* 2026-05-14 (#78): keep large numeric values on one line. */
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.kpi-chip-trend {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--d-text-muted);
  margin-top: 0.1rem;
}
.kpi-chip-trend.up   { color: var(--d-success); }
.kpi-chip-trend.down { color: var(--d-danger); }

.control-room-rail {
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 12px;
  padding: 0.75rem;
  overflow: auto;
  max-height: 70vh;
}
.control-room-rail h3 {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--d-text-muted);
  margin: 0.25rem 0 0.75rem;
  font-family: 'Inter', sans-serif;
}
.rail-turf {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.6rem 0.5rem;
  border-radius: 8px;
  border-bottom: 1px solid var(--d-border);
  gap: 0.5rem;
  text-decoration: none;
  color: var(--d-text);
}
.rail-turf:last-child { border-bottom: none; }
.rail-turf:hover { background: var(--d-surface-muted); text-decoration: none; color: var(--d-text); }
.rail-turf-name { font-weight: 600; font-size: 0.9rem; }
.rail-turf-sub  { font-size: 0.75rem; color: var(--d-text-muted); }
.rail-turf-pct  {
  font-family: 'Inter', sans-serif;
  font-weight: 700;
  font-size: 0.85rem;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: var(--d-surface-muted);
  color: var(--d-text-muted);
  white-space: nowrap;
}
.rail-turf-pct.ok   { background: rgba(21,128,61,0.12);  color: var(--d-success); }
.rail-turf-pct.warn { background: rgba(180,83,9,0.12);   color: var(--d-warning); }
.rail-turf-pct.bad  { background: rgba(185,28,28,0.12);  color: var(--d-danger); }

.control-room-map {
  position: relative;
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 12px;
  overflow: hidden;
  min-height: 460px;
}
.control-room-map .leaflet-container {
  height: 100%;
  min-height: 460px;
}

/* ============================================================
   S14 — VOLUNTEER HOME: Single-mission card
   One card, one turf, one giant CTA. No dashboard overwhelm.
   ============================================================ */
.mission-card {
  max-width: 640px;
  margin: 1rem auto;
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 18px;
  box-shadow: var(--d-shadow-2);
  overflow: hidden;
  position: relative;
}
.mission-header {
  background: linear-gradient(135deg, var(--d-primary-700) 0%, var(--d-primary-800) 100%);
  color: #ffffff;
  padding: 1.5rem 1.5rem 1.25rem;
}
.mission-header-eyebrow {
  display: inline-block;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
  color: var(--d-accent-300);
  margin-bottom: 0.5rem;
}
.mission-header h1 {
  color: #ffffff;
  margin: 0 0 0.25rem;
  font-size: clamp(1.4rem, 4vw, 1.75rem);
}
.mission-header-sub {
  color: var(--d-primary-200);
  font-size: 0.95rem;
  margin: 0;
}
.mission-body {
  padding: 1.25rem 1.5rem 1.5rem;
}
.mission-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
  margin-bottom: 1.25rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px dashed var(--d-border);
}
.mission-stat {
  text-align: center;
}
.mission-stat-value {
  display: block;
  font-family: 'Inter', sans-serif;
  font-weight: 800;
  font-size: clamp(1.3rem, 4vw, 1.7rem);
  color: var(--d-text);
  letter-spacing: -0.02em;
  font-feature-settings: 'tnum';
}
.mission-stat-label {
  font-size: 0.72rem;
  color: var(--d-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 600;
}

.mission-cta {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.mission-cta > * { flex: 1 1 auto; }
.mission-cta .btn-primary,
.mission-cta .btn-accent {
  min-height: 56px;
  font-size: 1.05rem;
  font-weight: 700;
  padding: 0.9rem 1.25rem;
}

/* An empty state version of the mission card — used on the
   volunteer home when no turf is assigned yet. */
.mission-card.is-empty .mission-header {
  background: linear-gradient(135deg, var(--d-primary-500) 0%, var(--d-primary-700) 100%);
}
.mission-card.is-empty .mission-stats { display: none; }

/* ============================================================
   S15 — CANVASS MAP: Map + list split
   On desktop: map takes ~65%, address list panel ~35%.
   On mobile: map on top (viewport-scaled), list below, both
   scrollable independently.
   ============================================================ */
.canvass-split {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: minmax(320px, 55vh) auto;
  gap: 0.75rem;
}
@media (min-width: 1024px) {
  .canvass-split {
    grid-template-columns: 1.85fr 1fr;
    grid-template-rows: 1fr;
    min-height: calc(100vh - 180px);
  }
}
.canvass-split-map {
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 12px;
  overflow: hidden;
  position: relative;
}
.canvass-split-map .map-container,
.canvass-split-map #map {
  height: 100%;
  min-height: 320px;
  margin: 0;
  border: none;
  border-radius: 0;
}
.canvass-split-list {
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  max-height: 60vh;
}
@media (min-width: 1024px) {
  .canvass-split-list { max-height: none; }
}
.canvass-split-list-header {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--d-border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--d-surface-muted);
}
.canvass-split-list-header h3 {
  margin: 0;
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--d-text-muted);
}
.canvass-split-list-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 0.5rem;
}

/* ============================================================
   S17 — TURF LIST: Card grid + progress bars
   Already partially present; normalized into a consistent card
   grid with visible progress bars on every card.
   ============================================================ */
.turf-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1rem;
}
.turf-card {
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 12px;
  padding: 1rem 1.1rem;
  box-shadow: var(--d-shadow-1);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  transition: all 0.2s ease;
}
.turf-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--d-shadow-2);
  border-color: var(--d-primary-300);
}
.turf-card-title {
  font-family: 'Inter', sans-serif;
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--d-text);
  margin: 0;
}
.turf-card-sub {
  font-size: 0.83rem;
  color: var(--d-text-muted);
}
.turf-card-progress {
  margin-top: 0.4rem;
}
.turf-card-progress-bar {
  width: 100%;
  height: 10px;
  background: var(--d-surface-muted);
  border-radius: 999px;
  overflow: hidden;
}
.turf-card-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--d-primary-500), var(--d-success));
  border-radius: 999px;
  transition: width 0.4s ease;
}
.turf-card-progress-label {
  display: flex;
  justify-content: space-between;
  font-size: 0.78rem;
  color: var(--d-text-muted);
  margin-bottom: 0.2rem;
}
.turf-card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 0.4rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--d-border);
}

/* ============================================================
   S18 — REPORTS: Stat card + deltas
   Reuses .stat-card + .stat-card-delta from S6.
   Report header gets a "vs prior period" compare selector.
   ============================================================ */
.report-compare {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin: 0.5rem 0 1rem;
  font-size: 0.88rem;
  color: var(--d-text-muted);
}
.report-compare label {
  font-weight: 600;
  color: var(--d-text);
}
.report-compare select {
  min-height: 36px;
  padding: 0.3rem 0.6rem;
  border-radius: 8px;
  border: 1px solid var(--d-border-strong);
  background: var(--d-surface);
  color: var(--d-text);
}

/* ============================================================
   S19 — OFFLINE: Corner sync chip, always-on
   A small pill in the bottom-right of the viewport, always
   visible to signed-in users. Shows sync state at a glance.
   ============================================================ */
.sync-chip {
  position: fixed;
  right: 1rem;
  bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  z-index: 1040;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.5rem 0.85rem;
  background: var(--d-surface);
  border: 1px solid var(--d-border);
  border-radius: 999px;
  box-shadow: var(--d-shadow-2);
  font-family: 'Inter', sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--d-text);
  cursor: default;
  pointer-events: auto;
  transition: all 0.2s ease;
}
.sync-chip-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--d-primary-400);
  flex-shrink: 0;
  box-shadow: 0 0 0 2px var(--d-surface);
}
.sync-chip[data-state="online"]  .sync-chip-dot { background: var(--d-success); }
.sync-chip[data-state="syncing"] .sync-chip-dot {
  background: var(--d-accent-500);
  animation: syncPulse 1.3s ease-in-out infinite;
}
.sync-chip[data-state="offline"] .sync-chip-dot { background: var(--d-danger); }
.sync-chip[data-state="offline"] { border-color: rgba(185,28,28,0.4); }

@keyframes syncPulse {
  0%, 100% { transform: scale(1);   box-shadow: 0 0 0 2px var(--d-surface); }
  50%      { transform: scale(1.4); box-shadow: 0 0 0 4px rgba(245,158,11,0.2); }
}
[data-theme="dark"] .sync-chip-dot { box-shadow: 0 0 0 2px var(--d-surface); }

/* Hide sync chip on print (already hidden by global print rule
   via `nav` selector, but be explicit) */
@media print {
  .sync-chip { display: none !important; }
}

/* Give the page a little bottom padding on mobile so the chip
   doesn't overlap footer content. Does not affect pages that
   already pad for the response bar (canvass). */
@media (max-width: 720px) {
  body { padding-bottom: calc(3rem + env(safe-area-inset-bottom, 0px)); }
}

/* ============================================================
   ADAPTIVE ACCENT for pre-existing components
   Re-tint a few things that were hardcoded to the old blue.
   ============================================================ */
.stat-card-number { color: var(--d-text); }
.map-layer-toggle button.active { background: var(--d-primary-700); }
.pwa-install-icon { background: var(--d-primary-700); }
.pwa-install-primary { background: var(--d-accent-500); color: #451a03; }
.pwa-install-primary:hover { background: var(--d-accent-600); }
.turf-progress-summary {
  background: linear-gradient(135deg, var(--d-surface-muted) 0%, var(--d-primary-50) 100%);
  border-left-color: var(--d-primary-700);
}
.turf-stat-value { color: var(--d-primary-700); }
[data-theme="dark"] .turf-stat-value { color: var(--d-accent-300); }

/* Links use the slate primary (calmer than blue) */
a { color: var(--d-primary-700); }
a:hover { color: var(--d-primary-800); }
[data-theme="dark"] a { color: var(--d-accent-300); }
[data-theme="dark"] a:hover { color: var(--d-accent-200); }

/* =========================================================
   END OF PHASE D
   ========================================================= */


/* ============================================================
   Breadcrumbs (Batch 2 #3)
   Slot is in base.html; each page overrides the block.
   ============================================================ */
.breadcrumbs {
  display: block;
  margin: 0.5rem auto 0 !important;
  padding: 0.4rem 0 !important;
  font-size: 0.85rem;
  color: var(--d-text-muted);
  background: transparent !important;
  background-color: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  min-height: 0 !important;
}
nav.breadcrumbs ul,
nav.breadcrumbs ol { padding: 0; margin: 0; list-style: none; }
.breadcrumbs:empty { display: none; }
.breadcrumbs a {
  color: var(--d-text-muted);
  text-decoration: none;
  transition: color 0.12s ease;
}
.breadcrumbs a:hover { color: var(--d-primary-600); text-decoration: underline; }
.breadcrumbs .sep {
  margin: 0 0.4rem;
  color: var(--d-border-strong, #cbd5e1);
}
.breadcrumbs .cur {
  color: var(--d-text);
  font-weight: 600;
}

/* ============================================================
   Segmented control (Batch 2 #10)
   Used to replace the Date Range dropdown with always-visible
   buttons inline with the page title.
   ============================================================ */
.seg-control {
  display: inline-flex;
  background: var(--d-surface-2, #f1f5f9);
  border-radius: 8px;
  padding: 3px;
  gap: 2px;
}
.seg-control button,
.seg-control .seg-opt {
  background: transparent;
  border: 0;
  padding: 0.4rem 0.85rem;
  font: 0.85rem/1 'Inter', sans-serif;
  font-weight: 600;
  border-radius: 6px;
  cursor: pointer;
  color: var(--d-text-muted);
  white-space: nowrap;
  transition: all 0.12s ease;
}
.seg-control button:hover,
.seg-control .seg-opt:hover { color: var(--d-text); }
.seg-control .seg-opt.on,
.seg-control button.on {
  background: #fff;
  color: var(--d-text);
  box-shadow: 0 1px 2px rgba(15,23,42,0.08);
}
[data-theme="dark"] .seg-control { background: rgba(255,255,255,0.06); }
[data-theme="dark"] .seg-control .seg-opt.on { background: var(--d-surface-2); }

/* ============================================================
   KPI zero-state encouragement link (Batch 2 #11)
   When a KPI chip's value is zero on a fresh campaign, the trend
   line becomes an actionable suggestion instead of "no change".
   ============================================================ */
.kpi-chip-trend a.kpi-zero-cta {
  color: var(--d-primary-600);
  font-weight: 600;
  text-decoration: none;
}
.kpi-chip-trend a.kpi-zero-cta:hover { text-decoration: underline; }
.kpi-chip[data-zero="true"] .kpi-chip-value { color: var(--d-text-muted); }

/* ────────────────────────────────────────────────────────────────
   Help center styles — added 2026-05-19 with the /help blueprint.
   Append to static/css/app.css.
   ──────────────────────────────────────────────────────────────── */

/* Breadcrumb row with back-to-dashboard button */
.help-breadcrumb {
  background: var(--card-background-color, #fff);
  border-bottom: 1px solid var(--muted-border-color, #e2e8f0);
  padding: 0.6rem 1.25rem;
  font-size: 0.9rem;
  color: var(--muted-color, #64748b);
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}
.help-breadcrumb a { color: #1e3a5f; text-decoration: none; }
.help-breadcrumb a:hover { text-decoration: underline; }
.help-breadcrumb .back-to-dash {
  font-weight: 600;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--muted-border-color, #e2e8f0);
  border-radius: 5px;
  background: var(--background-color, #f8fafc);
}
.help-breadcrumb .back-to-dash:hover {
  background: #e2e8f0;
  text-decoration: none;
}
.help-breadcrumb .sep,
.help-breadcrumb .crumb-sep { color: #94a3b8; }
.help-breadcrumb .crumb-current { color: var(--muted-color, #64748b); }

/* Two-column layout: sidebar + content */
.help-layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 2.5rem;
  align-items: start;
}
@media (max-width: 800px) {
  .help-layout {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }
}

/* Sidebar */
.help-toc h3 {
  font-family: 'Source Serif 4', serif;
  font-size: 0.9rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted-color, #64748b);
  margin: 0 0 0.75rem;
}
.help-toc ul {
  list-style: none;
  margin: 0; padding: 0;
}
.help-toc li { margin-bottom: 0.15rem; }
.help-toc a {
  display: block;
  padding: 0.4rem 0.75rem;
  border-radius: 5px;
  color: var(--color, #334155);
  text-decoration: none;
  font-size: 0.92rem;
}
.help-toc a:hover {
  background: var(--background-color, #f1f5f9);
}
.help-toc a.current {
  background: #1e3a5f;
  color: #fff;
  font-weight: 500;
}

/* Content column */
.help-content {
  background: var(--card-background-color, #fff);
  border: 1px solid var(--muted-border-color, #e2e8f0);
  border-radius: 10px;
  padding: 2.25rem 2.5rem;
}
.help-hero h1 {
  font-family: 'Source Serif 4', serif;
  font-size: 2rem;
  margin: 0 0 0.4rem;
}
.help-lede {
  color: var(--muted-color, #64748b);
  margin-bottom: 2rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--muted-border-color, #e2e8f0);
}

/* Category sections on the index */
.help-category { margin-bottom: 2.5rem; }
.help-category > h2 {
  font-family: 'Source Serif 4', serif;
  font-size: 1.3rem;
  margin: 0 0 1rem;
  color: var(--color, #0f172a);
}
.help-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 1rem;
}
.help-card {
  display: block;
  background: var(--background-color, #f8fafc);
  border: 1px solid var(--muted-border-color, #e2e8f0);
  border-radius: 8px;
  padding: 1.1rem 1.25rem;
  text-decoration: none;
  color: inherit;
  transition: box-shadow .15s ease, transform .15s ease;
}
.help-card:hover {
  box-shadow: 0 4px 12px rgba(15,23,42,0.08);
  transform: translateY(-1px);
  text-decoration: none;
}
.help-card h3 {
  font-family: 'Source Serif 4', serif;
  font-size: 1.05rem;
  margin: 0 0 0.4rem;
  color: #1e3a5f;
}
.help-card p {
  font-size: 0.9rem;
  color: var(--muted-color, #475569);
  margin: 0 0 0.6rem;
}
.help-card-cta {
  font-size: 0.85rem;
  font-weight: 600;
  color: #1e3a5f;
}

/* Article body */
.help-article h1 {
  font-family: 'Source Serif 4', serif;
  font-size: 1.9rem;
  margin: 0 0 0.4rem;
}
.help-article .help-meta {
  color: var(--muted-color, #64748b);
  font-size: 0.85rem;
  margin-bottom: 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--muted-border-color, #e2e8f0);
}
.help-article h2 {
  font-family: 'Source Serif 4', serif;
  font-size: 1.3rem;
  margin: 1.75rem 0 0.65rem;
  color: var(--color, #0f172a);
}
.help-article h3 {
  font-family: 'Source Serif 4', serif;
  font-size: 1.05rem;
  margin: 1.4rem 0 0.5rem;
}
.help-article p { margin: 0 0 1rem; line-height: 1.6; }
.help-article ol, .help-article ul { margin: 0 0 1.1rem; padding-left: 1.5rem; }
.help-article li { margin-bottom: 0.4rem; line-height: 1.55; }
.help-article .callout {
  background: #fef9e7;
  border-left: 4px solid #f59e0b;
  padding: 0.85rem 1.1rem;
  margin: 1.1rem 0;
  border-radius: 0 6px 6px 0;
  color: #78350f;
}
.help-article .callout strong { color: #78350f; }

/* Prev/next nav at the bottom of an article */
.help-prev-next {
  margin-top: 2.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--muted-border-color, #e2e8f0);
  display: flex;
  justify-content: space-between;
  gap: 1rem;
}
.help-prev-next a {
  color: #1e3a5f;
  text-decoration: none;
  font-weight: 500;
  font-size: 0.92rem;
}
.help-prev-next a:hover { text-decoration: underline; }

.help-footer-note {
  margin-top: 2rem;
  padding: 1rem 1.25rem;
  background: var(--background-color, #f1f5f9);
  border-left: 3px solid #1e3a5f;
  border-radius: 0 6px 6px 0;
  color: var(--muted-color, #475569);
  font-size: 0.92rem;
}


/* ────────────────────────────────────────────────────────────────
   Setup-checklist widget — added 2026-05-19 with onboarding Phase 1.
   Shows on the admin dashboard until all 4 milestones are complete,
   then disappears automatically.
   ──────────────────────────────────────────────────────────────── */
.onboarding-checklist {
  background: linear-gradient(135deg, #fff 0%, #f8fafc 100%);
  border: 1px solid #cbd5e1;
  border-left: 4px solid #1e3a5f;
  border-radius: 10px;
  padding: 1.5rem 1.75rem;
  margin: 0 0 1.5rem;
  box-shadow: 0 2px 8px rgba(15,23,42,0.05);
}
.onboarding-checklist-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  margin-bottom: 1.25rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid #e2e8f0;
}
.onboarding-checklist-header h2 {
  font-family: 'Source Serif 4', serif;
  font-size: 1.35rem;
  margin: 0 0 0.3rem;
  color: #0f172a;
}
.onboarding-lede {
  margin: 0;
  color: #475569;
  font-size: 0.92rem;
  max-width: 60ch;
}
.onboarding-progress {
  text-align: right;
  flex-shrink: 0;
}
.onboarding-progress-count {
  display: block;
  font-family: 'Source Serif 4', serif;
  font-size: 1.8rem;
  font-weight: 700;
  color: #1e3a5f;
  line-height: 1;
}
.onboarding-progress-label {
  font-size: 0.8rem;
  color: #64748b;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.onboarding-steps {
  list-style: none;
  margin: 0;
  padding: 0;
}
.onboarding-step {
  display: flex;
  gap: 0.85rem;
  padding: 0.65rem 0;
  border-bottom: 1px dashed #e2e8f0;
}
.onboarding-step:last-child { border-bottom: none; }

.onboarding-step-check {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #cbd5e1;
  color: #64748b;
  font-weight: 700;
  font-size: 0.95rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.onboarding-step.done .onboarding-step-check {
  background: #1e3a5f;
  border-color: #1e3a5f;
  color: #fff;
}
.onboarding-step-body { flex: 1; min-width: 0; }
.onboarding-step-title {
  font-weight: 600;
  font-size: 0.98rem;
  color: #0f172a;
  margin-bottom: 0.15rem;
}
.onboarding-step.done .onboarding-step-title {
  color: #64748b;
  text-decoration: line-through;
  text-decoration-color: rgba(100,116,139,0.4);
}
.onboarding-step-title a {
  color: #1e3a5f;
  text-decoration: none;
}
.onboarding-step-title a:hover { text-decoration: underline; }
.onboarding-step-meta {
  font-size: 0.85rem;
  color: #64748b;
}
.onboarding-step-help {
  margin-left: 0.4rem;
  color: #1e3a5f;
  text-decoration: none;
  font-weight: 500;
  white-space: nowrap;
}
.onboarding-step-help:hover { text-decoration: underline; }

@media (max-width: 640px) {
  .onboarding-checklist { padding: 1.25rem 1rem; }
  .onboarding-checklist-header { flex-direction: column; align-items: flex-start; }
  .onboarding-progress { text-align: left; }
}


/* ===== 2026-05-25 (11B): Defensive iOS auto-zoom prevention =====
   iOS Safari auto-zooms when a user taps any input/textarea/select whose
   font-size is below 16px. This rule guarantees a minimum 16px on form
   elements sitewide so future component additions can't regress. Pages
   that need smaller form fonts (e.g., dense admin tables) can override
   per-page with a more specific selector. */
input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]),
textarea,
select {
  font-size: max(16px, 1rem);
}
