/* Lead detail (admin) - /admin/leads/:id.
   Reuses the admin.css kit (.btn, .btn-icon, .modal-*, .form-*, .reg-chip,
   .reg-course-chip, .reg-enroll-status, .reg-answer-table, .empty-state,
   .toast, .filter-label); only bespoke layout and components live here.

   ── THIS FILE IS A KIT NOW, NOT ONE PAGE'S STYLESHEET ──────────────────────

   `.ld-*` started as the lead card and is today BORROWED, class by class, by
   two other screens: the unified Person page (`.per-page`, admin-person.css)
   and the extracted sale panel (`.edt-page`, admin-enrollment-detail.css).
   Both of those are Hebrew RTL islands, which is why the mirror block at the
   foot of this file exists and why each of them pays its own mirror bill in
   its own stylesheet.

   The consequence for anyone tidying up: A CLASS THAT LOOKS ORPHANED MAY BE IN
   DAILY USE TWO DIRECTORIES AWAY. Before deleting a rule, grep the class name
   across every `.vue`, every other stylesheet AND every spec - three of the
   specs (tests/enrollmentEntryPoints.spec.ts, tests/adminPersonRtlMirrors.spec.ts,
   tests/adminEnrollmentDetailRtlMirrors.spec.ts) read this file as TEXT and
   assert exact selector strings, so a rule nothing renders can still be pinned.
   Remember that several families are assembled at runtime
   (`ld-ch-chip--${tier}`, `ld-ch-conf--${confidence}`, `ld-ch-verdict--${tier}`,
   `ld-ct-status--${status}`): the modifier never appears in the source, only
   the stem does.

   On 2026-08-07 the blocks belonging to markup the Person page replaced - the
   breadcrumb, the header identity row, the opt-out banner, the controls row,
   the open-day registration card, the cancelled-sale sums, the hand-rolled
   composer and activity timeline, and the `.ld-modal-*` helpers - were removed
   after exactly that audit. What is left is either rendered today or pinned by
   a spec. */

/* ── Prev/next through the filtered list ──────────── */

/* Wraps the lead's name in the header row: [prev] name [next] [3 / 148].
   Rendered only when the page was reached from the leads table, which is what
   put the filtered view in `?list=`.

   The page root is an RTL island, so the RIGHT-pointing chevron is "previous";
   the icons are hand-flipped in LeadListNav.vue and every rule here uses
   logical properties, so this block needs no mirror at the end of the file. */
.ld-nav {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

/* Builds on .btn-icon (admin.css); only what the header context needs. */
.ld-nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  min-width: 34px;
  min-height: 34px;
  padding: 0;
  border: 1px solid #e8e9f0;
  border-radius: 999px;
  background: #fff;
  color: #5a5b6a;
}

.ld-nav-btn:hover:not(:disabled) {
  background: #f2f6fd;
  border-color: rgba(0, 113, 227, 0.3);
  color: #0071e3;
}

/* Flat and inert at the ends of the list, never missing: an arrow that
   disappears on the last lead reads as a broken page rather than as "there is
   nothing after this one". */
.ld-nav-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.ld-nav-btn:disabled:hover {
  background: #fff;
  color: #5a5b6a;
}

.ld-nav-btn i {
  font-size: 0.85rem;
}

.ld-nav-pos {
  font-size: 0.75rem;
  color: #8e8f9e;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Same 44px tap floor the rest of the panel uses on phones. */
@media (max-width: 767px) {
  .ld-nav-btn {
    min-width: 44px;
    min-height: 44px;
  }
}

/* ── Header card ──────────────────────────────────── */

.ld-header {
  background: #fff;
  border: 1px solid #e8e9f0;
  border-radius: 14px;
  padding: 1.25rem 1.5rem;
  box-shadow: 0 2px 10px rgba(0, 60, 130, 0.05);
  margin-bottom: 1.25rem;
}

.ld-header-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 0.9rem;
}

/* The relative half of a verbose date inside dense table cells. */
.ld-when-rel {
  color: #8a93a3;
  font-size: 0.72rem;
}

.ld-header-contact {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.1rem;
  margin-left: auto;
}

/* Controls row: status / owner / follow-up / timestamps */

/* Follow-up entry: a date input beside a time input, replacing the single
   datetime-local that discarded a date typed without a time and let Chrome's
   year segment swallow the time keystrokes. Same two-control shape as the
   enrollment-page deadlines (.ep-datetime), including the fixed time width -
   it holds "23:59" and nothing longer, so the date field takes the slack. */
.ld-followup {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.ld-followup-date {
  flex: 1 1 auto;
  min-width: 0;
}

.ld-followup-time {
  flex: 0 0 108px;
}

/* States the hour a date-only follow-up will be saved at, before it is saved.
   Sits outside .ld-followup so the overdue border cannot bleed onto it. */
.ld-followup-derived {
  font-size: 0.72rem;
  color: #8e8f9e;
  line-height: 1.5;
}

.ld-followup--overdue .form-input {
  border-color: #d9534f;
  color: #c0392b;
}

/* Quick actions */

.ld-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.1rem;
  padding-top: 1.1rem;
  border-top: 1px solid #f0f1f5;
}

/* ── Two-column grid (cards | timeline) ───────────── */

.ld-grid {
  display: grid;
  grid-template-columns: minmax(0, 11fr) minmax(0, 9fr);
  gap: 1.25rem;
  align-items: start;
}

.ld-col {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  min-width: 0;
}

/* ── Cards ────────────────────────────────────────── */

.ld-card {
  background: #fff;
  border: 1px solid #e8e9f0;
  border-radius: 14px;
  padding: 1.1rem 1.25rem;
  box-shadow: 0 2px 10px rgba(0, 60, 130, 0.05);
}

.ld-card-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
}

/* The gap lives on the body, so a collapsed card closes up to its head. */
.ld-card-body {
  margin-top: 0.85rem;
}

.ld-card-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.95rem;
  font-weight: 700;
  color: #191a23;
  margin: 0;
  min-width: 0;
  flex: 1;
}

.ld-card-title i {
  color: #8e8f9e;
  font-size: 0.85rem;
}

/* Collapse toggle: the whole title row is the hit area; head-level actions
   (edit pen, wa.me link) stay outside the button. */
.ld-card-toggle {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: inherit;
  cursor: pointer;
}

.ld-card-toggle:hover,
.ld-card-toggle:hover i {
  color: #0071e3;
}

.ld-card-caret {
  width: 0.8rem;
  flex-shrink: 0;
  font-size: 0.7rem;
}

.ld-card-count {
  background: #f0f1f5;
  color: #5a5b6a;
  border-radius: 999px;
  padding: 0.05rem 0.5rem;
  font-size: 0.72rem;
  font-weight: 700;
}

.ld-card-empty {
  color: #8e8f9e;
  font-size: 0.85rem;
}

/* Profile key/value grid */

.ld-kv {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  margin: 0;
}

.ld-kv-row {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 1rem;
  align-items: baseline;
}

.ld-kv-row dt {
  color: #8e8f9e;
  font-size: 0.8rem;
}

.ld-kv-row dd {
  margin: 0;
  color: #191a23;
  font-size: 0.88rem;
  overflow-wrap: anywhere;
}

/* ── WhatsApp conversation ────────────────────────── */

.ld-wa-window {
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.ld-wa-window--open {
  background: #e5f8ec;
  color: #1d8a4e;
}

.ld-wa-window--closed {
  background: #f0f1f5;
  color: #8e8f9e;
}

/* The three doors, sitting directly above the transcript: reply inside the
   panel (the green segment, and the only one that records) or hand off to
   WhatsApp Web or the app on the device. Rendered by the shared
   `WaActionGroup`, which owns the segmented look; this only places it. */

.ld-wa-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.6rem;
}

.ld-wa-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem 0.8rem;
  margin-bottom: 0.7rem;
  font-size: 0.82rem;
}

.ld-wa-profile {
  font-weight: 700;
  color: #191a23;
}

.ld-wa-id {
  color: #5a5b6a;
}

.ld-wa-inbound {
  margin-left: auto;
  font-size: 0.75rem;
  color: #8e8f9e;
}

/* Chat transcript: newest last, pinned to the bottom via JS scroll. */

.ld-wa-messages {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  max-height: 320px;
  overflow-y: auto;
  background: #fbfcfe;
  border: 1px solid #eef0f6;
  border-radius: 10px;
  padding: 0.7rem;
}

.ld-wa-msg {
  max-width: 85%;
  border-radius: 12px;
  padding: 0.45rem 0.65rem;
}

.ld-wa-msg--in {
  align-self: flex-start;
  background: #fff;
  border: 1px solid #e8e9f0;
  border-bottom-left-radius: 4px;
}

.ld-wa-msg--out {
  align-self: flex-end;
  background: #e5f8ec;
  border: 1px solid #c4ecd4;
  border-bottom-right-radius: 4px;
}

.ld-wa-msg-body {
  margin: 0;
  font-size: 0.85rem;
  color: #191a23;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* A message deleted for everyone, mirroring the inbox thread: the label at full
   strength above, the retracted text kept but greyed below. Greying the BODY
   rather than the row, so the label itself stays legible. */
.ld-wa-msg--deleted .ld-wa-msg-body {
  opacity: 0.55;
}

.ld-wa-msg-deleted {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  margin: 0 0 2px;
  font-size: 0.72rem;
  font-weight: 500;
  color: #d10032;
}

.ld-wa-msg-time {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.68rem;
  color: #8e8f9e;
  text-align: right;
}

/* Delivery state on outbound rows, read from the inbox API (the lead API's
   transcript carries none). Compact by design - the full ticks story lives in
   the inbox. `read` is the colored state and `failed` the alarming one, same
   semantics as the inbox ticks; everything in between stays muted. */
.ld-wa-msg-status {
  font-weight: 600;
}

.ld-wa-msg-status--read {
  color: #0b7bc0;
}

.ld-wa-msg-status--failed {
  color: #c0392b;
}

.ld-wa-msg-status--unknown {
  color: #b45309;
}

/* ── Marketing & attribution ──────────────────────── */

/* Subsections inside the marketing card (affiliate / campaign / click ids /
   WhatsApp bridge / other metadata), separated by hairlines. */
.ld-mk-sub {
  margin-top: 0.85rem;
  padding-top: 0.8rem;
  border-top: 1px solid #f0f1f5;
}

.ld-card-body > .ld-mk-sub:first-child,
.ld-mk-tech > .ld-mk-sub:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.ld-mk-subtitle {
  margin: 0 0 0.5rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #8e8f9e;
}

/* Technical sub-pane (landing URL + click/browser ids) - collapsed by default. */
.ld-mk-toggle {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #8e8f9e;
  text-align: inherit;
  cursor: pointer;
}

.ld-mk-toggle:hover {
  color: #0071e3;
}

.ld-mk-toggle i {
  font-size: 0.65rem;
}

.ld-mk-tech {
  margin-top: 0.6rem;
}

/* Long technical identifiers (gclid / fbc / fbp / raw metadata). */
.ld-mk-code {
  font-family: var(--font-mono, monospace);
  font-size: 0.76rem;
  word-break: break-all;
}

.ld-mk-link {
  color: #2456c4;
  font-size: 0.84rem;
  text-decoration: none;
  overflow-wrap: anywhere;
}

.ld-mk-link:hover {
  text-decoration: underline;
}

/* ── Traffic-channel verdict ──────────────────────────
   The card's one statement of HOW the lead arrived. Colour is keyed off
   ChannelVerdict.tier ("did we pay for this click"), never off the platform -
   which network it came from is a separate question answered in words. The
   swatches are the same ones .reg-source-badge--* uses in admin.css, so the
   lead detail and the open-day list speak one visual language.
   No physical offsets anywhere below, so the RTL island needs no mirror. */

/* Head chip: the verdict at a glance, next to the card title. */
.ld-ch-chip {
  flex-shrink: 0;
  max-width: 60%;
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.4;
}

/* The confidence word rides the chip only when the verdict is not confirmed. */
.ld-ch-chip-conf {
  font-weight: 500;
  opacity: 0.75;
}

/* Expanded verdict banner at the top of the card body. Shrink-wraps its
   content (inline-flex) so a short verdict does not become a wide empty bar. */
.ld-ch-verdict {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  max-width: 100%;
  padding: 0.5rem 0.7rem;
  border: 1px solid transparent;
  border-radius: 10px;
}

.ld-ch-label {
  font-size: 0.95rem;
  font-weight: 700;
}

.ld-ch-chip--paid,
.ld-ch-verdict--paid {
  background: #f5f3ff;
  color: #6d28d9;
  border-color: #ddd6fe;
}

.ld-ch-chip--likely-paid,
.ld-ch-verdict--likely-paid {
  background: #fffbeb;
  color: #92400e;
  border-color: #fde68a;
}

.ld-ch-chip--referral,
.ld-ch-verdict--referral {
  background: #ecfdf5;
  color: #047857;
  border-color: #a7f3d0;
}

.ld-ch-chip--unpaid,
.ld-ch-verdict--unpaid {
  background: #f3f4f6;
  color: #4b5563;
  border-color: #e5e7eb;
}

/* Unknown is not a claim, so it must not look like one: hollow fill and a
   dashed edge read as "undetermined" next to the four solid tiers. */
.ld-ch-chip--unknown,
.ld-ch-verdict--unknown {
  background: #fff;
  color: #6b7280;
  border-color: #cfd6e0;
  border-style: dashed;
}

.ld-ch-chip--unknown {
  font-weight: 600;
}

/* Confidence pill - three levels, same shape and swatches as .ld-ct-status. */
.ld-ch-conf {
  padding: 0.05rem 0.5rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.ld-ch-conf--confirmed {
  background: #e5f8ec;
  color: #1d8a4e;
}

.ld-ch-conf--likely {
  background: #fdf3e2;
  color: #b7791f;
}

.ld-ch-conf--uncertain {
  background: #f0f1f5;
  color: #8e8f9e;
}

.ld-ch-kv {
  margin-top: 0.6rem;
}

.ld-ch-listtitle {
  margin: 0.7rem 0 0.3rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #8e8f9e;
}

/* Evidence + caveats. The items are English sentences and the <ul> carries an
   explicit dir="ltr", so the bullet indent genuinely belongs on the left; the
   padding shorthand also clears global.css's RTL `ul { padding: 0 30px 0 0 }`,
   and text-align is spelled out because the RTL island inherits `right`. */
.ld-ch-list {
  margin: 0;
  padding: 0 0 0 1.15rem;
  text-align: left;
  font-size: 0.82rem;
  line-height: 1.5;
  color: #5a5b6a;
}

/* global.css sets `li { margin-bottom: 8px }` - reset it and space the items
   from the top instead, so the list closes up against what follows. */
.ld-ch-list li {
  margin-bottom: 0;
}

.ld-ch-list li + li {
  margin-top: 0.2rem;
}

/* What we could NOT establish - one step quieter than the evidence above it. */
.ld-ch-list--caveat {
  color: #8e8f9e;
}

.ld-attr-last {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.75rem;
}

.ld-attr-chip {
  background: #eef4ff;
  color: #2456c4;
  border: 1px solid #d5e3fb;
  border-radius: 6px;
  padding: 0.1rem 0.5rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.05em;
}

.ld-attr-chip--sm {
  font-size: 0.72rem;
}

.ld-attr-chip--archived {
  background: #f3f4f7;
  color: #8e8f9e;
  border-color: #e3e4ea;
  text-decoration: line-through;
}

.ld-attr-meta {
  font-size: 0.85rem;
  color: #5a5b6a;
}

.ld-attr-tag {
  margin-left: 0.5rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #8e8f9e;
}

/* Journey timeline (oldest first) */

.ld-journey {
  list-style: none;
  margin: 0.25rem 0 0;
  padding: 0;
  position: relative;
}

.ld-journey::before {
  content: '';
  position: absolute;
  left: 7px;
  top: 8px;
  bottom: 8px;
  width: 2px;
  background: #eef0f6;
}

.ld-journey-step {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem 0.6rem;
  padding: 0.35rem 0 0.35rem 1.6rem;
}

.ld-journey-step::before {
  content: '';
  position: absolute;
  left: 3px;
  top: 0.72em;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #b9c6e8;
}

.ld-journey-label {
  font-size: 0.82rem;
  color: #5a5b6a;
}

.ld-journey-ts {
  margin-left: auto;
  font-size: 0.75rem;
  color: #8e8f9e;
}

/* ── Open-day REQUEST (public wizard, books no seat) ──
   Sits above the registrations card and must never be mistaken for it. The
   whole visual argument is in the state strip at the top: amber while the
   request is unanswered (an open task), green once staff created the seat (a
   closed one). Deliberately NOT the .reg-chip family - those chips describe a
   registration's status, and this card has no registration to describe. */

.ld-odr-state {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.75rem 0.9rem;
  border-radius: 10px;
  border: 1px solid transparent;
}

.ld-odr-state > i {
  margin-top: 0.15rem;
  font-size: 0.9rem;
}

.ld-odr-state-lines {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  /* Takes the row so the CTA is pushed to the far edge, and shrinks instead of
     overflowing when the copy is long. */
  flex: 1 1 14rem;
  min-width: 0;
}

.ld-odr-state-title {
  font-size: 0.88rem;
  font-weight: 700;
}

/* An instruction to the reader rather than a fact about the lead, so it is the
   quieter half of the pair: the title states what happened, this line says what
   to do about it. (It used to cite `.ld-optout-hint` as the precedent for that
   split; that block was the lead card's own opt-out banner and is gone, so the
   rule is written out here rather than pointing at a class that no longer
   exists.) */
.ld-odr-state-hint {
  font-size: 0.78rem;
  line-height: 1.6;
  opacity: 0.9;
}

.ld-odr-state--open {
  background: #fffbeb;
  border-color: #fde68a;
  color: #92400e;
}

.ld-odr-state--handled {
  background: #f0fdf4;
  border-color: #bbf7d0;
  color: #166534;
}

.ld-odr-cta {
  align-self: center;
  flex: 0 0 auto;
}

.ld-odr-facts {
  margin-top: 0.85rem;
}

/* Reason a request cannot be actioned as-is, inline beside the date it is
   about (the date is closed, so it is not in the registration modal's list). */
.ld-odr-note {
  display: inline-block;
  margin-inline-start: 0.4rem;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  background: #fef3c7;
  color: #92400e;
  font-size: 0.72rem;
  font-weight: 700;
}

/* A question that was asked and deliberately left blank (WizardQuestion.
   skippable). Muted and italic, never red: nothing went wrong, and the row is
   kept precisely so "skipped" cannot be confused with "never asked". */
.ld-odr-answer-skipped {
  color: #8e8f9e;
  font-style: italic;
}

/* ── Enrollments + payments ledger ────────────────── */

/* LEFT IN DELIBERATELY, AND NOT BECAUSE IT IS RENDERED.
   The `.ld-enroll*` compact sale card was the lead page's own summary of a
   sale; the Person page shows the extracted sale panel (`.edt-*`) instead and
   nothing in `src/` emits any of these class names today. It stays whole for
   one reason: `tests/enrollmentEntryPoints.spec.ts` asserts, against this
   file's TEXT, that `.ld-enroll-open` exists exactly once and declares
   `display: inline-flex`. Half-deleting the group - dropping
   `.ld-enroll-cohort` while `.ld-enroll-open:hover .ld-enroll-cohort` survives
   to satisfy that spec - would leave something worse than dead CSS: a rule
   pointing at a class that no longer exists in the same file.
   `.ld-enroll-date` additionally has a live mirror in admin-person.css.
   If the spec is ever rewritten to pin the anchor's MARKUP rather than its
   rule, delete this whole block in the same change. */
.ld-enroll {
  border: 1px solid #eef0f6;
  border-radius: 10px;
  padding: 0.75rem 0.9rem;
}

.ld-enroll + .ld-enroll {
  margin-top: 0.75rem;
}

.ld-enroll-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.7rem;
}

.ld-enroll-cohort {
  font-size: 0.9rem;
  font-weight: 700;
  color: #191a23;
}

/* The cohort name opens that sale's own page (/admin/enrollments/:id). The
   anchor wraps the name and its arrow ONLY - the SKU chip, the status pill and
   the enrolment date are its siblings, because an aria-label on a link
   suppresses everything inside it for a screen reader and the cancelled pill
   was being suppressed along with it.

   `inline-flex` so the anchor hugs .ld-enroll-open-title exactly: as a plain
   block it would open a line box of its own and add the inherited leading to
   the head's row height. This way the head is laid out exactly as it was when
   the anchor WAS the head. The card's own controls sit outside it and are
   unaffected. */
.ld-enroll-open {
  display: inline-flex;
  align-items: center;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.ld-enroll-open-title {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
}

.ld-enroll-open-arrow {
  font-size: 0.7rem;
  color: #b6b8c6;
  transition: color 0.15s ease, transform 0.15s ease;
}

.ld-enroll-open:hover .ld-enroll-cohort,
.ld-enroll-open:focus-visible .ld-enroll-cohort {
  color: var(--primary-color, #0071e3);
  text-decoration: underline;
}

.ld-enroll-open:hover .ld-enroll-open-arrow,
.ld-enroll-open:focus-visible .ld-enroll-open-arrow {
  color: var(--primary-color, #0071e3);
  /* Page root is RTL, so forward is to the left. */
  transform: translateX(-2px);
}

.ld-enroll-open:focus-visible {
  outline: 2px solid var(--primary-color, #0071e3);
  outline-offset: 3px;
  border-radius: 6px;
}

.ld-enroll-date {
  margin-left: auto;
  font-size: 0.76rem;
  color: #8e8f9e;
}

.ld-progress-wrap {
  margin-top: 0.7rem;
}

.ld-progress-nums {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem;
  margin-bottom: 0.35rem;
  font-size: 0.85rem;
}

.ld-progress-paid {
  font-weight: 700;
  color: #191a23;
}

.ld-progress-expected {
  color: #8e8f9e;
  font-size: 0.78rem;
}

.ld-progress-over {
  margin-left: auto;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #b7791f;
}

.ld-progress {
  height: 8px;
  background: #eef0f6;
  border-radius: 999px;
  overflow: hidden;
}

/* Width is the paid/expected percentage - dynamic :style binding. */
.ld-progress-fill {
  height: 100%;
  border-radius: 999px;
  background: #10b981;
  transition: width 0.25s ease;
}

.ld-progress-fill--over {
  background: #f0a63a;
}

.ld-pay-scroll {
  overflow-x: auto;
  margin-top: 0.6rem;
}

.ld-pay-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8rem;
}

.ld-pay-table th {
  text-align: left;
  color: #8e8f9e;
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 0.35rem 0.5rem;
  border-bottom: 1px solid #eef0f6;
  white-space: nowrap;
}

.ld-pay-table td {
  padding: 0.4rem 0.5rem;
  border-bottom: 1px solid #f4f5f9;
  color: #191a23;
  white-space: nowrap;
}

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

.ld-pay-note {
  white-space: normal;
  color: #5a5b6a;
  max-width: 220px;
}

.ld-pay-amount--negative {
  color: #c0392b;
  font-weight: 600;
}

.ld-pay-actions {
  text-align: right;
}

.ld-add-payment {
  margin-top: 0.6rem;
}

/* SKU chip on the enrollment head (bundle overrides the cohort course type). */
.ld-enroll-sku {
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
  background: #eef4ff;
  color: #2456c4;
  border: 1px solid #d5e3fb;
  font-size: 0.72rem;
  font-weight: 700;
}

/* T10: money breakdown (מחיר מחירון · הנחה · סכום לתשלום). */
.ld-enroll-breakdown {
  margin-top: 0.5rem;
  font-size: 0.8rem;
  color: #5a5b6a;
}

/* T1: per-enrollment lifecycle actions (edit / cancel / permanent delete). */
.ld-enroll-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.6rem;
}

.ld-btn-danger {
  color: #dc2626;
  border-color: rgba(220, 38, 38, 0.4);
}

.ld-btn-danger:hover {
  background: #fef2f2;
  border-color: #dc2626;
  color: #b91c1c;
}

/* ── Contracts ────────────────────────────────────── */

.ld-contract {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem 0.75rem;
  border: 1px solid #eef0f6;
  border-radius: 10px;
  padding: 0.7rem 0.9rem;
}

.ld-contract + .ld-contract {
  margin-top: 0.75rem;
}

.ld-contract-main {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.7rem;
  min-width: 0;
}

.ld-contract-price {
  font-size: 0.88rem;
  font-weight: 700;
  color: #191a23;
}

.ld-contract-actions {
  display: flex;
  gap: 0.4rem;
}

/* Stands in for the copy button once the signing link has expired. */
.ld-contract-expired {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  color: #b23c17;
}

.ld-ct-status {
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
}

.ld-ct-status--pending {
  background: #fdf3e2;
  color: #b7791f;
}

.ld-ct-status--signed {
  background: #e5f8ec;
  color: #1d8a4e;
}

.ld-ct-status--cancelled {
  background: #f0f1f5;
  color: #8e8f9e;
}

/* ── Contact messages ─────────────────────────────── */

.ld-msg {
  border: 1px solid #eef0f6;
  border-radius: 10px;
  padding: 0.7rem 0.9rem;
}

.ld-msg + .ld-msg {
  margin-top: 0.75rem;
}

.ld-msg-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: 0.35rem;
}

.ld-msg-reason {
  font-size: 0.78rem;
  font-weight: 700;
  color: #5a5b6a;
}

.ld-msg-date {
  font-size: 0.75rem;
  color: #8e8f9e;
}

.ld-msg-body {
  margin: 0;
  font-size: 0.85rem;
  color: #191a23;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ── Modal helpers ────────────────────────────────── */

/* Payment-form toggle (T7). */
.ld-checkbox-group {
  margin-bottom: 1rem;
}

.ld-checkbox {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
  color: #191a23;
  cursor: pointer;
}

.ld-checkbox input {
  width: 1rem;
  height: 1rem;
  cursor: pointer;
}

.ld-checkbox-group .form-label-hint {
  display: block;
  margin-top: 0.25rem;
}

/* Enrollment status "cancelled" chip (admin.css only ships active/dropped). */
.ld-page .reg-enroll-status--cancelled {
  color: #6b7280;
  background: rgba(107, 114, 128, 0.1);
  border-color: rgba(107, 114, 128, 0.3);
}

/* ── Lifecycle map ────────────────────────────────── */
/* A full-width band under the grid: the 7-stage chart is far wider than the
   left column, and giving it the whole page is what keeps it off the
   horizontal scroller on a laptop. Every .llc-* override below is prefixed
   with .ld-page - admin-lead-detail.css loads BEFORE admin-lead-lifecycle.css,
   so an unprefixed rule would lose, and the prefix also keeps the standalone
   /admin/lead-lifecycle chart untouched. */

.ld-lifecycle-card {
  margin-top: 1.25rem;
}

.ld-lifecycle-link {
  flex: 0 0 auto;
  font-size: 0.78rem;
  font-weight: 600;
  color: #5a5b6a;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  white-space: nowrap;
}

.ld-lifecycle-link:hover {
  color: #0071e3;
}

.ld-lifecycle-link i {
  font-size: 0.7rem;
}

.ld-lifecycle-note {
  display: flex;
  align-items: flex-start;
  gap: 0.4rem;
  margin: 0.75rem 0 0;
  padding: 0.5rem 0.7rem;
  border-radius: 10px;
  background: #f6f8fc;
  border: 1px solid #e3e8f2;
  font-size: 0.78rem;
  color: #5a5b6a;
}

.ld-lifecycle-note i {
  margin-top: 0.15rem;
  color: #8e8f9e;
}

/* The one note left is a warning, not a caption - it sits above the map and
   owns the gap to it. */
.ld-lifecycle-note:first-child {
  margin-top: 0;
  margin-bottom: 0.75rem;
}

.ld-lifecycle-toggle {
  margin-bottom: 0.75rem;
}

/* The pane is the page's densest block - it does not need the standard
   head-to-body gap on top of the chart's own breathing room. */
.ld-lifecycle-card .ld-card-body {
  margin-top: 0.6rem;
}

/* The current node's ring, its drop shadow and the recommended dashed outline
   all paint outside the pill, and .llc-canvas clips vertically. */
.ld-page .llc-canvas {
  padding-top: 8px;
}

/* ── Marketing & attribution ──────────────────────── */
/* Last card on the page, a sibling of the lifecycle band rather than a member
   of the left column - that is what makes it last on a phone too, where the
   grid collapses and the column order stops meaning anything. */

.ld-marketing-card {
  margin-top: 1.25rem;
}

/* ── Responsive ───────────────────────────────────── */

@media (max-width: 1024px) {
  .ld-grid {
    grid-template-columns: 1fr;
  }

  .ld-header-contact {
    margin-left: 0;
    width: 100%;
  }

  /* 16px EXACTLY, and it is not a taste decision. iOS Safari zooms the whole
     page in when a focused form control's text is under 16px, and it never
     zooms back out on blur - the panel is left scrolled sideways and the staff
     member has to pinch their way back. 15.9px still triggers it. Applied at
     the tablet breakpoint rather than at 767px because iPad Safari is the same
     engine with the same rule. */
  .ld-followup-date,
  .ld-followup-time {
    font-size: 16px;
  }
}

@media (max-width: 767px) {
  .ld-header {
    padding: 1rem;
  }

  .ld-card {
    padding: 0.9rem 1rem;
  }

  .ld-actions .btn {
    flex: 1 1 auto;
    justify-content: center;
  }

  .ld-kv-row {
    grid-template-columns: 100px 1fr;
    gap: 0.6rem;
  }

  /* A verdict can be a full sentence. On a phone let it take its own line
     under the card title instead of squeezing the title to nothing. */
  .ld-card-head--chip {
    flex-wrap: wrap;
  }

  .ld-ch-chip {
    max-width: 100%;
    font-size: 0.68rem;
  }

  .ld-enroll-date,
  .ld-journey-ts,
  .ld-wa-inbound {
    margin-left: 0;
    width: 100%;
  }
}

/* ── Hebrew RTL island (.ld-page) mirrors ──────────────
   The page root sets direction: rtl (admin.css island block); these rules
   flip the physically-positioned bits: auto-margins, the journey rail and the
   payments-table alignment.

   Two mirrors used to sit here and no longer do - the transcript rail
   (`.ld-page .ld-timeline::before`) and the note timestamp
   (`.ld-page .ld-activity-time`). The hand-rolled activity timeline they
   flipped was deleted when the Person page moved its comments onto the shared
   `LeadActivityLog` (`.lal-*`), which is RTL by default and mirrors nothing.
   Do not re-add them from memory: a mirror for markup nothing renders is the
   dead weight this block is audited for, and `.lal-*` must never be mirrored
   at all - it would double-flip. */
.ld-page .ld-header-contact {
  margin-left: 0;
  margin-right: auto;
}
.ld-page .ld-wa-inbound {
  margin-left: 0;
  margin-right: auto;
}
.ld-page .ld-attr-tag {
  margin-left: 0;
  margin-right: 0.5rem;
}
.ld-page .ld-journey::before {
  left: auto;
  right: 7px;
}
.ld-page .ld-journey-step {
  padding: 0.35rem 1.6rem 0.35rem 0;
}
.ld-page .ld-journey-step::before {
  left: auto;
  right: 3px;
}
.ld-page .ld-journey-ts {
  margin-left: 0;
  margin-right: auto;
}
.ld-page .ld-enroll-date {
  margin-left: 0;
  margin-right: auto;
}
.ld-page .ld-progress-over {
  margin-left: 0;
  margin-right: auto;
}
.ld-page .ld-pay-table th {
  text-align: right;
}
.ld-page .ld-pay-actions {
  text-align: left;
}

/* The shared <=767 rules in admin-lead-lifecycle.css stack the stages into one
   column and hide the edges - correct here too. They are just spaced for a
   page that IS the chart; bolted under an already long lead page, the stage
   gutters add a screenful of dead air. */
@media (max-width: 767px) {
  .ld-page .llc-stage + .llc-stage {
    margin-top: 1rem;
  }

  .ld-page .llc-stage + .llc-stage::before {
    margin: -0.6rem 0 0.4rem;
    font-size: 0.7rem;
  }

  .ld-page .llc-family {
    padding: 0.6rem 0.7rem;
  }

  .ld-lifecycle-toggle {
    width: 100%;
    justify-content: center;
  }
}
