/*
  EVO TrustGuard — css/page-sales-pipeline.css
  Page-scoped styles for the ADMIN-ONLY Sales Pipeline (C103).

  M8.1: the page is PERMANENTLY DARK — data-theme="dark" is pinned statically
  on <html> (no toggle on admin surfaces), so every [data-theme="dark"] rule
  below is always active. The page now renders inside the shared admin
  dark-glass shell (.ash-* in /css/page-admin.css, loaded before this file);
  the portal bottom-nav + theme toggle were removed from the markup.

  Token-driven: surfaces / borders / text / red all use the shared design
  tokens (var(--bg)/--surface/--surface-elevated/--border/--text/--text-muted/
  --red) so dark-mode parity comes for free from the [data-theme] swap in
  shared-themes.css (launch is dark-only per LOCKED C99-A; this is light-ready).

  Convention compliance (css/AGENTS.md):
    - ALL buttons are RECTANGULAR — var(--radius-md) (8px). No pill buttons.
      The full-screen Call console's Call button (.sp-console-call) is a
      rectangular red action button, NOT a circular FAB (the C103 call-FAB
      was removed in this sprint).
    - Status pills use the platform 6px rounded-rect (.sp-pill), matching
      .client-status-pill / .status-pill — NOT a full 100px pill.
    - The only 50% radius is NOT a button: the small 28px decorative
      activity-log icon-circle (.sp-le-icon), analogous to .activity-dot /
      .buyer-dot in css/page-purchased-lead.css. No button uses a
      pill/circular radius.
    - 44px min touch targets on interactive controls.

  Six-state status vocabulary (status indicators — hardcoded hues, same
  pattern as the client payment pills): new / contacted / engaged / signed_up /
  not_interested / archived.
*/

/* Status hues (status indicators, not buttons). */
:root {
  --sp-new:        #3b82f6;
  --sp-contacted:  #f59e0b;
  --sp-engaged:    #14b8a6;
  --sp-signed-up:  #10b981;
  --sp-not:        #9a9a9a;
  --sp-archived:   #6f6f6f;
  /* M8.2a temperature hues (right-edge bar): warm orange / cold blue —
     aliases of the existing page hues so the palette stays closed. */
  --sp-warm:       #f59e0b;
  --sp-cold:       #3b82f6;
}

/* ── Access gate ── */
.sp-gate {
  min-height: 60vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  color: var(--text-muted);
  font-size: var(--text-base);
}

/* ── App container — sits inside the M8.1 admin shell grid; the 96px
   bottom-nav reserve was dropped with the bottom nav itself. ── */
.sp-app {
  max-width: 760px;
  margin: 0 auto;
  width: 100%;
  padding: var(--space-5) var(--space-5) calc(var(--space-8) + env(safe-area-inset-bottom));
}

/* ── Header ── */
.sp-header {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}
.sp-header-titles { flex: 1 1 auto; min-width: 180px; }
.sp-title {
  font-family: 'DM Serif Display', serif;
  font-size: var(--text-3xl);
  color: var(--text);
  margin: 0;
}
.sp-subtitle {
  font-size: var(--text-md);
  color: var(--text-muted);
  margin: var(--space-1) 0 0;
}
.sp-header-actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}
/* M8.3 — "Start call session" (the dialer entry, now the header's primary
   action). Full-width on narrow screens so the block-starting action is the
   dominant thumb target above the filter bar. */
@media (max-width: 560px) {
  #spCallBtn { flex: 1 1 100%; }
}

/* ── Buttons (rectangular, 8px) ── */
.sp-btn {
  font: inherit;
  font-size: var(--text-md);
  font-weight: var(--weight-medium, 500);
  border-radius: var(--btn-radius);
  padding: 0 var(--space-4);
  min-height: 44px;
  cursor: pointer;
  background: var(--btn-secondary-bg);
  border: var(--btn-secondary-border);
  box-shadow: var(--btn-secondary-shadow);
  color: var(--btn-secondary-text);
  transition: filter 0.15s ease, transform 0.18s var(--ease-spring);
  white-space: nowrap;
}
.sp-btn:hover { filter: brightness(1.06); }
.sp-btn:active { transform: scale(var(--press-scale)); }
.sp-btn-primary {
  background: var(--btn-primary-bg);
  border: var(--btn-primary-border);
  box-shadow: var(--btn-primary-shadow);
  color: var(--btn-primary-text);
  border-radius: var(--btn-radius);
}
.sp-btn-primary:hover { filter: brightness(1.06); }
/* Destructive action (long-press delete confirm). Contained tinted-red per the
   Glass button system (C97-A) — semantically the irreversible action. */
.sp-btn-danger {
  background: var(--btn-destructive-bg);
  border: var(--btn-destructive-border);
  color: var(--btn-destructive-text);
  border-radius: var(--btn-radius);
}
.sp-btn-danger:hover { filter: brightness(1.1); }
.sp-btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; }

/* ── Needs you today ── */
.sp-today {
  background: var(--surface);
  border: 1px solid var(--red);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-4-5);
  margin-bottom: var(--space-5);
}
.sp-today-head {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold, 600);
  color: var(--text);
  margin-bottom: var(--space-1);
}
.sp-today-count {
  background: var(--red);
  color: var(--white);
  font-size: var(--text-sm);
  font-weight: 700;
  border-radius: var(--radius-sm);
  padding: 1px var(--space-2);
}
.sp-today-desc {
  font-size: var(--text-md);
  color: var(--text-muted);
  margin-bottom: var(--space-3);
}
.sp-today-chips { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.sp-chip {
  background: var(--surface-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  min-height: 44px;
  font-size: var(--text-md);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  transition: border-color 0.15s;
  color: var(--text);
}
.sp-chip:hover { border-color: var(--red); }
.sp-chip-co { font-weight: var(--weight-semibold, 600); }
.sp-chip-due { font-size: var(--text-xs); font-weight: 700; color: var(--red); }
.sp-chip-due.is-over {
  color: var(--white);
  background: var(--red);
  padding: 1px var(--space-1-5);
  border-radius: var(--radius-sm);
}

/* ── Status filter ──
   The scrollable pill/tab bar (.sp-tabs / .sp-tab) was REMOVED in C103 — it
   collided with the document-level swipe-back gesture. The filter is now the
   shared C97-B <select> + glass dropdown, styled entirely by
   /css/_lib/list-header.css (.list-filterbar / .list-filter-select) +
   /css/_lib/dropdown.css. No page-scoped filter styling lives here by design.
   A small bottom margin keeps the cards clear of the filter row (list-header's
   filterbar carries its own internal spacing). */
.list-filterbar { margin-bottom: var(--space-3-5); }

/* ── Cards ── */
.sp-cards { display: flex; flex-direction: column; gap: var(--space-2-5); }
.sp-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--border);
  /* M8.2a temperature bar — the EXACT symmetric mirror of the status left
     bar: same 4px width, same height (full edge), same corners (the shared
     border-radius). Hue set by .t-warm / .t-cold below. */
  border-right: 4px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-3-5) var(--space-4);
  cursor: pointer;
  transition: background 0.15s, transform 0.15s;
  position: relative;
}
.sp-card:hover { background: var(--surface-elevated); }
.sp-card-row1 { display: flex; align-items: center; gap: var(--space-2-5); }
.sp-card-co { font-weight: var(--weight-semibold, 600); font-size: var(--text-lg); color: var(--text); }
.sp-card-star {
  margin-left: auto;
  color: var(--text-muted);
  font-size: var(--text-xl);
  background: none;
  border: none;
  cursor: pointer;
  line-height: 1;
  padding: var(--space-1);
  min-width: 44px;
  min-height: 44px;
}
.sp-card-star.is-on { color: #f5b301; }
.sp-card-meta { color: var(--text-muted); font-size: var(--text-md); margin-top: var(--space-0-5); }
.sp-card-row3 {
  display: flex;
  align-items: center;
  gap: var(--space-2-5);
  margin-top: var(--space-2);
  flex-wrap: wrap;
}
.sp-card-channel {
  font-size: var(--text-xs);
  color: var(--text-muted);
  background: var(--surface-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-0-5) var(--space-2);
}
.sp-card-fu { font-size: var(--text-sm); color: var(--text-muted); margin-left: auto; font-weight: 700; }
.sp-card-fu.is-over { color: var(--red); }
.sp-card-fu.is-today { color: var(--sp-contacted); }
.sp-card-act {
  color: var(--text-muted);
  font-size: var(--text-sm);
  margin-top: var(--space-2);
  border-top: 1px solid var(--border);
  padding-top: var(--space-2);
}

/* ── Status pill (6px rounded-rect, platform convention) ── */
.sp-pill {
  font-size: var(--text-xs);
  font-weight: 700;
  padding: var(--space-0-5) var(--space-2);
  border-radius: 6px;
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide, 0.04em);
}
.sp-pill.s-new           { background: rgba(59,130,246,0.16);  color: var(--sp-new); }
.sp-pill.s-contacted     { background: rgba(245,158,11,0.16);  color: var(--sp-contacted); }
.sp-pill.s-engaged       { background: rgba(20,184,166,0.16);  color: var(--sp-engaged); }
.sp-pill.s-signed_up     { background: rgba(16,185,129,0.18);  color: var(--sp-signed-up); }
.sp-pill.s-not_interested{ background: rgba(154,154,154,0.18); color: var(--sp-not); }
.sp-pill.s-archived      { background: rgba(111,111,111,0.18); color: var(--sp-archived); }

/* Left-border accent variants */
.sp-card.s-new           { border-left-color: var(--sp-new); }
.sp-card.s-contacted     { border-left-color: var(--sp-contacted); }
.sp-card.s-engaged       { border-left-color: var(--sp-engaged); }
.sp-card.s-signed_up     { border-left-color: var(--sp-signed-up); }
.sp-card.s-not_interested{ border-left-color: var(--sp-not); }
.sp-card.s-archived      { border-left-color: var(--sp-archived); }

/* Right-border temperature variants (M8.2a) — orange warm, blue cold. */
.sp-card.t-warm          { border-right-color: var(--sp-warm); }
.sp-card.t-cold          { border-right-color: var(--sp-cold); }

/* Contact-method presence icons (M8.2a) — the outreach .om-ico convention:
   dimmed by default, lit (.y) when the method exists on the lead. */
.sp-card-ico {
  color: var(--text-disabled);
  letter-spacing: 2px;
  white-space: nowrap;
  font-size: var(--text-sm);
}
/* Absent methods dim via opacity too — the 🌐 glyph is a color emoji that
   ignores CSS color (keeps present=lit / absent=dimmed honest). */
.sp-card-ico span:not(.y) { opacity: 0.3; }
.sp-card-ico .y { color: var(--text); }

.sp-empty { text-align: center; color: var(--text-muted); padding: var(--space-12) 0; font-size: var(--text-base); }

/* ── Background scroll-lock (C103 iOS fix) ──
   Applied to <body> by syncBodyScrollLock() while ANY full-screen overlay is
   open (drawer / call console / bottom-sheet / delete confirm). position:fixed
   + a saved scrollY (set inline as a negative `top` by the JS) is the
   iOS-robust technique — overflow:hidden alone leaks background scroll with the
   keyboard up. The console sizes itself to the visual viewport via inline
   styles in JS, so no CSS height hook is needed on .sp-console. */
.sp-scroll-locked {
  position: fixed;
  left: 0;
  width: 100%;
  overflow: hidden;
}

/* ── Drawer ── */
.sp-scrim {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.6);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s;
  z-index: 200;
}
.sp-scrim.is-open { opacity: 1; pointer-events: auto; }
.sp-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(480px, 100%);
  background: var(--bg);
  border-left: 1px solid var(--border);
  z-index: 210;
  transform: translateX(100%);
  transition: transform 0.28s ease;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.sp-drawer.is-open { transform: translateX(0); }
.sp-d-head {
  position: sticky;
  top: 0;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  /* Drawer is position:fixed; top:0 over a viewport-fit=cover viewport, so
     its header sits under the iOS status bar. Add the top inset to the
     existing space-4 pad (env → 0 on non-notch devices, so unaffected).
     Mirrors the portal-chrome.css .dash-nav calc(... + env(...)) idiom. */
  padding: calc(var(--space-4) + env(safe-area-inset-top, 0px)) var(--space-5) var(--space-4);
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  z-index: 2;
}
.sp-d-co { font-size: var(--text-xl); font-weight: 700; line-height: 1.2; color: var(--text); }
.sp-d-owner { color: var(--text-muted); font-size: var(--text-md); margin-top: var(--space-0-5); }
.sp-d-star {
  background: none; border: none; color: var(--text-muted);
  font-size: var(--text-2xl); cursor: pointer; line-height: 1;
  min-width: 44px; min-height: 44px;
}
.sp-d-star.is-on { color: #f5b301; }
.sp-d-x {
  margin-left: auto; background: none; border: none; color: var(--text-muted);
  font-size: var(--text-2xl); cursor: pointer; line-height: 1;
  min-width: 44px; min-height: 44px;
}
.sp-d-x:hover { color: var(--text); }
.sp-d-body { padding: var(--space-4-5) var(--space-5) calc(96px + env(safe-area-inset-bottom)); }

.sp-d-statusrow { display: flex; align-items: center; gap: var(--space-2-5); margin-bottom: var(--space-4-5); flex-wrap: wrap; }
.sp-d-statusrow label { font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; }

.sp-select, select.sp-d-status {
  font: inherit;
  font-size: var(--text-md);
  background: var(--surface-elevated);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-2-5);
  min-height: 44px;
  cursor: pointer;
}
/* M8.4 — the drawer Stage select is a C97-B glass select: the native control
   is visually hidden and the Tier-2 trigger fronts it. Size the trigger like
   the old native select inside the flex status row (the component default is
   width:100%, which would blow the row out). */
.sp-d-statusrow .tg-dd-select-trigger { width: auto; flex: 0 1 auto; min-width: 150px; }

.sp-nextbox {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--red);
  border-radius: var(--radius-md);
  padding: var(--space-3-5);
  margin-bottom: var(--space-4-5);
}
.sp-nextbox-lab { font-size: var(--text-xs); color: var(--red); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; margin-bottom: var(--space-1-5); }
.sp-nextbox-txt { font-size: var(--text-lg); color: var(--text); }
.sp-nextbox-fu { font-size: var(--text-md); color: var(--text-muted); margin-top: var(--space-2); }
.sp-nextbox-fu .is-over { color: var(--red); font-weight: 700; }
.sp-nextbox-fu .is-today { color: var(--sp-contacted); font-weight: 700; }

.sp-sect { margin-bottom: var(--space-5-5); }
.sp-sect h4 { font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.1em; font-weight: 700; margin-bottom: var(--space-2-5); }
.sp-info {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.sp-ir { display: flex; padding: var(--space-2-5) var(--space-3-5); border-bottom: 1px solid var(--border); font-size: var(--text-base); gap: var(--space-3); }
.sp-ir:last-child { border-bottom: none; }
.sp-ir-k { color: var(--text-muted); width: 92px; flex: none; font-size: var(--text-md); }
.sp-ir-v { color: var(--text); word-break: break-word; }
.sp-ir-v a { color: var(--sp-new); text-decoration: none; }
.sp-ir-v a:hover { text-decoration: underline; }

/* Reach-out actions */
.sp-reach { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.sp-act-btn {
  font: inherit;
  font-size: var(--text-md);
  font-weight: var(--weight-medium, 500);
  border-radius: var(--btn-radius);
  padding: 0 var(--space-3-5);
  min-height: 44px;
  cursor: pointer;
  background: var(--btn-secondary-bg);
  border: var(--btn-secondary-border);
  box-shadow: var(--btn-secondary-shadow);
  color: var(--btn-secondary-text);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1-5);
  transition: filter 0.15s ease, transform 0.18s var(--ease-spring);
}
.sp-act-btn:hover { filter: brightness(1.06); }
.sp-act-btn:active { transform: scale(var(--press-scale)); }
.sp-act-btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; }
.sp-act-btn.is-call {
  background: var(--btn-primary-bg);
  border: var(--btn-primary-border);
  box-shadow: var(--btn-primary-shadow);
  color: var(--btn-primary-text);
  border-radius: var(--btn-radius);
}
.sp-act-btn.is-call:hover { filter: brightness(1.06); }
.sp-reach-note { font-size: var(--text-sm); color: var(--text-muted); margin-top: var(--space-2); }

/* Activity log */
.sp-log { display: flex; flex-direction: column; }
.sp-le { display: flex; gap: var(--space-3); padding: var(--space-2-5) 0; border-bottom: 1px solid var(--border); }
.sp-le:last-child { border-bottom: none; }
.sp-le-icon {
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  background: var(--surface-elevated); border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center; font-size: var(--text-sm);
}
.sp-le-txt { font-size: var(--text-base); color: var(--text); white-space: pre-wrap; }
.sp-le-when { font-size: var(--text-xs); color: var(--text-muted); margin-top: var(--space-0-5); }
.sp-addnote { margin-top: var(--space-3); }
.sp-addnote textarea {
  width: 100%;
  background: var(--surface-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text);
  font: inherit;
  font-size: var(--text-base);
  padding: var(--space-2-5);
  resize: vertical;
  min-height: 60px;
}
.sp-addnote textarea:focus { outline: none; border-color: var(--red); }
.sp-addnote-row { display: flex; justify-content: flex-end; margin-top: var(--space-2); }

/* ── Call console (full-screen overlay, topmost — z-index above the drawer
   210 + sheets 310 so it slides over an open drawer). Flex column: a header
   that clears the iOS notch, a scrollable script region (flex:1), the Call
   button, and a sticky note bar pinned to the bottom. Token-driven →
   dark-mode parity is free. All rectangular (no FAB / pill). ── */
.sp-console {
  position: fixed;
  inset: 0;
  background: var(--bg);
  z-index: 400;
  display: flex;
  flex-direction: column;
  transform: translateY(100%);
  transition: transform 0.28s ease;
}
.sp-console.is-open { transform: translateY(0); }
.sp-console-head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  /* Full-screen overlay over a viewport-fit=cover viewport — the header sits
     under the iOS status bar. Add the top inset to the base pad (env → 0 on
     non-notch devices). Same idiom as .sp-d-head + portal-chrome .dash-nav. */
  padding: calc(var(--space-4) + env(safe-area-inset-top, 0px)) var(--space-5) var(--space-4);
  flex: none;
}
.sp-console-titles { flex: 1 1 auto; min-width: 0; }
.sp-console-co { font-size: var(--text-xl); font-weight: 700; line-height: 1.2; color: var(--text); word-break: break-word; }
.sp-console-sub { color: var(--text-muted); font-size: var(--text-md); margin-top: var(--space-0-5); }
.sp-console-x {
  margin-left: auto; background: none; border: none; color: var(--text-muted);
  font-size: var(--text-2xl); cursor: pointer; line-height: 1;
  min-width: 44px; min-height: 44px;
}
.sp-console-x:hover { color: var(--text); }
.sp-console-script {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: var(--space-5);
  font-size: var(--text-lg);
  line-height: 1.6;
  color: var(--text);
  white-space: pre-wrap;
  word-break: break-word;
}
.sp-console-script.is-empty { color: var(--text-muted); font-style: italic; }
.sp-console-call {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin: var(--space-4) var(--space-5);
  min-height: 56px;
  border-radius: var(--btn-radius);
  background: var(--btn-primary-bg);
  border: var(--btn-primary-border);
  box-shadow: var(--btn-primary-shadow);
  color: var(--btn-primary-text);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold, 600);
  text-decoration: none;
  transition: filter 0.15s ease, transform 0.18s var(--ease-spring);
}
.sp-console-call:hover { filter: brightness(1.06); }
.sp-console-call:active { transform: scale(var(--press-scale)); }
.sp-console-call:disabled { opacity: 0.55; cursor: not-allowed; transform: none; }
.sp-console-call svg { width: 22px; height: 22px; stroke: currentColor; stroke-width: 2; fill: none; }
.sp-console-notebar {
  flex: none;
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5) calc(var(--space-4) + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
  background: var(--surface);
}
.sp-console-note {
  flex: 1 1 auto;
  background: var(--surface-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text);
  font: inherit;
  font-size: var(--text-base);
  padding: var(--space-2-5);
  resize: none;
  min-height: 48px;
  max-height: 120px;
}
.sp-console-note:focus { outline: none; border-color: var(--red); }
.sp-console-notebar .sp-btn { flex: none; align-self: stretch; }

/* ── Bottom-sheet modals (Add/Edit lead, Import, Settings) ── */
.sp-modal-scrim {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.6);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s;
  z-index: 300;
}
.sp-modal-scrim.is-open { opacity: 1; pointer-events: auto; }
.sp-sheet {
  position: fixed;
  left: 50%;
  bottom: 0;
  transform: translate(-50%, 100%);
  width: min(560px, 100%);
  max-height: 92vh;
  background: var(--surface);
  border: 1px solid var(--border);
  border-bottom: none;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  z-index: 310;
  display: flex;
  flex-direction: column;
  transition: transform 0.28s ease;
}
.sp-sheet.is-open { transform: translate(-50%, 0); }
.sp-sheet-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
}
.sp-sheet-title { font-size: var(--text-xl); font-weight: 700; color: var(--text); margin: 0; }
.sp-sheet-x {
  margin-left: auto; background: none; border: none; color: var(--text-muted);
  font-size: var(--text-2xl); cursor: pointer; line-height: 1;
  min-width: 44px; min-height: 44px;
}
.sp-sheet-x:hover { color: var(--text); }
.sp-sheet-body { padding: var(--space-4) var(--space-5); overflow-y: auto; }
.sp-sheet-foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-3-5) var(--space-5) calc(var(--space-4) + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
}

.sp-field { display: flex; flex-direction: column; gap: var(--space-1-5); margin-bottom: var(--space-3-5); }
.sp-field-label { font-size: var(--text-sm); color: var(--text-muted); font-weight: var(--weight-medium, 500); }
.sp-field-row { display: flex; gap: var(--space-3); }
/* min-width:0 lets the two-up flex children shrink below the <input>'s
   intrinsic min-width (~20ch, strictly enforced by iOS Safari). Without it
   the children refuse to shrink, two side-by-side inputs overflow the sheet
   → horizontal scroll → the edit-sheet slide (M8.4.1 BUG 1). width:100% on
   the input below cannot rescue it because the flex PARENT won't shrink.
   iOS-visible / Chromium-invisible — same footgun as .list-search-input
   (list-header.css). Belt-and-braces: min-width:0 on the inputs too. */
.sp-field-row .sp-field { flex: 1; min-width: 0; }
.sp-field input,
.sp-field select,
.sp-field textarea {
  font: inherit;
  font-size: var(--text-input);
  background: var(--surface-elevated);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-2-5) var(--space-3);
  min-height: 44px;
  width: 100%;
  min-width: 0;
}
.sp-field textarea { resize: vertical; }
.sp-field input:focus,
.sp-field select:focus,
.sp-field textarea:focus { outline: none; border-color: var(--red); }

.sp-help { font-size: var(--text-sm); color: var(--text-muted); margin: 0 0 var(--space-3); line-height: 1.5; }
.sp-help code, .sp-help b { color: var(--text); }
.sp-import-textarea {
  width: 100%;
  font-family: var(--font-mono, 'Courier New', monospace);
  font-size: var(--text-md);
  background: var(--surface-elevated);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-2-5);
  resize: vertical;
}
.sp-import-textarea:focus { outline: none; border-color: var(--red); }
.sp-import-summary {
  margin-top: var(--space-3);
  font-size: var(--text-md);
  color: var(--text);
  background: var(--surface-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
}

/* ── Long-press delete confirm (centered modal, rectangular, token-driven) ──
   Distinct from the bottom-sheets — this is a small centered dialog. z-index
   420 sits above the call console (400) so a confirm raised over an open
   console (edge case) is still reachable; in practice long-press fires from a
   card with nothing else open. Token-driven → dark-mode parity is free. */
.sp-confirm-scrim {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.6);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s;
  z-index: 420;
}
.sp-confirm-scrim.is-open { opacity: 1; pointer-events: auto; }
.sp-confirm {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -48%);
  width: min(360px, calc(100% - 2 * var(--space-5)));
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  z-index: 421;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s, transform 0.2s;
}
.sp-confirm.is-open { opacity: 1; pointer-events: auto; transform: translate(-50%, -50%); }
.sp-confirm-title {
  font-family: 'DM Serif Display', serif;
  font-size: var(--text-xl);
  color: var(--text);
  margin: 0 0 var(--space-2);
}
.sp-confirm-text {
  font-size: var(--text-md);
  color: var(--text-muted);
  margin: 0 0 var(--space-4-5);
  line-height: 1.5;
}
.sp-confirm-btns { display: flex; flex-direction: column; gap: var(--space-2); }
.sp-confirm-btns .sp-btn { width: 100%; justify-content: center; }

@media (max-width: 560px) {
  .sp-app { padding-left: var(--space-3-5); padding-right: var(--space-3-5); }
  .sp-field-row { flex-direction: column; gap: 0; }
}

/* ════════════════════════════════════════════════════════════════════════
   TrustGuard Glass — per-page application (C103, DARK-ONLY per LOCKED C99-A)
   ════════════════════════════════════════════════════════════════════════
   Additive elevation/glass pass following the Phase-3G pattern (3G.2 overlay
   / 3G.3 Tier-1 raise / 3G.4 Tier-2 wells). CSS-only, no markup change. These
   dark-keyed rules sit at the END of the file so they win the cascade over the
   token-driven base rules above by source order at equal-or-higher specificity
   (mirrors the 3G.3.b / 3G.4 additive precedent). Light mode is left 100%
   untouched (reworked by Glass Phase 4). Every value resolves from the 3G.1
   tokens (/css/tokens.css + /shared-themes.css) — no new hexes, no token
   redefinition. MEANING-COLORS PRESERVED: status left-borders + pills, the red
   "Needs you today" treatment, and all red action accents are untouched or
   re-pinned. Safe-area-inset padding (sticky headers + note bar + sheet foot)
   is in the base rules above and is NOT edited here, so the insets hold.

   Surface → tier map:
     TIER 1 raised   → .sp-card (status .s-* left-border re-pinned) · .sp-today
                       band · .sp-chip
     TIER 3 glass    → .sp-drawer + .sp-d-head · .sp-console + .sp-console-head
                       + .sp-console-notebar · .sp-sheet (×4) · .sp-confirm
     TIER 2 recessed → .sp-field input/textarea (add/edit-lead inputs + settings
                       textareas) · .sp-console-note · .sp-addnote textarea ·
                       .sp-import-textarea
     UNTOUCHED       → #spFilter .list-filter-select (already Glass via
                       /css/_lib/dropdown.css) · native <select> status/Stage/
                       Channel (C97-B-owned, EXCLUDED from Tier-2 per 3G.4) */

/* ── TIER 1 — raised: lead cards. Mirrors the 3G.3.b .contract-card recipe:
   surface gradient + hairline top/right/bottom edge + ::before top-edge
   highlight + 18px radius + float shadow + spring :active (cards open the
   drawer). The 4px status border-LEFT is RE-PINNED below so the meaning accent
   survives the raise (the shared bulk override would otherwise clobber it). ── */
[data-theme="dark"] .sp-card {
  position: relative;
  overflow: hidden;
  background: var(--tier1-bg);
  border-top-color: var(--hairline);
  border-right-color: var(--hairline);
  border-bottom-color: var(--hairline);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-float);
  color: var(--text);
  transition: transform 0.18s var(--ease-spring), box-shadow 0.15s ease;
}
[data-theme="dark"] .sp-card::before {
  content: ""; position: absolute; top: 0; left: 14px; right: 14px;
  height: 1px; background: linear-gradient(90deg, transparent, var(--edge-highlight), transparent);
  pointer-events: none;
}
/* Re-pin the status-driven left-border accent (meaning color preserved). */
[data-theme="dark"] .sp-card.s-new            { border-left-color: var(--sp-new); }
[data-theme="dark"] .sp-card.s-contacted      { border-left-color: var(--sp-contacted); }
[data-theme="dark"] .sp-card.s-engaged        { border-left-color: var(--sp-engaged); }
[data-theme="dark"] .sp-card.s-signed_up      { border-left-color: var(--sp-signed-up); }
[data-theme="dark"] .sp-card.s-not_interested { border-left-color: var(--sp-not); }
[data-theme="dark"] .sp-card.s-archived       { border-left-color: var(--sp-archived); }
[data-theme="dark"] .sp-card:active {
  transform: scale(var(--press-scale));
  background: var(--tier1-bg);
}
/* Keep the raised look stable on desktop hover (the base flat surface-elevated
   hover reads wrong on the gradient). */
@media (hover: hover) {
  [data-theme="dark"] .sp-card:hover {
    background: var(--tier1-bg);
    border-top-color: var(--hairline);
    border-right-color: var(--hairline);
    border-bottom-color: var(--hairline);
    box-shadow: var(--shadow-float);
  }
}

/* ── TIER 1 — "Needs you today" band. Full recipe, but the red border is the
   meaning treatment so it is PRESERVED (not flipped to --hairline). Not
   pressable → no spring. ── */
[data-theme="dark"] .sp-today {
  position: relative;
  overflow: hidden;
  background: var(--tier1-bg);
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-float);
}
[data-theme="dark"] .sp-today::before {
  content: ""; position: absolute; top: 0; left: 14px; right: 14px;
  height: 1px; background: linear-gradient(90deg, transparent, var(--edge-highlight), transparent);
  pointer-events: none;
}

/* ── TIER 1 — "Needs you today" chips. Measured raise (gradient + hairline +
   float + spring); KEEP --radius-md (no-pill guardrail) and OMIT ::before (the
   14px-inset highlight collapses on a ~44px chip). Red :hover preserved. ── */
[data-theme="dark"] .sp-chip {
  background: var(--tier1-bg);
  border-color: var(--hairline);
  box-shadow: var(--shadow-float);
  color: var(--text);
  transition: transform 0.18s var(--ease-spring), border-color 0.15s ease;
}
[data-theme="dark"] .sp-chip:active { transform: scale(var(--press-scale)); }
@media (hover: hover) {
  [data-theme="dark"] .sp-chip:hover { border-color: var(--red); }
}

/* ── TIER 3 — glass overlays (panels). Mirrors the 3G.2 .sheet / .lp-modal
   recipe: translucent 5-layer glass (tint + BOTH backdrop-filter prefixes +
   glass-edge + glass-shadow + inset top-edge highlight). These show the
   admin's own (non-masked) data, so translucency is fine; the @supports block
   below keeps AA legibility on non-supporting browsers. ── */
[data-theme="dark"] .sp-drawer,
[data-theme="dark"] .sp-console,
[data-theme="dark"] .sp-sheet,
[data-theme="dark"] .sp-confirm {
  background: var(--tier3-tint);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border: 1px solid var(--glass-edge);
  box-shadow: var(--glass-shadow), inset 0 1px 0 var(--edge-highlight);
  color: var(--text);
}
/* Preserve the bottom-sheet's seamless bottom edge (base sets border-bottom:none). */
[data-theme="dark"] .sp-sheet { border-bottom: none; }

/* Glass sub-bars inside the drawer/console panels — the sticky header(s) +
   note bar carry their own opaque background in the base rules, so convert
   them to glass (tint + backdrop-filter + lit top edge) and KEEP their single
   divider border rather than a 4-side box border on a full-width bar. ── */
[data-theme="dark"] .sp-d-head,
[data-theme="dark"] .sp-console-head {
  background: var(--tier3-tint);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border-bottom-color: var(--glass-edge);
  box-shadow: inset 0 1px 0 var(--edge-highlight);
}
[data-theme="dark"] .sp-console-notebar {
  background: var(--tier3-tint);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border-top-color: var(--glass-edge);
  box-shadow: inset 0 1px 0 var(--edge-highlight);
}

/* Opaque-tint fallback where backdrop-filter is unsupported (covers the
   WebKit-prefix-only case too) — mirrors the components.css / shared-themes
   @supports blocks. Reads nearly identical to the frosted panel. ── */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  [data-theme="dark"] .sp-drawer,
  [data-theme="dark"] .sp-console,
  [data-theme="dark"] .sp-sheet,
  [data-theme="dark"] .sp-confirm,
  [data-theme="dark"] .sp-d-head,
  [data-theme="dark"] .sp-console-head,
  [data-theme="dark"] .sp-console-notebar {
    background: var(--tier3-tint-opaque);
  }
}

/* ── TIER 2 — recessed wells: text inputs + textareas. Mirrors the 3G.4 recipe
   (--tier2-bg inverted gradient + --tier2-inset inner shadow + --hairline
   edge). Native <select> is EXCLUDED (C97-B owns the glass select component) —
   the drawer status + Stage/Channel selects keep their flat dark surface. ── */
[data-theme="dark"] .sp-field input,
[data-theme="dark"] .sp-field textarea,
[data-theme="dark"] .sp-addnote textarea,
[data-theme="dark"] .sp-console-note,
[data-theme="dark"] .sp-import-textarea {
  background: var(--tier2-bg);
  border: 1px solid var(--hairline);
  box-shadow: var(--tier2-inset);
  color: var(--text);
}
/* Re-assert the red :focus accent (meaning) over the Tier-2 well border — the
   base :focus rules are equal-specificity + earlier in this file, so they would
   otherwise lose to the wells above. ── */
[data-theme="dark"] .sp-field input:focus,
[data-theme="dark"] .sp-field textarea:focus,
[data-theme="dark"] .sp-addnote textarea:focus,
[data-theme="dark"] .sp-console-note:focus,
[data-theme="dark"] .sp-import-textarea:focus {
  border-color: var(--red);
}

/* ── M8.2a — re-pin the temperature right-border (meaning color) over the
   dark Glass card recipe. The Tier-1 raise + its hover rule flip
   border-right-color to --hairline; these LAST-in-source rules win back the
   warm/cold hue at equal-or-higher specificity, exactly like the status
   left-border re-pins above. ── */
[data-theme="dark"] .sp-card.t-warm { border-right-color: var(--sp-warm); }
[data-theme="dark"] .sp-card.t-cold { border-right-color: var(--sp-cold); }
@media (hover: hover) {
  [data-theme="dark"] .sp-card.t-warm:hover { border-right-color: var(--sp-warm); }
  [data-theme="dark"] .sp-card.t-cold:hover { border-right-color: var(--sp-cold); }
}
