/* ============================================================
   פה ופה CRM – Main Stylesheet (RTL / Hebrew)

   DIRECTION: logical properties, not physical ones.
   Every offset, padding, margin, border and alignment that has a
   direction is written as *-inline-start / *-inline-end / start / end.
   The document is <html dir="rtl">, so inline-start resolves to the
   physical right and inline-end to the physical left; the rules below
   therefore render exactly as the physical ones they replaced. The
   point is not a behaviour change - it is that the stylesheet stops
   claiming a left edge it means as a right edge, so the next person
   reading `right: 19px` does not have to hold the flip in their head,
   and an LTR surface (an English report, an embedded form) is not
   silently mirrored.

   Top/bottom stay physical: they do not flip.
   `transform: translateX()` stays physical too - transforms are not
   direction-aware, and pairing one with a logical inset is correct.
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --primary:       #6C63FF;
  --primary-light: #EDE9FF;
  --primary-dark:  #5A52D5;
  --success:       #10B981;
  --success-light: #D1FAE5;
  --warning:       #F59E0B;
  --warning-light: #FEF3C7;
  /* Text ON --warning-light. --warning itself is a FILL colour: #F59E0B on
     #FEF3C7 is about 1.9:1, well under WCAG AA, and the conflict warning is
     the one element whose entire job is to be read. */
  --warning-dark:  #92400E;
  --danger:        #EF4444;
  --danger-light:  #FEE2E2;
  --info:          #3B82F6;
  --info-light:    #DBEAFE;
  --purple:        #8B5CF6;
  --purple-light:  #EDE9FE;
  --invested:      #059669;

  --bg:            #F8F9FC;
  --card-bg:       #FFFFFF;
  --border:        #E5E7EB;
  --border-focus:  #6C63FF;
  --text:          #1F2937;
  --text-muted:    #6B7280;
  --text-light:    #9CA3AF;

  /* ── Measured tokens for the anonymous pages ────────────────────────
     index.php, sso/login.php and sso/signup_request.php are the three
     screens someone who is not yet a customer ever sees, and every colour
     on them used to be a hex literal typed into a style attribute. They
     are tokens now for one reason: tools/contrast_audit.php can only
     measure what it can resolve, and a number buried in a PHP string is
     invisible to it. Every value below is in that script's table.

     --primary-on-white is NOT --primary. White on #6C63FF is 4.32:1,
     under the 4.5:1 floor for the button label, so the filled button takes
     this deeper tone (5.83:1) and --primary stays what it always was: the
     brand hue, used for the wordmark, borders and tints. --primary-deep is
     that button's hover, kept a step darker still so the hover remains
     visible now that the resting state moved.

     --login-fine replaces a literal #999 (2.85:1 on the white card) on the
     "או עם שם משתמש וסיסמה" lines, and --login-error-ink replaces
     --danger on --danger-light (3.08:1) for the failed-login message. */
  --primary-on-white:  #5A52D5;
  --primary-deep:      #4A43BF;
  --login-fine:        #5B6270;
  --login-error-ink:   #B42318;
  --sr-label:          #555555;
  --sr-note-bg:        #F3F5F8;
  --sr-note-ink:       #333333;

  --sidebar-w:     240px;
  --header-h:      64px;
  --radius:        10px;
  --radius-sm:     6px;
  --shadow:        0 1px 4px rgba(0,0,0,.08), 0 4px 16px rgba(0,0,0,.06);
  --shadow-sm:     0 1px 3px rgba(0,0,0,.06);
}

html { font-size: 16px; }
body {
  font-family: 'Heebo', sans-serif;
  background: var(--bg);
  color: var(--text);
  direction: rtl;
  min-height: 100vh;
}

/* ── Layout ─────────────────────────────────────────────────── */
.app-layout {
  display: flex;
  min-height: 100vh;
}

/* ── Sidebar ────────────────────────────────────────────────── */
.sidebar {
  width: var(--sidebar-w);
  background: #1E1B4B;
  color: #fff;
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0; right: 0; bottom: 0;
  z-index: 100;
}
.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 20px 16px;
  border-bottom: 1px solid rgba(255,255,255,.1);
}
.brand-logo { font-size: 28px; }
.brand-name { font-size: 15px; font-weight: 700; }
/* ── Logo image sizes ──────────────────────────────────────── */
/* The mark is navy-on-transparent, and both the sidebar (#1E1B4B) and the
   mobile top bar are dark. A white chip behind it is what keeps the wordmark
   legible there without shipping a second, light-on-dark artwork file. */
.brand-logo-img          { display: block; object-fit: contain; border-radius: 6px;
                           background: #fff; padding: 3px 6px; }
.brand-logo-img--sidebar { height: 40px; width: auto; }
.brand-logo-img--mobile  { height: 28px; width: auto; }

.sidebar-nav {
  flex: 1;
  padding: 12px 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  color: rgba(255,255,255,.7);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  transition: all .15s;
}
.nav-item:hover { background: rgba(255,255,255,.08); color: #fff; }
.nav-item.active { background: var(--primary); color: #fff; }
.nav-icon { font-size: 18px; width: 22px; text-align: center; }

.sidebar-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-top: 1px solid rgba(255,255,255,.1);
  font-size: 13px;
}
.user-info { display: flex; align-items: center; gap: 8px; color: rgba(255,255,255,.8); }
.user-avatar { font-size: 20px; }
/* On a <button> since the logout became a POST form (see includes/header.php).
   The reset properties are what a button needs to look like the bare glyph an
   <a> gave for free; min-height is the project's 44px touch target, which the
   link never had. */
.logout-form { display: flex; }
.logout-btn {
  color: rgba(255,255,255,.5);
  font-size: 18px;
  text-decoration: none;
  transition: color .15s;
  background: none;
  border: 0;
  padding: 0 8px;
  min-height: 44px;
  min-width: 44px;
  font-family: inherit;
  cursor: pointer;
}
.logout-btn:hover { color: var(--danger); }

/* ── Main Content ────────────────────────────────────────────── */
.main-content {
  flex: 1;
  margin-right: var(--sidebar-w);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 28px 0;
  min-height: 64px;
}
.page-title {
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
}
.page-actions { display: flex; gap: 10px; align-items: center; }
.page-body { padding: 20px 28px 40px; flex: 1; }

/* ── Cards ───────────────────────────────────────────────────── */
.card {
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 20px;
}
.card-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ── KPI Cards ───────────────────────────────────────────────── */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}
.kpi-card {
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 20px;
  display: flex;
  align-items: center;
  gap: 16px;
}
.kpi-icon {
  width: 52px; height: 52px;
  border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px;
  flex-shrink: 0;
}
.kpi-icon.purple { background: var(--primary-light); }
.kpi-icon.green  { background: var(--success-light); }
.kpi-icon.orange { background: var(--warning-light); }
.kpi-icon.blue   { background: var(--info-light); }
.kpi-value { font-size: 28px; font-weight: 700; line-height: 1; }
.kpi-label { font-size: 13px; color: var(--text-muted); margin-top: 4px; }

/* ── Buttons ─────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: var(--radius-sm);
  border: none;
  font-family: 'Heebo', sans-serif;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  transition: all .15s;
  white-space: nowrap;
}
/* --primary-on-white, not --primary: white on the brand hue measures
   4.32:1, and this button's label is body-sized text. See the token block
   at the top of this file, and tools/contrast_audit.php for the number. */
.btn-primary   { background: var(--primary-on-white); color: #fff; }
.btn-primary:hover { background: var(--primary-deep); }
.btn-success   { background: var(--success); color: #fff; }
.btn-success:hover { filter: brightness(.9); }
.btn-danger    { background: var(--danger); color: #fff; }
.btn-danger:hover { filter: brightness(.9); }
.btn-warning   { background: var(--warning); color: #fff; }
.btn-ghost     { background: transparent; color: var(--text-muted); border: 1px solid var(--border); }
.btn-ghost:hover { background: var(--bg); }
.btn-sm        { padding: 5px 12px; font-size: 13px; }
.btn-icon      { padding: 7px; width: 34px; height: 34px; justify-content: center; }

/* The share-link icon. .btn-icon is 34px — sized for a dense desktop
   toolbar — and this one is tapped by a broker standing in a stairwell, so
   it gets the 44px minimum comfortable target in every viewport rather than
   only under the mobile media query. No colour of its own: it inherits
   .btn-ghost like the buttons beside it. */
.btn-share     { min-width: 44px; min-height: 44px; padding: 7px; justify-content: center; }

/* ── Forms ───────────────────────────────────────────────────── */
.form-group { margin-bottom: 16px; }
.form-label { display: block; font-size: 13px; font-weight: 500; margin-bottom: 6px; color: var(--text); }
.form-control {
  width: 100%;
  padding: 9px 12px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: 'Heebo', sans-serif;
  font-size: 14px;
  color: var(--text);
  background: #fff;
  direction: rtl;
  transition: border-color .15s;
}
.form-control:focus {
  outline: none;
  border-color: var(--border-focus);
  box-shadow: 0 0 0 3px rgba(108,99,255,.12);
}
textarea.form-control { resize: vertical; min-height: 90px; }
select.form-control { cursor: pointer; }

.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.form-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }

/* ── Table ───────────────────────────────────────────────────── */
.table-wrap { overflow-x: auto; }
table.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.data-table thead th {
  background: var(--bg);
  padding: 10px 14px;
  text-align: start;
  font-weight: 600;
  font-size: 13px;
  color: var(--text-muted);
  border-bottom: 2px solid var(--border);
  white-space: nowrap;
}
.data-table thead th.sortable {
  cursor: pointer;
  user-select: none;
}
.data-table thead th.sortable:hover {
  background: var(--primary-light);
  color: var(--primary);
}
.data-table thead th.sort-active {
  color: var(--primary);
}
.sort-icon {
  font-size: 11px;
  opacity: 0.5;
  margin-inline-start: 4px;
}
th.sort-active .sort-icon {
  opacity: 1;
}
.data-table tbody tr {
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background .1s;
  position: relative;
}
.data-table tbody tr:hover { background: #F5F3FF; }
.data-table tbody td {
  padding: 11px 14px;
  vertical-align: middle;
}
.data-table tbody tr.inactive-lead {
  border-inline-start: 4px solid var(--danger);
}
.data-table tbody tr.inactive-lead td:last-child::after {
  content: ' ⚠';
  color: var(--danger);
}

/* ── Status Badge ────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

/* ── Filter Bar ──────────────────────────────────────────────── */
.filter-bar {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.filter-bar .form-control { width: auto; min-width: 160px; }
.search-box { position: relative; }
.search-box .form-control { padding-inline-start: 36px; }
.search-box::before {
  content: '🔍';
  position: absolute;
  inset-inline-start: 10px; top: 50%;
  transform: translateY(-50%);
  font-size: 14px;
  pointer-events: none;
}

/* ── Tabs ────────────────────────────────────────────────────── */
.tabs {
  display: flex;
  gap: 0;
  border-bottom: 2px solid var(--border);
  margin-bottom: 20px;
}
.tab-btn {
  padding: 10px 20px;
  border: none;
  background: none;
  font-family: 'Heebo', sans-serif;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: all .15s;
}
.tab-btn:hover { color: var(--primary); }
.tab-btn.active { color: var(--primary); border-bottom-color: var(--primary); }
.tab-content { display: none; }
.tab-content.active { display: block; }

/* ── Drawer (as centered popup) ─────────────────────────────── */
.drawer-overlay {
  display: none;
  position: fixed; inset: 0;
  background: rgba(0,0,0,.5);
  z-index: 200;
  align-items: center;
  justify-content: center;
}
.drawer-overlay.open { display: flex; }

.drawer {
  position: relative;
  width: min(900px, 92vw);
  max-height: 88vh;
  background: #fff;
  z-index: 201;
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 60px rgba(0,0,0,.25);
  transform: scale(.95);
  opacity: 0;
  transition: transform .2s ease, opacity .2s ease;
}
.drawer.open {
  transform: scale(1);
  opacity: 1;
}
.drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.drawer-title { font-size: 18px; font-weight: 700; }
.drawer-close {
  background: none; border: none;
  font-size: 20px; cursor: pointer;
  color: var(--text-muted);
  padding: 4px 8px;
  border-radius: 4px;
}
.drawer-close:hover { background: var(--bg); }
.drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
}

/* ── Status Picker ───────────────────────────────────────────── */
.status-badge-clickable {
  transition: opacity .15s;
}
.status-badge-clickable:hover { opacity: .75; }

.status-picker {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  margin: 8px 0 4px;
  box-shadow: var(--shadow);
  animation: fadeIn .15s ease;
}
.status-picker-options {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.status-picker-option {
  border-radius: 20px;
  padding: 5px 14px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  font-family: 'Heebo', sans-serif;
  transition: transform .1s, opacity .1s;
}
.status-picker-option:hover { transform: scale(1.05); opacity: .85; }

/* ── Table floating status picker ───────────────────────────── */
.table-status-picker-float {
  position: fixed;
  z-index: 9999;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 10px;
  min-width: 170px;
  animation: fadeIn .12s ease;
}
.table-status-picker-float .status-picker-options {
  display: flex; flex-direction: column; gap: 5px;
}

/* ── Hide-not-interested toggle ─────────────────────────────── */
.hide-toggle-label {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-size: 13px;
  color: var(--text-muted);
  white-space: nowrap;
  user-select: none;
}
.hide-toggle-label input[type="checkbox"] {
  width: 15px; height: 15px; cursor: pointer;
}

@keyframes fadeIn { from { opacity:0; transform:translateY(-4px); } to { opacity:1; transform:translateY(0); } }

/* ── Modal ───────────────────────────────────────────────────── */
.modal-overlay {
  display: none;
  position: fixed; inset: 0;
  background: rgba(0,0,0,.5);
  z-index: 300;
  align-items: center;
  justify-content: center;
}
.modal-overlay.open { display: flex; }
.modal {
  background: #fff;
  border-radius: var(--radius);
  box-shadow: 0 20px 60px rgba(0,0,0,.2);
  width: 480px;
  max-width: 95vw;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
}
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.modal-title { font-size: 16px; font-weight: 700; }
.modal-close {
  background: none; border: none;
  font-size: 20px; cursor: pointer;
  color: var(--text-muted);
  padding: 4px 8px;
  border-radius: 4px;
}
.modal-close:hover { background: var(--bg); }
.modal-body {
  padding: 20px;
  overflow-y: auto;
}

/* Opt-in wider dialog, added by the caller for the one thing that needs it:
   the duplicate scan lists several leads side by side with a phone, a mail
   and a status on each, which is unreadable at 480px. openModal() clears the
   class on every open, so a modal that did not ask for it never gets it. The
   max-width on .modal already keeps this inside a phone screen. */
.modal.modal-wide { width: 760px; }

/* ── כפילויות ליידים ────────────────────────────────────────────────────
   The duplicate groups inside that dialog. Green is "same phone or mail" and
   safe to merge in one click; orange is "similar name only" and may well be
   two different people, so the colour is the warning and the radio is the
   decision. No new modal and no new overlay - assets/js/leads.js opens the
   shared #modal through openModal(). */
.dd-scroll { max-height: 65vh; overflow-y: auto; padding-inline-start: 4px; }

.dd-group {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 8px;
  background: #fff;
}
/* The band down the START edge (right, in RTL) is what makes the two kinds
   tellable apart at a glance while scrolling a long list. */
.dd-group.dd-exact { border-inline-start: 4px solid #16a34a; }
.dd-group.dd-susp  { border-inline-start: 4px solid #d97706; }

.dd-group-head {
  display: flex; justify-content: space-between; align-items: center;
  gap: 8px; margin-bottom: 4px;
}
.dd-reason { font-size: 11px; font-weight: 700; }
.dd-exact .dd-reason { color: #16a34a; }
.dd-susp  .dd-reason { color: #d97706; }
.dd-group-actions { display: flex; gap: 6px; flex-shrink: 0; }

/* The label IS the radio's hit area, so the comfortable target belongs here
   rather than on the 15px control. */
.dd-lead {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 6px; border-radius: 6px; cursor: pointer;
  min-height: 40px;
}
.dd-lead:hover { background: var(--bg); }
.dd-lead input[type=radio] { margin-top: 4px; cursor: pointer; flex-shrink: 0; }
.dd-lead-main { flex: 1; font-size: 13px; min-width: 0; }
.dd-lead-id  { color: var(--text-muted); font-size: 11px; }
.dd-lead-sub {
  color: var(--text-muted); font-size: 11px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dd-group.dd-failed { outline: 2px solid #dc2626; }

.dd-bar {
  display: flex; justify-content: space-between; align-items: center;
  gap: 10px; flex-wrap: wrap;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 8px; padding: 8px 12px; margin-bottom: 12px;
}
.dd-note { font-size: 12px; color: var(--text-muted); margin: 4px 0 10px; }
.dd-warn {
  font-size: 12px; color: #92400e; background: #fffbeb;
  border: 1px solid #fde68a; border-radius: 6px;
  padding: 8px 10px; margin-bottom: 12px;
}
.dd-empty { padding: 16px 0; font-size: 13px; color: var(--text-muted); text-align: center; }

/* ── Draggable window headers ─────────────────────────────────
   The header of every floating window in this app is a drag handle:
   makeDraggable() in assets/js/app.js wires .modal-header (#modal, #lpModal,
   #pmModal), .drawer-header (#leadDrawer) and .fb-head (#feedbackModal).

   user-select:none is what stops a drag from painting a selection across the
   title on the way. It is on the handle only - the BODY of every one of
   these windows stays selectable and clickable, which is the whole point of
   dragging one out of the way in the first place.

   cursor:move is inside a min-width query because the drag itself is: under
   769px these boxes are full-width bottom sheets and app.js refuses to move
   them, so a move cursor there would promise something that does not happen.
   The close buttons declare cursor:pointer of their own and keep it. */
.modal-header,
.drawer-header,
.fb-head { user-select: none; }

@media (min-width: 769px) {
  .modal-header,
  .drawer-header,
  .fb-head { cursor: move; }
}

/* Held down: no easing between the frames of a drag. .drawer is the one that
   really has a transition (transform+opacity for its open animation); the
   rule is on all three so the next box to grow one is already covered. */
.modal.dragging,
.drawer.dragging,
.fb-modal.dragging { transition: none; }

/* ── Toast ───────────────────────────────────────────────────── */
.toast-container {
  position: fixed;
  bottom: 24px;
  inset-inline-end: 24px;
  z-index: 999;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.toast {
  padding: 12px 18px;
  border-radius: var(--radius-sm);
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  box-shadow: var(--shadow);
  animation: slideIn .3s ease;
  min-width: 220px;
}
.toast.success { background: var(--success); }
.toast.error   { background: var(--danger); }
.toast.info    { background: var(--primary); }
@keyframes slideIn {
  from { transform: translateY(20px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

/* ── Timeline (interactions) ─────────────────────────────────── */
.timeline { display: flex; flex-direction: column; gap: 0; }
.timeline-item {
  display: flex;
  gap: 14px;
  padding-bottom: 20px;
  position: relative;
}
.timeline-item:not(:last-child)::before {
  content: '';
  position: absolute;
  inset-inline-start: 19px;
  top: 28px;
  bottom: 0;
  width: 2px;
  background: var(--border);
}
.timeline-dot {
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--primary);
  flex-shrink: 0;
  margin-top: 4px;
  border: 3px solid #fff;
  box-shadow: 0 0 0 2px var(--primary);
}
.timeline-content { flex: 1; }
.timeline-meta {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-bottom: 6px;
  flex-wrap: wrap;
}
.timeline-date { font-size: 12px; color: var(--text-muted); }
.timeline-text {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  white-space: pre-wrap;
}
.timeline-item-actions {
  display: flex;
  gap: 2px;
  margin-inline-start: auto;
  opacity: 0;
  transition: opacity .15s;
}
.timeline-item:hover .timeline-item-actions { opacity: 1; }
.tl-action-btn {
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 2px 6px;
  cursor: pointer;
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-muted);
  transition: background .12s, border-color .12s;
}
.tl-action-btn:hover { background: var(--card); border-color: var(--border); color: var(--text); }
.tl-action-delete:hover { background: #fef2f2; border-color: #fecaca; color: #ef4444; }

/* ── Event type badge in timeline ───────────────────────────── */
.timeline-dot-event {
  background: #f59e0b;
  box-shadow: 0 0 0 2px #f59e0b;
}
.timeline-item-event > .timeline-content > .timeline-meta { flex-wrap: wrap; }

/* ── System activity log entries ────────────────────────────── */
.timeline-item-system {
  opacity: 0.75;
}
.timeline-item-system > .timeline-content {
  background: transparent;
  border: none;
  padding: 0 0 0 4px;
}
.timeline-dot-system {
  background: var(--text-light, #adb5bd);
  box-shadow: 0 0 0 2px var(--text-light, #adb5bd);
  width: 8px !important;
  height: 8px !important;
  margin-top: 5px;
}
.timeline-text-system {
  font-size: 12px;
  color: var(--text-muted);
  font-style: italic;
  white-space: normal;
}
.timeline-item-system .timeline-date {
  font-size: 11px;
}
.event-type-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: #fff7ed;
  color: #92400e;
  border: 1px solid #fcd34d;
  border-radius: 20px;
  padding: 2px 10px;
  font-size: 12px;
  font-weight: 600;
}
/* ── New event type inline row ───────────────────────────────── */
#newEventTypeRow { display: none; gap: 8px; align-items: center; }

/* ── Kanban ──────────────────────────────────────────────────── */
.kanban-board {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  padding-bottom: 20px;
  align-items: flex-start;
}
.kanban-col {
  flex-shrink: 0;
  width: 240px;
  background: var(--bg);
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  height: calc(100vh - 260px);
}
.kanban-col-header {
  padding: 12px 14px;
  font-weight: 600;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: var(--radius) var(--radius) 0 0;
  flex-shrink: 0;
}
.kanban-col-count {
  background: rgba(0,0,0,.12);
  color: inherit;
  border-radius: 20px;
  padding: 1px 8px;
  font-size: 12px;
}
.kanban-cards {
  flex: 1;
  min-height: 0;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
}
.kanban-card {
  background: #fff;
  border-radius: var(--radius-sm);
  padding: 12px;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: box-shadow .15s, transform .15s;
  border-inline-start: 3px solid transparent;
}
.kanban-card:hover { box-shadow: var(--shadow); transform: translateY(-1px); }
.kanban-card.dragging { opacity: .5; }
.kanban-card-name { font-weight: 600; font-size: 14px; margin-bottom: 4px; }
.kanban-card-phone { font-size: 12px; color: var(--text-muted); margin-bottom: 6px; }
.kanban-card-meta {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--text-light);
}
.kanban-drop-zone {
  min-height: 60px;
  border: 2px dashed var(--border);
  border-radius: var(--radius-sm);
  display: none;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 13px;
}
.kanban-drop-zone.active { display: flex; border-color: var(--primary); }

/* ── Progress Bar ────────────────────────────────────────────── */
.progress-bar-wrap {
  background: var(--border);
  border-radius: 20px;
  height: 10px;
  overflow: hidden;
}
.progress-bar {
  height: 100%;
  border-radius: 20px;
  background: var(--primary);
  transition: width .4s;
}

/* ── Reminder item ───────────────────────────────────────────── */
.reminder-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  margin-bottom: 10px;
  transition: background .1s;
}
.reminder-item:hover { background: var(--bg); }
.reminder-item.done { opacity: .5; }
.reminder-time { font-size: 13px; color: var(--warning); font-weight: 600; min-width: 80px; }
.reminder-note { font-size: 14px; flex: 1; }

/* ── Inactive indicator ──────────────────────────────────────── */
.inactive-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--danger);
  font-weight: 600;
}

/* ── Lead profile header v2 ──────────────────────────────────── */
.lead-header {
  background: var(--card);
  border-radius: var(--radius);
  margin-bottom: 16px;
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: 0 1px 6px rgba(0,0,0,.06);
}
.lh-top {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 18px 14px;
  background: linear-gradient(135deg, #f5f3ff, #eff6ff);
  border-bottom: 1px solid var(--border);
}
.lh-avatar {
  width: 50px; height: 50px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--primary), #818cf8);
  color: #fff;
  font-size: 18px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  letter-spacing: -1px;
  box-shadow: 0 2px 6px rgba(99,102,241,.35);
}
.lh-name {
  font-size: 19px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 6px;
  line-height: 1.2;
}
.lh-status-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.lh-invested-badge {
  display: inline-flex; align-items: center; gap: 4px;
  background: #dcfce7; color: #166534;
  padding: 2px 10px; border-radius: 20px;
  font-size: 12px; font-weight: 600;
}
.lh-score-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 10px; border-radius: 20px;
  font-size: 12px; font-weight: 600;
}
.lh-body {
  padding: 12px 18px 10px;
}
.lh-info-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 10px;
}
.lh-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 4px 11px;
  font-size: 13px;
  color: var(--text);
  line-height: 1.4;
}
.lh-chip a { color: inherit; text-decoration: none; }
.lh-chip a:hover { text-decoration: underline; }
.lh-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  padding: 10px 18px;
  background: var(--bg);
  border-top: 1px solid var(--border);
}
/* ── Interactions tab header ─────────────────────────────────── */
.interactions-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--border);
}
.interactions-count {
  font-size: 13px;
  color: var(--text-muted);
  font-weight: 500;
}

/* ── Investment payments section ────────────────────────────── */
.payments-section {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  margin-bottom: 12px;
}
.payments-header {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  font-size: 14px;
  font-weight: 600;
}
.payments-count { font-weight: 400; color: var(--text-muted); }
.payments-total { flex: 1; font-size: 13px; color: var(--text-muted); font-weight: 400; }
/* A wrapping flex row, not a five-column grid.
   90px 1fr auto 1fr 32px is 5 fixed tracks: on a 360px phone the date, the
   amount, the method badge, the note and the delete button were all crushed
   into whatever their track allowed, and the amount - the one number that
   matters - wrapped mid-figure or clipped. .inv-payment-row a few rules
   below already had this right; the two render the same information and now
   behave the same way. */
.payment-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
/* The date keeps the width its old track gave it, so a column of rows still
   lines up on a wide screen instead of ragging with the text length. */
.payment-row .payment-date { min-width: 90px; }
/* The note takes the rest of the line and is what gives way first. */
.payment-row .payment-notes { flex: 1 1 140px; min-width: 0; }
/* The delete control stays at the end of the row on every width. */
.payment-row > :last-child { margin-inline-start: auto; }
.payment-row:last-child { border-bottom: none; }
.payment-date { color: var(--text-muted); font-size: 12px; }
.payment-amount { font-weight: 600; color: var(--success); }
.payment-method-badge {
  display: inline-block;
  background: var(--primary-light);
  color: var(--primary);
  border-radius: 4px;
  padding: 1px 7px;
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
}
.payment-notes { color: var(--text-muted); font-size: 12px; }

/* ── Investment payments sub-rows (investments page table) ───── */
.inv-main-table tbody tr.inv-payments-sub td {
  background: var(--bg);
  padding: 0 12px 12px !important;
  border-top: none !important;
}
.inv-payments-list {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 4px 0 2px;
}
.inv-payment-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 14px;
  font-size: 13px;
}
.inv-pay-icon  { font-size: 15px; flex-shrink: 0; }
.inv-pay-date  { color: var(--text-muted); font-size: 12px; min-width: 72px; }
.inv-pay-amount { font-weight: 700; color: var(--success); font-size: 14px; }
.inv-pay-notes { color: var(--text-muted); font-size: 12px; font-style: italic; }

/* ── Investment card ─────────────────────────────────────────── */
.investment-summary {
  background: var(--success-light);
  border: 1px solid var(--success);
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  margin-bottom: 16px;
  font-size: 14px;
}
.investment-type-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}
.inv-type-btn {
  padding: 8px 16px;
  border-radius: 20px;
  border: 2px solid var(--border);
  background: none;
  font-family: 'Heebo', sans-serif;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all .15s;
}
.inv-type-btn.active {
  border-color: var(--primary);
  background: var(--primary-light);
  color: var(--primary);
}

/* ── Import page ─────────────────────────────────────────────── */
.upload-zone {
  border: 2px dashed var(--border);
  border-radius: var(--radius);
  padding: 40px 20px;
  text-align: center;
  cursor: pointer;
  transition: all .2s;
  background: var(--bg);
}
.upload-zone:hover, .upload-zone.dragover {
  border-color: var(--primary);
  background: var(--primary-light);
}
.upload-zone-icon { font-size: 40px; margin-bottom: 12px; }
.upload-zone-text { font-size: 15px; font-weight: 500; margin-bottom: 6px; }
.upload-zone-sub  { font-size: 13px; color: var(--text-muted); }

/* ── Chart container ─────────────────────────────────────────── */
.chart-container {
  position: relative;
  height: 200px;
}

/* ── Report filters ──────────────────────────────────────────── */
.report-filters {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
  background: var(--card-bg);
  padding: 16px 20px;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 20px;
}
.report-filters .form-group { margin-bottom: 0; }

/* ── Settings section ────────────────────────────────────────── */
.settings-section { margin-bottom: 32px; }
.settings-section-title {
  font-size: 16px;
  font-weight: 700;
  margin-bottom: 16px;
  padding-bottom: 8px;
  border-bottom: 2px solid var(--border);
  color: var(--primary);
}
.lookup-table .data-table td { vertical-align: middle; }

/* ── טבלאות (pages/lookups.php: city / neighbourhood / street) ─────── */
.lk-picked-city {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-bottom: 16px; padding: 10px 14px;
  background: var(--primary-light); border-radius: var(--radius-sm);
  font-size: 14px;
}
.lk-pager {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  margin-top: 14px; font-size: 13px; color: var(--text-muted);
}

.color-preview {
  width: 20px; height: 20px;
  border-radius: 50%;
  display: inline-block;
  border: 2px solid var(--border);
  vertical-align: middle;
}

/* ── Tags ────────────────────────────────────────────────────── */
.tag-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  cursor: default;
}
.tag-badge .tag-remove {
  cursor: pointer;
  opacity: 0.55;
  font-size: 10px;
  line-height: 1;
  margin-inline-start: 1px;
  transition: opacity .15s;
}
.tag-badge .tag-remove:hover { opacity: 1; }
.lead-tags-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  min-height: 26px;
  margin: 6px 0 2px;
}
.btn-add-tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 600;
  border: 1px dashed var(--border);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: border-color .15s, color .15s;
}
.btn-add-tag:hover { border-color: var(--primary); color: var(--primary); }
.tag-picker-popup {
  position: absolute;
  top: 4px;
  inset-inline-start: 0;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0,0,0,.14);
  padding: 12px 14px;
  z-index: 9999;
  min-width: 200px;
  max-width: 300px;
}
.tag-picker-list { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }
.tag-picker-divider {
  height: 1px;
  background: var(--border);
  margin: 10px 0 8px;
}
.tag-picker-new-btn {
  display: flex;
  align-items: center;
  gap: 5px;
  background: none;
  border: 1px dashed var(--border);
  border-radius: 20px;
  padding: 3px 12px;
  font-size: 12px;
  color: var(--primary);
  cursor: pointer;
  width: 100%;
  justify-content: center;
  transition: background .12s, border-color .12s;
}
.tag-picker-new-btn:hover { background: #f5f3ff; border-color: var(--primary); }
.new-tag-inline {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
}
.tag-row-badges { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.kanban-card-tags { display: flex; flex-wrap: wrap; gap: 3px; margin: 4px 0 2px; }

/* ── Utility ─────────────────────────────────────────────────── */
.text-muted { color: var(--text-muted); }
.text-danger { color: var(--danger); }
.mt-16 { margin-top: 16px; }
.gap-8 { gap: 8px; }
.flex { display: flex; }
.flex-end { justify-content: flex-end; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; }

/* ── Login page ──────────────────────────────────────────────── */
.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #1E1B4B 0%, #312E81 50%, #4C1D95 100%);
}
.login-card {
  background: #fff;
  border-radius: 16px;
  padding: 40px;
  width: 380px;
  box-shadow: 0 20px 60px rgba(0,0,0,.3);
  text-align: center;
}
.login-logo { margin-bottom: 8px; text-align: center; }
.login-sub { font-size: 14px; color: var(--text-muted); margin-bottom: 28px; }
/* The fine print under the Google button and above the password form. It
   was a literal #999 in a style attribute on both login pages: 2.85:1 on
   this white card, at 12px. */
.login-fine {
  text-align: center;
  color: var(--login-fine);
  font-size: 12px;
  margin-bottom: 14px;
}
.login-error {
  background: var(--danger-light);
  /* --danger is a FILL colour: #EF4444 on #FEE2E2 is 3.08:1, and this is
     the one line on the page whose entire job is to be read. */
  color: var(--login-error-ink);
  border-radius: var(--radius-sm);
  padding: 10px;
  font-size: 14px;
  margin-bottom: 16px;
}

/* ── Print ───────────────────────────────────────────────────── */
@media print {
  .sidebar, .page-header .page-actions, .filter-bar .btn,
  .drawer, .modal-overlay, #toastContainer { display: none !important; }
  .main-content { margin-right: 0 !important; }
  body { background: #fff; }
  .card { box-shadow: none; border: 1px solid #ccc; }
}

/* ── Loading ─────────────────────────────────────────────────── */
.loading-spinner {
  text-align: center;
  padding: 40px;
  color: var(--text-muted);
  font-size: 14px;
}
.loading-spinner::before {
  content: '⏳ ';
}

/* ── Empty state ─────────────────────────────────────────────── */
.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-muted);
}
.empty-state-icon { font-size: 48px; margin-bottom: 12px; }
.empty-state-text { font-size: 15px; }

/* ── Bulk selection ──────────────────────────────────────────── */
.lead-selected td { background: #ede9fe !important; }
.kpi-card-alert { border: 1.5px solid var(--danger) !important; }
.kpi-icon.red { background: #fef2f2; color: #b91c1c; }
.kpi-card-hot  { border: 1.5px solid #f97316; background: linear-gradient(135deg,#fff7ed,#fff); text-decoration:none; color:inherit; cursor:pointer; transition: box-shadow .15s, transform .1s; }
.kpi-card-hot:hover  { box-shadow: 0 4px 16px rgba(249,115,22,.25); transform: translateY(-2px); }
.kpi-card-good { border: 1.5px solid #eab308; background: linear-gradient(135deg,#fefce8,#fff); text-decoration:none; color:inherit; cursor:pointer; transition: box-shadow .15s, transform .1s; }
.kpi-card-good:hover { box-shadow: 0 4px 16px rgba(234,179,8,.25);  transform: translateY(-2px); }
.score-filter-badge { display:inline-flex;align-items:center;gap:6px;background:#fef3c7;border:1px solid #fbbf24;border-radius:20px;padding:4px 12px;font-size:13px;font-weight:600;color:#92400e; }
.score-filter-badge button { background:none;border:none;cursor:pointer;font-size:15px;line-height:1;color:#92400e;padding:0 0 0 2px; }
.kpi-card-invested { border: 1.5px solid #16a34a; background: linear-gradient(135deg,#f0fdf4,#fff); text-decoration:none; color:inherit; cursor:pointer; transition: box-shadow .15s, transform .1s; }
.kpi-card-invested:hover { box-shadow: 0 4px 16px rgba(22,163,74,.22); transform: translateY(-2px); }

/* ── File Attachments ────────────────────────────────────────── */
.files-list { display: flex; flex-direction: column; gap: 8px; }
.file-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.file-row:hover { border-color: var(--primary); background: var(--primary-light); }

/* ── Leads toolbar (desktop) ─────────────────────────────────── */
.leads-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  gap: 8px;
  flex-wrap: wrap;
}
.leads-toolbar-views   { display: flex; gap: 8px; }
.leads-toolbar-actions { display: flex; gap: 8px; align-items: center; }

/* ============================================================
   MOBILE – elements that exist only on mobile (hidden desktop)
   ============================================================ */
.mobile-top-bar,
.mobile-bottom-nav,
.mobile-nav-overlay { display: none !important; }

/* ============================================================
   MOBILE RESPONSIVE  ≤ 768px
   ============================================================ */
@media (max-width: 768px) {

  /* ── Mobile-only elements ─────────────────────────────── */
  .mobile-top-bar    { display: flex    !important; }
  .mobile-bottom-nav { display: flex    !important; }
  .hide-on-mobile    { display: none    !important; }

  /* ── Top bar (fixed) ──────────────────────────────────── */
  .mobile-top-bar {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 54px;
    background: #1E1B4B;
    z-index: 450;
    align-items: center;
    justify-content: space-between;
    padding: 0 12px;
    box-shadow: 0 2px 8px rgba(0,0,0,.25);
    gap: 10px;
  }
  .mobile-top-brand {
    display: flex;
    align-items: center;
    gap: 8px;
    color: #fff;
    font-size: 15px;
    font-weight: 700;
    white-space: nowrap;
  }
  .mobile-top-brand span { font-size: 22px; }
  .mobile-page-name {
    flex: 1;
    text-align: center;
    color: rgba(255,255,255,.75);
    font-size: 14px;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .mobile-hamburger {
    background: none;
    border: none;
    color: #fff;
    font-size: 24px;
    cursor: pointer;
    padding: 8px 6px;
    border-radius: 6px;
    line-height: 1;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
  }
  .mobile-hamburger:active { background: rgba(255,255,255,.12); }

  /* ── Sidebar → off-canvas panel ──────────────────────── */
  .sidebar {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: 260px;
    transform: translateX(110%);
    transition: transform .25s cubic-bezier(.4,0,.2,1);
    z-index: 520;
  }
  .sidebar.mobile-open { transform: translateX(0); }

  /* ── Overlay behind open sidebar ─────────────────────── */
  .mobile-nav-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.52);
    z-index: 510;
    cursor: pointer;
  }

  /* ── Main layout ──────────────────────────────────────── */
  .app-layout { display: block; }
  .main-content {
    margin-right: 0 !important;
    padding-top: 54px;
  }
  .page-header {
    padding: 12px 14px 4px;
    min-height: auto;
    flex-wrap: wrap;
    gap: 8px;
  }
  .page-title { font-size: 18px; }
  .page-body  { padding: 12px 12px 80px; }

  /* ── Bottom navigation bar ────────────────────────────── */
  .mobile-bottom-nav {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    height: 62px;
    background: #1E1B4B;
    z-index: 450;
    align-items: stretch;
    border-top: 1px solid rgba(255,255,255,.1);
  }
  .mob-nav-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    color: rgba(255,255,255,.5);
    text-decoration: none;
    font-size: 10px;
    font-weight: 600;
    border: none;
    background: none;
    font-family: 'Heebo', sans-serif;
    cursor: pointer;
    padding: 4px 2px;
    transition: color .15s, background .15s;
    -webkit-tap-highlight-color: transparent;
    position: relative;
  }
  .mob-nav-item.active { color: #fff; }
  .mob-nav-item.active::after {
    content: '';
    position: absolute;
    top: 0; left: 20%; right: 20%;
    height: 2px;
    background: var(--primary);
    border-radius: 0 0 4px 4px;
  }
  .mob-nav-item:active { background: rgba(255,255,255,.08); }
  .mob-nav-icon { font-size: 20px; line-height: 1; }

  /* ── Cards ────────────────────────────────────────────── */
  .card { padding: 14px; }

  /* ── KPI grid → 2 columns ─────────────────────────────── */
  .kpi-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
  .kpi-card { padding: 12px 14px; gap: 10px; }
  .kpi-value { font-size: 22px; }
  .kpi-icon  { width: 40px; height: 40px; font-size: 18px; border-radius: 10px; }

  /* ── Tables → horizontal scroll ──────────────────────── */
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .data-table { font-size: 13px; }
  .data-table thead th,
  .data-table tbody td { padding: 9px 10px; }

  /* ── Forms → single column ────────────────────────────── */
  .form-row   { grid-template-columns: 1fr !important; gap: 0 !important; }
  .form-row-3 { grid-template-columns: 1fr !important; gap: 0 !important; }
  .form-control { font-size: 16px; } /* prevent iOS zoom on focus */

  /* ── Filter bar → stacked ─────────────────────────────── */
  /* The `.filter-bar .form-control { width: 100% !important; min-width:
     unset !important; }` that used to sit here was dead: the identical
     declarations reappear further down THIS SAME @media block, in the
     `.filter-bar .form-control, .filter-bar input, .filter-bar select`
     rule, which wins on source order at equal specificity and importance.
     Two copies of a rule where only the last one has ever applied is how
     an edit to the first one silently does nothing. */
  .filter-bar { flex-direction: column; align-items: stretch; gap: 8px; }
  .filter-bar .search-box,
  .filter-bar .search-box .form-control { width: 100%; }

  /* ── Tabs → scrollable ────────────────────────────────── */
  .tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tab-btn { padding: 10px 16px; font-size: 13px; white-space: nowrap; flex-shrink: 0; }

  /* ── Drawer → full-width sheet sliding from bottom ────── */
  /* z-index must be above bottom nav (450) so buttons aren't hidden */
  .drawer-overlay {
    align-items: flex-end !important;
    z-index: 500 !important;
  }
  .drawer {
    width: 100vw !important;
    max-width: 100vw !important;
    max-height: 92vh !important;
    border-radius: 18px 18px 0 0 !important;
    transform: translateY(30px) scale(1) !important;
    opacity: 0;
  }
  .drawer.open {
    transform: translateY(0) scale(1) !important;
    opacity: 1;
  }
  .drawer-header { padding: 14px 16px; }
  .drawer-title  { font-size: 16px; }
  /* Extra bottom padding so last buttons are reachable above bottom nav */
  .drawer-body   { padding: 12px 14px 80px; }

  /* ── Modal → sheet from bottom ────────────────────────── */
  .modal-overlay {
    align-items: flex-end !important;
    z-index: 500 !important;
  }
  .modal {
    width: 100vw !important;
    max-width: 100vw !important;
    max-height: 90vh !important;
    border-radius: 18px 18px 0 0 !important;
  }
  .modal-header { padding: 14px 16px; }
  .modal-body   { padding: 14px 14px 80px; }

  /* ── Grid utilities ───────────────────────────────────── */
  .grid-2 { grid-template-columns: 1fr !important; gap: 10px !important; }
  .grid-3 { grid-template-columns: 1fr 1fr !important; gap: 10px !important; }

  /* ── Page actions ─────────────────────────────────────── */
  .page-actions { flex-wrap: wrap; gap: 6px; }
  .page-actions .btn { font-size: 13px; padding: 7px 12px; }

  /* ── Buttons: bigger touch targets ───────────────────── */
  .btn { min-height: 38px; }
  .btn-sm { min-height: 32px; }

  /* ── Toast → above bottom nav ─────────────────────────── */
  .toast-container {
    bottom: 72px;
    inset-inline-end: 50%;
    transform: translateX(-50%);
    align-items: center;
    width: 90vw;
    max-width: 340px;
  }
  .toast { min-width: unset; width: 100%; text-align: center; }

  /* ── Lead chips in drawer ─────────────────────────────── */
  .lh-info-grid { gap: 5px; }
  .lh-chip { font-size: 12px; padding: 3px 9px; }

  /* ── Investment type tabs ─────────────────────────────── */
  .investment-type-tabs { flex-wrap: wrap; gap: 6px; }
  .inv-type-btn { font-size: 12px; padding: 6px 10px; }

  /* ── Kanban ───────────────────────────────────────────── */
  .kanban-col { width: 210px; }

  /* ── Login card ───────────────────────────────────────── */
  .login-card { width: 94vw; padding: 28px 20px; }

  /* ── Settings → hide less-important table columns ─────── */
  .settings-section .data-table th.hide-mobile,
  .settings-section .data-table td.hide-mobile { display: none; }

  /* ── Reminder items ────────────────────────────────────── */
  .reminder-item { flex-wrap: wrap; }
  .reminder-time { min-width: auto; }

  /* ── Prevent horizontal overflow showing sidebar ──────── */
  html, body { overflow-x: hidden; }

  /* ── Filter bar: force 100% width, override inline styles ─ */
  .filter-bar .form-control,
  .filter-bar input,
  .filter-bar select {
    min-width: unset !important;
    width: 100% !important;
    max-width: 100% !important;
  }
  .filter-bar .hide-toggle-label { justify-content: flex-start; }

  /* ── Leads toolbar ────────────────────────────────────── */
  .leads-toolbar {
    padding: 10px 12px;
    gap: 8px;
  }
  .leads-toolbar-views   { flex: 1; }
  .leads-toolbar-actions { flex-wrap: wrap; }

  /* ── Leads table: hide less-important columns ─────────── */
  /* email (col 6), source (col 7), last_interaction (col 9) */
  .data-table thead th:nth-child(6),
  .data-table tbody td:nth-child(6),
  .data-table thead th:nth-child(7),
  .data-table tbody td:nth-child(7),
  .data-table thead th:nth-child(9),
  .data-table tbody td:nth-child(9) {
    display: none;
  }
  /* Let the table auto-fit without a fixed min-width */
  .data-table { min-width: unset; }
}

/* ── פה ופה wordmark (replaces the old logo image) ───────────── */
.brand-wordmark {
    font-family: 'Heebo', sans-serif;
    font-weight: 700;
    letter-spacing: -0.5px;
    color: var(--primary, #6C63FF);
    display: inline-block;
    white-space: nowrap;
}
/* Shrunk from 26/20px: the wordmark now sits BESIDE the logo image rather
   than standing in for it, so it plays the supporting role. */
.brand-wordmark--sidebar { font-size: 18px; }
.brand-wordmark--mobile  { font-size: 15px; }
/* The login hero's top bar. --primary on the dark backdrop is nowhere near
   readable, so this modifier restates the colour; the family, weight and
   tracking are what make it the same wordmark. It replaced --login, which
   sized the 34px wordmark that used to BE the login page's heading - the
   heading is the hero sentence now, and no element carried that class any
   more. */
.brand-wordmark--hero    { font-size: 19px; color: #fff; letter-spacing: -0.01em; }

/* ── נכסים (Properties): collapsible fieldset groups ─────────────────
   §8 progressive-disclosure — a real <fieldset>/<legend> pair per group
   (not a styled div), collapsed by default except the first one. ──── */
/* A ~88-field form stretched to a 1920px monitor puts the label at one edge
   and its input at the other, and makes every two-column row absurdly wide.
   Constrain it to a centred column (§5 container-width). 920px still fits the
   three-column rows comfortably without becoming a stretched line. */
.prop-narrow {
  max-width: 920px;
  margin-inline: auto;
}

.prop-fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card-bg);
  box-shadow: var(--shadow-sm);
  padding: 18px 20px;
  margin-bottom: 16px;
}
.prop-fieldset > legend {
  padding: 0 8px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  user-select: none;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px; /* §2 touch-target-size */
}
.prop-fieldset > legend::before {
  content: '▾';
  font-size: 12px;
  color: var(--text-muted);
  transition: transform .15s;
}
.prop-fieldset.collapsed > legend::before { transform: rotate(-90deg); }
.prop-fieldset.collapsed > .prop-fieldset-body { display: none; }
.prop-fieldset-body { padding-top: 12px; }

/* A collapsed section is one clickable bar, not a title above an empty box.
   Without trimming the padding, hiding the body still left ~36px of blank
   card below the legend, which looked like a broken container. */
.prop-fieldset.collapsed { padding-bottom: 0; cursor: pointer; }
.prop-fieldset.collapsed:hover { border-color: var(--primary-light); }
.prop-fieldset > legend:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Conditional sub-fields (has_ac -> ac_units, entry_type=date -> entry_date, …) */
/* Nesting is carried by the indent + background tint. A thick accent stripe
   here would be doing the same job a third time, and reads as decoration
   rather than structure. Keep the hairline rule only as a quiet edge. */
.cond-group {
  padding: 10px 14px;
  margin: 8px 0;
  margin-inline-start: 14px;
  background: var(--bg);
  border-radius: var(--radius-sm);
  border-inline-start: 1px solid var(--border);
}

.check-row { display: flex; align-items: center; gap: 8px; min-height: 44px; }
.check-row input[type="checkbox"] { width: 18px; height: 18px; cursor: pointer; flex-shrink: 0; }
.check-row label { cursor: pointer; font-size: 14px; }
.check-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 6px 16px; margin-bottom: 8px; }

/* Repeatable rows (balconies / parkings) */
.repeatable-row {
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  padding: 14px;
  margin-bottom: 12px;
}

.field-error { color: var(--danger); font-size: 12px; margin-top: 4px; min-height: 16px; }
.form-control.invalid { border-color: var(--danger); }

/* Photo grid */
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; }
.photo-thumb { position: relative; border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--border); aspect-ratio: 1; }
.photo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-thumb .photo-remove {
  position: absolute; top: 4px; inset-inline-end: 4px;
  background: rgba(0,0,0,.6); color: #fff; border: none; border-radius: 6px;
  width: 26px; height: 26px; cursor: pointer; font-size: 14px;
}

@media (max-width: 768px) {
  .prop-fieldset { padding: 14px 16px; }
  .check-grid { grid-template-columns: 1fr 1fr; }
}

/* ── נכסים (Properties): read-only view (pages/property_view.php) ──────
   Deliberately NOT .prop-fieldset — that class carries the collapse
   affordance (cursor:pointer legend, .collapsed state); this page has no
   progressive disclosure at all, every section that has content is always
   expanded, so it gets its own non-interactive shell instead. */
.prop-view-section {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card-bg);
  box-shadow: var(--shadow-sm);
  padding: 18px 20px;
  margin-bottom: 16px;
}
.prop-view-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 12px;
}
.prop-view-body {
  display: grid;
  /* Two tracks per pair: the label track sizes to the longest label in its
     column, so every value in that column starts on the same line and sits
     right beside its label instead of being pushed to the far edge. The row
     itself is display:contents so its label and value land directly in these
     tracks rather than in a box of their own. */
  grid-template-columns: repeat(3, max-content minmax(0, 1fr));
  gap: 0 24px;
}
.prop-view-row {
  display: contents;
}
.prop-view-row > * {
  align-self: baseline;
  padding: 7px 0;
  border-bottom: 1px solid var(--bg);
  font-size: 14px;
}
.prop-view-label { color: var(--text-muted); padding-inline-end: 16px; }
.prop-view-value { color: var(--text); font-weight: 500; }

/* Balcony / parking sub-lists inside the outdoor section */
.prop-view-subtitle {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
  margin: 14px 0 8px;
}
.prop-view-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  padding: 12px 14px;
  margin-bottom: 10px;
}
.prop-view-card:last-child { margin-bottom: 0; }
.prop-view-card-title { font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 6px; }

@media (max-width: 768px) {
  .prop-view-section { padding: 14px 16px; }
  .prop-view-body { grid-template-columns: max-content minmax(0, 1fr); }
}

/* ── מיקום: the GovMap embed (pages/property_view.php) ─────────────────
   The box holds either the iframe or a one-line status, and it keeps the
   same height either way — a card that collapses to nothing while the
   geocode is in flight, then shoves the rest of the page down when it
   lands, reads as a glitch. */
.prop-map {
  height: 320px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.prop-map-frame { width: 100%; height: 100%; border: 0; display: block; }
/* The same element says "loading", "not found" and "no address to look up".
   Only the first two live inside the box and want centring; the third is the
   card's whole body and reads as a normal line of text. */
.prop-map-status { color: var(--text-muted); font-size: 14px; margin: 0; }
.prop-map .prop-map-status { text-align: center; padding: 0 16px; }
.prop-map-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.prop-map-addr { font-size: 14px; color: var(--text); font-weight: 500; }
/* Same reason .btn-share carries its own 44px: .btn-sm drops to 32px under
   the mobile media query, and this link is tapped by a broker standing in
   front of the building. */
.prop-map-open { min-height: 44px; }

/* ── Match percentage ────────────────────────────────────────
   Two surfaces share these rules: the top-matches list on
   pages/lead_search_view.php, and the "🔍 מה מחפש" tab's profile rows
   (assets/js/lead_searches.js renders the same class names).

   Every one of these elements is rendered ONLY when lsScore() returned a
   real percentage. A lead with no saved search profile, or a profile with
   no criteria filled in, produces no element at all - not a 0%, not a dash,
   not an empty badge. There is deliberately no "empty" state to style here.

   The number itself is always --text and the reason line always
   --text-muted, so the high/mid bands only ever swap the pill behind an
   unchanged foreground: the contrast is the same in every band, and hue
   carries nothing the number and the reason text do not already say. */
.ls-match-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ls-match-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: inherit;
  text-decoration: none;
  /* A row is a link to the property; 44px keeps it comfortably tappable. */
  min-height: 44px;
}

.ls-match-row:hover { border-color: var(--primary); }

.ls-match-pct {
  flex: none;
  font-weight: 700;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  background: var(--border);
  border-radius: 999px;
  padding: 4px 10px;
  white-space: nowrap;
}

.ls-match-pct--high { background: var(--success-light); }
.ls-match-pct--mid  { background: var(--primary-light); }

.ls-match-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.ls-match-title { font-size: 14px; font-weight: 600; color: var(--text); }
.ls-match-sub   { font-size: 13px; color: var(--text-muted); }
.ls-match-why   { font-size: 13px; color: var(--text); }

/* The lead/profile picker above the properties table. Its own full-width
   line inside the filter bar: it is not a filter (it hides no rows), it
   decides whether a whole column exists, and sitting between two filters
   would read as one. */
.prop-match-picker {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.prop-match-picker .form-label { margin: 0; font-size: 13px; color: var(--text-muted); }
.prop-match-note { font-size: 13px; color: var(--text-muted); }

/* The match column's cells. There is no styling for "no lead chosen"
   because there is no cell then: the column is absent from the table. */
.prop-match-none { font-size: 13px; color: var(--text-muted); }
.prop-match-why  { font-size: 12px; color: var(--text-muted); margin-top: 4px; max-width: 220px; }

/* ── שיוך נכס לליד ─────────────────────────────────────────── */
.lp-rel-picker { display: flex; gap: 16px; flex-wrap: wrap; }
.lp-rel-picker label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.lp-results { max-height: 220px; overflow-y: auto; margin-top: 6px; }
.lp-result {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  width: 100%; padding: 8px 10px; min-height: 44px;
  background: none; border: none; border-bottom: 1px solid var(--border);
  text-align: start; cursor: pointer;
}
.lp-result:hover, .lp-result:focus-visible { background: var(--bg); }
.lp-result span { font-size: 12px; color: var(--text-muted); }
.lp-result-empty { padding: 10px; color: var(--text-muted); font-size: 13px; }

/* ── lkAttachTypeahead (assets/js/lookup_typeahead.js) ────────────────── */
/* .lk-ta-wrap holds the input + its .lp-results suggestion list; the list
   renders in-flow below the input (not an absolute overlay) so it is never
   clipped by a scrolling .modal-body. */
.lk-ta-wrap { width: 100%; }
.lp-result.lk-ta-active { background: var(--bg); }
/* One repeatable city row on pages/lead_search_form.php: the city name and the
   🗑 button share the first line, and the (optional, comma-separated)
   neighbourhoods field takes the whole second line - flex-basis:100% is what
   forces the wrap. Each input lives inside its own cell rather than being a
   direct flex child, because lkAttachTypeahead replaces the input with a
   .lk-ta-wrap and the two fields need different widths. min-width:0 keeps a
   long city name from forcing the row wider than the card. */
.ls-city-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start; padding: 10px 14px; }
.ls-city-cell { flex: 1; min-width: 0; }
.ls-hood-cell { flex-basis: 100%; min-width: 0; }
.lp-picked-chip { display: inline-block; margin-top: 6px; font-size: 13px; color: var(--success); }
.lp-count { font-size: 11px; font-weight: 600; }
.lp-group-title { margin: 14px 0 6px; font-size: 13px; font-weight: 600; color: var(--text-muted); }
.lp-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--border);
}
.lp-row-main { flex: 1; min-width: 0; }
.lp-row-sub { font-size: 12px; color: var(--text-muted); }

/* The match percentage a linked lead's own search profile gives this
   property (pages/property_view.php). The row is absent entirely for a lead
   with no saved search - there is no "empty" state to style, by design.
   flex-wrap plus a full-width reason line keeps the percentage and the name
   of the search it came from on one line, with the reasons under them: the
   badge's .prop-match-why is a block, so without flex-basis it would split
   them apart. */
.lp-row-match {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  margin-top: 6px;
}
.lp-row-match .prop-match-why { flex-basis: 100%; margin-top: 0; max-width: none; }
.lp-row-match-profile { font-size: 12px; color: var(--text-muted); }
.lp-search-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.lp-badge {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: 14px; line-height: 1;
}

/* ── Property view: details on the right, linked leads beside them ──────
   Both columns start flush under the page title rather than in a narrow
   centred column, so the wasted gutter on a wide screen becomes the
   sidebar. Collapses to one column before the sidebar gets too cramped
   to read a name and a phone number on one line. */
.prop-layout {
  display: grid;
  /* The details column keeps the 920px it always had — only its position
     changed, from centred to flush against the start edge. justify-content
     keeps the pair anchored there instead of stretching to fill. */
  grid-template-columns: minmax(0, 920px) 340px;
  justify-content: start;
  gap: 20px;
  align-items: start;
}
.prop-side { position: sticky; top: 20px; }
@media (max-width: 1024px) {
  .prop-layout { grid-template-columns: 1fr; }
  .prop-side   { position: static; }
}

/* ── Photo lightbox ─────────────────────────────────────────────────── */
.pm-lightbox {
  display: none;
  position: fixed; inset: 0;
  background: rgba(0,0,0,.85);
  z-index: 400;                 /* above .modal-overlay (300) */
  align-items: center; justify-content: center;
}
.pm-lightbox.open { display: flex; }
.pm-lightbox img { max-width: 88vw; max-height: 88vh; object-fit: contain; }
.pm-lb-nav, .pm-lb-close {
  position: absolute;
  background: rgba(0,0,0,.45); color: #fff;
  border: none; border-radius: 50%;
  width: 48px; height: 48px;    /* comfortably past the 44px touch minimum */
  font-size: 28px; line-height: 1; cursor: pointer;
}
.pm-lb-nav:hover, .pm-lb-close:hover { background: rgba(0,0,0,.75); }
.pm-lb-nav:focus-visible, .pm-lb-close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.pm-lb-prev  { inset-inline-start: 16px; }
.pm-lb-next  { inset-inline-end: 16px; }
/* Position only. The font-size used to be repeated here as 22px, silently
   overriding the 28px the shared .pm-lb-nav/.pm-lb-close rule sets - so the
   X was visibly smaller than the arrows beside it, in a 48px circle sized
   for the larger glyph. 28px is the deliberate value: it is what the two
   navigation buttons already render at, and the close control is the one a
   reader is most likely to be aiming for. */
.pm-lb-close { top: 16px; inset-inline-end: 16px; }
.pm-lb-pos {
  position: absolute; bottom: 16px;
  color: #fff; font-size: 13px; letter-spacing: .05em;
}

/* ── Modal content / footer ────────────────────────────────────────────
   .modal-content and .modal-footer were used in markup but never styled,
   so footer buttons were inline elements with no alignment or spacing and
   simply ran together. */
.modal-content { display: flex; flex-direction: column; min-height: 0; }
.modal-footer {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
}
.modal-footer .btn { margin: 0; }

/* Thumbnails in the property page sidebar: narrower than the modal grid,
   which is sized for a 720px dialog rather than a 340px column. */
.prop-side .photo-grid { grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); gap: 8px; }

/* ── בדיקה הנדסית / בדיקה משפטית ─────────────────────────────────────────
   The checklist inside the shared #modal, and the summary card beside the
   linked leads. Both are plain: the modal is fifteen rows of checkbox +
   note, and the card is a list of what was found. No new modal, no new
   overlay - assets/js/properties.js opens #modal through openModal(). */

/* The list scrolls inside the dialog rather than growing it past the
   viewport: fifteen rows with a note box each is taller than a laptop
   screen, and a modal you cannot reach the save button on is a broken one.
   The button below sits outside this box, so it is always reachable. */
.pin-list { max-height: 55vh; overflow-y: auto; padding-inline-end: 4px; }

.pin-row {
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.pin-row:last-child { border-bottom: 0; }

/* The label IS the checkbox's hit area (a wrapping <label>), so the 44px
   minimum belongs here and not on the 16px box itself. */
.pin-check {
  display: flex; align-items: center; gap: 10px;
  min-height: 44px;
  cursor: pointer;
}
.pin-check input[type="checkbox"] { width: 20px; height: 20px; flex: none; cursor: pointer; }
.pin-label { font-weight: 600; }

.pin-note {
  margin-top: 6px;
  min-height: 44px;
  resize: vertical;
  /* 16px so iOS does not zoom the page when the box is focused. */
  font-size: 16px;
}

.pin-actions {
  display: flex; justify-content: flex-end;
  padding-top: 12px; margin-top: 6px;
  border-top: 1px solid var(--border);
}
.pin-actions .btn { min-height: 44px; }

/* The summary card. Same .prop-view-section shell as its neighbours in the
   sidebar - it is a sibling of the linked-leads panel, not a new kind of
   thing - so only the inner list needs rules of its own. */
.pin-sum-group + .pin-sum-group { margin-top: 12px; }
.pin-sum-title {
  font-size: 13px; font-weight: 700;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.pin-sum-item { padding: 6px 0; border-bottom: 1px solid var(--border); }
.pin-sum-item:last-child { border-bottom: 0; }
.pin-sum-label { display: flex; align-items: flex-start; gap: 6px; }
/* The broker's own line breaks are kept, the same way the marketing text
   keeps them - without <br> markup, so it still re-wraps at 375px. */
.pin-sum-note { font-size: 12px; color: var(--text-muted); white-space: pre-wrap; }

/* ── פרופיל עסקי (business profile): image slots + live summary preview ──
   The preview is deliberately plain (§ product intent: a summary, not a
   landing-page mockup) — it reuses .prop-view-section for its card shell
   rather than inventing a second one. */
.bp-slot-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.bp-slot-thumb {
  width: 84px; height: 84px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  overflow: hidden;
  flex-shrink: 0;
}
.bp-slot-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bp-slot-actions { display: flex; gap: 8px; flex-wrap: wrap; }

.bp-preview-banner {
  height: 100px;
  border-radius: var(--radius-sm);
  background-color: var(--bg);
  background-size: cover;
  background-position: center;
  margin-bottom: -32px;
}
.bp-preview-body { text-align: center; padding-top: 8px; }
.bp-preview-avatar {
  width: 72px; height: 72px;
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid var(--card-bg);
  background: var(--bg);
  display: block;
  margin: 0 auto 8px;
}
.bp-preview-name { font-size: 16px; font-weight: 700; color: var(--text); }
.bp-preview-title, .bp-preview-company { font-size: 13px; color: var(--text-muted); }
.bp-preview-tagline { font-size: 13px; font-style: italic; color: var(--text-muted); margin-top: 6px; }
.bp-preview-contact { font-size: 12px; color: var(--text); margin-top: 10px; display: flex; flex-direction: column; gap: 3px; }

/* ── מה מחפש הליד (lead search profiles): drawer tab share controls ─────
   Share links live at the LEAD level, not per profile (a link can scope to
   one profile or the whole set — config/migrations/008_lead_share_links.sql)
   — the "🔗 קישורי שיתוף" block under the profile list in the "🔍 מה מחפש"
   drawer tab (assets/js/lead_searches.js — lsRenderShareSection /
   lsRenderLinkRow). A quiet inset box per link/creation-form, so the
   controls read as attached to the lead, not a separate heavyweight card. */
.ls-share-box {
  margin-top: 4px;
  padding: 10px 12px;
  background: var(--bg);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* The public link works for anyone who has it, no login — this note must be
   impossible to miss right above the copy button. */
.ls-share-note {
  font-size: 12px;
  line-height: 1.5;
  color: #92400e;
  background: var(--warning-light);
  border-radius: var(--radius-sm);
  padding: 6px 10px;
}
.ls-share-link-row { display: flex; gap: 8px; align-items: center; }
.ls-share-link-row .form-control { flex: 1; min-width: 0; font-size: 12px; }


/* ── תיאור שיווקי: the broker's pasted advert (pages/property_view.php) ──
   pre-wrap, not nl2br: it keeps the broker's line breaks AND their blank
   lines without adding markup, and still re-wraps a long line on a narrow
   screen, which a hard <br> would not. overflow-wrap keeps a long URL from
   pushing the column wider than the viewport. */
.prop-marketing {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    line-height: 1.75;
    font-size: 15px;
    max-width: 70ch;
    color: var(--text);
}
.prop-marketing a { color: var(--primary); text-decoration: underline; }
.prop-view-hint { font-size: 13px; color: var(--text-muted); margin: 0 0 10px; }


/* ══════════════════════════════════════════════════════════════════════
   דשבורד — the broker's branded header and the operational panels below
   it (pages/dashboard.php).

   Two rules govern everything here.

   1. COLOUR IS NEVER THE ONLY CARRIER. Every state that a colour marks
      also carries a word or a glyph: a flagged property says "אין תמונות",
      it is not merely tinted amber. So the page still reads correctly to
      anyone who cannot separate the hues.

   2. THE BRAND COLOUR IS ARBITRARY USER INPUT. Nothing here hardcodes it.
      The three custom properties below are set once, inline on
      .dash-brand, from psAccentSurface() / psAccentSurfaceDark() /
      psOnPrimary() in includes/public_share_helpers.php — the same
      treatment the public share pages use, so a broker's colour behaves
      identically on both sides of the product. psAccentSurface() darkens
      the colour only as far as WCAG AA needs, which is what makes
      --dash-on-accent (always #ffffff by that function's construction)
      safe on it at full opacity.

      Full opacity is the point: this bar never fades its own text to
      rgba(255,255,255,.8) for hierarchy, because that fade is exactly
      what drops a just-passing 4.5:1 pair under the floor. Hierarchy
      comes from size and weight instead.

   The density is deliberate — this is a tool a broker keeps open all day,
   not a page they are being sold something on. Spacing runs on an 8px
   step from 8 to 24, not the 32-96 a marketing page would use.
   ══════════════════════════════════════════════════════════════════════ */

.dash-brand {
  /* Fallbacks only. pages/dashboard.php always sets all three inline. */
  --dash-accent:      var(--primary);
  --dash-accent-dark: var(--primary-dark);
  --dash-on-accent:   #ffffff;

  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  padding: 18px 20px;
  margin-bottom: 20px;
  border-radius: var(--radius);
  background: linear-gradient(135deg, var(--dash-accent) 0%, var(--dash-accent-dark) 100%);
  color: var(--dash-on-accent);
}

/* The logo/photo slot. object-fit so a broker's non-square upload is
   cropped rather than squashed, and a fixed box so the bar's height does
   not depend on what they uploaded. */
.dash-brand-logo {
  width: 64px;
  height: 64px;
  flex: none;
  border-radius: var(--radius-sm);
  object-fit: cover;
  background: rgba(255,255,255,.14);
}
.dash-brand-mono {
  width: 64px;
  height: 64px;
  flex: none;
  border-radius: var(--radius-sm);
  border: 2px solid var(--dash-on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  font-weight: 700;
  color: var(--dash-on-accent);
}

.dash-brand-main { flex: 1 1 260px; min-width: 0; }
.dash-brand-name {
  font-size: 22px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--dash-on-accent);
}
.dash-brand-role {
  font-size: 16px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--dash-on-accent);
}
.dash-brand-tagline {
  font-size: 16px;
  line-height: 1.5;
  margin-top: 4px;
  color: var(--dash-on-accent);
}

/* Chips are outlined, never filled with a translucent white: a white wash
   over the accent lightens the surface under the label and quietly eats
   the contrast the accent was darkened to guarantee. A border does not. */
.dash-brand-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.dash-brand-chip {
  font-size: 13px;
  line-height: 1.4;
  padding: 4px 10px;
  border: 1px solid var(--dash-on-accent);
  border-radius: 999px;
  color: var(--dash-on-accent);
}

.dash-brand-contact {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  flex: 0 1 auto;
}
/* 44px minimum on every tap target, on every screen. */
.dash-brand-contact a,
.dash-brand-edit {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--dash-on-accent);
  color: var(--dash-on-accent);
  background: none;
  font-size: 16px;
  font-weight: 500;
  text-decoration: none;
}
.dash-brand-contact a:hover,
.dash-brand-edit:hover { background: rgba(0,0,0,.18); }
.dash-brand-contact a:focus-visible,
.dash-brand-edit:focus-visible { outline: 3px solid var(--dash-on-accent); outline-offset: 2px; }

/* No business profile yet. Not a broken empty bar: a bar that explains
   what it will become and links to the form that fills it. */
.dash-brand--empty { display: block; }
.dash-brand--empty .dash-brand-name { font-size: 18px; }

/* ── Operational panels ─────────────────────────────────────────────── */

/* A row list, not a table: every row here is "one thing plus when plus a
   way in", which a table's column headers only add ceremony to. */
.dash-list { display: flex; flex-direction: column; }
.dash-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 8px 4px;
  border-bottom: 1px solid var(--border);
  font-size: 16px;
  color: var(--text);
  text-decoration: none;
}
.dash-row:last-child { border-bottom: none; }
.dash-row:hover { background: var(--bg); }
.dash-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.dash-row-main { flex: 1; min-width: 0; display: block; }
/* block, not inline: these sit inside an <a> (the whole row is the target,
   so the 44px tap area is the row and not a link buried in it), and an
   inline span cannot be given a width to ellipsis against. */
.dash-row-title {
  display: block;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dash-row-sub { display: block; font-size: 13px; color: var(--text-muted); line-height: 1.5; }
/* Tabular figures so a column of counts and times does not jitter. */
.dash-row-value {
  flex: none;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 16px;
  color: var(--text);
}

/* A tag that always spells out what it means. Amber marks "needs
   attention", but the word next to it is what actually says so. */
.dash-tag {
  display: inline-block;
  font-size: 12px;
  line-height: 1.5;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--warning);
  color: #92400e;
  background: var(--warning-light);
  margin-inline-end: 4px;
}
/* A neutral kind label ("lead" / "property"). Amber and green both carry a
   verdict; a row's TYPE is not a verdict, so it gets neither. */
.dash-tag--kind { border-color: var(--border); color: var(--text-muted); background: var(--bg); }

/* The honesty line under a panel whose figure is capped or scoped. It is
   part of the panel, not a footnote nobody reads. */
.dash-note {
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-muted);
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

.dash-panels { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 20px; }

@media (max-width: 768px) {
  .dash-panels { grid-template-columns: 1fr; gap: 12px; }
  .dash-brand { padding: 14px; gap: 12px; }
  .dash-brand-name { font-size: 19px; }
  .dash-brand-contact { flex: 1 1 100%; }
  .dash-brand-contact a { flex: 1 1 auto; justify-content: center; }
}

/* ── ייבוא נכסים: the wizard ──────────────────────────────────
   One light scheme like the rest of the CRM. Every state that uses a
   colour also says the word: "זוהה" / "לא זוהה", "שלב נוכחי", the counts
   spelled out. Colour is decoration here, never the message. */
[hidden] { display: none !important; }

.pi-steps {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  margin-bottom: 16px;
}
.pi-step {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 8px 14px;
  border: 1.5px solid var(--border);
  border-radius: 99px;
  background: var(--card-bg);
  font-size: 16px;
  color: var(--text-muted);
}
.pi-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--border);
  color: var(--text);
  font-weight: 700;
  font-size: 14px;
}
.pi-step.is-done  { color: var(--text); }
.pi-step.is-done .pi-step-num { background: var(--success-light); }
.pi-step.is-active { border-color: var(--primary); color: var(--text); font-weight: 600; }
.pi-step.is-active .pi-step-num { background: var(--primary); color: #fff; }
.pi-step-state { font-size: 13px; font-weight: 400; color: var(--primary-dark); }

.pi-or {
  text-align: center;
  margin: 18px 0;
  color: var(--text-muted);
  font-size: 16px;
}
.pi-hint    { font-size: 14px; color: var(--text-muted); margin-top: 6px; line-height: 1.6; }
.pi-summary { font-size: 16px; line-height: 1.7; color: var(--text-muted); margin-bottom: 14px; }
.pi-sub     { font-size: 16px; font-weight: 600; margin: 18px 0 8px; }
.pi-row-sub { font-size: 13px; color: var(--text-muted); }

/* 44px minimum on every control in the wizard, desktop included: this page
   is used standing up with a phone in one hand. */
.pi-btn { min-height: 44px; font-size: 16px; padding: 10px 18px; }
.pi-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }

.pi-progress { margin-top: 16px; }
.pi-progress-text { margin-top: 8px; font-size: 15px; color: var(--text-muted); text-align: center; }

.pi-msg {
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  font-size: 16px;
  line-height: 1.7;
  border: 1px solid var(--border);
  background: var(--bg);
}
.pi-msg--error { border-color: var(--danger);  background: var(--danger-light);  color: #7f1d1d; }
.pi-msg--warn  { border-color: var(--warning); background: var(--warning-light); color: #78350f; }
.pi-msg--ok    { border-color: var(--success); background: var(--success-light); color: #065f46; }
.pi-msg--info  { border-color: var(--info);    background: var(--info-light);    color: #1e3a8a; }

/* The preview is wide by nature. It scrolls in here, so the page itself
   never scrolls sideways - not even at 375px. */
.pi-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.pi-map-table { min-width: 100%; }
.pi-map-table th, .pi-map-table td { white-space: nowrap; }
.pi-col-head { display: flex; align-items: center; gap: 6px; font-size: 14px; }
.pi-map-row td { padding: 8px 14px; background: var(--bg); }
.pi-map-select { min-width: 190px; min-height: 44px; font-size: 16px; }

.pi-tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 99px;
  font-size: 12px;
  font-weight: 600;
  border: 1px solid var(--border);
}
.pi-tag--ok      { background: var(--success-light); border-color: var(--success); color: #065f46; }
.pi-tag--unknown { background: var(--warning-light); border-color: var(--warning); color: #78350f; }

.pi-enum-group { margin-bottom: 20px; }
.pi-enum-title { font-size: 16px; font-weight: 600; margin-bottom: 8px; }
.pi-enum-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.pi-enum-raw { flex: 1 1 140px; font-size: 16px; }
.pi-enum-select { flex: 1 1 200px; min-height: 44px; font-size: 16px; }

/* The city an unresolved street/neighbourhood was found in. Said in TEXT next
   to the value, never implied by grouping alone: "hertzl" means nothing
   without knowing which city it was read in. */
.pi-loc-city { font-size: 15px; color: var(--text-muted); font-weight: 400; }
/* A free-text answer box with a datalist of the real lookup names. Same
   height and font size as the enum selects beside it - 44px tap target,
   16px text. */
.pi-loc-input { min-width: 0; }

.pi-counts { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 6px; }
.pi-count {
  flex: 1 1 140px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 16px;
  background: var(--bg);
}
.pi-count strong { display: block; font-size: 22px; }
.pi-count--ok  { border-color: var(--success); }
.pi-count--bad { border-color: var(--danger); }

.pi-problems {
  margin: 0;
  padding-inline-start: 20px;
  max-height: 300px;
  overflow-y: auto;
  font-size: 16px;
  line-height: 1.9;
}
.pi-result-line { font-size: 20px; font-weight: 700; margin-bottom: 10px; }
.pi-undo-lead { font-size: 16px; line-height: 1.7; margin-bottom: 10px; }
.pi-undo-sample { padding-inline-start: 20px; font-size: 15px; line-height: 1.8; }
.pi-batches { font-size: 16px; }

/* ── Visits calendar (pages/visits.php, assets/js/visits.js) ───────── */
.visits-deleted-marker {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  background: var(--danger-light);
  color: var(--danger);
}
.visits-row td { padding-top: 14px; padding-bottom: 14px; }
/* Week view can be wider than its column (7 cards, each min 120px) than the
   page. .main-content is a flex item of .app-layout with the default
   min-width:auto, so without an override it refuses to shrink below the
   grid's content width and grows the whole page instead of letting
   .visits-week-grid's own overflow-x:auto do its job. Scoped with :has() to
   the visits page only (the only page containing #visitsWeekView) so every
   other page keeps .main-content's default sizing. */
.main-content:has(#visitsWeekView) {
  min-width: 0;
}
.visits-week-grid {
  display: grid;
  /* 120px, matching the 768px override below. The two disagreed - 160 here,
     120 there - which meant the grid changed width at a breakpoint for no
     reason anyone had decided: a tablet at 800px got 7x160 = 1120px of grid
     inside a narrower column and scrolled horizontally, and one pixel later
     it did not. One number, and it is the one that fits. */
  grid-template-columns: repeat(7, minmax(120px, 1fr));
  gap: 10px;
  overflow-x: auto;
  padding-bottom: 6px;
  min-width: 0;
}
.visits-week-col {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  min-width: 160px;
}
.visits-week-col.is-today { border-color: var(--primary); }
.visits-week-col-head {
  display: flex;
  justify-content: space-between;
  padding: 8px 10px;
  font-weight: 600;
  font-size: 14px;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.visits-week-col-body { padding: 8px; display: flex; flex-direction: column; gap: 8px; min-height: 60px; }
.visits-week-empty { color: var(--text-muted); font-size: 13px; padding: 6px 2px; }
.visits-week-stop {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px;
  font-size: 13px;
  cursor: pointer;
  min-height: 44px;
}
.visits-week-stop:hover { background: var(--bg); }
.visits-week-stop-time { font-weight: 700; font-size: 13px; }
.visits-week-stop-prop { color: var(--text-muted); font-size: 12px; }

.visits-picker-results {
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.visits-picker-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  min-height: 44px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  font-size: 14px;
}
.visits-picker-row:last-child { border-bottom: none; }
.visits-picker-row:hover { background: var(--bg); }

.visits-empty-msg {
  color: var(--text-muted);
  font-size: 14px;
  padding: 12px;
  text-align: center;
}

.visits-stop-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 4px;
  border-bottom: 1px solid var(--border);
  min-height: 44px;
}
.visits-stop-dur { color: var(--text-muted); font-size: 13px; }

.visits-conflict-warn {
  margin-top: 10px;
  padding: 10px 12px;
  background: var(--warning-light);
  color: var(--warning-dark);
  border-radius: var(--radius-sm);
  font-size: 14px;
  line-height: 1.6;
}

.visits-delete-sample {
  margin-top: 10px;
  padding: 10px 12px;
  background: var(--bg);
  border-radius: var(--radius-sm);
  font-size: 13px;
  line-height: 1.8;
  max-height: 200px;
  overflow-y: auto;
}

.visits-link-msg {
  margin-top: 6px;
  font-size: 13px;
}

@media (max-width: 768px) {
  /* .visits-week-grid used to be restated here at 120px because the base
     rule said 160px. They agree now, so there is nothing left to override. */
  .pi-step { flex: 1 1 100%; }
  .pi-actions .pi-btn { flex: 1 1 100%; justify-content: center; }
}

/* ── WhatsApp tab in the lead drawer ──────────────────────────────────
   Built by loadLeadDrawer() in assets/js/leads.js, which used to write all
   of this as inline styles - including a hardcoded width:280px on the
   summary sidebar. The drawer is full width on a phone, so 280px of a 360px
   screen went to the sidebar and the conversation got the remainder. An
   inline style cannot carry a media query either, so the fix had to be a
   class before it could be a fix. */
.wa-tab { height: 520px; }
.wa-tab-split {
  display: flex;
  gap: 10px;
  height: 100%;
}
.wa-conversation {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.wa-summary {
  width: 280px;
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.wa-summary-head {
  padding: 8px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.wa-summary-btn { width: 100%; font-size: 11px; }
.wa-summary-body { flex: 1; overflow-y: auto; }
.wa-placeholder {
  padding: 20px 12px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
}

@media (max-width: 768px) {
  /* Stacked, because side by side there is no width to divide. The
     conversation comes first and keeps the height; the summary sits under
     it and is as tall as its content, so a reader is not scrolling a 130px
     window inside a 520px box. */
  .wa-tab { height: auto; }
  .wa-tab-split { flex-direction: column; }
  .wa-conversation {
    height: 420px;
    flex: none;
  }
  .wa-summary {
    width: 100%;
    max-height: 320px;
  }
}

/* ── Shared property board ─────────────────────────────────────────────
   This is a PUBLIC page and the only consumer-facing surface in this
   stylesheet, so it does not inherit the CRM's look: it declares its own
   tokens on .bd-page and supports BOTH colour schemes, unlike the CRM
   screens which ship one light scheme only.

   One accent hue, one radius scale, one stroke width for every icon.

   About the two oranges. --bd-accent (#ff6b1a) is the hue, and it is used
   for fills, borders and marks - not as a background behind white text:
   white on #ff6b1a is about 2.9:1, well under WCAG AA's 4.5:1 for body
   text. --bd-accent-ink (#c43d00) is the same hue taken far enough down to
   carry white text at about 5.2:1, and it is what the search button and
   every other white-on-orange surface use. Nothing on this page puts white
   text on --bd-accent itself.

   Shadows are tinted with the page's own dusk navy rather than pure black,
   which is what keeps them from reading as grey smudges over the cards. */
.bd-page {
  --bd-accent:       #ff6b1a;
  --bd-accent-ink:   #c43d00;  /* white text sits on THIS one */
  --bd-accent-soft:  #fff1e8;
  /* The ink drawn ON --bd-accent-ink, as a token rather than a literal
     #fff scattered through five rules, so tools/contrast_audit.php can
     resolve it. The dark scheme flips it (see the override below): the
     dark accent is bright, so white on it measures 2.4:1 and dark ink
     measures about 8:1.

     --bd-focus is the focus ring, and it is deliberately NOT --bd-accent.
     #ff6b1a as a ring on the white card is 2.85:1 and on the page 2.71:1,
     both under the 3:1 floor WCAG sets for a non-text indicator - which
     means the one control that tells a keyboard user where they are was
     the least visible thing on the page. --bd-accent-ink's value clears it
     at 5.23:1 and 4.97:1, in the same hue. */
  --bd-on-accent:    #ffffff;
  --bd-focus:        #c43d00;
  --bd-radius-card:  12px;
  --bd-shadow:       0 2px 8px rgba(23, 26, 38, .08);
  --bd-shadow-lift:  0 10px 30px rgba(23, 26, 38, .16);

  color: var(--text);
  background: var(--bg);
  font-size: 16px;
  line-height: 1.55;
  overflow-x: hidden;   /* nothing on this page may scroll the page sideways */
}

/* One measure for everything below the hero, matching the reference's
   single centred column of horizontal cards. */
.bd-wrap {
  max-width: 980px;
  margin: 64px auto 64px;
  padding: 0 16px;
}

/* Screen-reader-only label. Each control's visible affordance is its own
   placeholder or first option, which is a placeholder and not a name, so
   the name is supplied here rather than left to the placeholder. */
.bd-vh {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── Hero ─────────────────────────────────────────────────────────────
   The backdrop is a layered gradient and nothing else: there is no
   licensed photograph in this repository, and a public page must not
   hotlink one from elsewhere.

   To drop one in later, put the file at assets/img/board-hero.jpg and add
   it as the LAST layer of the background shorthand below:

       background:
         linear-gradient(...same two gradients...),
         url("../img/board-hero.jpg") center / cover no-repeat,
         #171A26;

   The gradients then become the dark overlay the white headline needs, and
   #171A26 stays as the fallback fill. No other rule has to change. */
.bd-hero {
  position: relative;
  padding: 72px 16px 0;
  background:
    radial-gradient(120% 140% at 80% 0%, rgba(255, 107, 26, .22) 0%, rgba(255, 107, 26, 0) 55%),
    linear-gradient(160deg, #1E2436 0%, #171A26 55%, #10131C 100%),
    #171A26;
  color: #fff;
}
.bd-hero-inner {
  max-width: 980px;
  margin: 0 auto;
  min-height: 168px;
  text-align: center;
}
.bd-hero-title {
  margin: 0 0 10px;
  font-size: 44px;
  line-height: 1.2;
  font-weight: 800;
  color: #fff;
  letter-spacing: -.01em;
}
.bd-hero-accent { color: var(--bd-accent); }
.bd-hero-sub {
  margin: 0;
  font-size: 18px;
  /* On #171A26 this is roughly 8:1, so the subtitle is a real sentence and
     not decoration that happens to be legible. */
  color: #C9CEDA;
}

/* ── The search bar ───────────────────────────────────────────────────
   One white pill floating over the hero's bottom edge. The negative margin
   is what makes it overlap; .bd-wrap's own top margin above restores the
   gap to the results, so the overlap never depends on the hero's height. */
.bd-search {
  position: relative;
  z-index: 2;
  max-width: 980px;
  margin: 36px auto -44px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 20px;
  box-shadow: var(--bd-shadow-lift);
}
.bd-search-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.bd-search-row--top { align-items: stretch; }

.bd-city {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 220px;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
}
.bd-city input {
  flex: 1;
  min-width: 0;
  min-height: 42px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 16px;
}
.bd-city input:focus { outline: none; }
.bd-city:focus-within { border-color: var(--bd-accent); }
.bd-ico { width: 20px; height: 20px; flex: none; color: var(--text-muted); }

/* Segmented tabs. Built from the deal_type labels the rest of the CRM
   uses, so there are more than the reference's three; they wrap instead of
   scrolling sideways, because nothing on this page scrolls sideways. */
.bd-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 4px;
  border-radius: 999px;
  background: var(--bg);
  border: 1px solid var(--border);
}
.bd-tab {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 14px;
  border-radius: 999px;
  font-size: 16px;
  color: var(--text-muted);
  cursor: pointer;
}
/* The radio itself is the control; the label is its face. Hidden from
   sight, never from the accessibility tree or the keyboard. */
.bd-tab input {
  position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.bd-tab.is-on { background: var(--bd-accent-ink); color: var(--bd-on-accent); font-weight: 600; }
.bd-tab:has(input:focus-visible) { outline: 3px solid var(--bd-focus); outline-offset: 2px; }

.bd-pill {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 1 1 150px;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  color: var(--text);
  font-size: 16px;
  cursor: pointer;
}
.bd-pill select {
  flex: 1;
  min-width: 0;
  min-height: 42px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 16px;
  cursor: pointer;
}
.bd-pill select:focus { outline: none; }
.bd-pill:focus-within { border-color: var(--bd-accent); }
.bd-pill--btn { flex: 0 1 auto; font-weight: 500; }
.bd-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--bd-accent-ink);
  color: var(--bd-on-accent);
  font-size: 14px;
  font-weight: 700;
}
.bd-go {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 32px;
  border: 0;
  border-radius: 999px;
  background: var(--bd-accent-ink);
  color: var(--bd-on-accent);
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
}
.bd-go:hover { background: #a83400; }

/* Navigation only: it leaves for the agency's own CRM host, where the login
   lives. Nothing is published from this page. */
.bd-publish {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 20px; margin: 0 0 20px;
  border-radius: 999px; font-weight: 600; text-decoration: none;
  border: 1px solid var(--bd-accent-ink);
  background: var(--card-bg); color: var(--bd-accent-ink);
}

/* ── Results ──────────────────────────────────────────────────────────*/
.bd-results-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
  margin: 0 0 16px;
}
.bd-results-count { margin: 0; font-size: 22px; font-weight: 700; }
.bd-results-city { margin: 0; color: var(--text-muted); font-size: 16px; }
/* Shown only when boardList() returned exactly BOARD_LIST_CAP rows, i.e.
   there are more properties on the board than this page holds. Quieter than
   the count above it but not hidden: a viewer who does not read it is no
   worse off than before, and one who does now knows to narrow the search. */
.bd-results-note {
  margin: 6px 0 0;
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1.5;
}

.bd-list { display: flex; flex-direction: column; gap: 14px; }

/* A wide, SHORT card: a fixed-height photo beside the text, and the money in
   its own column at the far side. The height is set by the photo (150px) plus
   the card's padding, so a card with a long title, four tags and an agency
   line is exactly as tall as a card with none of them - every row of the list
   scans at the same rhythm instead of each card sizing itself. */
.bd-card {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--bd-radius-card);
  background: var(--card-bg);
  box-shadow: var(--bd-shadow);
  overflow: hidden;
}
.bd-card[hidden] { display: none; }
.bd-card--mine { border-color: var(--bd-accent); }
.bd-card:hover { box-shadow: var(--bd-shadow-lift); }

/* The whole card is one link. The overlay covers the card and sits UNDER the
   two contact anchors, which are raised to z-index 2 - so a tap on a phone
   number dials and a tap anywhere else opens the listing. The focus ring is
   drawn on the overlay but sized to the card, so keyboard focus outlines the
   thing that will actually open. */
.bd-card-hit {
  position: absolute; inset: 0; z-index: 1;
  border-radius: inherit; text-decoration: none;
}
.bd-card-hit:focus-visible {
  outline: 2px solid var(--bd-accent); outline-offset: -3px;
}

.bd-card-main { display: flex; align-items: stretch; gap: 14px; padding: 10px; }
.bd-card-media { position: relative; flex: 0 0 200px; height: 150px; }
.bd-card-photo {
  width: 100%; height: 100%; object-fit: cover; display: block;
  border-radius: 10px; background: var(--bg);
}
.bd-card-photo--none {
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--border); color: var(--text-muted);
}
.bd-card-photo--none svg { width: 40px; height: 40px; }
/* Text, not colour alone: the badge says what the border colour means. */
.bd-card-mine {
  position: absolute; inset-block-start: 8px; inset-inline-start: 8px;
  margin: 0; padding: 4px 10px; border-radius: 999px;
  font-size: 14px; font-weight: 600;
  background: var(--bd-accent-soft); color: var(--bd-accent-ink);
}

/* min-width:0 on both text columns is what keeps a long unbroken title or a
   long agency name from widening the flex row past the viewport. */
.bd-card-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.bd-card-title {
  margin: 0 0 2px; font-size: 20px; font-weight: 700; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bd-card-loc {
  margin: 0 0 2px; color: var(--text-muted); font-size: 16px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bd-card-loc--phone { font-style: italic; }
.bd-card-facts {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: 6px 0 0; font-size: 16px;
}
.bd-dot { color: var(--text-muted); }
/* Pushed to the bottom of the middle column by margin-block-start:auto, so
   the tag row sits on one baseline across the whole list whatever the lines
   above it did. One row only: no wrap, and what does not fit is clipped. */
.bd-chips {
  display: flex; flex-wrap: nowrap; overflow: hidden; gap: 6px;
  margin: 10px 0 0; margin-block-start: auto; padding-block-start: 8px;
}
.bd-chip {
  flex: none;
  padding: 3px 10px; border-radius: 999px; font-size: 14px;
  border: 1px solid var(--border); color: var(--text-muted);
  white-space: nowrap;
}

/* The money column, at the card's far side (the LEFT in this RTL page).
   space-between puts the deal type at the top and the price at the very
   bottom - the card's bottom-left corner - which is where the reference
   marketplace keeps them, and is now the whole content of this column: the
   agency name, phone and email line that used to sit under the price is
   gone, since the listing page the card links to carries that at its own
   bottom. */
.bd-card-side {
  flex: 0 0 auto; min-width: 0; max-width: 42%;
  display: flex; flex-direction: column; align-items: flex-end;
  justify-content: space-between; text-align: end;
  padding-inline-end: 4px;
}
.bd-card-deal { margin: 0; font-size: 15px; color: var(--text-muted); }
.bd-card-price {
  margin: auto 0 0; font-size: 24px; font-weight: 800; white-space: nowrap;
}

/* "מחיר לפי פנייה", where the price is withheld and there is no number to
   offer instead. Smaller and muted: it is a sentence, not a figure, and it
   must not be mistaken for one at a glance. */
.bd-card-price--hidden {
  font-size: 16px; font-weight: 600; color: var(--text-muted);
  white-space: normal;
}

/* "יצירת קשר", standing where the price would be. margin-block-start:auto
   pins it to the BOTTOM of the money column, on the same baseline the price
   holds on its neighbours, so a mixed list still scans as one row of cards. */
.bd-card-contact {
  margin-block-start: auto;
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: flex-end; gap: 4px 10px; min-width: 0;
}
/* Raised above .bd-card-hit, the same way the tel: link below is, or the
   stretched card link swallows the press and opens the listing instead. */
.bd-card-contact-btn {
  position: relative; z-index: 2;
  min-height: 44px; padding: 0 16px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid var(--bd-accent-ink); border-radius: 999px;
  background: transparent; color: var(--bd-accent-ink);
  font: inherit; font-size: 15px; font-weight: 700; cursor: pointer;
  white-space: nowrap;
}
.bd-card-contact-btn:hover { background: var(--bd-accent-soft); }
.bd-card-contact-btn[hidden] { display: none; }
.bd-card-contact-out {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: flex-end; gap: 0 8px; min-width: 0;
}
.bd-card-contact-out[hidden] { display: none; }
.bd-card-contact-name {
  font-size: 14px; font-weight: 600; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
/* Same raise, same kept 44px target, and the same negative margin that keeps
   the target from adding 44px of height to the card. LTR digits so a number
   is not reordered on this RTL page. */
.bd-card-contact-tel {
  position: relative; z-index: 2;
  min-height: 44px; display: inline-flex; align-items: center;
  margin-block: -12px;
  direction: ltr; unicode-bidi: isolate;
  font-size: 15px; color: var(--bd-accent-ink); font-weight: 700;
  white-space: nowrap;
}

.bd-empty { color: var(--text-muted); padding: 48px 0; text-align: center; font-size: 16px; }

/* The two agency-specific empty states. Not styled as an error: neither
   "your agency is not approved yet" nor "you have published nothing yet" is
   a failure, they are explanations of an otherwise unexplained absence. */
.bd-notice {
  color: var(--text-muted);
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--bd-radius-card);
  padding: 14px 16px;
  margin: 0 0 20px;
  line-height: 1.7;
  font-size: 16px;
}

/* ── The "more filters" dialog ────────────────────────────────────────*/
.bd-modal { position: fixed; inset: 0; z-index: 50; display: flex;
  align-items: center; justify-content: center; padding: 16px; }
.bd-modal[hidden] { display: none; }
.bd-modal-back { position: absolute; inset: 0; background: rgba(23, 26, 38, .55); }
.bd-modal-box {
  position: relative;
  width: 100%; max-width: 560px; max-height: 88vh; overflow-y: auto;
  background: var(--card-bg); color: var(--text);
  border-radius: 18px; box-shadow: var(--bd-shadow-lift);
  padding: 18px;
}
.bd-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
/* The dialog's toggles filter the RENDERED cards, in the browser. This says
   so, and appears only when that distinction can mislead - when the board
   query hit its ceiling and the rendered cards are not the whole board. */
.bd-modal-note {
  margin: 10px 0 0;
  color: var(--text-muted);
  font-size: 14px;
  line-height: 1.5;
}
.bd-modal-head h2 { margin: 0; font-size: 20px; font-weight: 700; }
.bd-modal-x {
  min-width: 44px; min-height: 44px; display: inline-flex;
  align-items: center; justify-content: center;
  border: 0; border-radius: 999px; background: transparent;
  color: var(--text-muted); cursor: pointer;
}
.bd-modal-x svg { width: 22px; height: 22px; }

.bd-attrs {
  display: grid; gap: 10px; margin: 16px 0;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
}
.bd-attr {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; min-height: 84px; padding: 10px;
  border: 1px solid var(--border); border-radius: var(--bd-radius-card);
  background: var(--bg); color: var(--text);
  font: inherit; font-size: 15px; cursor: pointer;
}
.bd-attr-ico { width: 26px; height: 26px; color: var(--text-muted); }
/* Border AND fill AND aria-pressed: the on state is never colour alone. */
.bd-attr.is-on {
  border-color: var(--bd-accent-ink); background: var(--bd-accent-soft);
  color: var(--bd-accent-ink); font-weight: 600;
}
.bd-attr.is-on .bd-attr-ico { color: var(--bd-accent-ink); }

.bd-modal-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.bd-reset {
  min-height: 44px; padding: 0 12px; border: 0; background: transparent;
  color: var(--text-muted); font: inherit; font-size: 16px;
  text-decoration: underline; cursor: pointer;
}
.bd-apply {
  min-height: 44px; padding: 0 28px;
  border: 2px solid var(--bd-accent-ink); border-radius: 999px;
  background: transparent; color: var(--bd-accent-ink);
  font: inherit; font-size: 16px; font-weight: 700; cursor: pointer;
}
.bd-apply:hover { background: var(--bd-accent-soft); }
/* Set while the dialog is open, so the page behind it does not scroll. */
body.bd-locked { overflow: hidden; }

.bd-page :focus-visible { outline: 3px solid var(--bd-focus); outline-offset: 2px; }

/* ── Small screens ────────────────────────────────────────────────────
   Two steps, not one. Under 720px the hero shrinks and every search
   control goes full width, one per line, so nothing is squeezed under a
   tap target. Under 480px the card turns vertical: the photo goes on top
   at full width, because a 200px photo beside text on a 375px screen
   leaves the text about 120px of measure. */
@media (max-width: 720px) {
  .bd-hero { padding-top: 44px; }
  .bd-hero-inner { min-height: 0; text-align: start; }
  .bd-hero-title { font-size: 30px; }
  .bd-hero-sub { font-size: 16px; }
  .bd-search { border-radius: 16px; margin-bottom: -36px; }
  .bd-wrap { margin-top: 56px; }
  .bd-city, .bd-pill, .bd-pill--btn, .bd-go, .bd-tabs { flex: 1 1 100%; }
  .bd-go { justify-content: center; }
  .bd-results-count { font-size: 20px; }
}
/* The card stays HORIZONTAL on a phone - the photo shrinks to 120px instead
   of jumping on top of the text, which is what the reference marketplace
   does and what keeps a list of ten cards scannable with one thumb. Only the
   money column moves: it wraps onto its own full-width row under the photo
   and the text, because a price (or the contact button standing in for one)
   and a deal type cannot share 375px with a photo and a title and still hold
   their tap targets. */
@media (max-width: 480px) {
  .bd-card-main { flex-wrap: wrap; gap: 10px; }
  .bd-card-media { flex: 0 0 120px; height: 110px; }
  .bd-card-title { font-size: 18px; }
  .bd-card-facts { font-size: 15px; }
  .bd-card-side {
    flex: 1 0 100%; max-width: 100%;
    flex-direction: row; flex-wrap: wrap; align-items: baseline;
    justify-content: flex-start; text-align: start;
    gap: 0 10px; padding-inline-end: 0;
  }
  .bd-card-price { margin: 0; font-size: 21px; }
  .bd-card-price--hidden { font-size: 15px; }
  /* The contact stand-in goes back to reading with the row rather than
     hanging off its end, since this column is a horizontal strip here. */
  .bd-card-contact { margin-block-start: 0; justify-content: flex-start; }
  .bd-card-contact-out { justify-content: flex-start; }
}

/* This stylesheet otherwise ships one light scheme only; the board is the
   one public page, so it alone gets a dark override. The hero stays dark in
   both schemes, which is the point of a hero: its own contrast does not
   depend on the viewer's setting.
   --bd-accent-soft is re-pointed at a translucent orange rather than the
   light tint, and --bd-accent-ink at the brighter hue, because the light
   scheme's pairing (dark orange text on a near-white tint) inverts to
   roughly 1.4:1 on a dark surface. The dark pairing measures about 7:1. */
@media (prefers-color-scheme: dark) {
  /* body:has(.bd-page), not .bd-page alone: .bd-page is the centred page
     wrapper, and `body { background: var(--bg) }` resolves --bg from :root,
     which never changes here. Scoping only .bd-page left dark mode
     rendering a dark column with light gutters and light space below the
     fold. Scoping the override to body:has(.bd-page) instead covers the
     whole viewport, still touches nothing under :root, and cannot affect any
     other CRM screen: no other screen's markup carries .bd-page. */
  body:has(.bd-page) {
    --bg: #14161C;
    --card-bg: #1E212B;
    --border: #2E3140;
    --text: #E5E7EB;
    --text-muted: #9CA3AF;
  }
  body:has(.bd-page) .bd-page {
    --bd-accent-ink:  #FF8A45;
    --bd-accent-soft: rgba(255, 107, 26, .16);
    /* White on #FF8A45 is 2.36:1, so in the dark scheme the filled
       controls take dark ink on the bright orange instead: 8.16:1. This
       used to be a separate rule listing the three controls by name, which
       meant a fourth filled control added later would have silently kept
       white. It is the token now, so it cannot drift. */
    --bd-on-accent:   #171A26;
    /* #FF8A45 as a ring measures 6.86:1 on the dark card and 7.73:1 on the
       dark page, so the dark scheme's ring is the accent itself. */
    --bd-focus:       #FF8A45;
    --bd-shadow:      0 2px 8px rgba(0, 0, 0, .45);
    --bd-shadow-lift: 0 10px 30px rgba(0, 0, 0, .55);
  }
  body:has(.bd-page) .bd-go:hover { background: #FFA06B; }
}

/* ── Street ↔ neighbourhood chips (pages/lookups.php, assets/js/lookups.js) ──
   config/migrations/025_street_neighborhoods.sql: a street can belong to
   several neighbourhoods, so both tabs show a wrapping chip list rather than
   one value. The 44px min-height on every control here is the project's
   touch-target floor - these sit inside a dense table where they would
   otherwise collapse to the text's own height. */
.lk-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.lk-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 10px; border-radius: 999px;
  background: var(--primary-light); color: var(--text);
  font-size: 12px; white-space: nowrap;
}
.lk-expand-row > td { background: var(--bg); }
.lk-expand-body { padding: 10px 4px; font-size: 13px; }

/* ══════════════════════════════════════════════════════════════════════
   LOGIN HERO - index.php and sso/login.php
   ══════════════════════════════════════════════════════════════════════

   A full-viewport dark hero with a looping video behind it, a top bar, a
   staggered entrance, and the login card as the one primary action. The
   design was handed over as React + Tailwind; this is the same design
   language in the stack this project actually runs on, which is plain CSS
   with no build step.

   DIRECTION. The source design is LTR. Everything positional below is
   logical (inset-inline-*, padding-inline, text-align: start, flex with
   space-between), so the RTL document mirrors it without a second
   stylesheet. The ONE physical value is .lh-video object-position, and it
   is mirrored by hand - see the note there.

   CONTRAST. Text over a video cannot be measured against a token, so
   .lh-scrim is what makes the numbers exist at all. The brightest pixel in
   assets/video/hero.mp4 is #4A1E90; tools/contrast_audit.php composites the
   scrim over THAT and measures every text pairing here against the result.
   Replace the video and those rows have to be re-measured - the audit says
   so at the pairing.
   ────────────────────────────────────────────────────────────────────── */

.lh-page {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;      /* the mobile URL bar must not crop the card */
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
  background: linear-gradient(160deg, #1B1940 0%, #12132A 55%, #0B0C1A 100%);
  color: #fff;
}

/* ── The backdrop ────────────────────────────────────────────────────
   Absolute rather than fixed: on a short viewport the card scrolls, and a
   fixed layer under a scrolling card jumps on iOS the moment the keyboard
   opens. The poster is the layer background-image, so a reader with
   reduced motion (who never gets the video element below) still sees the
   frame rather than the flat gradient. */
.lh-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-color: #0B0C1A;
  background-size: cover;
  background-repeat: no-repeat;
  background-position: 30% center;
}
.lh-video {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  /* The source design says 70% center: it is LTR, its copy sits on the
     left, and 70% pushes the subject away from the words. Our copy sits on
     the RIGHT, so the mirror of that intent is 30%. object-position has no
     logical form, which is why this is the one hand-flipped value here. */
  object-position: 30% center;
}
.lh-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Topmost layer first. The violet wash sits UNDER the darkening pass,
     which is why the audit background stack lists it second.
     The .76 floor is measured, not chosen: the shipped hero.mp4 reaches
     pure #FFFFFF, so every stop has to hold AA against WHITE, not against
     the video's average. At .52 the mid band gave white text 4.01:1 and
     the 60% muted text 2.49:1 - both under 4.5. .76 is the first value
     where both clear it (9.79 and 4.72). Replacing the video cannot make
     this too weak, only needlessly strong, because white is the worst
     case there is. */
  background:
    linear-gradient(to bottom,
      rgba(7, 8, 18, .80) 0%,
      rgba(7, 8, 18, .76) 42%,
      rgba(7, 8, 18, .84) 100%),
    radial-gradient(90% 70% at 50% 45%,
      rgba(108, 99, 255, .18) 0%,
      rgba(108, 99, 255, 0) 72%);
}

/* Everything that is not the backdrop rides above it. */
.lh-top, .lh-main, .lh-foot { position: relative; z-index: 2; }

/* ── Top bar ─────────────────────────────────────────────────────────── */
.lh-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px clamp(16px, 4vw, 44px);
}
.lh-brand { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; }
/* The mark is navy on transparent, the same reason .brand-logo-img wears a
   white chip in the sidebar: on this backdrop it would otherwise vanish. */
.lh-brand-mark {
  height: 40px;
  width: auto;
  display: block;
  object-fit: contain;
  border-radius: 8px;
  background: #fff;
  padding: 3px 6px;
}
.lh-links { display: flex; align-items: center; gap: clamp(8px, 2vw, 26px); }
.lh-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 4px;
  color: rgba(255, 255, 255, .82);
  font-size: 14px;
  text-decoration: none;
}
.lh-links a:hover { color: #fff; text-decoration: underline; }

/* ── Hamburger ───────────────────────────────────────────────────────── */
.lh-burger, .lh-menu-close {
  display: none;               /* the desktop link set is the default */
  width: 44px;
  height: 44px;
  padding: 0;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
  background: rgba(255, 255, 255, .06);
  /* A real control, so its boundary is held to WCAG 1.4.11. .28 measured
     2.4:1 on this backdrop; .45 measures 4.37:1. */
  border: 1px solid rgba(255, 255, 255, .45);
  border-radius: 10px;
  cursor: pointer;
}
.lh-burger-bar {
  display: block;
  width: 18px;
  height: 2px;
  background: #fff;
  border-radius: 2px;
  transition: transform .24s ease;
}
/* The close control is the same two bars, crossed. */
.lh-menu-close {
  display: flex;
  position: absolute;
  inset-block-start: 14px;
  inset-inline-end: clamp(16px, 4vw, 44px);
}
.lh-menu-close .lh-burger-bar:first-child { transform: translateY(3.5px) rotate(45deg); }
.lh-menu-close .lh-burger-bar:last-child  { transform: translateY(-3.5px) rotate(-45deg); }

/* ── The mobile menu ─────────────────────────────────────────────────
   visibility, not the hidden attribute: it is transitionable, so the menu
   animates closed as well as open, and it still takes the panel out of the
   tab order and out of the accessibility tree. assets/js/login_hero.js only
   flips the class. */
.lh-menu {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(9, 10, 22, .97);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  /* visibility is NOT eased, it is delayed - and only on the way out.
     Transitioning it symmetrically means the menu is still computed as
     hidden on the frame it opens, and focus() on a hidden element is a
     no-op: the keyboard stayed on the burger every time. 0s here with a
     .24s delay holds the panel visible while it fades away, and 0s with
     no delay below makes it focusable the instant the class lands. */
  transition: opacity .24s ease, transform .24s ease, visibility 0s linear .24s;
}
.lh-menu.is-open {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity .24s ease, transform .24s ease, visibility 0s;
}
.lh-menu-links { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.lh-menu-links a {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  padding: 0 28px;
  color: #fff;
  font-size: 20px;
  font-weight: 500;
  text-decoration: none;
}
.lh-menu-links a:hover { text-decoration: underline; }
/* Nothing behind the menu may scroll while it is up. */
.lh-menu-open, .lh-menu-open body { overflow: hidden; }

/* ── The hero itself ─────────────────────────────────────────────────
   Two columns once there is room: the words on the inline-start, the card
   on the inline-end. One column below that, card last. The card is the
   primary action either way - this is a login page, not a brochure. */
.lh-main {
  flex: 1;
  width: 100%;
  max-width: 1180px;
  margin-inline: auto;
  padding: clamp(20px, 4vh, 48px) clamp(16px, 4vw, 44px) clamp(24px, 4vh, 48px);
  display: grid;
  grid-template-columns: 1fr;
  align-content: center;
  justify-items: stretch;
  gap: 30px;
  text-align: start;
}
.lh-copy { max-width: 640px; }

.lh-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 20px;
  padding: 7px 15px;
  /* .24 measured 2.13:1 against the 3:1 floor for a non-text boundary.
     .38 clears it at 3.3:1 - see tools/contrast_audit.php. */
  border: 1px solid rgba(255, 255, 255, .38);
  border-radius: 999px;
  font-size: 13px;
  letter-spacing: .01em;
  color: rgba(255, 255, 255, .78);
}
.lh-badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #9C97FF;
  flex: none;
}
/* Weight 500, tight leading, tight tracking - the source design headline
   voice. Heebo carries 500, and Hebrew at this size takes the negative
   tracking without crowding. */
.lh-title {
  margin: 0 0 18px;
  font-size: clamp(30px, 5.4vw, 58px);
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: -0.02em;
  color: #fff;
}
.lh-line { display: block; }
.lh-lede {
  margin: 0;
  max-width: 44ch;
  font-size: clamp(15px, 1.5vw, 18px);
  line-height: 1.65;
  color: rgba(255, 255, 255, .76);
}

/* ── The card ────────────────────────────────────────────────────────
   .login-card supplies the white surface, the radius and the lift; this
   only frees it from its fixed 380px so it can share a grid track. */
.lh-card {
  width: 100%;
  max-width: 400px;
  margin-inline: auto;
  text-align: center;
}

/* ── The signup-request entry point ──────────────────────────────────
   sso/signup_request.php cannot be linked to: it requires the signed
   cookie sso/google.php sets after Google verifies an address, so a direct
   link lands on "start over". The route in is therefore the Google start
   URL - the same target as the sign-in button. An address that belongs to
   no agency comes out of that flow ON the request form, which is why the
   note below says where the first screen will come from. Being sent to
   Google without warning is the surprise this exists to prevent. */
.lh-alt {
  margin: 18px 0 0;
  padding-block-start: 16px;
  border-block-start: 1px solid var(--border);
  font-size: 14px;
  color: var(--text-muted);
}
.lh-alt-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: 6px;
  font-weight: 600;
  color: var(--primary-on-white);
}
.lh-alt-note {
  margin: 0;
  font-size: 12px;
  color: var(--login-fine);
}

/* ── The legal line ──────────────────────────────────────────────────── */
.lh-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 clamp(16px, 4vw, 44px) 22px;
  font-size: 14px;
}
.lh-foot a { color: rgba(255, 255, 255, .86); }
.lh-foot-sep { color: rgba(255, 255, 255, .45); }

/* ── Focus ───────────────────────────────────────────────────────────
   .form-control:focus sets outline:none and replaces it with a 12%-alpha
   ring, which is the faintest indicator on either page. These two rules
   restore a real one: white over the hero, the measured --border-focus
   inside the white card. Both are more specific than the rule they
   override and both come after it. */
.lh-page :focus-visible { outline: 3px solid #fff; outline-offset: 2px; border-radius: 4px; }
.lh-page .lh-card :focus-visible,
.lh-page .lh-card .form-control:focus-visible {
  outline: 3px solid var(--border-focus);
  outline-offset: 2px;
}

/* ── The staggered entrance ──────────────────────────────────────────
   The source design fadeSlideUp, at its four delays. `both` so each
   element starts invisible and stays put afterwards; turning the animation
   off (below) therefore reveals everything rather than hiding it. */
@keyframes lh-fade-slide-up {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}
.lh-badge { animation: lh-fade-slide-up .8s cubic-bezier(.22, .61, .36, 1) .2s both; }
.lh-title { animation: lh-fade-slide-up .8s cubic-bezier(.22, .61, .36, 1) .4s both; }
.lh-lede  { animation: lh-fade-slide-up .8s cubic-bezier(.22, .61, .36, 1) .7s both; }
.lh-card  { animation: lh-fade-slide-up .8s cubic-bezier(.22, .61, .36, 1) .9s both; }

/* ── Two columns once there is room for both ─────────────────────────── */
@media (min-width: 900px) {
  .lh-main {
    grid-template-columns: minmax(0, 1fr) 400px;
    align-items: center;
    gap: clamp(32px, 5vw, 72px);
  }
  .lh-card { margin-inline: 0; }
}

/* ── Phone: the link set becomes a menu ──────────────────────────────── */
@media (max-width: 860px) {
  .lh-links { display: none; }
  .lh-burger { display: flex; }
  .lh-menu { display: flex; }
  .lh-title { font-size: clamp(28px, 8vw, 40px); }
  .lh-main { gap: 24px; }
}

/* ── Reduced motion ──────────────────────────────────────────────────
   No autoplay video: the poster on .lh-media shows through instead, and
   login_hero.js pauses the element so a display:none video is not merely
   an invisible one. The entrance animations stop too - the elements are
   simply there. */
@media (prefers-reduced-motion: reduce) {
  .lh-video { display: none; }
  .lh-badge, .lh-title, .lh-lede, .lh-card { animation: none; }
  .lh-menu { transition: none; }
  .lh-burger-bar { transition: none; }
}

/* ── Dark scheme ─────────────────────────────────────────────────────
   The hero is dark in both schemes, which is the point of a hero: its
   contrast does not depend on the viewer setting. The CARD is the part
   that has to stay readable, and it does that by staying a light surface -
   every control inside it (.form-control, .btn, the Google button) is
   drawn for a light background, and the tokens they resolve are measured
   against #ffffff in tools/contrast_audit.php. Pinned here so a future
   :root dark override cannot flip the surface out from under them. A pure
   white card on a dark screen glares, so it sits deeper rather than
   dimmer - the ink stays at its measured ratio. */
@media (prefers-color-scheme: dark) {
  .lh-page .lh-card {
    background: #fff;
    color: var(--text);
    box-shadow: 0 24px 70px rgba(0, 0, 0, .62);
  }
}

/* ── שלח משוב: the sidebar trigger and its dialog ─────────────────────
   Markup in includes/header.php, behaviour in assets/js/feedback.js.

   The trigger sits on the sidebar's own surface (#1E1B4B), so it is drawn
   against that, not against the page: a translucent white fill and a white
   focus ring, the same treatment .nav-item above it gets. The dialog is on
   the page and is drawn in the CRM's light scheme like every other modal
   here.

   Every target is at least 44px, and every interactive element in this
   block has a :focus-visible ring of its own. The chips in particular are
   the one place a keyboard user has to be able to see where they are: they
   also carry a filled state, and "selected" and "focused" must not look
   like the same thing. */
.sidebar-feedback {
  padding: 8px 8px 4px;
}
.feedback-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 44px;
  padding: 10px 14px;
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, .07);
  color: rgba(255, 255, 255, .88);
  font-family: 'Heebo', sans-serif;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.feedback-trigger:hover { background: rgba(255, 255, 255, .14); color: #fff; }
.feedback-trigger:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }
.feedback-trigger-icon { font-size: 16px; line-height: 1; }

/* z-index 600, and it has to be higher than every other overlay here.
   .modal-overlay and .drawer-overlay sit at 300 (500 under the mobile media
   query) because they are opened from the MAIN CONTENT, with the sidebar
   either beside them or shut. This one is opened from INSIDE the sidebar,
   and under 768px that sidebar is an off-canvas panel at z-index 520 over
   its own scrim at 510. At 300 the dialog would have rendered behind both,
   on the one path a phone reaches it by. feedback.js also closes the mobile
   nav on open; this is the half that does not depend on that still being
   true. Below .toast-container (999), which must stay readable over it. */
.fb-overlay {
  position: fixed;
  inset: 0;
  z-index: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(0, 0, 0, .5);
}
/* [hidden] is the closed state, and a display rule above it would win. */
.fb-overlay[hidden] { display: none; }

.fb-modal {
  width: 460px;
  max-width: 100%;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  background: var(--card-bg);
  color: var(--text);
  border-radius: var(--radius);
  box-shadow: 0 20px 60px rgba(0, 0, 0, .2);
}
.fb-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--border);
}
.fb-title { font-size: 16px; font-weight: 700; margin: 0; }
.fb-x {
  min-width: 44px;
  min-height: 44px;
  border: none;
  background: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-family: inherit;
  font-size: 18px;
  cursor: pointer;
}
.fb-x:hover { background: var(--bg); color: var(--text); }
.fb-x:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }

.fb-body { padding: 18px 20px; overflow-y: auto; }
.fb-kinds { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.fb-chip {
  min-height: 44px;
  padding: 8px 20px;
  border: 1.5px solid var(--border);
  border-radius: 999px;
  background: var(--card-bg);
  color: var(--text-muted);
  font-family: 'Heebo', sans-serif;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.fb-chip:hover { background: var(--bg); color: var(--text); }
.fb-chip.is-on {
  background: var(--primary-on-white);
  border-color: var(--primary-on-white);
  color: #fff;
}
.fb-chip:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }

.fb-label { display: block; font-size: 13px; font-weight: 500; margin-bottom: 6px; }
.fb-text {
  width: 100%;
  min-height: 130px;
  padding: 10px 12px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-bg);
  color: var(--text);
  font-family: 'Heebo', sans-serif;
  font-size: 14px;
  line-height: 1.6;
  resize: vertical;
}
.fb-text:focus-visible { outline: 3px solid var(--primary); outline-offset: 1px; border-color: var(--border-focus); }

.fb-error {
  margin-top: 10px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  background: var(--danger-light);
  color: #991B1B;
  font-size: 13px;
}
.fb-error[hidden] { display: none; }

.fb-foot {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
}
/* The footer pair are the two 44px targets a thumb reaches for. */
.fb-foot .btn { min-height: 44px; padding-inline: 22px; }
.fb-foot .btn:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }
.fb-foot .btn:disabled { opacity: .6; cursor: not-allowed; }

@media (prefers-reduced-motion: reduce) {
  .feedback-trigger, .fb-chip { transition: none; }
}

/* ── pages/app.php: the Android companion app ──────────────────────────
   A read-first page: six feature cards, one download, one token manager.
   Its own classes rather than the inline styles the settings screen grew,
   because the only thing here that needs a media query is the card grid
   and an inline style cannot carry one. */
.appx-hero {
  background: linear-gradient(135deg, var(--primary-on-white), var(--primary-deep));
  color: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 26px 24px;
  margin-bottom: 22px;
}
.appx-hero-name { font-size: 22px; font-weight: 700; line-height: 1.25; }
.appx-hero-sub  { font-size: 14px; margin-top: 8px; opacity: .92; max-width: 62ch; }

.appx-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px;
  margin-bottom: 22px;
}
.appx-feature { display: flex; gap: 14px; }
.appx-feature-icon {
  width: 44px; height: 44px;
  border-radius: 12px;
  background: var(--primary-light);
  display: flex; align-items: center; justify-content: center;
  font-size: 21px;
  flex-shrink: 0;
}
.appx-feature-title { font-size: 15px; font-weight: 700; margin-bottom: 8px; }
.appx-list { list-style: none; margin: 0; padding: 0; }
.appx-list li {
  position: relative;
  padding-inline-start: 16px;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--text);
}
.appx-list li + li { margin-top: 6px; }
/* The marker is drawn rather than a list-style, so it keeps its place on
   the start edge under dir=rtl without the browser flipping a bullet box. */
.appx-list li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: .62em;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--primary);
}

/* The download. Deliberately the loudest thing on the page below the fold. */
.appx-download {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  border: 2px solid var(--primary-light);
}
.appx-download-main { flex: 1 1 260px; min-width: 0; }
.appx-download .btn {
  min-height: 44px;
  padding-inline: 26px;
  font-size: 15px;
}
.appx-meta { font-size: 12px; color: var(--text-muted); margin-top: 6px; }
.appx-note {
  background: var(--warning-light);
  border: 1px solid var(--warning);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  font-size: 13px;
  line-height: 1.6;
  margin-top: 16px;
}
.appx-missing {
  background: var(--danger-light);
  border: 1px solid var(--danger);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  font-size: 13px;
}

/* ── The token manager, moved here from pages/settings.php ─────────── */
.appx-token-new {
  background: var(--success-light);
  border: 1px solid #86EFAC;
  border-radius: var(--radius-sm);
  padding: 12px;
  margin-bottom: 14px;
}
.appx-token-new-value {
  flex: 1;
  min-width: 0;
  font-family: monospace;
  font-size: 13px;
  padding: 10px;
  min-height: 44px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
}
.appx-token-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: 6px;
  background: var(--card-bg);
}
.appx-token-row-main { flex: 1 1 200px; min-width: 0; }
.appx-token-label { font-weight: 600; }
.appx-token-sub {
  font-size: 11px;
  color: var(--text-muted);
  font-family: monospace;
  word-break: break-all;
}
/* Every control in this card is tapped on a phone while setting the phone
   up, which is the one context this whole page exists for. */
.appx-token-card .btn,
.appx-token-card .form-control { min-height: 44px; }
.appx-token-create { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.appx-token-create .form-control { flex: 1 1 220px; }
.appx-endpoints {
  font-size: 11px;
  background: var(--bg);
  padding: 10px;
  border-radius: var(--radius-sm);
  margin-top: 8px;
  overflow-x: auto;
}

@media (max-width: 640px) {
  .appx-hero { padding: 20px 16px; }
  .appx-hero-name { font-size: 19px; }
  .appx-download .btn { width: 100%; justify-content: center; }
}
