:root {
  --ink: #0B2436;
  --slate: #14304A;
  --slate-soft: #1D4468;
  --glass: #3E8FD0;
  --glass-light: #EAF3F8;
  --bg: #F4F8FA;
  --surface: #FFFFFF;
  --silver: #9FB4C2;
  --silver-soft: #D7E3E9;
  --amber: #F2A93B;
  --success: #2FA36B;
  --success-soft: #E4F5EC;
  --danger: #D9534F;
  --danger-soft: #FBEAE9;
  --text: #0F2733;
  --text-muted: #5C7484;
  --font-display: 'Space Grotesk', sans-serif;
  --font-body: 'Inter', sans-serif;
  --radius: 12px;
  /* Two-layer shadows (a tight ambient layer + a soft diffuse one) read as
     more considered than a single flat shadow at the same total darkness —
     the standard trick for a "premium" card without making it heavier. */
  --shadow-sm: 0 1px 2px rgba(11, 36, 54, 0.05), 0 4px 12px rgba(11, 36, 54, 0.05);
  --shadow-md: 0 4px 14px rgba(11, 36, 54, 0.07), 0 14px 32px rgba(11, 36, 54, 0.10);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased; scrollbar-gutter: stable;
  overflow-y: scroll;
  touch-action: manipulation;
}

a { color: inherit; text-decoration: none; }
button { font-family: var(--font-body); cursor: pointer; }
input, select, textarea { font-family: var(--font-body); }

.app {
  display: flex;
  min-height: 100vh;
}

/* ---------- Sidebar ---------- */
.sidebar {
  width: 236px;
  flex-shrink: 0;
  background: linear-gradient(180deg, var(--ink) 0%, var(--slate) 100%);
  color: #fff;
  display: flex;
  flex-direction: column;
  padding: 22px 16px;
  position: sticky;
  top: 0;
  height: 100vh;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px 26px 10px;
}
.brand-mark { color: var(--amber); display: flex; }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-name { font-family: var(--font-display); font-weight: 600; font-size: 15.5px; letter-spacing: 0.2px; }
.brand-sub { font-size: 11px; color: var(--silver); letter-spacing: 1.5px; text-transform: uppercase; margin-top: 2px; }

.nav { display: flex; flex-direction: column; gap: 4px; }
.nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  color: rgba(255,255,255,0.72);
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-item-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: rgba(255,255,255,0.5);
}
.nav-item-icon svg {
  width: 18px;
  height: 18px;
}

.nav-badge {
  margin-left: auto;
  background: #ef4444;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 10px;
  line-height: 1.4;
}
.nav-item:hover .nav-item-icon,
.nav-item.active .nav-item-icon {
  color: #fff;
}
.nav-item:hover { background: rgba(255,255,255,0.06); color: #fff; }
.nav-item.active { background: rgba(62,143,208,0.22); color: #fff; box-shadow: inset 3px 0 0 var(--glass);}
.nav-menu-wrap { position: relative; margin-top: 8px; }
.nav-menu-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  color: #fff;
  border-radius: 9px;
  padding: 14px 16px;
  font-size: 15.5px;
  font-weight: 600;
}
.nav-menu-btn:hover { background: rgba(255,255,255,0.1); }
.nav-menu-icon { font-size: 18px; line-height: 1; }
.nav-menu-dropdown {
  display: none;
  position: fixed;
  width: 50vw;
  max-width: 220px;
  background: var(--slate);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 10px;
  padding: 8px;
  box-shadow: var(--shadow-md);
  z-index: 6000;
}
.nav-menu-dropdown.open { display: flex; }
/* Opened from the bottom tab bar's "More" button — those 4 routes are
   already sitting right on the tab bar underneath it, so repeating them
   here just makes the "everything else" list longer to scan. */
.nav-menu-dropdown-compact .nav-item[data-route="dashboard"],
.nav-menu-dropdown-compact .nav-item[data-route="pipeline"],
.nav-menu-dropdown-compact .nav-item[data-route="schedule"],
.nav-menu-dropdown-compact .nav-item[data-route="texts"] {
  display: none;
}

.notif-btn {
  margin-top: 10px;
  background: rgba(242,169,59,0.14);
  border: 1px solid rgba(242,169,59,0.35);
  color: var(--amber);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 12.5px;
  font-weight: 600;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
}
.notif-btn::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--amber);
  flex-shrink: 0;
}
.notif-btn.is-on { background: rgba(47,163,107,0.14); border-color: rgba(47,163,107,0.35); color: #6FD9A6; }
.notif-btn.is-on::before { background: #6FD9A6; }
.notif-btn:hover { filter: brightness(1.1); }

.sidebar-footer {
  margin-top: auto;
  font-size: 11.5px;
  color: var(--silver);
  padding: 10px;
  border-top: 1px solid rgba(255,255,255,0.08);
  padding-top: 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.sidebar-logout {
  background: transparent;
  border: 1px solid rgba(255,255,255,0.16);
  color: rgba(255,255,255,0.72);
  border-radius: 6px;
  padding: 5px 9px;
  font-size: 11px;
  font-weight: 600;
  flex-shrink: 0;
}
.sidebar-logout:hover { background: rgba(255,255,255,0.08); color: #fff; }

/* ---------- Main ---------- */
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 22px 32px;
  background: var(--surface);
  border-bottom: 1px solid var(--silver-soft);
  position: sticky;
  top: 0;
  z-index: 5;
}
.topbar h1 { font-family: var(--font-display); font-size: 21px; font-weight: 600; margin: 0; letter-spacing: -0.01em; }
.topbar-actions { display: flex; gap: 10px; }

.view { padding: 28px 32px 60px 32px; }

/* ---------- Buttons ---------- */
.btn {
  border: none;
  border-radius: 8px;
  padding: 9px 16px;
  font-size: 13.5px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: transform 0.08s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--ink); color: #fff; }
.btn-primary:hover { background: var(--slate-soft); }
.btn-accent { background: var(--amber); color: var(--ink); }
.btn-accent:hover { filter: brightness(1.05); }
.btn-ghost { background: transparent; color: var(--text); border: 1px solid var(--silver-soft); }
.btn-ghost:hover { background: var(--glass-light); }
.btn-danger { background: var(--danger-soft); color: var(--danger); }
.btn-danger:hover { background: var(--danger); color: #fff; }
.btn-success { background: var(--success-soft); color: var(--success); }
.btn-success:hover { background: var(--success); color: #fff; }
.btn-sm { padding: 6px 11px; font-size: 12.5px; }

/* ---------- Cards / grids ---------- */
.grid { display: grid; gap: 20px; }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-2 { grid-template-columns: 2fr 1fr; }

.card {
  background: var(--surface);
  border-radius: var(--radius);
  border: 1px solid var(--silver-soft);
  box-shadow: var(--shadow-sm);
  padding: 22px;
  transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
/* A no-op on touch devices (nothing to hover), but on desktop this is the
   difference between a page of flat boxes and one that feels responsive to
   the cursor — the same trick used across most polished dashboard UIs. */
@media (hover: hover) {
  .card:hover { box-shadow: var(--shadow-md); border-color: var(--silver); transform: translateY(-1px); }
}

.stat-card {
  position: relative;
  overflow: hidden;
}
.stat-card::after {
  content: "";
  position: absolute;
  top: 0; right: 0;
  width: 70px; height: 100%;
  background: linear-gradient(115deg, transparent 40%, rgba(62,143,208,0.08) 50%, transparent 60%);
}
.stat-label { font-size: 12px; color: var(--text-muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.6px; }
.stat-value { font-family: var(--font-display); font-size: 30px; font-weight: 700; margin-top: 6px; color: var(--ink); letter-spacing: -0.015em; }
.stat-sub { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; }
.stat-value.amber { color: var(--amber); }
.stat-value.success { color: var(--success); }
.stat-value.danger { color: var(--danger); }

.section-title {
  font-family: var(--font-display);
  font-size: 15.5px;
  font-weight: 600;
  margin: 0 0 14px 0;
  letter-spacing: -0.005em;
}

/* ---------- Pipeline (kanban) ---------- */
.pipeline-board {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 14px;
  align-items: start;
}
.pipeline-col {
  background: var(--glass-light);
  border-radius: var(--radius);
  border: 1px solid var(--silver-soft);
  min-height: 200px;
  display: flex;
  flex-direction: column;
}
.pipeline-col-header {
  padding: 12px 14px;
  border-bottom: 1px solid var(--silver-soft);
  position: relative;
  overflow: hidden;
}
.pipeline-col-header::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--stage-color, var(--glass));
}
.pipeline-col-title { font-family: var(--font-display); font-weight: 600; font-size: 13.5px; padding-left: 8px; }
.pipeline-col-meta { font-size: 11.5px; color: var(--text-muted); padding-left: 8px; margin-top: 2px; }
.pipeline-col-body { padding: 10px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
/* Pipeline's columns are much narrower than Schedule's full-width job-card
   layout these buttons were designed for, so "Open lead" and "Edit" need
   their own tighter treatment here instead of wrapping across two lines.
   Phone width drops the board to one full-width column (see the phone
   layout section below), so that narrow-column squeeze no longer applies
   there — shrinking the buttons down to an 11px/24px-tall tap target on a
   phone was an accident of this rule having no lower bound, not something
   phone width ever needed. Scoped to wider screens only; phone keeps the
   normal, comfortably-sized .btn-sm used everywhere else. */
@media (min-width: 721px) {
  .pipeline-col .job-card-footer .btn {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 11px;
    padding: 5px 7px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* Same narrow-column problem for "Take profit" / "Don't take profit" —
     side by side they don't have room for the full label even at the
     smallest sane font size. Stacking them full-width, one per row, means
     the whole label always fits instead of ellipsizing. */
  .pipeline-col .lead-card-profit-row {
    flex-direction: column;
  }
  .pipeline-col .lead-card-profit-row .btn-take-profit,
  .pipeline-col .lead-card-profit-row .btn-no-profit {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    width: 100%;
  }
}

/* .lead-card now reuses the shared .job-card look (see below) — this class
   name is kept on the pipeline card element for the older selectors below
   (.lead-card-select/-footer/-profit-row) and for existing test hooks, but
   no longer carries its own background/border/cursor; the card is no longer
   clickable as a whole, only its explicit buttons are. */
.lead-card-select { margin-top: 8px; width: 100%; font-size: 11.5px; padding: 4px 6px; border-radius: 6px; border: 1px solid var(--silver-soft); background: var(--bg); }

.empty-col { padding: 18px 10px; text-align: center; color: var(--text-muted); font-size: 12px; }

/* ---------- Tables ---------- */
.table { width: 100%; border-collapse: collapse; }
.table th {
  text-align: left;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-muted);
  padding: 10px 14px;
  border-bottom: 1px solid var(--silver-soft);
}
.table td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--silver-soft);
  font-size: 13.5px;
}
.table tr.clickable:hover { background: var(--glass-light); cursor: pointer; }
.table-wrap { background: var(--surface); border-radius: var(--radius); border: 1px solid var(--silver-soft); overflow: hidden; }
/* Month accordion used by the Contacts/Companies/Texts bins — see
   binMonthAccordionHtml() in app.js. Plain button + collapsible body,
   matching the existing "Business settings" toggle pattern on Team. */
.bin-month-group { margin-bottom: 10px; }
.bin-month-group:last-child { margin-bottom: 0; }
.bin-month-toggle { display: flex; align-items: center; gap: 8px; width: 100%; padding: 10px 12px; border: 1px solid var(--silver-soft); border-radius: var(--radius); background: var(--surface); cursor: pointer; text-align: left; font: inherit; }
.bin-month-toggle:hover { background: var(--glass-light); }
.bin-month-caret { color: var(--text-muted); flex-shrink: 0; }
.bin-month-label { font-weight: 600; color: var(--ink); flex: 1 1 auto; }
.bin-month-count { color: var(--text-muted); font-size: 13px; background: var(--silver-soft); border-radius: 999px; padding: 1px 9px; }
.bin-month-body { margin-top: 8px; }
.text-list { display: flex; flex-direction: column; gap: 12px; }
.text-card { background: var(--surface); border: 1px solid var(--silver-soft); border-radius: var(--radius); padding: 14px 16px; }
.text-card-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.text-card-contact { font-weight: 700; font-size: 14px; }
.text-card-phone { font-size: 11.5px; color: var(--text-muted); }
.text-card-type { font-size: 12px; color: var(--text-muted); }
.text-card-body { font-size: 13.5px; line-height: 1.5; white-space: normal; word-break: break-word; margin: 8px 0 12px; }
.text-card-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.text-card-actions a.btn { text-decoration: none; }
/* A customer's inbound reply, distinct from the app's own outbound drafts —
   a light blue left accent so it reads as "they said this back", not just
   another item in the same list. */
.text-card-inbound { border-left: 3px solid var(--glass); background: var(--glass-light); }
.job-pin-badge { background: #F2A93B; color: #fff; width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12px; border: 2px solid #fff; box-shadow: 0 1px 4px rgba(0,0,0,0.3); }
.team-pin-badge { background: #2FA36B; color: #fff; width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12px; border: 2px solid #fff; box-shadow: 0 1px 4px rgba(0,0,0,0.3); }
.job-loc-num { background: var(--glass-light); color: var(--glass); font-weight: 700; font-size: 12px; width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
/* Done jobs on Job Locations — pushed to the back of the list, shown green
   with a tick instead of their old stop number, both on the pin and the
   list row, so a finished job reads as finished at a glance. */
.job-pin-badge-done { background: var(--success, #2FA36B); }
.job-loc-num-done { background: rgba(47,163,107,0.15); color: var(--success, #2FA36B); }
.job-loc-card-done { border-left: 3px solid var(--success, #2FA36B); background: rgba(47,163,107,0.06); opacity: 0.8; }
.job-loc-done-tick { color: var(--success, #2FA36B); font-weight: 700; }
.map-pin-drop { filter: drop-shadow(0 2px 3px rgba(0,0,0,0.4)); }
.badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 100px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.badge-open { background: var(--glass-light); color: var(--glass); }
.badge-won { background: var(--success-soft); color: var(--success); }
.badge-lost { background: var(--danger-soft); color: var(--danger); }

/* ---------- Forms ---------- */
.form-row { display: flex; flex-direction: column; gap: 5px; margin-bottom: 14px; }
.form-row label { font-size: 12.5px; font-weight: 600; color: var(--text-muted); }
.form-row input, .form-row select, .form-row textarea {
  padding: 9px 11px;
  border: 1px solid var(--silver-soft);
  border-radius: 7px;
  font-size: 16px;
  background: var(--bg);
}
.form-row input:focus, .form-row select:focus, .form-row textarea:focus {
  outline: 2px solid var(--glass);
  outline-offset: 1px;
  background: #fff;
}
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.address-input-row { display: flex; gap: 8px; align-items: center; }
.address-input-row input { flex: 1; min-width: 0; }
.address-input-row .btn { flex-shrink: 0; white-space: nowrap; }
@media (max-width: 480px) {
  .address-input-row { flex-wrap: wrap; }
  .address-input-row input { flex-basis: 100%; }
  .address-input-row .btn { flex: 1; justify-content: center; }
}

/* ---------- Toolbar ---------- */
.toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; gap: 12px; }
.search-input {
  padding: 8px 12px;
  border-radius: 8px;
  border: 1px solid var(--silver-soft);
  font-size: 13px;
  width: 240px;
  background: var(--surface);
}

/* ---------- Modal ---------- */
.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(11,36,54,0.45);
  display: flex; align-items: center; justify-content: center;
  z-index: 5000;
  padding: 20px;
}
.modal {
  background: var(--surface);
  border-radius: 12px;
  width: 100%;
  max-width: 520px;
  max-height: 88vh;
  overflow-y: auto;
  box-shadow: 0 24px 60px rgba(11,36,54,0.3);
}
.modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 22px;
  border-bottom: 1px solid var(--silver-soft);
}
.modal-header h2 { font-family: var(--font-display); font-size: 17px; margin: 0; letter-spacing: -0.01em; }
.modal-close { background: none; border: none; font-size: 20px; color: var(--text-muted); line-height: 1; }
.modal-body { padding: 20px 22px; }
.modal-footer { padding: 16px 22px; border-top: 1px solid var(--silver-soft); display: flex; justify-content: flex-end; gap: 10px; }
.modal-lg { max-width: 720px; }

/* ---------- Detail page ---------- */
.detail-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  margin-bottom: 20px;
}
.detail-eyebrow { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-muted); font-weight: 700; }
.detail-title { font-family: var(--font-display); font-size: 24px; font-weight: 700; margin: 4px 0 0 0; letter-spacing: -0.015em; }
.detail-meta { color: var(--text-muted); font-size: 13.5px; margin-top: 4px; }
.back-link { font-size: 13px; color: var(--glass); font-weight: 600; display: inline-flex; align-items: center; gap: 4px; margin-bottom: 14px; }
.back-link:hover { text-decoration: underline; }

.info-list { display: flex; flex-direction: column; gap: 12px; }
.info-row { display: flex; justify-content: space-between; font-size: 13.5px; border-bottom: 1px dashed var(--silver-soft); padding-bottom: 10px; }
.info-row-label { color: var(--text-muted); }
.info-row-value { font-weight: 600; text-align: right; }

.related-item {
  display: flex; justify-content: space-between; align-items: center;
  padding: 10px 12px;
  border: 1px solid var(--silver-soft);
  border-radius: 8px;
  margin-bottom: 8px;
  font-size: 13px;
}
.related-item:hover { background: var(--glass-light); cursor: pointer; }

.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-muted);
}
.empty-state h3 { font-family: var(--font-display); color: var(--text); margin-bottom: 6px; }

.chart-wrap { position: relative; height: 260px; }

@media (max-width: 1100px) {
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .grid-2 { grid-template-columns: 1fr; }
  .pipeline-board { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
}

/* ---------- Phone layout ---------- */
@media (max-width: 720px) {
  .app { flex-direction: column; }

  .sidebar {
    position: sticky;
    top: 0;
    z-index: 10;
    width: 100%;
    height: auto;
    flex-direction: row;
    align-items: center;
    padding: 12px 14px;
    gap: 14px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .brand { padding: 0; flex-shrink: 0; }
  .sidebar-footer { display: none; }
  .notif-btn { margin-top: 0; flex-shrink: 0; white-space: nowrap; width: auto; }
  .nav-menu-wrap { margin-top: 0; flex-shrink: 0; width: auto; }
.nav-menu-btn { width: auto; white-space: nowrap; }
.nav-item { font-size: 14px; }
 .nav-item.active { box-shadow: none; background: var(--glass); }

  .topbar {
    padding: 18px 18px;
    flex-wrap: wrap;
    row-gap: 12px;
  }
  .topbar h1 { font-size: 19px; }
  .topbar-actions { width: 100%; }
  .topbar-actions .btn { flex: 1; justify-content: center; }

  /* Bottom padding clears the fixed mobile-tab-bar (see its own rules
     below) plus the home-indicator safe area on notched phones, instead
     of the flat 50px this used before the tab bar existed. */
  .view { padding: 20px 16px 16px 16px; padding-bottom: calc(86px + env(safe-area-inset-bottom)); }

  .grid { gap: 14px; }
  .grid-4, .grid-3, .grid-2 { grid-template-columns: 1fr; }
  .card { padding: 18px; }

  .stat-value { font-size: 28px; }
  .stat-label { font-size: 12.5px; }

  .pipeline-board { grid-template-columns: 1fr; gap: 16px; }
  .pipeline-col-body { gap: 10px; padding: 12px; }
  .lead-card { padding: 14px 15px; }
  .lead-card-title { font-size: 14.5px; }

  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .table { min-width: 620px; }
  .table th, .table td { padding: 13px 16px; font-size: 14px; }

  .btn { padding: 11px 18px; font-size: 14.5px; }
  .btn-sm { padding: 9px 14px; font-size: 13.5px; }

  .form-grid { grid-template-columns: 1fr; }
  .form-row input, .form-row select, .form-row textarea { padding: 12px 13px; font-size: 15px; }

  .modal-backdrop { padding: 0; align-items: flex-end; }
  .modal { max-width: 100%; width: 100%; border-radius: 16px 16px 0 0; max-height: 92vh; }
  .modal-header { padding: 18px 20px; }
  .modal-body { padding: 18px 20px; }
  .modal-footer { padding: 16px 20px; flex-direction: column-reverse; }
  .modal-footer .btn { width: 100%; justify-content: center; }

  .detail-title { font-size: 21px; }
  .detail-header { flex-direction: column; gap: 12px; }

  .chart-wrap { height: 220px; }
}

/* ---------- Mobile bottom tab bar ---------- */
/* Phone-only, native-app-style primary navigation: the 4 most-used
   sections sit in actual thumb reach at the bottom of the screen instead
   of behind a menu button up at the top. Hidden entirely on desktop/tablet
   widths, where the existing sidebar nav already covers this job. */
.mobile-tab-bar { display: none; }
@media (max-width: 720px) {
  .mobile-tab-bar {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 5000;
    background: #000000;
    border-top: 1px solid rgba(255,255,255,0.10);
    box-shadow: 0 -4px 16px rgba(11,36,54,0.18);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom)) 4px;
  }
  .mobile-tab-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 6px 2px;
    border: none;
    background: none;
    color: rgba(255,255,255,0.55);
    font-family: var(--font-body);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    position: relative;
    cursor: pointer;
    transition: color 0.15s ease;
  }
  .mobile-tab-item svg {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
  }
  .mobile-tab-item.active { color: var(--amber); }
  .mobile-tab-badge {
    position: absolute;
    top: 2px;
    right: calc(50% - 18px);
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    background: var(--danger);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
  }
}

/* ---------- Door Knocking ---------- */
.knock-map-card { position: relative; }

/* Leads / Map segmented toggle, sitting where the old always-visible search
   bar used to be — search is still reachable via the 🔍 FAB's own overlay
   (which also has the "jump to a scheduled job" list), so nothing was lost
   by freeing up this space for the toggle instead. */
.knock-view-toggle {
  display: inline-flex;
  background: #fff;
  border-radius: 999px;
  padding: 4px;
  gap: 4px;
  box-shadow: 0 2px 8px rgba(11,36,54,0.18);
  margin: 0 auto 10px;
}
.knock-view-toggle-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 700;
  padding: 8px 16px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.knock-view-toggle-btn-active { background: var(--glass); color: #fff; }

/* Same fix as knock-search-overlay/knock-filter-overlay above: an explicit
   `display` beats the browser's default `[hidden]{display:none}`, so without
   this override toggling `.hidden = true` on this list would do nothing. */
.knock-leads-list[hidden] { display: none !important; }
.knock-leads-list { display: flex; flex-direction: column; gap: 12px; }
.knock-leads-chips {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 2px;
}
.knock-leads-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  border: 1px solid var(--silver-soft);
  background: #fff;
  color: var(--text-muted);
  border-radius: 999px;
  padding: 6px 12px 6px 6px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  opacity: 0.5;
}
.knock-leads-chip-active { opacity: 1; border-color: var(--knock-status-color); color: var(--ink); }
.knock-leads-chip .knock-status-icon { width: 18px; height: 18px; flex-shrink: 0; }
.knock-leads-chip .knock-status-icon svg { width: 10px; height: 10px; }
.knock-leads-chip-count { color: var(--text-muted); font-weight: 700; }
.knock-leads-cards { display: flex; flex-direction: column; gap: 8px; }
.knock-lead-card {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  border: none;
  background: #fff;
  border-radius: 12px;
  padding: 12px 14px;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(11,36,54,0.1);
}
.knock-lead-card:hover { background: var(--glass-light); }
.knock-lead-card-icon {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; color: #fff;
}
.knock-lead-card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.knock-lead-card-address { font-size: 13.5px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.knock-lead-card-meta { font-size: 11.5px; color: var(--text-muted); }
.knock-lead-card-chevron { color: var(--text-muted); font-size: 18px; flex-shrink: 0; }

.knock-fab-stack {
  position: absolute;
  z-index: 500;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.knock-fab-stack-left { top: 14px; left: 14px; }
.knock-fab-stack-right-top { top: 14px; right: 14px; }
.knock-fab-stack-bottom-right { bottom: 14px; right: 14px; }
.knock-fab-stack-bottom-left { bottom: 14px; left: 14px; }

.knock-fab {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: none;
  background: #fff;
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px rgba(11,36,54,0.28);
  cursor: pointer;
  transition: transform 0.1s ease, box-shadow 0.15s ease, background 0.15s ease;
  padding: 0;
}
.knock-fab:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(11,36,54,0.32); }
.knock-fab svg { width: 18px; height: 18px; }
.knock-fab-active { background: var(--glass); color: #fff; }
.knock-fab-accent-green { background: var(--success); color: #fff; }
.knock-fab-accent-orange { background: #F2A93B; color: #fff; }
.knock-fab-accent-blue { background: #4a90d9; color: #fff; }
.knock-fab-live { box-shadow: 0 0 0 3px rgba(58,167,109,0.45), 0 2px 8px rgba(11,36,54,0.28); }

/* Giving these an explicit `display` means the browser's default
   `[hidden] { display: none }` rule no longer wins the cascade (an author
   style always beats a user-agent style, regardless of specificity) — so
   without this override, toggling the `hidden` attribute in JS did nothing
   and both panels sat visible on the map at all times. This is the actual
   fix for the "everything overlaps" bug. */
.knock-search-overlay[hidden],
.knock-filter-overlay[hidden] {
  display: none !important;
}

.knock-search-overlay {
  position: absolute;
  z-index: 600;
  top: 14px;
  left: 14px;
  right: 14px;
  max-height: calc(100% - 28px);
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: #fff;
  border-radius: 10px;
  padding: 6px;
  box-shadow: 0 2px 10px rgba(11,36,54,0.28);
  overflow: hidden;
}
.knock-search-row { display: flex; gap: 8px; flex-shrink: 0; }
.knock-search-row .search-input { flex: 1; }
.knock-search-close {
  border: none;
  background: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: 14px;
  padding: 0 6px;
  flex-shrink: 0;
}

.knock-scheduled-heading {
  font-size: 11px;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2px 4px 0;
  flex-shrink: 0;
}
.knock-scheduled-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  overflow-y: auto;
  min-height: 0;
}
.knock-scheduled-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: left;
  border: none;
  background: var(--bg);
  border-radius: 8px;
  padding: 7px 9px;
  cursor: pointer;
}
.knock-scheduled-item:hover { background: var(--glass-light); }
.knock-scheduled-top { display: flex; justify-content: space-between; gap: 8px; }
.knock-scheduled-name { font-size: 12.5px; font-weight: 700; color: var(--ink); }
.knock-scheduled-date { font-size: 11px; color: var(--text-muted); white-space: nowrap; }
.knock-scheduled-address { font-size: 11.5px; color: var(--text-muted); }
.knock-scheduled-empty { font-size: 12px; color: var(--text-muted); padding: 4px; }

.knock-filter-overlay {
  position: absolute;
  z-index: 600;
  top: 14px;
  left: 14px;
  right: 14px;
  background: #fff;
  border-radius: 10px;
  padding: 10px 34px 10px 10px;
  box-shadow: 0 2px 10px rgba(11,36,54,0.28);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.knock-filter-overlay .knock-search-close { position: absolute; top: 6px; right: 6px; }
.knock-filter-row { display: flex; align-items: center; gap: 8px; font-size: 12.5px; cursor: pointer; }
.knock-filter-row .knock-status-icon { width: 20px; height: 20px; }
.knock-filter-row .knock-status-icon svg { width: 11px; height: 11px; }
.knock-filter-divider {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--text-muted); border-top: 1px solid var(--silver-soft); padding-top: 8px; margin-top: 2px;
}

.knock-stats-pill {
  position: absolute;
  z-index: 500;
  /* Stacked above the new bottom-left FAB (Refresh) rather than sharing its
     corner, so the two don't overlap. */
  bottom: 64px;
  left: 14px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  background: rgba(255,255,255,0.94);
  border-radius: 10px;
  padding: 6px 10px;
  box-shadow: 0 2px 8px rgba(11,36,54,0.2);
  max-width: calc(100% - 100px);
}
.knock-stat { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--text-muted); white-space: nowrap; }
.knock-stat strong { color: var(--ink); font-family: var(--font-display); }
.knock-stat-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--knock-status-color, var(--glass)); display: inline-block; }
.knock-hint { font-size: 12.5px; color: var(--text-muted); margin-top: 10px; text-align: center; }

.knock-pin-wrap { background: transparent; border: none; }
.knock-pin {
  width: 28px; height: 28px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: #fff;
  box-shadow: 0 2px 6px rgba(11,36,54,0.35), 0 0 0 2px #fff;
}
.knock-pin svg { width: 15px; height: 15px; }

/* Lead/scheduled-job pins — used both in the Pipeline/Schedule "View on map"
   overview modal and as an overlay on the Door Knocking map. A rounded
   square rather than door-knocking's circle, so the two pin families read as
   different things at a glance even on the same map. */
.lead-knock-pin-wrap { background: transparent; border: none; }
.lead-knock-pin {
  width: 26px; height: 26px;
  border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px;
  color: #fff;
  box-shadow: 0 2px 6px rgba(11,36,54,0.35), 0 0 0 2px #fff;
}
.leads-map-geocoding-note {
  padding: 8px 14px;
  font-size: 12.5px;
  color: var(--text-muted);
  text-align: center;
  border-top: 1px solid var(--silver-soft);
}

.knock-my-location-wrap { background: transparent; border: none; }
.knock-my-location-dot {
  width: 16px;
  height: 16px;
  margin: 3px;
  background: #4285F4;
  border: 3px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 0 2px rgba(66,133,244,0.35), 0 2px 6px rgba(11,36,54,0.4);
  position: relative;
}
.knock-my-location-dot::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 36px;
  height: 36px;
  margin: -18px 0 0 -18px;
  border-radius: 50%;
  background: rgba(66,133,244,0.28);
  animation: knock-pulse 2s ease-out infinite;
}
@keyframes knock-pulse {
  0% { transform: scale(0.35); opacity: 0.8; }
  100% { transform: scale(1); opacity: 0; }
}

/* The generic "recenter on my location" button added to every other map
   (Job Locations, address pickers, the leads map modal) — a plain Leaflet
   control button styled to match the app's other round map buttons. */
.my-location-control { border: none !important; box-shadow: 0 2px 8px rgba(11,36,54,0.28) !important; }
.my-location-control a {
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff;
  color: #4285F4;
  border-radius: 4px;
  cursor: pointer;
}
.my-location-control a:hover { background: #f4f7fb; }
.my-location-control svg { width: 18px; height: 18px; }

.knock-status-icon {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--knock-status-color);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: #fff;
}
.knock-status-icon svg { width: 12px; height: 12px; }

.knock-status-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--knock-status-color);
  color: #fff;
  border-radius: 20px;
  padding: 2px 8px 2px 4px;
  font-size: 10.5px;
  font-weight: 700;
}
.knock-status-chip svg { width: 10px; height: 10px; }

.knock-status-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
  margin-top: 6px;
}
.knock-status-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  border: 1.5px solid var(--silver-soft);
  background: #fff;
  border-radius: 8px;
  padding: 6px 7px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.knock-status-btn:hover { border-color: var(--knock-status-color); }
.knock-status-btn-active { background: var(--knock-status-color); border-color: var(--knock-status-color); color: #fff; }
.knock-status-btn-active .knock-status-icon { background: rgba(255,255,255,0.3); }
.knock-status-label { line-height: 1.15; }

.knock-popup { font-family: var(--font-body); min-width: 200px; }
.knock-popup-title { font-family: var(--font-display); font-weight: 600; font-size: 13.5px; margin-bottom: 4px; }
.knock-popup-meta { font-size: 11.5px; color: var(--text-muted); margin-bottom: 6px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.knock-popup-notes { font-size: 12px; color: var(--text); margin-bottom: 8px; }
.knock-popup-input {
  width: 100%;
  padding: 7px 9px;
  border: 1px solid var(--silver-soft);
  border-radius: 6px;
  font-size: 12.5px;
  margin-bottom: 8px;
  box-sizing: border-box;
}
.knock-btn-delete {
  width: 100%;
  margin-top: 8px;
  background: none;
  border: 1px solid var(--silver-soft);
  color: var(--text-muted);
  border-radius: 6px;
  padding: 6px 8px;
  font-size: 11.5px;
  cursor: pointer;
}
.knock-btn-delete:hover { background: var(--danger-soft); color: var(--danger); border-color: var(--danger); }
.knock-popup-directions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 100%;
  margin-top: 8px;
  padding: 7px 8px;
  border-radius: 6px;
  background: var(--glass-light);
  color: var(--glass);
  font-size: 12px;
  font-weight: 600;
  text-align: center;
  box-sizing: border-box;
}
.knock-popup-directions:hover { background: var(--glass); color: #fff; }

.leaflet-popup-content-wrapper { border-radius: 10px; }

@media (max-width: 720px) {
  .knock-fab { width: 38px; height: 38px; }
  .knock-fab svg { width: 16px; height: 16px; }
  .knock-fab-stack { gap: 8px; }
  .knock-stats-pill { max-width: calc(100% - 90px); }
  #knock-map { height: 60vh !important; }
}

/* ---------- Door Knocking: fullscreen mode ---------- */
body.knock-fullscreen-active { overflow: hidden; }
body.knock-fullscreen-active .sidebar,
body.knock-fullscreen-active .topbar,
body.knock-fullscreen-active .mobile-tab-bar {
  /* The phone bottom tab bar is z-index 5000 — higher than the fullscreen
     map's own z-index 4000 — so without this it sits on top of the map
     and covers the "exit fullscreen" button in the bottom-right corner,
     making it impossible to tap your way back out. */
  display: none;
}
body.knock-fullscreen-active .view {
  padding: 0;
}
body.knock-fullscreen-active .knock-page {
  display: flex;
  flex-direction: column;
  position: fixed;
  inset: 0;
  z-index: 4000;
  background: var(--bg);
  padding: 10px 14px;
}
body.knock-fullscreen-active .knock-map-card {
  flex: 1;
  min-height: 0;
}
body.knock-fullscreen-active #knock-map {
  height: 100% !important;
}
body.knock-fullscreen-active .knock-hint {
  flex-shrink: 0;
  margin-top: 6px;
}
@media (max-width: 720px) {
  body.knock-fullscreen-active .knock-hint { display: none; }
}

/* ---------- Schedule (job list) ---------- */
.schedule-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.schedule-search-input { flex: 1; box-sizing: border-box; margin-bottom: 0; }
.schedule-add-btn {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: var(--glass);
  color: #fff;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.schedule-add-btn:hover { filter: brightness(1.08); }

.schedule-tabs { display: flex; gap: 6px; margin-bottom: 12px; flex-wrap: wrap; }
.schedule-tab {
  border: 1px solid var(--silver-soft);
  background: var(--surface);
  color: var(--text-muted);
  border-radius: 100px;
  padding: 7px 16px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.schedule-tab:hover { background: var(--glass-light); }
.schedule-tab.active { background: var(--glass); color: #fff; border-color: var(--glass); }

.schedule-list { display: flex; flex-direction: column; gap: 10px; }
.job-card {
  background: var(--surface);
  border: 1px solid var(--silver-soft);
  border-left: 3px solid var(--stage-color, var(--glass));
  border-radius: var(--radius);
  padding: 14px 16px;
}
.job-card-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; flex-wrap: wrap; }
.job-card-name { font-weight: 700; font-size: 14.5px; }
/* Wherever a card's name is really a link to that lead/contact/company's
   full detail page (data-name-open set) rather than plain text. */
.job-card-name[data-name-open] { cursor: pointer; }
.job-card-name[data-name-open]:hover { text-decoration: underline; }
.job-card-value { font-family: var(--font-display); font-weight: 700; color: var(--success); font-size: 14.5px; white-space: nowrap; }
.job-card-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 6px; }
.job-card-status-pill {
  font-size: 11px;
  font-weight: 700;
  color: var(--pill-color, var(--glass));
  background: color-mix(in srgb, var(--pill-color, var(--glass)) 14%, transparent);
  padding: 3px 9px;
  border-radius: 100px;
}
.job-card-chip {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  background: var(--glass-light);
  padding: 3px 8px;
  border-radius: 100px;
}
.job-card-distance { margin-left: auto; color: var(--text-muted); background: transparent; padding: 3px 0; }
.job-card-row { font-size: 12.5px; color: var(--text-muted); margin-top: 6px; }
.job-card-notes { color: var(--text); }
.job-card-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.job-card-actions a.btn { text-decoration: none; }
.job-card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--silver-soft);
}
.job-card-avatar { display: flex; align-items: center; gap: 6px; }
.job-card-delete { color: #d33; border-color: rgba(211,51,51,0.35); }
.job-card-delete:hover { background: rgba(211,51,51,0.12); border-color: #d33; }
.avatar-circle {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.avatar-name { font-size: 12px; color: var(--text-muted); font-weight: 600; white-space: nowrap; }

/* ---------- Schedule: calendar tab ---------- */
.cal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.cal-month-label { font-weight: 700; font-size: 14.5px; }
.cal-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; margin-bottom: 4px; }
.cal-weekday { text-align: center; font-size: 11px; font-weight: 600; color: var(--text-muted); padding: 4px 0; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; margin-bottom: 16px; }
.cal-cell {
  aspect-ratio: 1 / 1;
  border: 1px solid var(--silver-soft);
  background: var(--surface);
  border-radius: 8px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 2px;
}
.cal-cell:hover { background: var(--glass-light); }
.cal-cell-empty { border: none; background: transparent; cursor: default; }
.cal-cell-num { font-size: 12px; font-weight: 600; }
.cal-cell-today .cal-cell-num { color: var(--glass); }
.cal-cell-selected { background: var(--glass); border-color: var(--glass); }
.cal-cell-selected .cal-cell-num { color: #fff; }
.cal-cell-dot {
  font-size: 9px;
  font-weight: 700;
  color: #fff;
  background: var(--success);
  border-radius: 100px;
  padding: 0 5px;
  line-height: 1.4;
}
.cal-cell-selected .cal-cell-dot { background: #fff; color: var(--glass); }
.cal-selected-heading { font-weight: 700; font-size: 13.5px; margin-bottom: 8px; }

.recurring-section-heading { font-weight: 700; font-size: 14.5px; margin-bottom: 10px; }
.recurring-calendar-heading { margin-top: 20px; }
.recurring-customers-list { margin-bottom: 4px; }

/* The toggle only exists to manage phone-width clutter — on wider screens
   the full card is already comfortably sized, so it stays out of the way.
   Declared before the @media block below on purpose: both rules target
   .job-card-more-toggle with equal specificity, so source order decides,
   and this default has to lose to the media query's display:block, not
   win over it. */
.job-card-more-toggle { display: none; }

@media (max-width: 720px) {
  .schedule-tabs { gap: 8px; }
  .schedule-tab { flex: 1; text-align: center; padding: 8px 10px; }
  /* Two per row instead of one full-width button per row — the same
     actions in roughly half the vertical space. */
  .job-card-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .job-card-actions .btn { justify-content: center; }
  .job-card-footer { flex-wrap: wrap; }
  .cal-weekday { font-size: 9px; }

  /* Cards default to a compact summary (name, value, stage, date, phone,
     address) with the less-frequently-needed stuff — Open/Edit/Delete, the
     stage picker, Take/Don't-take profit, Paid/Canceled — tucked behind a
     "More" toggle. Cuts a long Pipeline/Schedule/Contacts list down from
     several screens of scrolling to something that actually fits. A card
     can still start pre-expanded (see jobCardHtml's showResolve) when its
     hidden actions are the reason you're looking at it in the first place. */
  .job-card-more-toggle {
    display: block;
    width: 100%;
    margin-top: 10px;
    padding: 9px 0 2px 0;
    border: none;
    border-top: 1px solid var(--silver-soft);
    background: none;
    color: var(--glass);
    font-size: 12.5px;
    font-weight: 700;
    text-align: center;
    cursor: pointer;
  }
  .job-card:not(.expanded) .job-card-footer,
  .job-card:not(.expanded) .lead-card-footer {
    display: none;
  }
}

/* Companies: table on desktop (plenty of width, a fine scannable format),
   cards on phone (matches Contacts/Pipeline/Schedule instead of being the
   one list left needing a sideways scroll to see every column). */
.companies-card-list { display: none; }
@media (max-width: 720px) {
  .companies-table-wrap { display: none; }
  .companies-card-list { display: flex; }
}

/* ---------- Today's Jobs banner ---------- */
.jobs-today-card { border-left: 4px solid var(--amber); }
.jobs-today-header { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.jobs-today-count {
  font-size: 12px;
  font-weight: 700;
  color: var(--amber);
  background: rgba(242,169,59,0.15);
  padding: 3px 10px;
  border-radius: 100px;
  white-space: nowrap;
}
.jobs-today-list { display: flex; flex-direction: column; gap: 10px; }
.jobs-today-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  background: var(--glass-light);
  border-radius: 8px;
  padding: 10px 12px;
  border-left: 3px solid transparent;
}
/* A job whose date has already passed but was never marked Paid or
   Canceled — it doesn't drop off the Dashboard just because the day
   moved on, it stays here (however overdue) until it's resolved. */
.jobs-today-row-overdue {
  border-left-color: var(--danger);
  background: var(--danger-soft);
}
.jobs-today-overdue-chip {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  color: var(--danger);
  background: var(--danger-soft);
  border-radius: 100px;
  padding: 1px 8px;
  margin-left: 4px;
  vertical-align: middle;
}
.jobs-today-name { font-weight: 700; font-size: 14px; }
.jobs-today-recur { font-weight: 500; font-size: 11.5px; color: var(--text-muted); }
.jobs-today-sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.jobs-today-phone {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--glass);
  margin-top: 4px;
  text-decoration: none;
}
.jobs-today-phone:hover { text-decoration: underline; }
.jobs-today-phone-none { color: var(--text-muted); font-weight: 400; }
.jobs-today-contact-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 4px; }
.jobs-today-contact-row .jobs-today-phone { margin-top: 0; }
.jobs-today-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.jobs-today-done-badge {
  font-size: 12px; font-weight: 600; color: var(--success, #2FA36B);
  white-space: nowrap;
}
.jobs-today-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin: -4px 0 10px; }

/* ---------- Today's Profit card (and the weekly one, same look) ---------- */
.jobs-today-profit, .jobs-week-profit { border-left: 4px solid var(--success, #2FA36B); }
.jobs-week-profit { border-left-color: var(--glass, #3E8FD0); }
.jobs-today-profit-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.jobs-today-profit-nav { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.jobs-today-profit-nav .btn { padding: 3px 10px; font-size: 12px; }
.jobs-today-profit-row { display: flex; justify-content: space-between; align-items: baseline; }
.jobs-today-profit-label { font-size: 13px; font-weight: 600; color: var(--text-muted); }
.jobs-today-profit-amount { font-size: 18px; font-weight: 700; }
.jobs-today-profit-names { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.jobs-today-profit-sub { margin-top: 8px; padding-left: 14px; border-left: 2px solid var(--silver-soft); }
.jobs-today-profit-sub-label { font-size: 12.5px; font-weight: 600; }
.jobs-today-profit-empty { font-size: 13px; color: var(--text-muted); padding: 4px 0 2px; }
.jobs-today-rain {
  display: none; font-size: 12.5px; font-weight: 600; color: var(--glass);
  background: none; border: none; padding: 0; font-family: inherit; cursor: pointer;
}
.jobs-today-rain:hover:not(:disabled) { text-decoration: underline; }
.jobs-today-rain:disabled { cursor: default; opacity: 0.85; }
.jobs-today-stop {
  display: inline-block; font-size: 10.5px; font-weight: 700; color: #fff; background: var(--glass);
  padding: 1px 7px; border-radius: 100px; margin-right: 6px; vertical-align: middle;
}

@media (max-width: 720px) {
  .jobs-today-row { flex-direction: column; align-items: stretch; }
  .jobs-today-actions { justify-content: stretch; }
  .jobs-today-actions .btn { flex: 1; justify-content: center; }
}

.invoice-section { border-top: 1px solid var(--silver-soft); padding-top: 14px; margin-top: 4px; }
.form-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 12px; }
.mini-label { font-size: 11px; color: var(--text-muted); display: block; margin-bottom: 4px; }
.invoice-item-row { display: grid; grid-template-columns: 1fr 60px 80px 28px; gap: 6px; margin-bottom: 6px; align-items: center; }
.invoice-item-row input { padding: 7px 9px; font-size: 13px; }
.invoice-item-remove { background: none; border: none; color: var(--text-muted); font-size: 18px; cursor: pointer; line-height: 1; }
.invoice-item-remove:hover { color: var(--danger); }
.invoice-items-total { font-size: 13px; font-weight: 600; margin-top: 6px; }
.invoice-link-result { font-size: 12px; color: var(--text-muted); margin-left: 8px; word-break: break-all; }
.clock-status { font-size: 13px; color: var(--text-muted); }
@media (max-width: 720px) {
  .form-grid-3 { grid-template-columns: 1fr; }
  .invoice-item-row { grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; }
  .invoice-item-remove { justify-self: end; }
}

.global-search-wrap { position: relative; padding: 0 16px; margin: 10px 0; }
.global-search-input {
  width: 100%; padding: 9px 12px; border-radius: 8px; border: 1px solid rgba(255,255,255,0.15);
  background: rgba(255,255,255,0.08); color: #fff; font-size: 13px;
}
.global-search-input::placeholder { color: rgba(255,255,255,0.5); }
.global-search-input:focus { outline: none; border-color: var(--amber); background: rgba(255,255,255,0.12); }
.global-search-results {
  position: absolute; left: 16px; right: 16px; top: calc(100% + 4px); background: var(--surface);
  border-radius: 8px; box-shadow: var(--shadow-md); max-height: 340px; overflow-y: auto; z-index: 50; padding: 6px 0;
}
.global-search-group-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); padding: 6px 12px 2px; }
.global-search-row { display: flex; flex-direction: column; padding: 7px 12px; text-decoration: none; color: var(--ink); }
.global-search-row:hover { background: var(--bg); }
.global-search-row-title { font-size: 13px; font-weight: 600; }
.global-search-row-sub { font-size: 11.5px; color: var(--text-muted); }
.global-search-empty { padding: 10px 12px; font-size: 13px; color: var(--text-muted); }

.mobile-search-close { display: none; }
@media (max-width: 720px) {
  /* Lifted out of the sidebar's sideways-scrolling strip into a full-width
     overlay anchored to the very top of the screen while the search button
     is active — see initMobileSearchToggle in app.js. */
  .global-search-wrap.mobile-search-open {
    position: fixed;
    top: 0; left: 0; right: 0;
    padding: 14px 44px 14px 16px;
    margin: 0;
    background: var(--ink);
    box-shadow: var(--shadow-md);
    z-index: 7000;
  }
  .global-search-wrap.mobile-search-open .global-search-results {
    left: 16px; right: 16px; max-height: 70vh;
  }
  .mobile-search-close {
    display: none;
    position: absolute;
    top: 12px; right: 10px;
    width: 30px; height: 30px;
    border: none;
    background: none;
    color: #fff;
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
  }
  .global-search-wrap.mobile-search-open .mobile-search-close { display: block; }
}

.recurring-missed-chip { color: var(--danger); background: var(--danger-soft); }
.recurring-price-chip { color: #9C6B00; background: rgba(242,169,59,0.18); }

/* An occurrence whose date has passed but hasn't been marked Paid or
   Canceled yet — stays on the Upcoming list (never silently drops to
   Past), just called out so it doesn't get lost among on-time jobs. */
.job-card-overdue { border-left-color: var(--danger); }
.job-card-overdue-chip { color: var(--danger); background: var(--danger-soft); }

/* ---------- Quick undo toast ---------- */
.undo-toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 9999;
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--ink);
  color: #fff;
  padding: 12px 14px 12px 18px;
  border-radius: 100px;
  box-shadow: var(--shadow-md);
  max-width: calc(100vw - 32px);
  animation: undoToastIn 0.2s ease-out;
}
@keyframes undoToastIn {
  from { opacity: 0; transform: translateX(-50%) translateY(8px); }
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
.undo-toast-msg { font-size: 13.5px; white-space: nowrap; }
.undo-toast-actions { display: flex; gap: 6px; }
.undo-toast-btn {
  background: rgba(255,255,255,0.14);
  color: #fff;
  border: none;
  border-radius: 100px;
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.undo-toast-btn:hover { background: rgba(255,255,255,0.24); }
.undo-toast-btn:disabled { opacity: 0.7; cursor: default; }
.undo-toast-close {
  background: none;
  border: none;
  color: rgba(255,255,255,0.6);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
}
.undo-toast-close:hover { color: #fff; }
@media (max-width: 720px) {
  /* Clear the fixed mobile-tab-bar (z-index 5000, see its own rules above)
     with the same offset the page content already uses for that — see
     .view's padding-bottom — so the toast doesn't sit on top of the tab bar
     and block nav taps underneath for the few seconds it's visible. */
  .undo-toast { bottom: calc(86px + env(safe-area-inset-bottom)); }
}
@media (max-width: 520px) {
  .undo-toast { left: 12px; right: 12px; bottom: calc(86px + env(safe-area-inset-bottom)); transform: none; max-width: none; flex-wrap: wrap; }
  @keyframes undoToastIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
  }
}

.weekly-route-list { display: flex; flex-direction: column; gap: 2px; }
.weekly-route-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 9px; border-radius: 7px; font-size: 13px;
}
.weekly-route-row-light { background: var(--success-soft); }
.weekly-route-day { flex: 1; font-weight: 600; }
.weekly-route-count { color: var(--text-muted); }
.weekly-route-dist { color: var(--text-muted); min-width: 56px; text-align: right; }
.suggest-day-result { font-size: 12.5px; color: var(--text-muted); margin-top: 6px; }

.lead-photo-group { margin-bottom: 16px; }
.lead-photo-group:last-child { margin-bottom: 0; }
.lead-photo-group-label { font-size: 12px; font-weight: 600; color: var(--text-muted); margin-bottom: 8px; }
.lead-photo-grid { display: flex; flex-wrap: wrap; gap: 10px; }
.lead-photo-thumb {
  position: relative; width: 88px; height: 88px; border-radius: 8px; overflow: hidden;
  display: block; background: var(--bg);
}
.lead-photo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.lead-photo-remove {
  position: absolute; top: 3px; right: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: rgba(0,0,0,0.65); color: #fff; border: none; font-size: 13px; line-height: 1; cursor: pointer;
}
.lead-photo-add {
  width: 88px; height: 88px; border-radius: 8px; border: 1.5px dashed var(--silver-soft);
  display: flex; align-items: center; justify-content: center; font-size: 12.5px; color: var(--text-muted);
  cursor: pointer;
}
.lead-photo-add:hover { border-color: var(--glass); color: var(--glass); }

.brand {
  background: #000000 !important;
  color: #ffffff !important;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  row-gap: 8px;
  width: 100%;
position: relative;
} .brand-name, .brand-sub {
  color: #ffffff !important;
}
.brand-logo {
  height: 32px;
  width: auto;
  margin-left: auto;
  position: relative;
  z-index: 1;
}
.sidebar {
  background: #000000 !important;
}
.brand .notif-btn {
  width: auto;
  margin-top: 0;
  white-space: normal;
  flex-shrink: 1;
  position: relative;
  z-index: 1;
}

.nav-menu-btn-mobile {
  display: none;
}
/* Same equal-specificity-vs-media-query ordering rule as
   .job-card-more-toggle above: this default has to be declared before the
   @media block so the media query's display:flex is the one that wins at
   phone width, not this display:none. */
.mobile-search-btn { display: none; }
@media (max-width: 720px) {
  .nav-menu-wrap { display: none; }
  /* The topbar hamburger is now redundant with the bottom tab bar's "More"
     button, which opens this exact same dropdown — keeping both around
     would just be visual clutter in an already tight header. */
  .nav-menu-btn-mobile {
    display: none;
  }
  /* Keep the search button + title left-aligned as a cluster rather than
     letting space-between push the title away to the far right now that
     there are two items on this row instead of one. */
  .topbar { gap: 12px; justify-content: flex-start; }
  .topbar-actions { margin-left: auto; }

  .mobile-search-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    flex-shrink: 0;
    border-radius: 8px;
    border: 1px solid var(--silver-soft);
    background: var(--surface);
    color: var(--ink);
    padding: 0;
  }
  .mobile-search-btn svg { width: 18px; height: 18px; }
  .mobile-search-btn:hover { background: var(--bg); }
}
.stat-card[data-stat] { cursor: pointer; transition: transform 0.15s ease, box-shadow 0.15s ease; }
.stat-card[data-stat]:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.stat-detail-row {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--silver-soft);
}
.stat-detail-main { flex: 1; }
/* A stat-detail row's name/title area doubles as a link into that lead's
   full detail page — same idea as the job-card-name links below. */
.stat-detail-main[data-name-open] { cursor: pointer; }
.stat-detail-main[data-name-open]:hover .stat-detail-title { text-decoration: underline; }
.stat-detail-delete {
  flex-shrink: 0;
  border: 1px solid rgba(217,83,79,0.35);
  background: rgba(217,83,79,0.1);
  color: var(--danger);
  border-radius: 6px;
  padding: 5px 10px;
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}
.stat-detail-delete:hover { background: var(--danger); color: #fff; }
.stat-detail-row:last-child { border-bottom: none; }
.stat-detail-title { font-weight: 600; font-size: 14px; color: var(--ink); }
.stat-detail-sub { font-size: 12.5px; color: var(--text-muted); margin-top: 2px; }
.stat-detail-value { text-align: right; flex-shrink: 0; }
.stat-detail-amount { font-weight: 700; font-size: 15px; color: var(--success); }
.stat-detail-recurring { font-size: 11.5px; color: var(--text-muted); margin-top: 2px; }
.lead-card-footer { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.lead-card-footer .lead-card-select { width: 100%; margin-top: 0; }
.lead-card-profit-row { display: flex; gap: 6px; }
.btn-take-profit, .btn-no-profit {
  flex: 1;
  border-radius: 6px;
  padding: 5px 6px;
  font-size: 10.5px;
  font-weight: 600;
  cursor: pointer;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.btn-take-profit {
  background: rgba(47,163,107,0.14);
  border: 1px solid rgba(47,163,107,0.35);
  color: var(--success);
}
.btn-take-profit:hover { background: var(--success); color: #fff; }
.btn-no-profit {
  background: var(--glass-light);
  border: 1px solid var(--silver-soft);
  color: var(--text-muted);
}
.btn-no-profit:hover { background: var(--silver-soft); color: var(--text); }
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--silver-soft);
  border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--silver);
}
* {
  scrollbar-width: thin;
  scrollbar-color: var(--silver-soft) transparent;
}

/* ==========================================================================
   Motion — every page, card, modal, badge, and button in the app gets a
   small, consistent bit of animation. Nothing here changes layout or colors,
   only how things arrive on screen and respond to a tap. Two mechanisms do
   almost all of the work with no JS involved:
   1) A CSS animation on a selector auto-plays whenever a NEW element
      matching it is inserted into the page — and every render*() function in
      app.js replaces its container's content wholesale (innerHTML = ...),
      so cards/rows/pages are always freshly-inserted elements. That's what
      makes this "everything" without touching every render function.
   2) transition properties handle continuous states (hover/press/focus).
   ========================================================================== */

@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes popIn {
  from { opacity: 0; transform: scale(0.94); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes softPulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.15); }
}

/* Every page rises + fades in as it loads — covers every route in the app,
   since #view's content is fully replaced on every navigation. */
#view > * { animation: fadeInUp 0.32s ease both; }
#view > *:nth-child(2) { animation-delay: 0.03s; }
#view > *:nth-child(3) { animation-delay: 0.06s; }
#view > *:nth-child(4) { animation-delay: 0.09s; }

/* The Dashboard's stat cards and sections already had staggered
   animation-delay values wired up inline in app.js (0ms, 175ms, 350ms...) —
   this is the animation that actually plays them. */
.dash-fade { animation: fadeInUp 0.45s ease both; }

/* Cards and list rows fade/rise in on every insert — first load AND every
   re-render (tab switch, search, filter, day pick, drag to a new pipeline
   column) since these elements are recreated fresh each time. */
.job-card,
.recurring-customer-card,
.lead-card,
.jobs-today-row,
.text-card,
.table tbody tr {
  animation: fadeInUp 0.3s ease both;
}

/* Modals: backdrop fades, the modal itself fades + gently pops up — one
   shared system, so every modal in the app (add/edit lead, contact, etc.)
   gets this automatically. */
.modal-backdrop { animation: fadeIn 0.18s ease both; }
.modal { animation: popIn 0.22s cubic-bezier(0.2, 0.8, 0.3, 1.1) both; }

/* .auth-card is the shared panel every public, no-login page builds its
   content on (login, book-a-quote, invoice, rate, accept-quote, account) —
   this one rule gives all of them a consistent fade-up entrance without
   touching each page's own markup or inline styles. Success/confirmation
   states inside those pages (e.g. book.html's #book-success) reuse the same
   animation the moment they're un-hidden via JS-toggled display. */
.auth-card, .book-success { animation: fadeInUp 0.5s cubic-bezier(0.22, 1, 0.36, 1) both; }

/* Buttons already had a small press transition — add a lift on hover for the
   filled/colored variants so they feel a bit more alive. */
.btn:active { transform: scale(0.96) translateY(1px); }
.btn-primary:hover, .btn-accent:hover, .btn-danger:hover, .btn-success:hover { transform: translateY(-1px); }

/* Notification badges (Dashboard's Today's-Jobs count, Follow-ups count)
   pulse gently on a loop so an unread count actually catches your eye
   instead of just sitting there. */
.nav-badge { animation: softPulse 1.8s ease-in-out infinite; }

/* Calendar "today" cell gets the same treatment so it's easy to spot. */
.cal-cell-today { animation: softPulse 2.4s ease-in-out infinite; }

/* Inputs get a smooth focus transition instead of snapping. */
input, select, textarea {
  transition: border-color 0.15s ease, box-shadow 0.15s ease, outline-offset 0.15s ease;
}

/* Schedule tabs slide their active state in smoothly instead of snapping. */
.schedule-tab { transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.1s ease; }
.schedule-tab:active { transform: scale(0.96); }

/* Respect the "reduce motion" OS/browser setting — everything above becomes
   an instant, no-motion state instead of trying to fade/pop/pulse. */
@media (prefers-reduced-motion: reduce) {
  #view > *,
  .dash-fade,
  .job-card,
  .recurring-customer-card,
  .lead-card,
  .jobs-today-row,
  .text-card,
  .table tbody tr,
  .modal-backdrop,
  .modal,
  .nav-badge,
  .cal-cell-today,
  .auth-card,
  .book-success {
    animation: none !important;
  }
  * {
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- Packages page --- */
.packages-header {
  display: flex;
  align-items: center;
  gap: 20px;
  background: linear-gradient(135deg, var(--ink), var(--slate-soft));
  border-radius: var(--radius);
  padding: 26px 28px;
  margin-bottom: 20px;
  box-shadow: var(--shadow-sm);
}
.packages-logo {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  flex-shrink: 0;
  box-shadow: 0 2px 10px rgba(0,0,0,0.35);
  background: #0B0B0B;
  object-fit: cover;
}
.packages-header-text h2 {
  color: #fff;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 22px;
  margin: 0 0 6px;
}
.packages-header-text p {
  color: rgba(255,255,255,0.78);
  font-size: 13.5px;
  margin: 0;
  max-width: 620px;
}
.pkg-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-bottom: 22px;
}
@media (max-width: 1100px) { .pkg-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 640px) { .pkg-grid { grid-template-columns: 1fr; } }
.pkg-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--silver-soft);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 22px 18px 18px;
  display: flex;
  flex-direction: column;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.pkg-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.pkg-card-highlight {
  border-color: var(--amber);
  box-shadow: 0 0 0 2px rgba(242,169,59,0.35), var(--shadow-md);
}
.pkg-ribbon {
  position: absolute;
  top: -11px;
  left: 18px;
  background: var(--amber);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 999px;
  box-shadow: 0 2px 6px rgba(0,0,0,0.2);
}
.pkg-name {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 18px;
  font-weight: 600;
  color: var(--ink);
  margin: 4px 0 2px;
}
.pkg-frequency {
  font-size: 12.5px;
  color: var(--text-muted);
  margin-bottom: 14px;
}
.pkg-price {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 30px;
  font-weight: 700;
  color: var(--ink);
  line-height: 1;
  margin-bottom: 2px;
}
.pkg-price span { font-size: 13px; font-weight: 500; color: var(--text-muted); }
.pkg-tagline {
  font-size: 13px;
  color: var(--text-muted);
  margin: 10px 0 14px;
  line-height: 1.45;
}
.pkg-features {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
  flex: 1;
}
.pkg-features li {
  font-size: 13px;
  color: var(--text);
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 8px;
  line-height: 1.4;
}
.pkg-features li::before {
  content: "✓";
  color: var(--success);
  font-weight: 700;
  flex-shrink: 0;
}
.pkg-edit-form { margin-top: 10px; }
.pkg-edit-form textarea { min-height: 84px; resize: vertical; font-family: inherit; }
.pkg-edit-highlight-row { display: flex; align-items: center; gap: 8px; margin: 10px 0 0; font-size: 13px; color: var(--text-muted); }
.pkg-card-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: auto; padding-top: 14px; border-top: 1px solid var(--silver-soft); }
.pkg-card-actions .btn { flex: 1; }

/* Package plans — view-mode "sheet" (a single unified document rather than
   a row of separate cards), used only by viewHtml(); edit mode still uses
   the .pkg-grid/.pkg-card rules above unchanged. */
.pkg-sheet {
  background: var(--surface);
  border: 1px solid var(--silver-soft);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  margin-bottom: 16px;
}
.pkg-sheet-header {
  display: flex;
  align-items: center;
  gap: 20px;
  background: linear-gradient(135deg, var(--ink), var(--slate-soft));
  padding: 26px 28px;
}
.pkg-sheet-logo {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  flex-shrink: 0;
  box-shadow: 0 2px 10px rgba(0,0,0,0.35);
  background: #0B0B0B;
  object-fit: cover;
}
.pkg-sheet-title {
  color: #fff;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 22px;
  margin: 0 0 6px;
}
.pkg-sheet-sub {
  color: rgba(255,255,255,0.78);
  font-size: 13.5px;
  margin: 0;
  max-width: 620px;
}
.pkg-sheet-rows { display: flex; flex-direction: column; }
.pkg-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 20px;
  padding: 22px 28px;
  border-top: 1px solid var(--silver-soft);
}
.pkg-sheet-rows .pkg-row:first-child { border-top: none; }
.pkg-row-highlight {
  background: rgba(242,169,59,0.06);
  box-shadow: inset 4px 0 0 var(--amber);
}
.pkg-row-main { min-width: 0; }
.pkg-row-name {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 17px;
  font-weight: 600;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.pkg-row-ribbon {
  background: var(--amber);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
}
.pkg-row-freq {
  font-size: 12.5px;
  color: var(--text-muted);
  margin: 3px 0 8px;
}
.pkg-row-tagline {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.45;
  margin-bottom: 10px;
  max-width: 520px;
}
.pkg-row-features {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.pkg-row-features li {
  font-size: 12.5px;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 6px;
}
.pkg-row-features li::before {
  content: "✓";
  color: var(--success);
  font-weight: 700;
  flex-shrink: 0;
}
/* The save badge and the row's action buttons (Copy / Send to a customer)
   live together in one right-hand column — there's no dollar figure to
   anchor a separate price column anymore, so splitting them into two
   columns just left one looking empty. */
.pkg-row-price {
  text-align: right;
  min-width: 150px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 10px;
}
.pkg-row-regular {
  font-size: 14px;
  color: var(--text-muted);
  text-decoration: line-through;
}
.pkg-row-discounted {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 28px;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.15;
}
.pkg-row-save {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: rgba(47,163,107,0.12);
  border: 1px solid rgba(47,163,107,0.35);
  color: var(--success);
  font-size: 13px;
  font-weight: 700;
  padding: 5px 14px;
  border-radius: 999px;
}
.pkg-row-save svg { flex-shrink: 0; }
.pkg-row-plain-label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
}
.pkg-row-actions { display: flex; flex-direction: column; gap: 8px; min-width: 150px; }
.pkg-page-actions { display: flex; gap: 8px; flex-wrap: wrap; }
@media (max-width: 720px) {
  .pkg-row {
    grid-template-columns: 1fr;
    justify-items: start;
  }
  .pkg-row-price { text-align: left; align-items: flex-start; width: 100%; }
  .pkg-row-actions { flex-direction: row; width: 100%; }
  .pkg-row-actions .btn { flex: 1; }
}

/* Personalized plan quote modal (openPersonalizedQuoteModal in app.js) —
   picks a paid job, then builds a per-customer chart discounted off that
   job's price. Reuses .pkg-row-name/-freq/-tagline/-features/-regular/
   -discounted/-save/-plain-label (leaf styles, no grid assumptions) inside
   its own 2-column .pq-row grid, since the main .pkg-row's 3-column grid
   expects an actions column this modal doesn't have. */
.pq-capture-header {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--glass-light);
  border-radius: var(--radius);
  padding: 16px 18px;
  margin-bottom: 4px;
}
.pq-capture-sub { font-size: 13px; color: var(--text-muted); margin-top: 4px; }
.pq-list { display: flex; flex-direction: column; }
.pq-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 16px 4px;
  border-top: 1px solid var(--silver-soft);
}
.pq-list .pq-row:first-of-type { border-top: none; }
/* The save badge and the Proceed button live together here as one cluster —
   there's no dollar figure to anchor the column anymore (every job's real
   price is quoted after the fact), so grouping the discount with the actual
   call-to-action keeps this column from reading as empty/unfinished. */
.pq-row-price {
  text-align: right;
  min-width: 160px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 10px;
}
.pq-off-row { margin-top: 10px; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.pq-off-row .mini-label { margin: 0 0 2px; }
.pq-off-input { width: 90px; text-align: right; }
@media (max-width: 640px) {
  .pq-row { grid-template-columns: 1fr; }
  .pq-row-price { text-align: left; align-items: flex-start; }
  .pq-off-row { align-items: flex-start; }
}

/* ==========================================================================
   Intro splash screen — shown on every fresh page load (index.html and
   login.html both include it, since it should appear whether you're
   already signed in or not). Rising soap bubbles + the real logo fading in,
   held for a few seconds, then the whole thing fades away to reveal
   whatever the app decided to show underneath (dashboard or the sign-in
   form) — which has been loading in the background the entire time.
   The bubble count/timing is driven by splash.js; this just styles them.
   ========================================================================== */
.app-splash {
  position: fixed;
  inset: 0;
  z-index: 99999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at top, var(--slate) 0%, var(--ink) 65%);
  overflow: hidden;
  transition: opacity 0.6s ease;
}
.app-splash--hiding { opacity: 0; pointer-events: none; }

.app-splash-bubbles { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }

.app-splash-bubble {
  position: absolute;
  bottom: -10%;
  left: var(--x, 50%);
  width: var(--size, 30px);
  height: var(--size, 30px);
  border-radius: 50%;
  background: radial-gradient(circle at 32% 26%,
    rgba(255,255,255,0.95) 0%,
    rgba(255,255,255,0.45) 10%,
    rgba(184,226,255,0.28) 42%,
    rgba(120,190,255,0.14) 72%,
    rgba(120,190,255,0.04) 100%);
  border: 1px solid rgba(255,255,255,0.4);
  box-shadow:
    0 0 10px rgba(140,200,255,0.35),
    inset 0 0 14px rgba(255,255,255,0.35),
    inset -5px -6px 12px rgba(70,140,210,0.3);
  opacity: 0;
  animation: splashBubbleRise var(--duration, 4.2s) cubic-bezier(0.32, 0.1, 0.5, 1) var(--delay, 0s) both;
  will-change: transform, opacity;
}
.app-splash-bubble::after {
  content: "";
  position: absolute;
  top: 16%;
  left: 20%;
  width: 30%;
  height: 18%;
  background: rgba(255,255,255,0.85);
  border-radius: 50%;
  filter: blur(1px);
  transform: rotate(-18deg);
}
@keyframes splashBubbleRise {
  0%   { transform: translate3d(0, 0, 0) scale(0.85); opacity: 0; }
  6%   { opacity: var(--bubble-opacity, 0.8); }
  24%  { transform: translate3d(var(--drift-1, 14px), -28vh, 0) scale(1); }
  48%  { transform: translate3d(var(--drift-2, -18px), -55vh, 0) scale(1.04); }
  73%  { transform: translate3d(var(--drift-3, 12px), -82vh, 0) scale(0.98); }
  90%  { opacity: var(--bubble-opacity, 0.8); }
  100% { transform: translate3d(var(--drift-4, 0), -112vh, 0) scale(0.88); opacity: 0; }
}

.app-splash-logo {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  opacity: 0;
  transform: translateY(16px) scale(0.94);
  animation: splashLogoIn 2.2s cubic-bezier(0.16, 0.9, 0.28, 1) 0.55s both;
}
.app-splash-logo-badge {
  width: 108px;
  height: 108px;
  border-radius: 50%;
  overflow: hidden;
  background: #0B2436;
  box-shadow:
    0 0 0 3px rgba(255,255,255,0.1),
    0 0 40px rgba(62,143,208,0.45),
    0 10px 30px rgba(0,0,0,0.4);
  animation: splashBadgeGlow 2.6s ease-in-out 1.4s infinite;
}
.app-splash-logo-badge img { width: 100%; height: 100%; object-fit: cover; display: block; }
.app-splash-brand-name { font-family: var(--font-display); font-weight: 700; font-size: 21px; color: #fff; letter-spacing: 0.3px; }
.app-splash-brand-sub { font-size: 11.5px; color: rgba(255,255,255,0.6); letter-spacing: 3px; text-transform: uppercase; }

@keyframes splashLogoIn {
  0% { opacity: 0; transform: translateY(16px) scale(0.94); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes splashBadgeGlow {
  0%, 100% { box-shadow: 0 0 0 3px rgba(255,255,255,0.1), 0 0 40px rgba(62,143,208,0.45), 0 10px 30px rgba(0,0,0,0.4); }
  50% { box-shadow: 0 0 0 3px rgba(255,255,255,0.16), 0 0 55px rgba(62,143,208,0.65), 0 10px 30px rgba(0,0,0,0.4); }
}

@media (prefers-reduced-motion: reduce) {
  .app-splash-bubble { display: none; }
  .app-splash-logo { animation: none; opacity: 1; transform: none; }
  .app-splash-logo-badge { animation: none; }
}
@media (max-width: 480px) {
  .app-splash-logo-badge { width: 84px; height: 84px; }
  .app-splash-brand-name { font-size: 18px; }
}

