/* ═══════════════════════════════════════════════════════════════
   Admin booking link row
   The Location info card has a row showing the per-location admin
   booking URL (/admin/book/:slug) with a Copy button. Mono path,
   tucked inputs, small action buttons — keeps the row compact in
   the form layout without dominating.
   ═══════════════════════════════════════════════════════════════ */
.booking-link-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.booking-link-path {
  flex: 1 1 auto;
  min-width: 0;
  padding: 8px 12px;
  background: var(--card-tint, #FAF7F1);
  border: 1px solid var(--border-soft, rgba(39, 41, 54, 0.10));
  border-radius: 8px;
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.88rem;
  color: var(--text);
  white-space: nowrap;
  overflow-x: auto;
  user-select: all;
}
.booking-link-copy {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: 0 0 auto;
}

/* ═══════════════════════════════════════════════════════════════
   ZIP → tech assignment rows
   One row per ZIP, with a 5-digit numeric input, an arrow, a tech
   <select>, and a remove button. The server expects sequential
   indices (zip_techs[0]..[N-1]); the JS re-indexes after every
   add/remove so qs parsing on the server stays consistent.
   ═══════════════════════════════════════════════════════════════ */
.zip-tech-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}
.zip-tech-empty {
  margin: 4px 0 0;
  color: var(--text-muted, rgba(39, 41, 54, 0.7));
}
.zip-tech-row {
  display: grid;
  grid-template-columns: 110px 16px 1fr 32px;
  gap: 10px;
  align-items: center;
}
.zip-tech-zip {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid rgba(39, 41, 54, 0.12);
  border-radius: 8px;
  padding: 8px 12px;
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.95rem;
  letter-spacing: 0.04em;
  color: var(--text);
  background: #fff;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.zip-tech-zip:focus {
  outline: none;
  border-color: transparent;
  box-shadow: var(--sw-focus-shadow, 0 0 0 1px #F38A3F, 0 6px 13px rgba(243, 138, 63, 0.30));
}
.zip-tech-arrow {
  color: var(--text-muted, rgba(39, 41, 54, 0.5));
  text-align: center;
  font-size: 0.95rem;
  user-select: none;
}
.zip-tech-select {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid rgba(39, 41, 54, 0.12);
  border-radius: 8px;
  padding: 8px 36px 8px 12px;
  font-size: 0.95rem;
  color: var(--text);
  background-color: #fff;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23272936' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'><path d='M4 6l4 4 4-4'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 14px;
  cursor: pointer;
  min-width: 0;
}
.zip-tech-select:focus {
  outline: none;
  border-color: transparent;
  box-shadow: var(--sw-focus-shadow, 0 0 0 1px #F38A3F, 0 6px 13px rgba(243, 138, 63, 0.30));
}
.zip-tech-remove {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-muted, rgba(39, 41, 54, 0.6));
  width: 32px;
  height: 32px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.zip-tech-remove:hover {
  background: rgba(39, 41, 54, 0.06);
  color: var(--text);
}
.zip-tech-add {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* ═══════════════════════════════════════════════════════════════
   "How techs get assigned" — algorithm explainer
   Numbered chain of pick rules. Each step shows the rule + a brief
   rationale + (where applicable) the current location's state for
   that step. Mirrors pickTechForBooking exactly.
   ═══════════════════════════════════════════════════════════════ */
.pick-chain {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  counter-reset: pick-step;
}
.pick-chain-step {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 12px;
  align-items: start;
}
.pick-chain-num {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(224, 122, 42, 0.12);
  color: var(--orange-dark, #B86012);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 0.92rem;
  font-variant-numeric: tabular-nums;
}
.pick-chain-body strong {
  display: block;
  font-weight: 600;
  font-size: 0.98rem;
  color: var(--text);
  margin-bottom: 4px;
}
.pick-chain-body p {
  margin: 0 0 4px;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--text);
}
.pick-chain-state {
  font-size: 0.82rem !important;
  color: var(--text-muted, rgba(39, 41, 54, 0.7)) !important;
  font-style: italic;
}

/* ═══════════════════════════════════════════════════════════════
   Activity tab — booking-session log
   Renders a scrolling list of session cards on the per-location
   Activity page. Each card shows status, the customer's progress
   through the booking flow, and (for completed bookings) the
   assigned tech + reason. Filter chips at the top swap visibility.
   ═══════════════════════════════════════════════════════════════ */
.activity-filter {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  background: var(--card-tint, #FAF7F1);
  border: 1px solid var(--border-soft, rgba(39, 41, 54, 0.08));
  border-radius: 999px;
}
.activity-filter-btn {
  appearance: none;
  border: 0;
  background: transparent;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-muted, rgba(39, 41, 54, 0.7));
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.activity-filter-btn:hover { color: var(--text); }
.activity-filter-btn.is-active {
  background: #fff;
  color: var(--text);
  box-shadow: 0 1px 2px rgba(39, 41, 54, 0.06);
}

.activity-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.activity-item {
  border: 1px solid var(--border-soft, rgba(39, 41, 54, 0.08));
  border-radius: 14px;
  padding: 14px 16px;
  background: #fff;
  transition: box-shadow 0.18s ease;
}
.activity-item:hover { box-shadow: 0 2px 8px rgba(39, 41, 54, 0.05); }
/* Subtle left-edge accent so the status reads at a glance even
   when the user has scrolled past the pill. */
.activity-status-completed { border-left: 3px solid #2E8B57; }
.activity-status-abandoned { border-left: 3px solid rgba(39, 41, 54, 0.20); }
.activity-status-in_progress { border-left: 3px solid var(--orange, #E07A2A); }

.activity-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.activity-row-main {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.activity-row-meta time {
  font-size: 0.85rem;
  color: var(--text-muted, rgba(39, 41, 54, 0.7));
  white-space: nowrap;
}

.activity-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.activity-pill-completed { background: #E6F2EB; color: #2E8B57; }
.activity-pill-abandoned { background: rgba(39, 41, 54, 0.06); color: var(--text-muted, rgba(39, 41, 54, 0.7)); }
.activity-pill-in_progress { background: rgba(224, 122, 42, 0.12); color: var(--orange-dark, #B86012); }
/* Admin-filed pill — surfaced next to the status pill when the
   booking came in via /admin/book/:slug (lead source = "Admin
   Booking" in HCP). Brand orange so it visually pops against the
   green Booked pill, and the same icon that's used in the admin
   booking banner so the connection reads clearly. */
.activity-pill-admin {
  background: rgba(224, 122, 42, 0.12);
  color: var(--orange-dark, #B86012);
  gap: 4px;
}
/* Override pill — marks bookings where the admin opted into one of
   the bypass toggles (closed-day/blackout or trip-charge). Lead-time
   bypass is automatic on every admin booking, so it's not worth
   surfacing on its own. Yellow-amber tone reads as "audit this" w/o
   being alarming. */
.activity-pill-bypass {
  background: rgba(204, 152, 24, 0.14);
  color: #C66518;
  gap: 4px;
}

.activity-step {
  font-size: 0.92rem;
  color: var(--text);
}
.activity-step strong { font-weight: 600; }

.activity-pick-reason {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 0.78rem;
  font-weight: 500;
  border: 1px solid transparent;
}
.activity-pick-reason-continuity {
  background: rgba(46, 139, 87, 0.08);
  color: #2E8B57;
  border-color: rgba(46, 139, 87, 0.20);
}
.activity-pick-reason-round_robin {
  background: rgba(39, 41, 54, 0.04);
  color: var(--text-muted, rgba(39, 41, 54, 0.7));
  border-color: rgba(39, 41, 54, 0.10);
}

.activity-summary {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.activity-summary-row {
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: 8px;
  align-items: baseline;
  font-size: 0.92rem;
  line-height: 1.4;
}
.activity-summary-label {
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--text-muted, rgba(39, 41, 54, 0.7));
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.activity-summary-value { color: var(--text); word-break: break-word; }

.activity-details {
  margin-top: 10px;
  border-top: 1px dashed rgba(39, 41, 54, 0.10);
  padding-top: 8px;
}
.activity-details summary {
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--text-muted, rgba(39, 41, 54, 0.7));
  user-select: none;
}
.activity-details summary:hover { color: var(--text); }
.activity-events {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.85rem;
}
.activity-events li {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: baseline;
  color: var(--text);
}
.activity-events time {
  color: var(--text-muted, rgba(39, 41, 54, 0.7));
  font-variant-numeric: tabular-nums;
  font-size: 0.78rem;
  min-width: 110px;
}
.activity-events code {
  background: rgba(39, 41, 54, 0.05);
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 0.78rem;
}
.activity-decision {
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgba(39, 41, 54, 0.03);
  border: 1px solid rgba(39, 41, 54, 0.08);
}
.activity-decision h4 {
  margin: 0 0 8px;
  font-size: 0.82rem;
  color: var(--text);
}
.activity-decision-grid {
  display: grid;
  grid-template-columns: 86px minmax(0, 1fr);
  gap: 6px 10px;
  font-size: 0.84rem;
}
.activity-decision-grid > span {
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.68rem;
}
.activity-decision-grid strong {
  min-width: 0;
  word-break: break-word;
}
.activity-decision-busy {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.activity-conflict {
  display: block;
  color: var(--text);
  word-break: break-word;
}

/* ═══ Drop-off funnel ════════════════════════════════════════════════
   Sits above the "Recent sessions" card in the per-location Activity
   tab. Aggregates the abandoned sessions into a funnel: each row is
   one step of the booking flow, the bar shows what % of abandoned
   customers reached that step, and the action chips below the bar
   show what those customers DID while there. The row matching the
   biggest drop-off gets the .is-worst flag for visual emphasis. */
.dropoff-card { margin-bottom: 18px; }
.dropoff-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.dropoff-row {
  /* Hairline divider between rows. Lighter than .card2's outer rule
     so the funnel reads as a cohesive block, not a stack of cards. */
  padding: 14px 16px;
  border: 1px solid rgba(39, 41, 54, 0.08);
  border-radius: 12px;
  background: #fff;
  transition: border-color 0.15s, background 0.15s;
}
.dropoff-row.is-worst {
  /* The biggest-drop row gets a soft orange skin so the eye lands
     there first. Matches the orange-soft pill treatment elsewhere
     in the dashboard for "needs attention" signals. */
  border-color: rgba(224, 122, 42, 0.32);
  background: var(--orange-soft);
}
.dropoff-row-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.dropoff-step-num {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 3px 8px;
  background: rgba(39, 41, 54, 0.06);
  border-radius: 6px;
}
.dropoff-row.is-worst .dropoff-step-num {
  background: rgba(224, 122, 42, 0.18);
  color: var(--orange-dark);
}
.dropoff-step-label {
  font-size: 1rem;
  font-weight: 600;
  color: var(--navy);
}
.dropoff-reached {
  margin-left: auto;
  font-size: 0.88rem;
  color: var(--text);
}
.dropoff-reached strong {
  font-size: 1rem;
  color: var(--navy);
}

/* Funnel bar — visualizes what percent of all abandoned customers
   reached this step. Bars naturally shrink left-to-right as the
   funnel progresses (fewer customers reach each subsequent step). */
.dropoff-bar {
  width: 100%;
  height: 10px;
  background: rgba(39, 41, 54, 0.06);
  border-radius: 999px;
  overflow: hidden;
  margin-bottom: 12px;
}
.dropoff-bar-fill {
  height: 100%;
  background: var(--orange);
  border-radius: 999px;
  /* Smooth fill so the bar reads as a live measurement, not a static
     graphic. 0.6s matches the success-card check-draw cadence. */
  transition: width 0.6s cubic-bezier(0.65, 0, 0.35, 1);
}
.dropoff-row.is-worst .dropoff-bar-fill {
  background: var(--orange-dark);
}

/* "Dropped off here" call-out: the headline data point per row. */
.dropoff-here {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}
.dropoff-here-pill {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  background: rgba(220, 38, 38, 0.08);
  color: #b91c1c;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
}
.dropoff-row.is-worst .dropoff-here-pill {
  background: rgba(220, 38, 38, 0.16);
}
.dropoff-here-pct {
  font-size: 0.82rem;
  color: var(--text-muted);
}

/* Action chips — what the abandoned customers DID at this step. The
   server's `eventLabels` map translates the internal event-type
   names (service_picked, address_resolved, etc.) into the friendly
   labels rendered here. Counts pile up across all abandoned
   sessions, so a chip of "Address resolved 12" means 12 abandoned
   customers got an address to resolve before bailing. */
.dropoff-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
.dropoff-actions-label {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin-right: 4px;
}
.dropoff-action-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 4px 4px 10px;
  background: #fff;
  border: 1px solid rgba(39, 41, 54, 0.12);
  border-radius: 999px;
  font-size: 0.82rem;
  color: var(--text);
}
.dropoff-row.is-worst .dropoff-action-chip {
  background: rgba(255, 255, 255, 0.7);
}
.dropoff-action-chip[data-event="outside_area"] {
  /* "Outside service area" deserves its own visual key — the customer
     COULDN'T book regardless of how good the form was, so admins read
     this as "we don't have coverage" rather than "form needs work". */
  border-color: rgba(220, 38, 38, 0.25);
  background: rgba(220, 38, 38, 0.06);
  color: #b91c1c;
}
.dropoff-action-chip[data-event="submit_failed"] {
  border-color: rgba(220, 38, 38, 0.35);
  background: rgba(220, 38, 38, 0.08);
  color: #b91c1c;
  font-weight: 600;
}
.dropoff-action-label { line-height: 1; }
.dropoff-action-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  background: rgba(39, 41, 54, 0.08);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--navy);
}
.dropoff-action-chip[data-event="outside_area"] .dropoff-action-count,
.dropoff-action-chip[data-event="submit_failed"] .dropoff-action-count {
  background: rgba(220, 38, 38, 0.18);
  color: #b91c1c;
}

@media (max-width: 600px) {
  .dropoff-row { padding: 12px 12px; }
  .dropoff-reached { margin-left: 0; width: 100%; }
  .dropoff-row-head { gap: 6px; }
}

