/* Design tokens consumed by the explicit component overrides below — not a full retheme, since Bootstrap 5.1 hardcodes hex/px rather than var(). */
:root {
  --radius-sm: 0.5rem;
  --radius-md: 0.75rem;
  --radius-lg: 1rem;
  --radius-pill: 999px;

  --shadow-1: 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.10);
  --shadow-2: 0 2px 4px rgba(16, 24, 40, 0.06), 0 6px 16px rgba(16, 24, 40, 0.12);
  --shadow-3: 0 12px 32px rgba(16, 24, 40, 0.18);

  --border-subtle: #e2e5ea;
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  
  --safe-top: max(env(safe-area-inset-top), 12px);
  --safe-bottom: env(safe-area-inset-bottom);

  /* Mobile clearance above .app-bottom-nav (72px tall) + the home-indicator inset;
     shared by every fixed bottom bar (.reserve-bar, .route-nav-bar, .pd-action-bar). */
  --bottom-clearance: calc(72px + var(--safe-bottom));
}

/* Design tokens for the Property Details / Route redesign (Claude Design comp
   "CRM Door Knocking App Review"). Scoped to .pd-shell rather than :root: names are
   kept verbatim from the comp so its markup/CSS can be copy-pasted here again later,
   but generic names like --text/--bg/--card would otherwise leak into the global
   cascade. Applied on the Details/Route page wrappers only — --bs-primary, the app
   chrome (topbar/sidebar/bottom-nav) and body { font-family } are untouched by
   design; adopting this system app-wide is a separate, later decision. */
.pd-shell {
  --bg: oklch(97% 0.004 265);
  --card: #ffffff;
  --border: oklch(91% 0.006 265);
  --text: oklch(23% 0.02 265);
  --muted: oklch(52% 0.015 265);
  --faint: oklch(68% 0.012 265);
  --accent: oklch(56% 0.19 265);
  --accent-dark: oklch(47% 0.18 265);
  --accent-tint: oklch(95% 0.025 265);
  --accent-tint-text: oklch(45% 0.16 265);
  --chrome: oklch(24% 0.03 265);
  --chrome-muted: oklch(62% 0.02 265);
  --chrome-active: oklch(78% 0.11 265);
  --success: oklch(55% 0.13 150);
  --success-tint: oklch(95% 0.03 150);
  --warning: oklch(50% 0.15 70);
  --warning-tint: oklch(96% 0.05 80);
  --danger: oklch(55% 0.19 25);
  --danger-tint: oklch(95% 0.035 25);
  --neutral-bg: oklch(94% 0.007 265);
  --neutral-text: oklch(42% 0.012 265);
  --font-head: 'Outfit', sans-serif;
  --font-body: 'Source Sans 3', sans-serif;
}

html {
  font-size: 15px;
}

@media (min-width: 768px) {
  html {
    font-size: 16px;
  }
}

/* Height set 3x on html/body — 100% fallback, 100dvh modern, var(--vh100) JS override from _Layout.cshtml — each overrides the last only where supported, so keep all three. */
html {
  position: relative;
  height: 100%;
  height: 100dvh;
  height: var(--vh100, 100dvh);
}

body {
  display: flex;
  flex-direction: column;
  height: 100%;
  height: 100dvh;
  height: var(--vh100, 100dvh);
  overflow: hidden;
  background-color: #f4f5f7;
  /* Containing block for .app-bottom-nav's position:absolute (see that rule for why not fixed). */
  position: relative;
}

.app-scroll {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  /* .app-topbar used to carry this (it's now commented out in _Layout.cshtml, see the
     header-removal note there) — content is the first thing under the status bar/notch
     now, so the safe-area clearance moved here instead of disappearing with it. */
  padding-top: var(--safe-top);
}

/* Sticky footer: app-main fills header-to-scroll-bottom even on short pages, so an empty My List doesn't show a gap above the fixed bottom nav. */
.app-main {
  flex: 1 0 auto;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.btn-info {
  color: white;
}

.badge {
  border-radius: var(--radius-pill);
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: 0.4em 0.75em;
}

/* Bootstrap 5.1 lacks .text-bg-* (added in 5.1.3); solid colors, not tinted, since this app is read outdoors and pastel badges wash out in direct sun. */
.text-bg-primary   { color: #fff; background-color: var(--bs-primary); }
.text-bg-secondary { color: #fff; background-color: #6c757d; }
.text-bg-success   { color: #fff; background-color: #198754; }
.text-bg-danger    { color: #fff; background-color: #dc3545; }
.text-bg-dark      { color: #fff; background-color: #212529; }
.text-bg-warning   { color: #423400; background-color: #ffc107; }
.text-bg-info      { color: #04414d; background-color: #0dcaf0; }
.text-bg-light     { color: #495057; background-color: #eef0f3; border: 1px solid var(--border-subtle); }

/* --- App chrome --- */

.app-topbar {
  background-color: #1a1d29;
  padding-top: var(--safe-top);
}

/* Hamburger menu: match app chrome, keep items comfortably tappable (44px) so Leaderboard/Sign out can't be fat-fingered. */
.app-topbar .dropdown-menu {
  background-color: #1a1d29;
  min-width: 14rem;
  padding: 0.5rem 0;
}

.app-topbar .dropdown-menu .dropdown-item,
.app-topbar .dropdown-menu .dropdown-item-text {
  padding: 0.75rem 1.25rem;
}
/* Leave room for the fixed bottom nav on phones (plus iPhone home indicator). */
@media (max-width: 767.98px) {
  .app-main {
    padding-bottom: var(--bottom-clearance);
  }
}

/* position:absolute, not fixed — on-device, this WKWebView's fixed containing block falls short of the true screen bottom by ~the top safe-area inset; anchoring to body instead reaches it, since body is sized off --vh100 (screen.height in this scenario, see _Layout.cshtml) and never scrolls itself (.app-scroll does, as a sibling of this nav, not a parent). */
.app-bottom-nav {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1030;
  display: flex;
  background-color: #1a1d29;
  padding-bottom: var(--safe-bottom);
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.25);
}

.app-bottom-nav-item {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 10px 4px 8px;
  min-height: 56px;
  color: #9aa0b5;
  text-decoration: none;
  font-size: 0.7rem;
}

.app-bottom-nav-item:hover,
.app-bottom-nav-item:focus {
  color: #ffffff;
}

.app-bottom-nav-item.active {
  color: #4da3ff;
  font-weight: 600;
}

/* .app-bottom-nav-item is shared by <a> tabs and the "More" trigger, which has
   to be a <button> since it opens a sheet instead of navigating. */
button.app-bottom-nav-item {
  background: transparent;
  border: 0;
  font-family: inherit;
}

/* Desktop-only left sidebar, replacing the top navbar at md+ (mobile keeps the top bar + bottom nav above, untouched). */
.app-sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 1030;
  width: 220px;
  background-color: #1a1d29;
  padding: 1.25rem 0 1rem;
  overflow-y: auto;
}

.app-sidebar-brand {
  display: block;
  padding: 0 1.25rem 1.25rem;
  color: #ffffff;
  font-weight: 600;
  font-size: 1.15rem;
  text-decoration: none;
}

.app-sidebar-nav {
  display: flex;
  flex-direction: column;
}

.app-sidebar-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 1.25rem;
  border-left: 3px solid transparent;
  color: #9aa0b5;
  text-decoration: none;
  font-size: 0.9rem;
}

.app-sidebar-item:hover,
.app-sidebar-item:focus {
  color: #ffffff;
}

.app-sidebar-item.active {
  color: #4da3ff;
  font-weight: 600;
  border-left-color: #4da3ff;
  background-color: rgba(77, 163, 255, 0.08);
}

.app-sidebar-footer {
  padding: 1rem 1.25rem 0;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.app-sidebar-user-link {
  display: block;
  color: #9aa0b5;
  font-size: 0.85rem;
  text-decoration: none;
}

.app-sidebar-user-link:hover,
.app-sidebar-user-link:focus {
  color: #ffffff;
}

/* A labelled band of sidebar links that belong to a different tier than the ones
   above them. Each link reuses .app-sidebar-item's layout; only the label color
   and the active state distinguish one group from another. */
.app-sidebar-group {
  margin-top: 0.5rem;
  padding-top: 0.875rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.app-sidebar-group-label {
  padding: 0 1.25rem 0.5rem;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
}

/* Platform tools (Sub-Accounts/Usage/Plans): a distinct tier of access, not just
   more nav items — gold, matching the "Admin Console Screens" comp. Gold means
   "one tier above this company", so no other group may borrow it. */
.app-sidebar-platform .app-sidebar-group-label {
  color: #e8b93f;
}

.app-sidebar-platform .app-sidebar-item.active {
  color: #ffffff;
  font-weight: 600;
  border-left-color: #e8b93f;
  background-color: rgba(232, 185, 63, 0.1);
}

@media (min-width: 768px) {
  .app-main-with-sidebar {
    margin-left: 220px;
    width: calc(100% - 220px);
  }

  .reserve-bar,
  .route-nav-bar {
    left: 220px;
  }
}

/* Settings hub. Desktop reads as a second sidebar beside the primary one (mockup #16); below md
   the sub-nav is replaced entirely by a "← Company Settings" back link to the grouped mobile menu
   (Views/CompanySettings/Menu.cshtml) — a phone has no room for a nav-beside-content layout. */
.settings-shell {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
}

.settings-heading {
  display: none;
}

.settings-back-link {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.25rem 0 1rem;
  color: var(--muted);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
}

.settings-back-link:hover,
.settings-back-link:focus {
  color: var(--accent);
}

.settings-nav {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  padding-bottom: 0.25rem;
  -webkit-overflow-scrolling: touch;
}

.settings-nav-item {
  flex: 0 0 auto;
  padding: 0.5rem 0.9rem;
  border: 1px solid #dee2e6;
  border-radius: 999px;
  color: #495057;
  text-decoration: none;
  font-size: 0.9rem;
  white-space: nowrap;
}

.settings-nav-item:hover,
.settings-nav-item:focus {
  color: #0d6efd;
  border-color: #9ec5fe;
}

.settings-nav-item.active {
  color: #ffffff;
  background-color: #0d6efd;
  border-color: #0d6efd;
  font-weight: 600;
}

.settings-content-header {
  margin-bottom: 1rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid #dee2e6;
}

/* Forms in the hub read better capped than stretched across a wide monitor; tables keep the full content width. */
.settings-form {
  max-width: 560px;
}

/* Drag-to-reorder rows (Lead Statuses, Custom Fields, a field's Options) — see wwwroot/js/reorder-list.js. */
.reorder-handle-cell {
  width: 1%;
  white-space: nowrap;
}

.settings-drag-handle {
  cursor: grab;
  color: var(--muted);
  /* Without this, a touch drag on the handle is read as a page scroll first. */
  touch-action: none;
  padding: 0 0.5rem;
}

.settings-drag-handle:active {
  cursor: grabbing;
}

.settings-reorder-ghost {
  opacity: 0.4;
  background-color: #f1f3f5;
}

.settings-reorder-chosen td {
  background-color: #eef4ff;
}

@media (min-width: 768px) {
  .settings-shell {
    grid-template-columns: 210px minmax(0, 1fr);
    gap: 0;
    align-items: start;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
  }

  .settings-aside {
    background: var(--card);
    border-right: 1px solid var(--border);
    padding: 1.5rem 0 1.5rem;
    align-self: stretch;
  }

  .settings-content {
    padding: 1.75rem 2rem;
  }

  .settings-heading {
    display: block;
    padding: 0 1.25rem 0.75rem;
    font-size: 1.1rem;
    font-weight: 700;
  }

  /* Vertical list on desktop, filled accent background on the active row (mockup #16) rather
     than the primary sidebar's left-border marker — this is a lighter, white-panel chrome. */
  .settings-nav {
    flex-direction: column;
    gap: 0;
    overflow-x: visible;
  }

  .settings-nav-item {
    padding: 0.65rem 1.25rem;
    border: 0;
    border-radius: 0;
    font-family: var(--font-body, inherit);
  }

  .settings-nav-item.active {
    color: #ffffff;
    background-color: var(--accent);
    font-weight: 600;
  }
}

/* The whole card is a stretched-link to Details; raise action buttons (e.g. "Knock") above its overlay to keep them tappable. */
.property-card .card-body .btn {
  position: relative;
  z-index: 2;
}

/* Same trick for the multi-select checkbox so it stays tappable over the card link. */
.property-card .card-body .reserve-check {
  position: relative;
  z-index: 2;
  width: 1.4rem;
  height: 1.4rem;
  margin-top: 0.1rem;
  cursor: pointer;
}

/* Select mode: the checkbox stays hidden and the whole card becomes the tap target (click handler intercepts stretched-link navigation, see Index.cshtml). */
.property-list.select-mode .selectable-card {
  cursor: pointer;
}

.property-list .selectable-card.selected {
  border-color: var(--bs-primary);
  background-color: rgba(13, 110, 253, 0.08);
}

/* Reserved cards have no checkbox, so their Details link goes inert (pointer-events: none) while picking leads to reserve; normal browsing is untouched. */
.property-list.select-mode .property-card:not(.selectable-card) .stretched-link {
  pointer-events: none;
}

/* Sticky "Reserve for today" action bar; sits above the phone bottom nav. */
.reserve-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1029;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 1rem;
  background-color: #ffffff;
  border-top: 1px solid #dee2e6;
}

@media (max-width: 767.98px) {
  .reserve-bar {
    bottom: var(--bottom-clearance);
  }
}

/* Previous/Full Route/Next bar — a floating rounded pill (Claude Design's
   "EminenceCRM UI Review" comp, "03 · Route planner"), not an edge-to-edge strip.
   Fixed-width Prev/Next slots (empty <span> placeholders hold the slot when
   hidden) keep "Full Route" centered; 1px dividers separate the three sections
   instead of a gap, matching the comp. Sits above .app-bottom-nav;
   .pd-action-bar-stacked (on the .pd-action-bar above it, Route page only) adds
   its own extra offset to clear it. */
.route-nav-bar {
  position: fixed;
  left: 1rem;
  right: 1rem;
  bottom: 0;
  z-index: 1029;
  height: 52px;
  display: flex;
  align-items: center;
  background: var(--chrome, #1a1d29);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-2);
}

.route-nav-bar-step {
  /* Wider than tall on purpose: Prev/Next flank the "Full Route" label with only a 1px divider
     between them, and 52px (matching the bar's height) was too easy to overshoot into the label. */
  flex: 0 0 76px;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  color: #fff;
  padding: 0;
}

.route-nav-bar-step.route-nav-bar-next {
  color: var(--chrome-active, #fff);
}

.route-nav-bar-divider {
  flex: 0 0 1px;
  width: 1px;
  height: 22px;
  background: rgba(255, 255, 255, 0.18);
}

.route-nav-bar-label {
  flex: 1 1 auto;
  background: transparent;
  border: 0;
  color: #fff;
  font-weight: 600;
  font-family: var(--font-head, inherit);
  font-size: 0.85rem;
  text-align: center;
}

@media (max-width: 767.98px) {
  .route-nav-bar {
    /* Small gap above the bottom nav so the pill visibly floats, rather than
       sitting flush against it like the old edge-to-edge bar did. */
    bottom: calc(var(--bottom-clearance) + 8px);
  }
}

/* Keep the last card visible above the fixed route bars (.pd-action-bar +
   .route-nav-bar stacked). */
.route-page {
  padding-bottom: 168px;
}

/* Same idea as .route-page, but only one fixed bar (.pd-action-bar) sits below it. */
.property-actions-page {
  padding-bottom: 100px;
}

/* Street View photo (shared partial, Route page too); fixed height so the page doesn't jump while the proxy fetches from Google. */
.street-view-photo {
  width: 100%;
  height: 200px;
  object-fit: cover;
  background-color: #eef0f3;
}

/* --- Property Details / Route redesign components (.pd-shell tokens) --- */

/* .pd-header wraps .pd-hero (photo) + .pd-header-content (title/meta/buttons/fact-strip). A plain
   block below md — same stacked layout as before this pair existed — becoming a flex row at md+
   (comp 10h) with a fixed-size photo beside the content column. */
.pd-header-content {
  min-width: 0;
}

.pd-hero {
  position: relative;
  height: 200px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background-color: var(--border, #eef0f3);
  margin-bottom: 0.75rem;
}

.pd-hero .street-view-photo {
  height: 100%;
  border-radius: 0;
}

@media (min-width: 768px) {
  .pd-header {
    display: flex;
    gap: 20px;
    align-items: flex-start;
  }

  .pd-hero {
    width: 300px;
    height: 186px;
    flex: 0 0 auto;
    margin-bottom: 0;
  }

  .pd-header-content {
    flex: 1;
  }

  /* Buttons next to the title (comp 10h), same rounded-rect treatment as .pd-actions-row .btn. */
  .pd-header-actions .btn {
    border-radius: var(--radius-md);
  }
}

.pd-hero-back {
  position: absolute;
  top: 10px;
  left: 12px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 40px;
  padding: 0 14px;
  border-radius: var(--radius-pill);
  background: rgba(20, 20, 35, 0.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}

.pd-hero-back:hover,
.pd-hero-back:focus {
  color: #fff;
}

.pd-title {
  font-family: var(--font-head);
  font-weight: 700;
}

.pd-meta {
  color: var(--muted);
}

.pd-facts {
  color: var(--muted);
}

/* Tint modifiers layer on top of the existing .badge base (pill radius/weight already set above). */
.pd-tint-accent {
  background-color: var(--accent-tint);
  color: var(--accent-tint-text);
}

.pd-tint-success {
  background-color: var(--success-tint);
  color: var(--success);
}

.pd-tint-warning {
  background-color: var(--warning-tint);
  color: var(--warning);
}

.pd-tint-danger {
  background-color: var(--danger-tint);
  color: var(--danger);
}

.pd-tint-neutral {
  background-color: var(--neutral-bg);
  color: var(--neutral-text);
}

/* Restyles the existing native <select> (Lead Status) as a pill — same element,
   same onchange/form submit, appearance only. */
.pd-status-select {
  appearance: none;
  -webkit-appearance: none;
  background-color: var(--accent-tint);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23453a80' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.6rem center;
  color: var(--accent-tint-text);
  border: 0;
  border-radius: var(--radius-pill);
  font-weight: 600;
  font-size: 0.85rem;
  padding: 0.4rem 1.75rem 0.4rem 0.9rem;
}

.pd-actions-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Share/Edit are the rounded-rect (not full-pill) style from the comp's Status/Share/Edit row. */
.pd-actions-row .btn {
  border-radius: var(--radius-md);
}

/* Owner card's primary-phone marker — Phones[0] is already the primary number
   (PropertyContactVm doc comment), not a fabricated presence signal. */
.pd-primary-star {
  color: var(--accent);
}

.pd-info-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 0.875rem;
  background: var(--card);
}

.pd-info-label {
  font-family: var(--font-head);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--faint);
  margin-bottom: 0.5rem;
}

/* Added alongside the existing .nav.nav-tabs classes on #detailsTabs (its only usage app-wide). */
.pd-tabs {
  border-bottom-color: var(--border);
}

.pd-tabs .nav-link {
  font-family: var(--font-head);
  font-weight: 600;
  color: var(--faint);
  border: 0;
  border-bottom: 2px solid transparent;
}

.pd-tabs .nav-link.active {
  color: var(--accent);
  background: transparent;
  border-bottom-color: var(--accent);
}

/* Fixed bottom bar (Directions/Knock/Zillow), replacing the folding FAB — phone only.
   .pd-action-bar-stacked (Route page only, see ViewData["ShowsWayfindingBar"] in
   _PropertyDetails.cshtml) adds the extra offset for .route-nav-bar sitting below it.
   At md+ the same three buttons render inline next to the title instead (.pd-header-actions,
   comp 10h) and this bar is hidden — unlike .reserve-bar/.route-nav-bar it was never given a
   left:220px sidebar-clearance offset, because on desktop it isn't meant to exist at all. */
.pd-action-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1029;
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
}

@media (max-width: 767.98px) {
  .pd-action-bar {
    bottom: var(--bottom-clearance);
  }
}

@media (min-width: 768px) {
  .pd-action-bar {
    display: none;
  }
}

.pd-action-bar.pd-action-bar-stacked {
  bottom: 68px;
}

@media (max-width: 767.98px) {
  .pd-action-bar.pd-action-bar-stacked {
    bottom: calc(var(--bottom-clearance) + 68px);
  }
}

.pd-action-bar .btn {
  flex: 1;
  min-height: 52px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  border: 0;
  border-radius: var(--radius-lg);
  font-family: var(--font-head);
  font-weight: 600;
  background-color: var(--accent-tint);
  color: var(--accent-tint-text);
}

.pd-action-bar .btn-primary {
  flex: 1.15;
  background-color: var(--accent);
  color: #fff;
  box-shadow: 0 8px 20px rgba(40, 30, 120, 0.28);
}

/* Properties Index (Views/Properties/Index.cshtml) — full redesign, not just the
   filter-preset placeholders: persistent search bar, 44px icon-only Filter button,
   single-pill property cards. */
.pd-filter-btn {
  position: relative;
  width: 44px;
  padding: 0;
}

.pd-filter-dot {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
}

.pd-select-pill {
  background-color: var(--accent-tint);
  color: var(--accent-tint-text);
  border: 0;
  border-radius: var(--radius-pill);
  font-weight: 600;
}

.pd-property-card {
  border-radius: var(--radius-lg);
}

.pd-property-card .pd-title {
  font-size: 1rem;
}

/* Positioned badge (e.g. "Reserved") pinned to a .pd-property-card's top-right
   corner, for cards whose header row doesn't already reserve space for it. */
.pd-property-card-badge {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
}

/* Circular initials avatar (Contacts list). Size is a custom property so a
   caller can override it inline (style="--pd-avatar-size:32px") without a
   parallel size-modifier class. */
.pd-avatar {
  --pd-avatar-size: 40px;
  width: var(--pd-avatar-size);
  height: var(--pd-avatar-size);
  border-radius: 50%;
  background-color: var(--accent-tint);
  color: var(--accent-tint-text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: calc(var(--pd-avatar-size) * 0.34);
}

/* Contact/case role badge — same visual language as .pd-tint-neutral but named
   for what it is so People-tab/Contacts-list markup reads clearly. */
.pd-role-pill {
  display: inline-flex;
  align-items: center;
  background-color: var(--neutral-bg);
  color: var(--neutral-text);
  font-weight: 600;
  font-size: 0.7rem;
  padding: 0.2rem 0.6rem;
  border-radius: var(--radius-pill);
}

/* Phone number rendered as a pill with a leading status dot (green = a number
   is on file, faint = none). Wraps a tel: link when a number exists. */
.pd-phone-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 0.35rem 0.7rem;
  font-weight: 600;
  font-size: 0.8rem;
  color: var(--accent);
  text-decoration: none;
}

.pd-phone-pill-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--success);
  flex: 0 0 auto;
}

.pd-phone-pill-muted {
  color: var(--faint);
}

/* Icon-only circular call button (Contacts list row) — distinct from .pd-phone-pill,
   which shows the digits themselves (People tab). Green tint when a number is on
   file, neutral/inert when not. */
.pd-call-btn {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  background: var(--success-tint);
  color: var(--success);
}

.pd-call-btn.pd-call-btn-muted {
  background: var(--neutral-bg);
  color: var(--faint);
}

.pd-phone-pill-muted .pd-phone-pill-dot {
  background: var(--faint);
}

.pd-contact-card,
.pd-case-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 0.875rem;
}

.pd-contact-card + .pd-contact-card,
.pd-case-card + .pd-case-card {
  margin-top: 0.625rem;
}

.pd-contact-card.pd-contact-card-destination {
  border-color: var(--accent);
}

/* Activity-tab timeline marker. Color modifiers map to the same tint palette
   used elsewhere rather than inventing new colors per event/outcome. */
.pd-timeline-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--neutral-text);
  flex: 0 0 auto;
  margin-top: 5px;
}

.pd-timeline-dot-accent { background: var(--accent); }
.pd-timeline-dot-warning { background: var(--warning); }
.pd-timeline-dot-success { background: var(--success); }
.pd-timeline-dot-danger { background: var(--danger); }

/* "+" icon-button style replacing plain text "Add X" buttons (Add person/Add
   case/Add contact-row actions). */
.pd-icon-btn-add {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  gap: 0.35rem;
  height: 36px;
  padding: 0 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--accent);
  font-weight: 600;
  font-size: 0.8125rem;
}

/* Small icon-only edit/delete affordance replacing plain "Edit"/"Unlink" text
   links, same tap target size as other .btn-sm controls in these tabs. */
.pd-edit-pencil {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  color: var(--faint);
  background: transparent;
  border: 0;
}

.pd-edit-pencil:hover,
.pd-edit-pencil:focus {
  color: var(--muted);
  background: var(--neutral-bg);
}

/* My List (Views/Properties/MyList.cshtml) — icon-only remove button replacing the old text
   "Remove" button; same position/z-index trick as .property-card .card-body .btn so it stays
   tappable above the card's stretched-link. */
.pd-list-remove-btn {
  position: relative;
  z-index: 2;
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--muted);
  padding: 0;
}

.pd-list-remove-btn:hover,
.pd-list-remove-btn:focus {
  color: var(--danger);
  border-color: var(--danger);
}

/* My Account (Views/Profile/Index.cshtml) — inert placeholder rows for Edit profile/Change
   password: no <a>, no chevron-click affordance, real functionality is future work. */
.pd-list-row-disabled {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.8rem 1rem;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--faint);
  cursor: not-allowed;
}

.pd-list-row-disabled-last {
  border-bottom: 0;
}

/* Mobile Company Settings menu (Views/CompanySettings/Menu.cshtml) — same list-row language as
   .pd-more-sheet-item, but not coupled to #moreSheet's locally-scoped token set since this page
   is wrapped in .pd-shell directly and has its own tokens already. */
.pd-settings-menu-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.8rem 1rem;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text);
  text-decoration: none;
  font-size: 0.95rem;
  font-weight: 600;
}

.pd-settings-menu-item:hover,
.pd-settings-menu-item:focus {
  color: var(--accent);
}

.pd-settings-menu-item-last {
  border-bottom: 0;
}

/* "More" bottom-nav sheet. _Layout.cshtml isn't .pd-shell-wrapped app-wide, so
   #moreSheet carries its own small scoped token set instead (smallest blast
   radius) — see the .pd-shell doc comment above for why full adoption is a
   separate decision. */
#moreSheet {
  --accent: oklch(56% 0.19 265);
  --accent-tint: oklch(95% 0.025 265);
  --accent-tint-text: oklch(45% 0.16 265);
  --font-head: 'Outfit', sans-serif;
}

.pd-more-sheet-item {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 0.8rem 0.25rem;
  border-bottom: 1px solid var(--border-subtle);
  color: inherit;
  text-decoration: none;
  background: transparent;
  border-left: 0;
  border-right: 0;
  border-top: 0;
  width: 100%;
  text-align: left;
  font-size: 0.95rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}

.pd-more-sheet-item:last-child {
  border-bottom: 0;
}

.pd-more-sheet-item.text-danger {
  color: var(--bs-danger, #dc3545);
}

.pd-more-sheet-icon {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: var(--accent-tint);
  color: var(--accent-tint-text);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}

/* Quick-filter chips (My Knocks / Activity History "All"/"Converted" tabs) — compact, left-aligned
   pill toggle links. Deliberately not the same class as .settings-nav-item (Settings hub sub-nav,
   a different control in a different context that happens to look similar) or .pd-period-item
   (Leaderboard's period switcher, which stretches to fill its row — these chips must not). */
.pd-chip-row {
  display: flex;
  gap: 0.5rem;
}

.pd-chip {
  padding: 0.4rem 0.9rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--muted);
  font-weight: 600;
  font-size: 0.8125rem;
  text-decoration: none;
}

.pd-chip.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* Leaderboard (Views/Leaderboard/Index.cshtml). */
.pd-period-row {
  display: flex;
  gap: 0.5rem;
}

.pd-period-item {
  flex: 1;
  text-align: center;
  padding: 0.5rem 0;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--muted);
  font-weight: 600;
  font-size: 0.85rem;
  text-decoration: none;
}

.pd-period-item.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.pd-leaderboard-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  padding: 0.75rem 0.875rem;
}

/* Current rep's own row — always tinted, even outside the top 3. */
.pd-leaderboard-row-you {
  background: var(--accent-tint);
  border-color: var(--accent);
}

.pd-leaderboard-rank {
  width: 1.75rem;
  text-align: center;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--faint);
  flex: 0 0 auto;
}

/* Gold/silver/bronze on the top 3 only — everyone else stays neutral (.pd-rank-plain inherits
   the base .pd-leaderboard-rank color) so the list doesn't turn into a color soup. */
.pd-rank-gold { color: #b8860b; }
.pd-rank-silver { color: #8a92a1; }
.pd-rank-bronze { color: #a9713f; }

.pd-leaderboard-name {
  flex: 1 1 auto;
  font-weight: 600;
  font-size: 0.95rem;
}

.pd-leaderboard-sublabel {
  font-size: 0.65rem;
  color: var(--faint);
}

/* Route page stop-progress header (Views/Route/Index.cshtml). */
.pd-route-segment {
  flex: 1;
  height: 5px;
  border-radius: 3px;
  background: var(--border);
}

.pd-route-segment.pd-route-segment-filled {
  background: var(--accent);
}

/* Typeahead dropdown in the Create Route popup. */
.route-suggestions {
  z-index: 5;
  max-height: 220px;
  overflow-y: auto;
}

/* --- Field-friendly touch targets --- */

@media (max-width: 767.98px) {
  .form-control, .form-select {
    min-height: 44px;
  }

  /* min-height alone leaves button text top-aligned; flex centering fixes it (skip .btn-link so inline text links stay compact). */
  .btn:not(.btn-link) {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

/* Square 44px tap target on any viewport for icon buttons (Share, tel:). */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
}

/* --- Loading overlay (site.js): shows on every link/form navigation by default. --- */

/* z-index above Bootstrap's modal (1055) so it covers the Create Route popup. */
.loading-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  background: rgba(255, 255, 255, 0.85);
}

.loading-overlay.show {
  display: flex;
}

/* --- PWA install banner (site.js pwa-install.js) --- */

.pwa-install-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  /* Above .app-bottom-nav (1030): safe since this only renders in a regular browser tab, never the standalone WKWebView the bottom-nav's absolute-positioning workaround targets. */
  z-index: 1035;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  padding-bottom: calc(0.75rem + var(--safe-bottom));
  background-color: #1a1d29;
  color: #fff;
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.25);
}

.pwa-install-icon {
  border-radius: var(--radius-sm);
  flex: 0 0 auto;
}

.pwa-install-text {
  flex: 1 1 auto;
  font-size: 0.85rem;
  line-height: 1.3;
}

.pwa-install-banner .btn-close {
  filter: invert(1);
  flex: 0 0 auto;
}

/* --- Full Route modal map (Views/Route/Index.cshtml, route-map.js) --- */

#route-map {
  height: 60vh;
}

/* Fullscreen modal on phones: map fills the space above unmapped rows/footer, never fully collapsing when the list underneath is long. */
@media (max-width: 575.98px) {
  #routeModal .modal-body {
    display: flex;
    flex-direction: column;
  }

  #route-map {
    flex: 1 1 auto;
    height: auto;
    min-height: 45vh;
  }
}

/* Shared elevation/radius system for cards/buttons/forms/dropdowns/modals/alerts/tables. Shadows are additive to borders (a shadow alone washes out in direct sun); .card avoids transform/filter since that would create a new containing block that could re-parent a nearby position:fixed sibling (.property-actions, .reserve-bar, .route-nav-bar). */

.card {
  border-color: var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-1);
}

.card > .card-header:first-child {
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}

.btn {
  border-radius: var(--radius-sm);
  transition: background-color 0.15s var(--ease-standard), border-color 0.15s var(--ease-standard),
    box-shadow 0.15s var(--ease-standard), color 0.15s var(--ease-standard);
}

.btn-primary, .btn-success, .btn-danger, .btn-warning, .btn-info, .btn-dark {
  box-shadow: var(--shadow-1);
}

.btn-icon {
  border-radius: var(--radius-sm);
}

.form-control, .form-select {
  border-radius: var(--radius-sm);
  border-color: #d7dbe3;
}

.dropdown-menu {
  border-color: var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-2);
}

.modal-content {
  border: 0;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
}

.modal {
  padding-top: var(--safe-top);
  padding-bottom: var(--safe-bottom);
}

.offcanvas {
  padding-top: var(--safe-top);
  padding-bottom: var(--safe-bottom);
}

/* Bootstrap's offcanvas-bottom defaults to height:30vh and is position:fixed —
   both wrong here: our sheets (More menu, filter drawer) need to size to content
   up to a cap, and .app-bottom-nav below documents a WKWebView PWA defect where
   fixed-position elements fall short of the true screen bottom by ~the top
   safe-area inset. Match that same position:absolute workaround here. */
.offcanvas-bottom {
  position: absolute;
  height: auto;
  max-height: 60vh;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  /* Base .offcanvas reserves --safe-top for top-anchored drawers clearing the
     notch/status bar — a bottom sheet has no reason to reserve that space at
     its own top, but inherits the rule above unless reset here. */
  padding-top: 0;
}

.offcanvas-bottom .offcanvas-body {
  overflow-y: auto;
  padding-bottom: calc(1rem + var(--safe-bottom));
}

/* Hidden-checkbox/radio + styled-label pill toggle. The input keeps its normal
   name/value/asp-for wiring (form submission, tag-helper hidden-input pairing for
   bool props) — only the label's appearance communicates checked state, via the
   sibling combinator below. Always pair a <label for="..."> with the input's id. */
.pd-pill-check {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}

.pd-pill-label {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  background-color: #fff;
  border: 1px solid var(--border, var(--border-subtle));
  color: var(--muted, #6b7280);
  font-weight: 600;
  font-size: 0.8125rem;
  padding: 0.4rem 0.9rem;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  user-select: none;
}

.pd-pill-check:checked + .pd-pill-label {
  background-color: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.pd-pill-check:focus-visible + .pd-pill-label {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.pd-pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Chip groups that collapse to one line and expand in place — property-chip-filters.js
   measures actual rendered widths, so this class only ever gets toggled by JS, never
   hardcoded server-side (a name-only allow list can't know how many chips fit a line). */
.pd-pill-hidden {
  display: none !important;
}

/* The toggle slot is a flex sibling of .pd-pill-row, not one of the row's own wrapping
   children — top-aligned so it sits at a fixed spot beside line 1 regardless of how many
   lines the row grows to when expanded. Narrows the row's available width automatically
   (no manual "does the toggle also fit" measurement needed), and means every tap to
   collapse lands in the same place it took to expand. */
.pd-chip-group-body {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
}

.pd-chip-group-body > .pd-pill-row {
  flex: 1 1 auto;
  min-width: 0;
}

.pd-chip-group-body > [data-chip-toggle-slot] {
  flex: 0 0 auto;
}

/* Marks the first chip past the quick-line cut when a group is expanded, so there's a
   visible break between "stays visible" and "goes away on Show less" — plain .pd-pill-row
   gap alone reads as one continuous list. Extra top margin only: it's the first chip of a
   wrapped line, so this reads as space above that line rather than an indent. */
.pd-pill-expand-start {
  margin-top: 0.5rem;
}

.pd-chip-toggle {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  cursor: pointer;
  background-color: #fff;
  border: 1px dashed var(--border, var(--border-subtle));
  color: var(--accent);
  font-weight: 600;
  font-size: 0.8125rem;
  padding: 0.4rem 0.9rem;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}

.pd-chip-toggle svg {
  transition: transform 0.15s ease;
}

.pd-chip-toggle[aria-expanded="true"] svg {
  transform: rotate(180deg);
}

/* The county-only "+N more" chip past the expanded cap — focuses the search box rather
   than revealing more chips, so it reads as a link, not another toggle. */
.pd-chip-overflow {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  background-color: #fff;
  border: 1px solid var(--border, var(--border-subtle));
  color: var(--muted, #6b7280);
  font-weight: 600;
  font-size: 0.8125rem;
  padding: 0.4rem 0.9rem;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}

.alert {
  border: 0;
  border-radius: var(--radius-md);
}

.alert-success {
  background-color: #e6f4ea;
  color: #1e4620;
}

.alert-warning {
  background-color: #fff3cd;
  color: #4d3800;
}

.alert-danger {
  background-color: #fbe7e9;
  color: #5c141c;
}

.table > thead {
  background-color: #f8f9fb;
}

.table > thead th {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #6b7280;
  border-bottom: 1px solid var(--border-subtle);
}

.app-sidebar-item,
.app-bottom-nav-item,
.settings-nav-item {
  transition: color 0.15s var(--ease-standard), background-color 0.15s var(--ease-standard),
    border-color 0.15s var(--ease-standard);
}

/* --- Admin Console (Platform: Sub-Accounts / Usage / Plans / Billing, plus Legal
   and the tenant-facing Adjust Seats screens) redesign components (.plat-shell
   tokens, Claude Design comp "EminenceCRM Admin Console Screens"). Same token
   values as .pd-shell (Property Details/Route) but kept as its own scope, not
   merged: the two are separate comps and a shared name would blur which comp a
   future edit should match. Everything under this scope traces back to a screen
   in that one comp file, whether the audience is SuperAdmin-only (Sub-Accounts,
   Usage, Plans, Migrate, Legal) or a tenant admin (CompanySettings/Billing/Seats
   and SeatsReview) — the scope tracks the comp, not the permission level. */
.plat-shell {
  --bg: oklch(97% 0.004 265);
  --card: #ffffff;
  --border: oklch(91% 0.006 265);
  --text: oklch(23% 0.02 265);
  --muted: oklch(52% 0.015 265);
  --faint: oklch(68% 0.012 265);
  --accent: oklch(56% 0.19 265);
  --accent-dark: oklch(47% 0.18 265);
  --accent-tint: oklch(95% 0.025 265);
  --accent-tint-text: oklch(45% 0.16 265);
  --success: oklch(55% 0.13 150);
  --success-tint: oklch(95% 0.03 150);
  --warning: oklch(50% 0.15 70);
  --warning-tint: oklch(96% 0.05 80);
  --danger: oklch(55% 0.19 25);
  --danger-tint: oklch(95% 0.035 25);
  --neutral-bg: oklch(94% 0.007 265);
  --neutral-text: oklch(42% 0.012 265);
  --font-head: 'Outfit', sans-serif;
  --font-body: 'Source Sans 3', sans-serif;
  font-family: var(--font-body);
  color: var(--text);
}

.plat-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.plat-header h1 {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.5rem;
  margin: 0 0 0.35rem;
  color: var(--text);
}

.plat-header p {
  font-size: 0.85rem;
  color: var(--muted);
  line-height: 1.55;
  margin: 0;
  max-width: 640px;
}

/* Breadcrumb replacing a plain "← Back" link on drill-down pages (e.g. Billing). */
.plat-breadcrumb {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--muted);
  margin-bottom: 0.35rem;
}

.plat-breadcrumb a {
  color: var(--muted);
  text-decoration: none;
}

.plat-breadcrumb a:hover {
  color: var(--accent);
}

.plat-breadcrumb-sep {
  color: var(--faint);
}

.plat-breadcrumb-current {
  color: var(--text);
  font-weight: 600;
}

.plat-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 1rem;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(20, 20, 60, .03), 0 6px 16px rgba(20, 20, 60, .04);
}

.plat-card-body {
  padding: 1.25rem 1.5rem;
}

/* Card title bar with an optional right-aligned action (e.g. each document editor's
   "Preview" link) — the header/body split .plat-card-body alone doesn't give. */
.plat-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--border);
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 0.85rem;
}

/* Definition-list summary (Billing page): label column + value column. */
.plat-summary {
  display: grid;
  grid-template-columns: 130px 1fr;
  gap: 0.85rem 0;
  font-size: 0.875rem;
  margin: 0;
}

.plat-summary dt {
  color: var(--faint);
  font-weight: 400;
}

.plat-summary dd {
  margin: 0;
}

.plat-table > thead th {
  font-family: var(--font-head);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--faint);
  border-bottom: 1px solid var(--border);
  background: transparent;
  padding: 0.85rem 1.25rem;
}

.plat-table > tbody > tr > td {
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  font-size: 0.875rem;
  color: var(--text);
}

.plat-table > tbody > tr:last-child > td {
  border-bottom: 0;
}

/* Checkout picker: the plan closest to solving an at-/over-cap account's problem
   gets the same accent-tint row treatment as the mock's highlighted Growth row. */
.plat-table > tbody > tr.table-plat-suggested > td {
  background-color: var(--accent-tint);
}

.plat-table-name {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--text);
}

.plat-table-meta {
  font-size: 0.78rem;
  color: var(--muted);
  margin-top: 0.15rem;
}

/* Status/tag pills — tint modifiers on a shared pill base, same idea as .pd-tint-*. */
.plat-pill {
  display: inline-block;
  padding: 0.22rem 0.65rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
}

.plat-pill-success { background-color: var(--success-tint); color: var(--success); }
.plat-pill-warning { background-color: var(--warning-tint); color: var(--warning); }
.plat-pill-danger  { background-color: var(--danger-tint);  color: var(--danger); }
.plat-pill-neutral { background-color: var(--neutral-bg);   color: var(--neutral-text); }
.plat-pill-accent  { background-color: var(--accent-tint);  color: var(--accent-tint-text); }

/* Button reskin: Bootstrap's default (blue) .btn-primary becomes the comp's indigo
   accent inside this scope only — same technique as .pd-action-bar .btn-primary. */
.plat-shell .btn {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.85rem;
  border-radius: 0.625rem;
}

.plat-shell .btn-primary {
  background-color: var(--accent);
  border-color: var(--accent);
}

.plat-shell .btn-primary:hover,
.plat-shell .btn-primary:focus {
  background-color: var(--accent-dark);
  border-color: var(--accent-dark);
}

.plat-shell .btn-outline-primary {
  color: var(--accent);
  border-color: var(--border);
}

.plat-shell .btn-outline-primary:hover,
.plat-shell .btn-outline-primary:focus {
  color: #fff;
  background-color: var(--accent);
  border-color: var(--accent);
}

.plat-shell .btn-outline-secondary {
  color: var(--text);
  border-color: var(--border);
}

.plat-shell .btn-outline-secondary:hover,
.plat-shell .btn-outline-secondary:focus {
  color: var(--text);
  background-color: var(--neutral-bg);
  border-color: var(--border);
}

.plat-shell .btn-outline-danger {
  border-color: var(--border);
}

/* Overflow ("⋮") action menu — Bootstrap's dropdown component, restyled. */
.plat-kebab {
  width: 2.25rem;
  height: 2.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  line-height: 1;
}

.plat-kebab::after {
  display: none;
}

.plat-shell .dropdown-menu {
  border-color: var(--border);
  border-radius: 0.75rem;
  box-shadow: 0 6px 16px rgba(20, 20, 60, .1);
  padding: 0.35rem;
  font-size: 0.85rem;
}

.plat-shell .dropdown-item {
  border-radius: 0.5rem;
  padding: 0.5rem 0.75rem;
}

.plat-shell .dropdown-item:hover,
.plat-shell .dropdown-item:focus {
  background-color: var(--accent-tint);
  color: var(--accent-tint-text);
}

.plat-shell .dropdown-item.text-danger:hover,
.plat-shell .dropdown-item.text-danger:focus {
  background-color: var(--danger-tint);
  color: var(--danger);
}

.plat-shell .dropdown-item:disabled,
.plat-shell .dropdown-item.disabled {
  color: var(--faint);
}

/* Forms (Create/Edit/AssignPlan), wrapped in .plat-card for visual consistency
   with the four mocked list/detail pages. */
.plat-shell .form-label {
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--text);
}

.plat-shell .form-control,
.plat-shell .form-select {
  border-color: var(--border);
  border-radius: 0.625rem;
}

.plat-shell .form-control:focus,
.plat-shell .form-select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 0.2rem var(--accent-tint);
}

.plat-shell .form-text {
  color: var(--muted);
}

/* Markdown source inside a .plat-card (Legal documents editor) — the shaded, monospace
   look of a code block, while staying a real, editable textarea. */
.plat-shell .legal-editor {
  background: var(--neutral-bg);
  border: none;
  border-radius: 0;
  padding: 1rem 1.25rem;
  min-height: 320px;
  width: 100%;
  resize: vertical;
}

.plat-shell .legal-editor:focus {
  box-shadow: none;
  background: #fff;
}

.plat-shell h2.plat-subhead {
  font-family: var(--font-head);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--faint);
  margin: 0 0 0.75rem;
}

/* Tab strip shared by the /SubAccounts/Legal pages (_LegalDocumentTabs.cshtml): sits
   under the breadcrumb, above the page's own h1, so a super-admin can move between the
   editor and the version history without leaving the section. */
.plat-tabs {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid var(--border);
  margin: 0.6rem 0 1.25rem;
  overflow-x: auto;
}

.plat-tabs-item {
  padding: 0.55rem 0.85rem;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--muted);
  white-space: nowrap;
}

.plat-tabs-item:hover {
  color: var(--text);
}

.plat-tabs-item.active {
  color: var(--text);
  border-bottom-color: var(--accent);
}

/* Side-by-side "current vs. target" comparison, e.g. Migrate. The target card gets
   the accent tint so it reads as the destination, not just a second identical card. */
.plat-compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

.plat-card-highlight {
  background: var(--accent-tint);
  border-color: var(--accent);
}

.plat-card-highlight .plat-card-body dt {
  color: var(--accent-tint-text);
  opacity: .75;
}

.plat-card-highlight .plat-card-body dd {
  color: var(--accent-tint-text);
}

/* Seat-count stepper (Adjust seats). The number input stays the real form control —
   these buttons only nudge its value, so keyboard entry and validation are untouched. */
.plat-stepper {
  display: flex;
  align-items: center;
  gap: 1.1rem;
}

.plat-stepper-btn {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.625rem;
  border: 1px solid var(--border);
  background: #fff;
  color: var(--accent);
  font-size: 1.1rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.plat-stepper-btn:hover {
  background: var(--accent-tint);
}

.plat-stepper input[type="number"] {
  width: 4rem;
  text-align: center;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.5rem;
  border: none;
  background: transparent;
  padding: 0;
  -moz-appearance: textfield;
}

.plat-stepper input[type="number"]::-webkit-inner-spin-button,
.plat-stepper input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* --- Import flow (Claude Design comp "22 Import") ------------------------- */

/* Tokens repeated rather than shared with .pd-shell/.plat-shell for the reason given
   above those blocks: the names come verbatim from the comp so its markup can be
   pasted back in, and generic names like --text/--card must not leak to :root.
   --info/--info-tint and --violet/--violet-tint are new here — the preview's
   "new case on existing property" tile and contact slot 4 need a fifth and sixth
   hue that neither existing scope defines. */
.imp-shell {
  --bg: oklch(97% 0.004 265);
  --card: #ffffff;
  --border: oklch(91% 0.006 265);
  --text: oklch(23% 0.02 265);
  --muted: oklch(52% 0.015 265);
  --faint: oklch(68% 0.012 265);
  --accent: oklch(56% 0.19 265);
  --accent-dark: oklch(47% 0.18 265);
  --accent-tint: oklch(95% 0.025 265);
  --accent-tint-text: oklch(45% 0.16 265);
  --success: oklch(55% 0.13 150);
  --success-tint: oklch(95% 0.03 150);
  --warning: oklch(50% 0.15 70);
  --warning-tint: oklch(96% 0.05 80);
  --danger: oklch(55% 0.19 25);
  --danger-tint: oklch(95% 0.035 25);
  --info: oklch(58% 0.14 230);
  --info-tint: oklch(95% 0.025 230);
  --violet: oklch(55% 0.16 305);
  --violet-tint: oklch(95% 0.025 305);
  --neutral-bg: oklch(94% 0.007 265);
  --neutral-text: oklch(42% 0.012 265);
  --font-head: 'Outfit', sans-serif;
  --font-body: 'Source Sans 3', sans-serif;
  font-family: var(--font-body);
  color: var(--text);
}

.imp-shell h1 {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 25px;
  margin: 0;
  color: var(--text);
}

.imp-lede {
  font-size: 13.5px;
  color: var(--muted);
  margin: 6px 0 0;
}

.imp-back {
  font-size: 12.5px;
  color: var(--muted);
  text-decoration: none;
}

.imp-back:hover {
  color: var(--accent);
}

.imp-file-pill {
  font: 600 12.5px var(--font-body);
  background: var(--neutral-bg);
  color: var(--neutral-text);
  padding: 4px 11px;
  border-radius: var(--radius-pill);
}

.imp-rowcount {
  font-size: 12.5px;
  color: var(--faint);
}

/* Step tracker — the comp's one structural addition, on all four screens so the
   flow stops reading as four unrelated pages. Rendered by _ImportSteps.cshtml. */
.imp-steps {
  display: flex;
  align-items: center;
  max-width: 760px;
}

.imp-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.imp-step-dot {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #fff;
  border: 1.5px solid var(--border);
  color: var(--faint);
  display: flex;
  align-items: center;
  justify-content: center;
  font: 600 13px var(--font-body);
}

.imp-step-dot.is-done,
.imp-step-dot.is-current {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* Only the current step gets the halo, so "where am I" survives a glance at a
   tracker whose earlier dots carry the same fill. */
.imp-step-dot.is-current {
  box-shadow: 0 0 0 4px var(--accent-tint);
}

.imp-step-label {
  font: 600 12px var(--font-body);
  color: var(--faint);
  white-space: nowrap;
}

.imp-step.is-done .imp-step-label,
.imp-step.is-current .imp-step-label {
  color: var(--text);
}

/* Bottom margin, not centring: the connector aligns with the dots, which sit
   above their labels. */
.imp-step-line {
  flex: 1;
  height: 2px;
  background: var(--border);
  margin: 0 8px 20px;
}

.imp-step-line.is-done {
  background: var(--accent);
}

@media (max-width: 575.98px) {
  .imp-step-label {
    font-size: 10.5px;
  }

  .imp-step-line {
    margin: 0 4px 20px;
  }
}

/* Grids. Every one collapses to a single or two-up column on phones: Import is
   admin work done on a laptop, but a squashed five-across grid is unreadable
   rather than merely cramped. */
.imp-upload-grid {
  display: grid;
  gap: 24px;
}

@media (min-width: 992px) {
  .imp-upload-grid {
    grid-template-columns: 1.15fr 1fr;
    align-items: start;
  }
}

.imp-grid-5,
.imp-grid-3 {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 768px) {
  .imp-grid-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 992px) {
  .imp-grid-5 {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* Upload */

.imp-dropzone {
  background: #fff;
  border: 1.5px dashed var(--border);
  border-radius: 16px;
  padding: 56px 32px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
  cursor: pointer;
  transition: border-color 0.15s var(--ease-standard), background-color 0.15s var(--ease-standard);
}

.imp-dropzone:hover,
.imp-dropzone:focus-visible {
  border-color: var(--accent);
  outline: none;
}

.imp-dropzone.is-dragover {
  border-color: var(--accent);
  background: var(--accent-tint);
}

.imp-dropzone-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--accent-tint);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.imp-dropzone-title {
  font: 600 16px var(--font-head);
}

.imp-dropzone-or {
  font-size: 13.5px;
  color: var(--muted);
}

.imp-dropzone-hint {
  font-size: 12px;
  color: var(--faint);
  margin-top: 4px;
}

.imp-dropzone-rule {
  width: 100%;
  height: 1px;
  background: var(--border);
  margin: 18px 0 2px;
}

@media (max-width: 767.98px) {
  .imp-dropzone {
    padding: 36px 20px;
  }
}

.imp-card {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 18px 20px;
}

.imp-card-head {
  font: 600 13px var(--font-head);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--faint);
}

.imp-chip {
  font: 600 12.5px var(--font-body);
  background: var(--success-tint);
  color: var(--success);
  padding: 6px 12px;
  border-radius: var(--radius-pill);
}

.imp-callout {
  background: var(--accent-tint);
  border-radius: 14px;
  padding: 16px 20px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--accent-tint-text);
}

.imp-callout-danger {
  background: var(--danger-tint);
  color: var(--danger);
  border-radius: 12px;
  padding: 14px 18px;
  font-size: 13.5px;
}

/* "Also supported" scan rows — the label column is fixed so the values line up. */
.imp-deflist {
  display: flex;
  gap: 14px;
  font-size: 13px;
}

.imp-deflist-term {
  flex: 0 0 90px;
  font: 600 12.5px var(--font-body);
  color: var(--muted);
}

/* Contact slots. The best idea on the old screen, pushed further by the comp: the
   slot's colour is carried by the role card's top bar AND by the tint of every
   row mapped into it, so one person's columns read as a group. Colours are
   assigned by slot number, so .imp-slot-N and .imp-row-slot-N must stay in step
   with the regex in Map.cshtml's script. */
.imp-slot-card {
  background: #fff;
  border: 1px solid var(--border);
  border-top: 3px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
}

.imp-slot-card-title {
  font: 600 12.5px var(--font-body);
  color: var(--text);
  margin-bottom: 8px;
}

.imp-slot-1 { border-top-color: var(--accent); }
.imp-slot-2 { border-top-color: var(--success); }
.imp-slot-3 { border-top-color: var(--warning); }
.imp-slot-4 { border-top-color: var(--violet); }
.imp-slot-5 { border-top-color: var(--danger); }

/* Tables. Kept as real <table>s rather than the comp's flex rows: they carry the
   header association a flex grid loses, and .table-responsive gives the phone
   fallback for free. The <colgroup> widths reproduce the comp's flex ratios. */
.imp-table {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
}

.imp-table table {
  margin: 0;
  font-size: 13px;
  color: var(--text);
}

.imp-table thead th {
  font: 600 11.5px var(--font-head);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--faint);
  border-bottom: 1px solid var(--border);
  padding: 11px 12px;
  white-space: nowrap;
}

.imp-table thead th:first-child { padding-left: 20px; }
.imp-table thead th:last-child { padding-right: 20px; }

.imp-table tbody td {
  padding: 11px 12px;
  border-bottom: 1px solid var(--border);
  border-top: 0;
  vertical-align: middle;
}

.imp-table tbody td:first-child { padding-left: 17px; }
.imp-table tbody td:last-child { padding-right: 20px; }

.imp-table tbody tr:last-child td { border-bottom: 0; }

/* The 3px status stripe rides the first cell rather than the <tr>: a border on a
   row is dropped under border-collapse, which every Bootstrap table uses. */
.imp-table tbody td:first-child {
  border-left: 3px solid transparent;
}

.imp-col-name { font: 600 13px var(--font-body); }
.imp-col-samples { color: var(--muted); }

.imp-row-required td { background: var(--success-tint); }
.imp-row-required td:first-child { border-left-color: var(--success); }

.imp-row-error td { background: var(--danger-tint); }
.imp-row-error td:first-child { border-left-color: var(--danger); }

/* The preview's Note column: muted commentary on an ordinary row, the reason for
   the rejection on an error one. */
.imp-note { color: var(--muted); }
.imp-row-error .imp-note { color: var(--danger); }

.imp-row-slot-1 td { background: var(--accent-tint); }
.imp-row-slot-1 td:first-child { border-left-color: var(--accent); }
.imp-row-slot-2 td { background: var(--success-tint); }
.imp-row-slot-2 td:first-child { border-left-color: var(--success); }
.imp-row-slot-3 td { background: var(--warning-tint); }
.imp-row-slot-3 td:first-child { border-left-color: var(--warning); }
.imp-row-slot-4 td { background: var(--violet-tint); }
.imp-row-slot-4 td:first-child { border-left-color: var(--violet); }
.imp-row-slot-5 td { background: var(--danger-tint); }
.imp-row-slot-5 td:first-child { border-left-color: var(--danger); }

/* Status pills */
.imp-pill {
  display: inline-block;
  font: 600 12px var(--font-body);
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}

.imp-pill-new { background: var(--success-tint); color: var(--success); }
.imp-pill-case { background: var(--info-tint); color: var(--info); }
.imp-pill-updated { background: var(--warning-tint); color: var(--warning); }
.imp-pill-unchanged { background: var(--neutral-bg); color: var(--neutral-text); }
/* White, not danger-tint: this one pill sits on a danger-tinted row. */
.imp-pill-error { background: #fff; color: var(--danger); }

/* Stat tiles */
.imp-stat {
  background: #fff;
  border: 1px solid var(--border);
  border-top: 3px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
}

.imp-stat-value {
  font: 700 24px var(--font-head);
}

.imp-stat-label {
  font-size: 12.5px;
  color: var(--muted);
  margin-top: 2px;
}

.imp-stat-success { border-top-color: var(--success); }
.imp-stat-info { border-top-color: var(--info); }
.imp-stat-warning { border-top-color: var(--warning); }
.imp-stat-neutral { border-top-color: var(--faint); }
.imp-stat-danger { border-top-color: var(--danger); }

.imp-stat-muted {
  background: var(--neutral-bg);
}

.imp-stat-muted .imp-stat-value {
  color: var(--neutral-text);
}

.imp-done-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--success-tint);
  display: flex;
  align-items: center;
  justify-content: center;
}

.imp-done-title {
  font: 700 26px var(--font-head);
}

/* Sticky action bar. Fixed rather than sticky so it clears the sidebar the same
   way .reserve-bar/.route-nav-bar do (see the md+ left:220px rule above); the
   .imp-shell-with-bar padding is what stops it covering the last table row. */
.imp-footer-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1029;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 14px 1rem;
  background: #fff;
  border-top: 1px solid var(--border);
}

@media (min-width: 768px) {
  .imp-footer-bar {
    left: 220px;
    padding: 14px 40px;
  }
}

@media (max-width: 767.98px) {
  .imp-footer-bar {
    bottom: var(--bottom-clearance);
  }
}

.imp-shell-with-bar {
  padding-bottom: 88px;
}

.imp-footer-note {
  font-size: 12.5px;
  color: var(--faint);
}

.imp-footer-ok {
  font-size: 12.5px;
  color: var(--success);
  display: flex;
  align-items: center;
  gap: 6px;
}

.imp-footer-warn {
  font-size: 12.5px;
  color: var(--danger);
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Buttons — same reskin technique as .plat-shell: Bootstrap's blue .btn-primary
   becomes the comp's indigo accent inside this scope only. The footer bar is a
   sibling of .imp-shell (it is fixed), so it is listed alongside it throughout. */
.imp-shell .btn,
.imp-footer-bar .btn {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 13.5px;
  border-radius: 10px;
  padding: 11px 22px;
}

.imp-shell .btn-primary,
.imp-footer-bar .btn-primary {
  background-color: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.imp-shell .btn-primary:hover,
.imp-shell .btn-primary:focus,
.imp-footer-bar .btn-primary:hover,
.imp-footer-bar .btn-primary:focus {
  background-color: var(--accent-dark);
  border-color: var(--accent-dark);
}

.imp-shell .btn-outline-secondary,
.imp-footer-bar .btn-outline-secondary {
  color: var(--text);
  border-color: var(--border);
  background: #fff;
}

.imp-shell .btn-outline-secondary:hover,
.imp-shell .btn-outline-secondary:focus,
.imp-footer-bar .btn-outline-secondary:hover,
.imp-footer-bar .btn-outline-secondary:focus {
  color: var(--text);
  background-color: var(--neutral-bg);
  border-color: var(--border);
}

.imp-shell .form-select,
.imp-shell .form-control {
  font-family: var(--font-body);
  font-size: 12.5px;
  border-color: var(--border);
  border-radius: 8px;
  padding: 6px 10px;
}

.imp-shell .form-select:focus,
.imp-shell .form-control:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 0.2rem var(--accent-tint);
}

/* Duplicate-target marker from Map.cshtml's script — restyled to stay legible
   against the row tints, which Bootstrap's own .is-invalid treatment is not. */
.imp-shell .form-select.is-invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 0.15rem var(--danger-tint);
  background-image: none;
  padding-right: 10px;
}


/* --- Desktop Properties workspace (Views/Properties/_DesktopIndex.cshtml) ---

   Claude Design "10 Properties · 10g". No new token scope: the comp's :root set is the same one
   .pd-shell already declares verbatim, and this is the same area, so the partial wraps itself in
   .pd-shell and only the .pw-* components below are new. A fourth token block would be a second copy
   to keep in step for nothing.

   Everything here is inside .pd-shell and the partial itself is d-none d-md-block, so none of it
   applies on a phone — the card list is untouched. */
.pw-desk {
  font-family: var(--font-body);
  color: var(--text);
}

.pw-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.pw-title {
  font: 700 1.375rem var(--font-head);
  margin: 0;
}

.pw-subhead {
  font-size: 0.8125rem;
  color: var(--muted);
  margin-top: 2px;
}

.pw-head-actions {
  display: flex;
  gap: 0.5rem;
  flex-shrink: 0;
}

.pw-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  border-radius: 9px;
  padding: 0.5rem 0.875rem;
  font: 600 0.8125rem var(--font-body);
  border: 1px solid transparent;
  text-decoration: none;
  white-space: nowrap;
}

.pw-btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.pw-btn-primary:hover {
  background: var(--accent-dark);
  border-color: var(--accent-dark);
  color: #fff;
}

.pw-btn-primary:disabled {
  opacity: 0.55;
}

.pw-btn-ghost {
  background: var(--card);
  border-color: var(--border);
  color: var(--text);
}

.pw-btn-ghost:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* --- Stat strip --- */
.pw-stats {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 0.75rem;
  margin-top: 1.125rem;
}

.pw-stat {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0.875rem 1rem;
}

.pw-stat-label {
  font: 600 0.65rem var(--font-head);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--faint);
}

.pw-stat-value {
  font: 700 1.625rem var(--font-head);
  margin-top: 6px;
}

.pw-stat-warning { color: var(--warning); }
.pw-stat-success { color: var(--success); }

.pw-stat-note {
  font-size: 0.7188rem;
  color: var(--muted);
  margin-top: 2px;
}

/* --- Saved-view tabs --- */
.pw-views {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 1.25rem;
  border-bottom: 1px solid var(--border);
}

.pw-view {
  display: inline-block;
  padding: 0.625rem 0.75rem;
  font: 600 0.8438rem var(--font-head);
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.pw-view:hover { color: var(--text); }

.pw-view.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.pw-view-count {
  color: var(--faint);
  font-weight: 400;
}

/* A shared view carries a dot rather than a word: the tab row is tight, and the title attribute
   carries the meaning for anyone who needs it spelled out. */
.pw-view-shared {
  font-size: 0.5rem;
  vertical-align: middle;
  color: var(--accent);
}

.pw-view-wrap {
  display: inline-flex;
  align-items: center;
}

.pw-view-remove {
  border: 0;
  background: none;
  color: var(--faint);
  font-size: 1rem;
  line-height: 1;
  padding: 0 0.25rem;
  opacity: 0;
}

.pw-view-wrap:hover .pw-view-remove,
.pw-view-remove:focus-visible {
  opacity: 1;
}

.pw-view-remove:hover { color: var(--danger); }

.pw-view-save {
  margin-left: auto;
  border: 0;
  background: none;
  color: var(--accent);
  font: 500 0.7812rem var(--font-body);
  padding: 0.5rem 0;
}

/* --- Filter chip bar --- */
.pw-filters {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding-top: 0.875rem;
}

.pw-search {
  display: flex;
  max-width: 300px;
  flex: 1 1 220px;
}

.pw-search-icon {
  border: 1px solid var(--border);
  border-right: 0;
  border-radius: 8px 0 0 8px;
  padding: 0 0.625rem;
  display: flex;
  align-items: center;
  color: var(--muted);
  background: var(--card);
}

.pw-search-input {
  flex: 1;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: 0 8px 8px 0;
  height: 34px;
  padding: 0 0.625rem;
  font-size: 0.8125rem;
  background: var(--card);
  color: var(--text);
}

.pw-search-input:focus,
.pw-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 0.15rem var(--accent-tint);
}

.pw-chip {
  border: 1px solid var(--border);
  background: var(--card);
  border-radius: 999px;
  padding: 0.4375rem 0.8125rem;
  font: 600 0.7812rem var(--font-body);
  color: var(--muted);
  white-space: nowrap;
}

.pw-chip.active,
.pw-chip:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* An applied value, removable. The href drops just this one filter and re-indexes the rest —
   see WithoutValue in the partial. */
.pw-chip-applied {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: var(--accent);
  border: 1px solid var(--accent);
  color: #fff;
  border-radius: 999px;
  padding: 0.4375rem 0.8125rem;
  font: 600 0.7812rem var(--font-body);
  text-decoration: none;
  white-space: nowrap;
}

.pw-chip-applied:hover {
  background: var(--accent-dark);
  border-color: var(--accent-dark);
  color: #fff;
}

.pw-applied {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding-top: 0.625rem;
}

.pw-chip-clear {
  font-size: 0.7812rem;
  color: var(--muted);
  text-decoration: none;
}

.pw-chip-clear:hover { color: var(--danger); }

.pw-chip-menu {
  padding: 0.75rem;
  min-width: 220px;
  border-color: var(--border);
}

.pw-chip-menu-wide { min-width: 300px; }

.pw-chip-menu-scroll {
  max-height: 340px;
  overflow-y: auto;
}

.pw-check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8125rem;
  padding: 0.25rem 0;
  cursor: pointer;
}

.pw-field-label {
  font: 600 0.65rem var(--font-head);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--faint);
  margin: 0.625rem 0 0.25rem;
}

.pw-field-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.375rem;
}

.pw-field-pair input {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.25rem 0.5rem;
  font-size: 0.8125rem;
  min-width: 0;
  background: var(--card);
  color: var(--text);
}

.pw-select {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.25rem 0.5rem;
  font-size: 0.8125rem;
  background: var(--card);
  color: var(--text);
}

.pw-sort {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.7812rem;
  color: var(--muted);
}

.pw-assign-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: var(--accent-tint);
  color: var(--accent-tint-text);
  border-radius: 10px;
  padding: 0.625rem 0.875rem;
  margin-top: 0.875rem;
  font-size: 0.8125rem;
}

/* --- Table --- */
.pw-table-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  margin-top: 0.875rem;
  /* The comp's card clips its own header/footer rows; the table's own borders do the rest. */
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(20, 20, 60, 0.03), 0 6px 16px rgba(20, 20, 60, 0.04);
}

.pw-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  margin: 0;
}

.pw-table thead th {
  font: 600 0.65rem var(--font-head);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--faint);
  padding: 0.625rem 0.5rem;
  border-bottom: 1px solid var(--border);
  text-align: left;
}

.pw-table thead th:first-child,
.pw-table tbody td:first-child { padding-left: 1rem; }

.pw-table thead th:last-child,
.pw-table tbody td:last-child { padding-right: 1rem; }

.pw-table tbody td {
  padding: 0.75rem 0.5rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.8125rem;
  vertical-align: top;
  overflow-wrap: anywhere;
}

.pw-table tbody tr:last-child td { border-bottom: 0; }

.pw-row:hover { background: var(--bg); }

.pw-row-selected,
.pw-row-selected:hover { background: var(--accent-tint); }

/* Reserved rows stay visible and readable — they are excluded from selection, not from the list.
   Hiding them is the ExcludeReserved filter's job, and it is the rep's choice. */
.pw-row-reserved .pw-address { color: var(--muted); }

.pw-address {
  font: 600 0.8438rem var(--font-body);
  color: var(--text);
  text-decoration: none;
}

.pw-address:hover { color: var(--accent); }

.pw-address-sub {
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 2px;
}

.pw-row-note {
  font-size: 0.7188rem;
  color: var(--faint);
}

.pw-muted { color: var(--muted); }
.pw-dash { color: var(--faint); }
.pw-never { color: var(--success); }

/* Sheriff sale inside 30 days — the only value in the table that earns a colour, matching the
   stat tile above it. */
.pw-urgent {
  color: var(--warning);
  font-weight: 600;
}

.pw-pill {
  display: inline-block;
  border-radius: 999px;
  padding: 0.25em 0.6em;
  font: 600 0.6875rem var(--font-body);
  background: var(--neutral-bg);
  color: var(--neutral-text);
}

.pw-pill-accent {
  background: var(--accent-tint);
  color: var(--accent-tint-text);
}

.pw-pill-danger {
  background: var(--danger-tint);
  color: var(--danger);
}

.pw-tag {
  display: inline-block;
  border-radius: 999px;
  padding: 0.2em 0.5em;
  font: 600 0.625rem var(--font-body);
  margin-left: 0.375rem;
  vertical-align: middle;
}

.pw-tag-danger { background: var(--danger); color: #fff; }
.pw-tag-dark { background: #212529; color: #fff; }
.pw-tag-warning { background: var(--warning-tint); color: var(--warning); }

.pw-row-menu {
  border: 0;
  background: none;
  color: var(--faint);
  padding: 0 0.375rem;
  line-height: 1;
  font-size: 1rem;
}

.pw-row-menu:hover { color: var(--text); }

.pw-empty {
  text-align: center;
  color: var(--muted);
  padding: 3rem 1rem;
}

/* --- Bulk toolbar --- */
.pw-bulk {
  display: none;
  align-items: center;
  gap: 0.75rem;
  background: var(--card);
  border: 1px solid var(--accent);
  border-radius: 12px;
  padding: 0.625rem 0.875rem;
  margin-top: 0.75rem;
  box-shadow: 0 6px 20px rgba(20, 20, 60, 0.08);
}

.pw-bulk.show { display: flex; }

.pw-bulk-over {
  border-color: var(--danger);
  background: var(--danger-tint);
}

.pw-bulk-count {
  font: 600 0.8438rem var(--font-body);
}

.pw-bulk-assign {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.8125rem;
  color: var(--muted);
  margin: 0;
}

/* --- Footer --- */
.pw-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.875rem;
  font-size: 0.7812rem;
  color: var(--muted);
}

.pw-pager {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* --- Desktop Property Details: five tabs become three columns (Claude Design "10 Properties · 10h") ---

   One markup for both, not a desktop-only view. _PropertyDetails is shared with the Route page, so a
   fork would be two arrangements to keep in step and a second Street View proxy request per page load.

   The show/hide toggle is depth-independent: `.tab-pane` / `.tab-pane.active` below match any tab-pane
   regardless of how deeply it's nested, so it doesn't matter whether a pane sits directly under
   .tab-content or inside a grouping wrapper — unlike an earlier version keyed to one exact DOM path
   (`.pd-detail-grid > .pd-detail-col > .tab-pane`), which broke the moment that path stopped matching
   exactly. #detailsTabs/.tab-pane is the only nav-tabs usage app-wide (site-wide grep), so this doesn't
   risk colliding with some other tab component. Bootstrap's own `.tab-content > .tab-pane` rule simply
   doesn't match once a pane has a wrapper parent, so there's no specificity fight with it either. */
.tab-pane {
  display: none;
}

.tab-pane.active {
  display: block;
}

/* .pd-detail-col groups a column's pane(s) (Views/Shared/_PropertyDetails.cshtml) — a plain block below
   md (invisible to phone layout, since it has no border/padding of its own) and its own flex column at
   md+, so each column's content stacks to its own natural height instead of being forced into shared
   grid row tracks with the other two columns (that forcing is what previously left gaps above shorter
   cards — e.g. Custom fields floating below a shorter People column while Cases ran longer). */
/* Compound selector (not just .pd-detail-col-wide) so this beats the plain .pd-detail-col{flex:1 1 0}
   inside the md+ block below regardless of source order — same specificity otherwise, and that rule
   comes later in the file. */
.pd-detail-col.pd-detail-col-wide {
  flex: 1.15 1 0;
}

/* Fact strip beside the hero — Bootstrap's own d-none/.d-md-grid utilities do the showing. */
.pd-fact-strip {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.625rem;
}

.pd-fact {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 11px;
  padding: 0.6875rem 0.8125rem;
}

.pd-fact-value {
  font: 700 1.0625rem var(--font-head);
  margin-top: 5px;
}

.pd-fact-urgent { color: var(--warning); }
.pd-fact-empty { color: var(--faint); }

.pd-fact-note {
  font-size: 0.7188rem;
  color: var(--muted);
}

/* Lead status card: the .pd-status-select pill dropdown in place of the label/value/note stack every
   other fact card uses — same live <select>/form as the (mobile-only) .pd-actions-row copy. */
.pd-fact-status .pd-status-select {
  width: 100%;
}

/* Card header titles + flat "+ Add X" text-link (comp 10h) — desktop only; mobile keeps the bordered
   icon+text pill button (.pd-icon-btn-add) and no title, since the tab label above already names the
   pane. Card markup/class is shared with mobile (Views/Shared/_PropertyDetails.cshtml), so only the
   md+ half of this changes anything there. */
.pd-card-header-title {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 0.84375rem;
}

/* Trash icon, distinguished from the (still grey) pencil edit icon it used to share a look with —
   the only two icon-button affordances .pd-edit-pencil covers on this page. */
.pd-delete-icon {
  color: var(--danger);
}

.pd-delete-icon:hover,
.pd-delete-icon:focus {
  color: var(--danger);
  background: var(--danger-tint);
}

/* Breadcrumb + Prev/Next lead (Views/Properties/Details.cshtml). */
.pd-crumb {
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.7812rem;
  color: var(--muted);
  margin-bottom: 0.75rem;
}

.pd-crumb a { color: var(--accent); text-decoration: none; }
.pd-crumb a:hover { color: var(--accent-dark); }
.pd-crumb-sep { color: var(--faint); }
.pd-crumb-current { font-weight: 600; color: var(--text); }

.pd-crumb-nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* An end-of-list edge renders the label greyed rather than removing it, so the pair does not
   jump sideways as a rep walks the list. */
.pd-crumb-off { color: var(--faint); }

@media (min-width: 768px) {
  /* Tabs are the phone affordance; on a laptop there is no reason to tap through five panes. */
  .pd-shell .pd-tabs { display: none; }

  .pd-detail-grid {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
  }

  .pd-detail-col {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-width: 0;
  }

  /* Every pane visible at once — .fade leaves the inactive ones at opacity 0, and the base .tab-pane
     rule above would otherwise hide every pane but the phone's active one. */
  .pd-detail-col > .tab-pane,
  .pd-detail-col > .tab-pane.fade {
    display: block;
    opacity: 1;
  }

  /* Column one is People then Overview (which at this point is just the Custom fields card — see
     .pd-overview-summary below), per the comp. The overview pane is second in the DOM (its tab is
     first on a phone), so it's reordered here rather than moved — moving it would change nothing on
     desktop and everything about the phone's default tab. */
  #overview-pane { order: 2; }

  /* Overview's other three cards are each said in full by a column of its own here. */
  .pd-overview-summary { display: none; }

  /* Card header titles + flat text-link "Add" affordance (comp 10h), replacing the mobile bordered
     icon+text pill button — the same .pd-icon-btn-add markup, restyled only at this breakpoint. */
  .pd-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.75rem 1rem !important;
    border-bottom: 1px solid var(--border) !important;
  }

  .pd-card-header .pd-icon-btn-add {
    height: auto;
    padding: 0;
    border: 0;
    background: transparent;
  }
}

/* --- Legal pages (Views/Legal) --- */
/* Minimal chrome for a HideNav page reachable both anonymously and while signed in — no sidebar,
   just the brand and (when authenticated) a way back. */
.legal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 1rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--border-subtle);
}

.legal-brand {
  font-family: 'Outfit', sans-serif;
  font-weight: 700;
  font-size: 1.1rem;
  color: inherit;
}

/* A prose column, narrower than the app's full-width grids: these are read, not scanned. */
.legal-page {
  max-width: 46rem;
  margin: 0 auto 3rem;
  line-height: 1.65;
}

.legal-footer {
  margin-top: 2.25rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border-subtle);
  font-size: 0.875rem;
  color: var(--muted, #6c757d);
}

.legal-title {
  font-size: 1.75rem;
  margin-bottom: 0.25rem;
}

.legal-meta {
  color: var(--muted);
  font-size: 0.875rem;
  margin-bottom: 2rem;
}

.legal-page h2 {
  font-size: 1.125rem;
  margin-top: 2.25rem;
  margin-bottom: 0.75rem;
}

.legal-page h3 {
  font-size: 1rem;
  font-weight: 600;
  margin-top: 1.5rem;
  margin-bottom: 0.5rem;
}

.legal-page p,
.legal-page li {
  font-size: 0.9375rem;
}

.legal-page ul {
  padding-left: 1.25rem;
}

.legal-page li {
  margin-bottom: 0.4rem;
}

/* Wide on a phone by nature, so it scrolls inside itself rather than widening the page. */
.legal-table-wrap {
  overflow-x: auto;
}

.legal-table {
  width: 100%;
  min-width: 34rem;
  border-collapse: collapse;
  margin: 1rem 0 1.5rem;
  font-size: 0.875rem;
}

.legal-table th,
.legal-table td {
  border: 1px solid var(--border);
  padding: 0.5rem 0.625rem;
  text-align: left;
  vertical-align: top;
}

.legal-table th {
  background: #f6f7f9;
  font-weight: 600;
}

/* Markdown source, not prose: a monospace column so a lawyer's pasted text keeps its shape. */
.legal-editor {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.8125rem;
  line-height: 1.5;
}

/* --- Share composer (Views/Properties/_ShareModal.cshtml, property-share.js) --- */

/* Deliberately not modal-fullscreen-sm-down: the backdrop staying visible above and below is what
   makes it read as a popup you can dismiss by tapping past it. */
.pd-share-content {
  max-height: 85vh;
}

.pd-share-content .modal-body {
  overflow-y: auto;
}

.pd-share-tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
}

.pd-share-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.125rem;
  position: relative;
  padding: 0.625rem 0.625rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  cursor: pointer;
  min-height: 60px;
}

.pd-share-tile:has(.pd-share-tile-check:disabled) {
  cursor: default;
  opacity: 0.55;
}

.pd-share-tile-check {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  margin: 0;
}

.pd-share-tile-name {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 0.875rem;
  padding-right: 1.25rem;
}

.pd-share-tile-count {
  font-size: 0.75rem;
  color: var(--faint);
}

/* On, so its content is in the message. Matches .pd-chip.active, which already means "on" here. */
.pd-share-tile.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.pd-share-tile.active .pd-share-tile-count {
  color: rgba(255, 255, 255, 0.75);
}

/* Open, so the row below belongs to this tile. Reads whether or not the tile is on. */
.pd-share-tile-open::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -9px;
  transform: translateX(-50%);
  border: 8px solid transparent;
  border-top-color: var(--border);
}

.pd-share-panel {
  margin-top: 1rem;
  padding: 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg);
  max-height: 34vh;
  overflow-y: auto;
}

.pd-share-row {
  padding: 0.375rem 0.25rem;
}

.pd-share-row + .pd-share-row {
  border-top: 1px solid var(--border);
}

.pd-share-check {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  cursor: pointer;
  font-size: 0.875rem;
}

.pd-share-check .form-check-input {
  margin-top: 0.2rem;
  flex-shrink: 0;
}

.pd-share-line,
.pd-share-when {
  display: block;
}

.pd-share-line {
  font-weight: 600;
}

.pd-share-when,
.pd-share-role {
  font-size: 0.75rem;
  color: var(--muted);
}

.pd-share-numbers {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding: 0.375rem 0 0.125rem 1.625rem;
}

.pd-share-number {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.8125rem;
  cursor: pointer;
}

.pd-share-number .form-check-input {
  margin: 0;
}

/* The one place the message is legible before it is sent, so it keeps its own line breaks. */
.pd-share-preview {
  margin: 0.25rem 0 0;
  padding: 0.625rem 0.75rem;
  border-radius: var(--radius-lg);
  background: var(--neutral-bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 30vh;
  overflow-y: auto;
}

.pd-share-copied {
  margin-right: auto;
  font-size: 0.8125rem;
  color: var(--success);
}

/* --- Drag-to-reorder phone rows on the contact forms (phone-rows.js) --- */

/* The rows post as repeated name="Phones" and bind in document order, so dragging one is the whole
   edit: no re-indexing, nothing to save separately. */
.phone-row .phone-handle {
  display: flex;
  align-items: center;
  padding: 0 0.625rem;
  border: 1px solid var(--bs-border-color);
  border-right: 0;
  border-radius: 0.375rem 0 0 0.375rem;
  background: var(--bs-tertiary-bg);
  color: var(--bs-secondary-color);
  cursor: grab;
  /* Without this, a touch drag on the handle is read as a page scroll first. */
  touch-action: none;
}

.phone-row .phone-handle:active {
  cursor: grabbing;
}

.phone-row-ghost {
  opacity: 0.4;
}

.phone-row-chosen {
  box-shadow: 0 0 0 2px var(--bs-primary);
  border-radius: 0.375rem;
}
