:root {
  /* ACCELQ brand theme: deep blue + white + green, matching the logo. */
  --ink: #1e3ae8;        /* AccelQ blue -- sidebar background */
  --ink-deep: #142db8;   /* darker blue, sidebar gradient depth */
  --panel: #ffffff;
  --panel-2: #f1f4fc;
  --border: #e1e6f5;
  --border-strong: #aab4d6; /* more visible divider, used where a pale --border reads as invisible (e.g. dense data tables) */
  --text: #131a33;
  --text-dim: #6b7280;
  --teal: #22c55e;       /* AccelQ green -- primary accent, success */
  --amber: #f5a623;
  --coral: #ff6b6b;
  --violet: #1e3ae8;     /* AccelQ blue -- secondary accent, gradients */
  --bg: #f4f6fb;
  --radius: 10px;
  --font-family: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, sans-serif;

  /* Table view density -- app-wide (every <table>, not just Contacts),
     set from Settings > Appearance and applied via body[data-density]
     below. These "comfortable" values match what every table already
     shipped with, so a user who never touches the setting sees no change.
     Each is a clamp() so it also scales a little with the viewport --
     see the "fluid type scale" comment on html{} below for why. */
  --table-font-size: clamp(12px, 0.55vw + 11px, 13px);
  --table-header-font-size: clamp(11px, 0.5vw + 10px, 12px);
  --table-cell-padding-y: 10px;
  --table-cell-padding-x: 10px;
  --table-header-padding-y: 8px;
  --table-header-padding-x: 10px;
}

/* Fluid type scale: instead of every rule below being frozen at one literal
   px value regardless of window size, the root font-size itself flexes
   with viewport width (clamp(min, preferred, max) -- never smaller than
   14px, never larger than 16px, scaling smoothly in between). Any rule
   written in rem then automatically scales with it. Only the highest-
   traffic, always-on-screen text (sidebar nav/brand, topbar title, buttons,
   filter inputs, table cells via the vars above) was converted to rem for
   this pass -- the bulk of one-off in-page text keeps its existing px
   sizing rather than risking a full rewrite of every rule in this file. */
html { font-size: clamp(14px, 0.6vw + 12.5px, 16px); }

* { box-sizing: border-box; }

.hidden { display: none !important; }

body {
  margin: 0;
  font-family: var(--font-family);
  background: var(--bg);
  color: var(--text);
  font-size: 1rem;
}

body[data-density="compact"] {
  --table-font-size: clamp(11px, 0.5vw + 10px, 12px);
  --table-header-font-size: clamp(10px, 0.45vw + 9px, 11px);
  --table-cell-padding-y: 5px;
  --table-cell-padding-x: 8px;
  --table-header-padding-y: 4px;
  --table-header-padding-x: 8px;
}
body[data-density="spacious"] {
  --table-font-size: clamp(13px, 0.6vw + 12px, 14px);
  --table-header-font-size: clamp(12px, 0.55vw + 11px, 13px);
  --table-cell-padding-y: 16px;
  --table-cell-padding-x: 14px;
  --table-header-padding-y: 12px;
  --table-header-padding-x: 14px;
}

#login-screen {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at 20% 20%, #3654f5 0%, var(--ink) 60%);
}

.login-card {
  width: 360px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 36px 32px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}

.brand-mark {
  width: 34px;
  height: 34px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--teal), var(--violet));
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  color: #ffffff;
}

.brand-name { font-size: clamp(1.125rem, 0.5vw + 1rem, 1.25rem); font-weight: 700; letter-spacing: 0.3px; }
.brand-sub { color: var(--text-dim); font-size: 13px; margin-bottom: 24px; }

label { display: block; font-size: 12px; color: var(--text-dim); margin: 14px 0 6px; }

input, select, textarea, button {
  font-family: inherit;
}

input, select, textarea {
  width: 100%;
  padding: 10px 12px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 14px;
}

textarea { resize: vertical; min-height: 60px; }

/* Outreach draft / compose content only (contact drafts, follow-ups,
   templates, sequence steps, Accounts Gem output, the Fresh Email
   compose box) -- deliberately scoped to this one class rather than
   changed on the base font vars, since the rest of the app's font and
   sizes are staying exactly as they are. font-size is fixed at 11pt
   (matches Word/Outlook's "11" point size) regardless of any per-user
   Appearance font setting elsewhere. */
.draft-font {
  font-family: Calibri, Candara, "Segoe UI", Optima, Arial, sans-serif !important;
  font-size: 11pt !important;
  color: #000000 !important;
}

button {
  cursor: pointer;
  font-family: inherit;
}

.btn {
  border: none;
  border-radius: 8px;
  padding: 10px 16px;
  font-size: clamp(0.85rem, 0.3vw + 0.78rem, 0.875rem);
  font-weight: 600;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
}

.btn-primary {
  background: linear-gradient(135deg, var(--teal), var(--violet));
  color: #ffffff;
  border: none;
}

.btn-danger { background: var(--coral); color: #2a0a0a; border: none; }
.btn-full { width: 100%; margin-top: 20px; }
.btn-small { padding: 6px 10px; font-size: clamp(0.72rem, 0.25vw + 0.67rem, 0.75rem); }

/* Without this, a disabled button (e.g. "Use this" before a key is saved,
   or the placeholder Import-source cards) renders pixel-identical to an
   enabled one -- same gradient, same color -- so clicking it silently does
   nothing with zero visual sign why. That reads as "the app didn't respond"
   rather than "this button isn't available yet." */
.btn:disabled, .btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  filter: grayscale(0.3);
}

.error-text { color: var(--coral); font-size: 13px; margin-top: 10px; min-height: 16px; }
.hint { color: var(--text-dim); font-size: 12px; margin-top: 18px; line-height: 1.5; }

.login-row { display: flex; align-items: center; justify-content: space-between; margin-top: 14px; }
.login-remember { display: flex !important; align-items: center; gap: 6px; margin: 0 !important; font-size: 13px; color: var(--text); cursor: pointer; }
.login-remember input[type="checkbox"] { width: 14px; height: 14px; margin: 0; cursor: pointer; accent-color: var(--ink); }
.login-row a, .modal-link { color: var(--ink); font-size: 13px; text-decoration: none; }
.login-row a:hover, .modal-link:hover { text-decoration: underline; }

#app-shell { display: none; min-height: 100vh; }
#app-shell.active { display: flex; }
#login-screen.hidden { display: none; }

.sidebar {
  width: 220px;
  flex-shrink: 0;
  background: linear-gradient(180deg, var(--ink) 0%, var(--ink-deep) 100%);
  border-right: none;
  padding: 20px 14px;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  color: #ffffff;
  /* Collapsing (see .sidebar-collapse-btn) animates this down to 0 rather
     than just yanking it away, so the rest of the layout visibly reflows
     instead of jump-cutting. */
  transition: width 0.18s ease, padding 0.18s ease;
}

body[data-sidebar="collapsed"] .sidebar {
  width: 0;
  padding-left: 0;
  padding-right: 0;
  overflow: hidden;
}

.sidebar .brand { padding: 0 6px; margin-bottom: 12px; }
.sidebar .brand-name { color: #ffffff; }

/* Top-right of the sidebar's own content (the brand row), matching the
   dark sidebar rather than the light .icon-btn used in the topbar -- same
   shape/sizing language, just themed for the blue background it sits on. */
.sidebar-collapse-btn {
  margin-left: auto;
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  background: transparent;
  border: 1px solid transparent;
  color: rgba(255, 255, 255, 0.72);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.sidebar-collapse-btn:hover { background: rgba(255, 255, 255, 0.14); color: #ffffff; }

/* Reopen tab: fixed top-left, only shown once the sidebar is collapsed.
   Uses the same teal->blue brand gradient as .brand-mark/.btn-primary so it
   reads as "part of this app" rather than a generic floating control. */
.sidebar-expand-btn {
  display: none;
  position: fixed;
  top: 14px;
  left: 14px;
  z-index: 60;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--teal), var(--violet));
  color: #ffffff;
  border: none;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(19, 26, 51, 0.22);
}
.sidebar-expand-btn:hover { filter: brightness(1.08); }
body[data-sidebar="collapsed"] .sidebar-expand-btn { display: flex; }

.sidebar-profile {
  display: block;
  width: 100%;
  text-align: left;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 20px;
  cursor: pointer;
}

.sidebar-profile:hover { border-color: var(--teal); }
.sidebar-profile-name { font-size: clamp(0.8rem, 0.3vw + 0.73rem, 0.8125rem); font-weight: 600; color: #ffffff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-profile-title { font-size: clamp(0.68rem, 0.25vw + 0.63rem, 0.6875rem); color: rgba(255, 255, 255, 0.68); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  color: rgba(255, 255, 255, 0.72);
  cursor: pointer;
  font-size: clamp(0.85rem, 0.3vw + 0.78rem, 0.875rem);
  margin-bottom: 4px;
}

.nav-item:hover { background: rgba(255, 255, 255, 0.1); color: #ffffff; }
.nav-item.active { background: rgba(255, 255, 255, 0.14); color: var(--teal); font-weight: 600; }

.badge {
  margin-left: auto;
  background: var(--coral);
  color: #ffffff;
  border-radius: 999px;
  font-size: 11px;
  padding: 1px 7px;
  font-weight: 700;
}

.sidebar-footer { margin-top: auto; padding-top: 16px; border-top: 1px solid rgba(255, 255, 255, 0.18); font-size: 13px; }
.sidebar-footer,
.sidebar-footer #current-user-name { color: #ffffff; }
.sidebar-footer .role-tag { color: rgba(255, 255, 255, 0.68); font-size: 12px; }
.sidebar-footer .btn { background: rgba(255, 255, 255, 0.1); color: #ffffff; border-color: rgba(255, 255, 255, 0.25); }
.sidebar-footer .btn:hover { background: rgba(255, 255, 255, 0.18); }

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

.topbar {
  min-height: 52px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 20px;
  flex-wrap: wrap;
  row-gap: 6px;
  position: relative; /* anchors .leave-ticker, which floats in the gap
    between .topbar-left and .topbar-right rather than taking part in
    their flex sizing -- see the comment on .leave-ticker below. */
}

.topbar h1 { font-size: 1.0625rem; margin: 0; flex-shrink: 0; }

/* Admin-only "who's on leave/WFH today" readout, rendered into
   #view-title-extra on the Leaves/WFH page (see renderLeave() /
   startLeaveTicker() in app.js). .topbar-left and .topbar-right are both
   flex-shrink:0 with space-between on their parent, so the gap between the
   page title and the topbar's buttons is otherwise just empty room -- this
   floats centered in that gap via absolute positioning instead of fighting
   the sibling flex boxes for it. */
.leave-ticker {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  background: rgba(30, 58, 232, 0.06);
  border: 1px solid rgba(30, 58, 232, 0.15);
  border-radius: 999px;
  padding: 6px 14px;
  white-space: nowrap;
  max-width: min(46vw, 380px);
  pointer-events: none;
}
.leave-ticker-clock { position: relative; width: 14px; height: 14px; flex-shrink: 0; }
.leave-ticker-clock-ring {
  position: absolute;
  inset: 0;
  border: 1.5px solid rgba(30, 58, 232, 0.35);
  border-radius: 50%;
}
.leave-ticker-clock-hand {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1.5px;
  height: 6px;
  background: #1e3ae8;
  transform-origin: 50% 100%;
  transform: translate(-50%, -100%) rotate(0deg);
  animation: leave-ticker-hand-spin 3s linear infinite;
}
@keyframes leave-ticker-hand-spin {
  from { transform: translate(-50%, -100%) rotate(0deg); }
  to { transform: translate(-50%, -100%) rotate(360deg); }
}
.leave-ticker-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #3ebd82;
  flex-shrink: 0;
  animation: leave-ticker-pulse 2.4s ease-in-out infinite;
}
@keyframes leave-ticker-pulse {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 1; }
}
.leave-ticker-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.leave-ticker-text.leave-ticker-fading { opacity: 0; transform: translateY(4px); }
@media (max-width: 900px) {
  .leave-ticker { display: none; }
}
.topbar-left { display: flex; gap: 14px; align-items: center; flex-shrink: 0; }
.topbar-right { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; row-gap: 6px; justify-content: flex-end; min-width: 0; }
/* justify-content: flex-end (not the default flex-start) so that when this
   row doesn't have room for every filter + action button on one line, the
   overflow (e.g. "Quick Add" / "+ New Contact") wraps to a second line
   still hugging the right edge -- lined up under the settings gear --
   instead of collapsing to the left edge under the search box, stranded
   away from the rest of the toolbar. */
#topbar-actions { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; row-gap: 6px; justify-content: flex-end; }

/* Toolbar buttons that sit alongside the folded-in filters (Accounts,
   Contacts) -- smaller than the app's default .btn so title + filters +
   all six action buttons realistically fit on one header line instead of
   the default button padding forcing an early wrap. */
.btn-compact { padding: 6px 10px; font-size: clamp(0.8rem, 0.28vw + 0.74rem, 0.8125rem); }

/* Compact filter controls folded directly into the topbar (Accounts,
   Contacts) so the page title, the search/filter row, and the action
   buttons all live in one slim header band instead of a separate
   full-width filter card underneath -- that used to cost an extra card's
   worth of border/padding/margin before a single table row was visible.
   Sits inline with the toolbar buttons in #topbar-actions. */
.topbar-filters { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.topbar-filters input, .topbar-filters select {
  padding: 6px 9px;
  font-size: clamp(0.8rem, 0.28vw + 0.74rem, 0.8125rem);
}
/* Fixed pixel widths, not "auto" -- a <select> with width:auto sizes itself
   to its widest <option> (a long account/company name can blow one up past
   300px), which silently broke the single-row layout as soon as real data
   with long names loaded even though it looked fine with short placeholder
   text. Fixed widths keep the row's total size predictable regardless of
   what the options say; long option text just clips inside the box. */
.topbar-filters input[type="text"] { width: 150px; flex-shrink: 0; }
.topbar-filters input[type="date"] { width: 132px; flex-shrink: 0; }
.topbar-filters select { width: 106px; flex-shrink: 0; text-overflow: ellipsis; }
.topbar-filter-count { font-size: 12px; color: var(--text-dim); white-space: nowrap; }
.topbar-divider { width: 1px; align-self: stretch; background: var(--border); margin: 2px 2px; }

/* ---- Two-row toolbar for list views with filters (Contacts, Accounts) ----
   These are the only topbars that combine a title, a filter/search group,
   AND a full row of action buttons -- too much to ever fit on one line
   without either wrapping unpredictably (buttons stranding on their own
   left-aligned row, disconnected from the rest of the toolbar) or crowding
   everything together. Instead this pins it to exactly two clean rows:
     Row 1: page title, filters + result count, settings -- all close
            together with one small consistent gap, no pushed-apart gaps
     Row 2: Search Apollo, Export CSV, Export XLSX, Import, Quick Add, +New
            -- left-aligned, starting right under the title
   `:has()` scopes this to only topbars that actually contain .topbar-filters
   -- simpler topbars elsewhere (Leads, Leave, etc., often just one button)
   are untouched and keep their original single-row layout.
   The trick: make the two wrapper divs (.topbar-right, #topbar-actions)
   `display: contents` so their children become direct flex items of
   .topbar itself, then use `order` to place title/filters/gear on row 1.
   The existing .topbar-divider (already sitting in the markup right
   between the filters and the buttons) is repurposed as the forced line
   break: flex-basis:100% makes it alone fill row 1's remaining width so
   everything after it -- the buttons -- is pushed onto a fresh row 2.
   Deliberately no margin-left:auto anywhere in this block -- an earlier
   version pushed the gear and the button row to the far right edge, which
   just left a big dead gap in the middle instead of looking intentional. */
.topbar:has(.topbar-filters) {
  justify-content: flex-start;
  column-gap: 14px;
}
.topbar:has(.topbar-filters) .topbar-right,
.topbar:has(.topbar-filters) #topbar-actions {
  display: contents;
}
.topbar:has(.topbar-filters) .topbar-left { order: 1; }
.topbar:has(.topbar-filters) .topbar-filters { order: 2; }
.topbar:has(.topbar-filters) #settings-gear-btn { order: 3; }
.topbar:has(.topbar-filters) .topbar-divider {
  order: 4;
  flex-basis: 100%;
  width: auto;
  height: 0;
  margin: 0;
  background: none;
  align-self: auto;
}
.topbar:has(.topbar-filters) .btn-compact { order: 5; }

/* Streak strip shown beside the page title on Activity Report -- a quick
   glance at which of the last few workdays have a logged entry. */
.streak-strip { display: flex; align-items: center; gap: 6px; background: var(--panel-2); border-radius: 999px; padding: 5px 10px; }
.streak-strip .streak-label { font-size: 11px; color: var(--text-dim); margin-right: 2px; }
.streak-strip .streak-count { font-size: 11px; color: var(--text-dim); margin-left: 2px; font-weight: 600; }
.streak-dot { width: 18px; height: 18px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; }
.streak-dot.done { background: #e3f9ec; color: #16a34a; }
.streak-dot.missing { background: #fdeaea; color: #d64545; }

/* Activity Report summary tiles -- same color language as the table's
   group headers (mapped=green, emails=blue, linkedin=amber, responses=
   coral) so the tiles read as totals of those same groups. */
.tiles-heading { font-size: 12px; font-weight: 600; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.4px; margin: 4px 0 8px; }
.activity-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin-bottom: 20px; }
.activity-tile { border-radius: 12px; padding: 14px 18px; border: 1px solid transparent; }
.activity-tile .tile-label { font-size: 12px; }
.activity-tile .tile-value { font-size: 22px; font-weight: 700; margin-top: 4px; }
.activity-tile.tile-mapped { background: rgba(34, 197, 94, 0.12); color: #15803d; border-color: rgba(34, 197, 94, 0.35); }
.activity-tile.tile-emails { background: rgba(30, 58, 232, 0.08); color: #1e3ae8; border-color: rgba(30, 58, 232, 0.3); }
.activity-tile.tile-linkedin { background: rgba(245, 166, 35, 0.16); color: #b8790f; border-color: rgba(245, 166, 35, 0.4); }
.activity-tile.tile-responses { background: rgba(255, 107, 107, 0.12); color: #c23636; border-color: rgba(255, 107, 107, 0.35); }

.icon-btn {
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-dim);
  cursor: pointer;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.icon-btn:hover { background: var(--panel-2); color: var(--text); border-color: var(--border); }
.icon-btn.active-icon { color: var(--teal); background: var(--panel-2); border-color: var(--border); }

.content { padding: 14px 16px; overflow-y: auto; }

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

/* The Dashboard's top row of 5 glance cards (Total Companies, Total
   Contacts, Leads Achieved, Leaves/WFH, Approve/Pending) -- kept to a
   single row on any reasonably wide screen instead of auto-fit's usual
   wrap, so the last card doesn't fall to a lonely second row. Narrower
   widths still degrade gracefully via the media queries below rather than
   squeezing 5 columns into a phone-sized viewport. */
.stat-grid-5 {
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 12px;
}
.stat-grid-5 .stat-card { padding: 14px; }
.stat-grid-5 .stat-card .label { font-size: 11px; }
.stat-grid-5 .stat-card .value { font-size: 22px; }
@media (max-width: 1100px) {
  .stat-grid-5 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .stat-grid-5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.stat-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px;
  position: relative;
  overflow: hidden;
}

.stat-card .label { color: var(--text-dim); font-size: 12px; letter-spacing: 0.2px; max-width: calc(100% - 40px); }
.stat-card .value { font-size: 26px; font-weight: 700; margin-top: 6px; }
.stat-card .accent-teal { color: var(--teal); }
.stat-card .accent-amber { color: var(--amber); }
.stat-card .accent-coral { color: var(--coral); }
.stat-card .accent-violet { color: var(--violet); }

.stat-card-icon {
  position: absolute; top: 16px; right: 16px;
  width: 34px; height: 34px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.stat-card-icon.icon-teal { background: #e3f9ec; color: #16a34a; }
.stat-card-icon.icon-amber { background: #fff4e0; color: #b8790f; }
.stat-card-icon.icon-coral { background: #fdeaea; color: #d64545; }
.stat-card-icon.icon-violet { background: #e7ecff; color: var(--violet); }

.section-label {
  display: flex; align-items: center; gap: 7px;
  color: var(--text-dim); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.4px;
  margin: 18px 0 10px;
}
.section-label:first-child { margin-top: 0; }
.section-label .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }

/* Follow-up Pipeline stepper on the Dashboard: Fresh Email (amber, the
   one-off first-touch send) leading into a horizontal, brand-gradient
   funnel from stage 1 (green) to stage 5 (blue), each stage clickable
   through to the matching sends in Emailing > Emails. Built with plain
   flex/CSS -- no chart library needed for six connected dots. */
.followup-stepper {
  display: flex; align-items: flex-start; margin-top: 12px;
  overflow-x: auto; padding-bottom: 4px;
}
.followup-stage {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  min-width: 132px; cursor: pointer; padding: 8px 6px; border-radius: 10px;
  transition: background 0.15s;
}
.followup-stage:hover { background: var(--panel-2); }
.followup-stage-num {
  width: 38px; height: 38px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--stage-color); color: #ffffff; font-weight: 700; font-size: 15px;
  box-shadow: 0 4px 10px rgba(19, 26, 51, 0.18);
}
/* Fresh Email uses a paper-plane icon instead of a step number -- it isn't
   "step 0" of the cadence, it's the send that starts it. */
.followup-stage-icon svg { width: 16px; height: 16px; }
.followup-stage-label { font-size: 12px; font-weight: 600; color: var(--text); white-space: nowrap; margin-top: 8px; }
.followup-stage-sub { font-size: 11px; color: var(--text-dim); margin-top: 8px; white-space: nowrap; }
.followup-stage-connector { flex: 1 1 24px; height: 2px; background: var(--border); margin-top: 25px; min-width: 20px; }

/* Diamond layout per stage card: Today/This Week pinned to the top-left
   and top-right corners, This Month/Pending pinned to the bottom-left and
   bottom-right corners, with the stage's icon+label centered between the
   two rows -- so each card reads as a small compass around its identity
   rather than a plain list of numbers. */
.followup-stage-metrics { display: flex; justify-content: space-between; width: 100%; margin: 6px 0; }
.followup-stage-metric {
  display: flex; flex-direction: column; align-items: center; min-width: 44px;
}
.followup-stage-metric-value { font-size: 16px; font-weight: 700; color: var(--stage-color); line-height: 1.2; }
.followup-stage-metric-label { font-size: 9.5px; color: var(--text-dim); margin-top: 2px; white-space: nowrap; text-transform: uppercase; letter-spacing: 0.02em; }

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  margin-bottom: 14px;
}

.panel h2 { font-size: 15px; margin: 0 0 14px; }

.row-between { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }

table { width: 100%; border-collapse: collapse; font-size: var(--table-font-size); }
th { text-align: left; color: var(--text-dim); font-weight: 600; padding: var(--table-header-padding-y) var(--table-header-padding-x); border-bottom: 1px solid var(--border); font-size: var(--table-header-font-size); text-transform: uppercase; }
td {
  padding: var(--table-cell-padding-y) var(--table-cell-padding-x);
  border-bottom: 1px solid var(--border);
  /* Once a column's width is locked (table-layout:fixed, set by the
     resizable-table feature below, or just a narrow manually-resized
     column), an unbreakable long token -- an email address, a full URL --
     has nowhere to wrap and was overflowing straight past the column edge,
     visually sitting on top of whatever the next column drew (e.g. the
     LinkedIn icon landing mid-email-address). Forcing a break keeps every
     cell's content inside its own column no matter how narrow it gets. */
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Companion to the overflow-wrap/word-break rule above. makeTableResizable()
   in app.js briefly toggles this class on a table while it measures each
   column's natural width, so that measurement isn't taken with every word
   treated as breakable at any character -- which used to let a free-text
   column (e.g. Contacts' "Title") get its width frozen at 20-30px. See the
   comment in makeTableResizable() for the full story. */
.measuring-natural-width td,
.measuring-natural-width th {
  white-space: nowrap !important;
  overflow-wrap: normal !important;
  word-break: normal !important;
}

/* Any <select> living in a table cell, on ANY table -- Contacts'
   Status/Draft Type, Assign Users' Role/Reports-to, Field Permissions'
   Manager/User tiers, and any future one. Every table here becomes
   table-layout:fixed once makeTableResizable() runs (see below), which
   locks each column to a fixed pixel width -- but a plain <select> still
   has the base input/select/textarea rule's width:100% AND its own
   browser-native "shrink to fit the longest option" sizing floor, so
   once a row's selected option (or a manual column resize) needed more
   room than that fixed column width, the select rendered wider than its
   cell and visually sat on top of the next column ("overlapping"). This
   pins the select to its cell exactly (min-width:0 overrides the native
   sizing floor) and ellipsizes instead of overflowing, so it can never
   be wider than its own column no matter the option text or how far a
   column gets resized down. Also carries the density-driven padding/font
   size so switching density changes row height end to end rather than
   just the empty space around a full-size control. Scoped to select only
   -- a checkbox or date input picking up the same rules would look
   broken. */
td select {
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: var(--table-cell-padding-y) 10px;
  font-size: var(--table-font-size);
}
tr:last-child td { border-bottom: none; }

/* Manual per-column/per-row resize -- every table gets a thin drag handle
   on each header's right edge (column width) and each row's right edge
   (row height), added automatically by enhanceResizableTables() in app.js.
   Mouse: drag. Keyboard: Tab to a handle, then arrow keys (Shift for a
   bigger step). Widths/heights are remembered per browser via localStorage,
   keyed to that table's own header text, so they survive re-renders
   (filtering, editing a row) but don't leak across unrelated tables. */
.col-resize-handle {
  position: absolute;
  top: 0;
  right: -4px;
  width: 8px;
  height: 100%;
  cursor: col-resize;
  z-index: 2;
  touch-action: none;
}
.col-resize-handle:hover, .col-resize-handle:focus-visible {
  background: var(--teal);
  opacity: 0.4;
  outline: none;
}
.row-resize-handle {
  position: absolute;
  left: 0;
  bottom: -4px;
  width: 100%;
  height: 8px;
  cursor: row-resize;
  z-index: 2;
  touch-action: none;
}
.row-resize-handle:hover, .row-resize-handle:focus-visible {
  background: var(--teal);
  opacity: 0.4;
  outline: none;
}
table.resizable-table th { position: relative; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.resizable-table td:last-child { position: relative; }

.pill {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}
.pill-new { background: #e7ecff; color: #3b5bdb; }
.pill-contacted { background: #eaf7e6; color: #4c9a45; }
.pill-qualified { background: #e3fbf6; color: #0f9d6e; }
.pill-proposal { background: #fff4e0; color: #b8790f; }
.pill-negotiation { background: #e7ecff; color: var(--violet); }
.pill-won { background: #e3f9ec; color: #16a34a; }
.pill-lost { background: #fdeaea; color: #d64545; }
.pill-pending_manager, .pill-pending_hr, .pill-pending { background: #fff4e0; color: #b8790f; }
.pill-approved { background: #e3f9ec; color: #16a34a; }
.pill-rejected { background: #fdeaea; color: #d64545; }

.table-scroll { overflow-x: auto; }
.table-scroll table { min-width: 1080px; }
.table-scroll th.group { text-align: center; border-left: 1px solid var(--border); }
.table-scroll th.subhead { font-size: 11px; text-transform: none; text-align: center; }
.table-scroll td.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Activity Report -- same columns/data as the plain table above, just
   color-coded group headers, status pills, zebra striping, and the Date/
   Country columns pinned so they stay visible while scrolling right
   through the wide grouped columns. */
.activity-table th { text-transform: none; }
.activity-table td, .activity-table th { padding: 11px 14px; border-right: 1px solid var(--border-strong); border-bottom: 1px solid var(--border-strong); }
.activity-table td:last-child, .activity-table th:last-child { border-right: none; }
.activity-table tbody tr:last-child td { border-bottom: none; }
.activity-table table { border: 1px solid var(--border-strong); border-radius: 8px; border-collapse: separate; border-spacing: 0; }
/* Theme the header's top row (Date/Country/Campaign/Status/action, plus the
   already-colored group cells) with a light brand-blue band so the whole
   row reads as one cohesive header instead of colored islands on white. */
.activity-table thead th { background: rgba(30, 58, 232, 0.05); color: var(--ink); }
.activity-table th.group-mapped, .activity-table th.subhead-mapped { background: rgba(34, 197, 94, 0.12); color: #15803d; }
.activity-table th.group-emails, .activity-table th.subhead-emails { background: rgba(30, 58, 232, 0.08); color: #1e3ae8; }
.activity-table th.group-linkedin { background: rgba(245, 166, 35, 0.16); color: #b8790f; }
.activity-table th.group-responses, .activity-table th.subhead-responses { background: rgba(255, 107, 107, 0.12); color: #c23636; }
.activity-table tbody tr:nth-child(even) td:not(.sticky-col1):not(.sticky-col2) { background: var(--panel-2); }
.activity-table tbody tr:hover td:not(.sticky-col1):not(.sticky-col2) { background: #eef1ff; }
.activity-table .sticky-col1, .activity-table .sticky-col2 {
  position: sticky;
  background: var(--panel);
  z-index: 1;
}

/* Contacts table -- same light brand-blue header band as Activity Report,
   plus a subtle row hover, so the table reads as themed rather than the
   plain default table styling above. */
/* The header tint (background-image, a flat rgba wash) is layered over a
   solid background-color rather than used as a plain translucent
   background -- a sticky header needs to fully hide whatever row has
   scrolled underneath it, and a 5%-alpha rgba on its own lets that row's
   text show straight through. */
.contacts-table thead th { background-image: linear-gradient(rgba(30, 58, 232, 0.05), rgba(30, 58, 232, 0.05)); background-color: var(--panel); color: var(--ink); position: sticky; top: 0; z-index: 2; }
.contacts-table tbody tr:hover td { background: var(--panel-2); }
.contacts-table thead .sticky-col1 { z-index: 4; }

/* Accounts table -- same sticky-header treatment as Contacts above. */
.accounts-table thead th { background-image: linear-gradient(rgba(30, 58, 232, 0.05), rgba(30, 58, 232, 0.05)); background-color: var(--panel); color: var(--ink); position: sticky; top: 0; z-index: 2; }
.accounts-table tbody tr:hover td { background: var(--panel-2); }

/* Why every list here (Contacts, Accounts) needs an actual bounded,
   internally-scrolling box, not just "grow with the row count and let the
   page scroll": `.table-scroll`'s overflow-x:auto (needed so a wide,
   column-resized table pans sideways in its own tidy scrollbar instead of
   the whole page) forces its overflow-y to compute as non-`visible` too,
   per the CSS overflow spec's "if one axis is non-visible, `visible` on
   the other becomes `auto`" rule -- and ANY non-`visible` value (auto,
   clip, hidden, scroll -- tried them all) makes that box a genuine "scroll
   container" *by spec definition*, regardless of whether it can actually
   be scrolled. A `position:sticky` header always sticks against its
   NEAREST such ancestor, so `.table-scroll` wins over the real page/
   window scroll every time -- and since `.table-scroll` was never given a
   height, it never itself needs to scroll, so sticking to it is a no-op:
   the header just scrolls away with the rows instead of freezing
   ("overlapping" the row that ends up underneath it). There's no way
   around this while overflow-x:auto lives on the same box a sticky header
   needs to stick within -- confirmed empirically, not just reasoned about
   -- so both tables now always get their own bounded, scrollable region
   (like Contacts' old opt-in "Fit window" mode did), which is also
   exactly the sticky-header pattern this same overflow-x:auto trick
   already works correctly for real. Generous enough to fill most of a
   normal screen below the topbar/filter row; caps out rather than
   growing the whole page for a very long list. */
.contacts-table, .accounts-table {
  max-height: calc(100vh - 220px);
  overflow-y: auto;
}

/* "Fit window" (the toggle next to Import/Quick Add on Contacts) opts
   into a shorter box -- useful when something else on the page (a scope
   banner, bulk-action bar) needs room above it too. */
.contacts-table.contacts-table--bounded {
  max-height: calc(100vh - 340px);
  min-height: 220px;
}

/* Compact filter bar (search/status/account/owner row above the table) --
   tighter padding and shorter inputs than the app's default form controls,
   so the row of filters reads as a toolbar instead of eating a big vertical
   slice of the page above the table. */
.filter-bar-compact {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 8px 14px;
}
.filter-bar-compact input, .filter-bar-compact select {
  padding: 6px 10px;
  font-size: 13px;
}

/* Header-row entry point for the per-column show/hide + quick-filter panel
   (Contacts table) -- sits next to the select-all checkbox so the control
   lives in the table's own header row rather than a separate toolbar. */
.col-menu-btn {
  border: none;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 4px;
  vertical-align: middle;
}
.col-menu-btn:hover { background: rgba(30, 58, 232, 0.12); color: var(--ink); }

/* Inline per-column filter trigger living right in a table header cell's own
   label ("Title ▾") -- the filter for a column sits on that column, not in a
   separate bar floating above the whole table. th-filter-pop is the little
   floating panel it opens, appended to <body> (positioned via inline
   top/left set in JS from the trigger's own bounding rect) so it survives
   the table re-rendering underneath it while it's open. */
.th-filter { display: inline-flex; align-items: center; gap: 5px; }
/* Always shown as a visible little chip (not just on hover/active) -- a
   bare unicode ▾ at text-dim color on a white header all but disappeared,
   so every trigger gets a light tinted background and a bigger arrow all
   the time, with the active state (a filter is currently applied to this
   column) just switching that same chip to solid blue. */
.th-filter-btn {
  border: none;
  background: rgba(30, 58, 232, 0.12);
  color: var(--ink);
  cursor: pointer;
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  padding: 4px 7px;
  border-radius: 5px;
}
.th-filter-btn:hover { background: rgba(30, 58, 232, 0.24); }
.th-filter-btn-active { background: #1e3ae8; color: #fff; }
.th-filter-btn-active:hover { background: #1e3ae8; color: #fff; }
.th-filter-pop {
  position: fixed;
  z-index: 50;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
  padding: 10px;
  min-width: 190px;
}
.th-filter-pop input, .th-filter-pop select { width: 100%; }

/* Master filters on/off button, sitting at the very end of the header row
   (its own last <th>, matched by an empty trailing <td> in every body row so
   the table stays a valid grid). "On" (the default) tints blue like an
   active column filter, since the whole point of this button is filtering
   being available; "off" sits muted like the plain col-menu-btn ⋮ trigger,
   and every column's ▾ disappears back to a plain label while it's off. */
.filters-toggle-btn-on { background: rgba(30, 58, 232, 0.18); color: var(--ink); }
.filters-toggle-btn-on:hover { background: rgba(30, 58, 232, 0.3); }

/* Email column: send icon, same visual language as the LinkedIn glyph next
   to it -- a small rounded swatch, brand-colored and clickable when the
   contact has an email on file, muted and inert when not. */
.email-icon { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; border-radius: 6px; border: none; cursor: pointer; }
.email-icon-active { color: #1e3ae8; background: rgba(30, 58, 232, 0.1); }
.email-icon-active:hover { background: rgba(30, 58, 232, 0.2); }
.email-icon-empty { color: var(--text-dim); background: var(--panel-2); opacity: 0.6; cursor: default; }

/* Status/Draft Type used to force a min-width here (to keep "5th Followup"
   from clipping to nothing) or a fixed px width -- both fights with manual
   column resize: shrink either column below that number and the select
   overflows past the column edge into its neighbor again ("mixing"). The
   shared `td select` rule above now handles sizing (100% of whatever the
   column actually is, ellipsis if that's too narrow) for every table, so
   nothing column-specific is needed here any more. */

/* LinkedIn column: a small "in" glyph instead of a raw URL field -- brand
   blue and clickable when a URL is on file, muted and inert when not. */
.linkedin-icon { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 6px; }
.linkedin-icon-active { color: #0a66c2; background: rgba(10, 102, 194, 0.1); }
.linkedin-icon-active:hover { background: rgba(10, 102, 194, 0.2); }
.linkedin-icon-empty { color: var(--text-dim); opacity: 0.35; }

/* Draft column: a small, single-line, click-to-expand chip -- deliberately
   not a free-flowing text cell, so a long AI-generated draft doesn't blow
   out the row height or column width. */
.draft-pill {
  display: inline-block;
  max-width: 140px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--panel-2);
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  text-align: left;
}
.draft-pill:hover { border-color: var(--teal); color: #15803d; }

/* Contacts table's checkbox column stays pinned to the left edge while
   scrolling through the wide row of columns to its right (Date/LinkedIn/
   Draft/etc added it well past one screen width) -- same sticky technique
   as Activity Report's pinned columns, just a single narrow column here. */
.contacts-table .sticky-col1 {
  position: sticky;
  left: 0;
  background: var(--panel);
  z-index: 1;
  border-right: 1px solid var(--border-strong);
}
.contacts-table thead .sticky-col1 { z-index: 3; background: rgba(30, 58, 232, 0.05); color: var(--ink); }
.activity-table thead .sticky-col1, .activity-table thead .sticky-col2 { z-index: 3; background: rgba(30, 58, 232, 0.05); color: var(--ink); }
.activity-table .sticky-col1 { left: 0; min-width: 100px; }
.activity-table .sticky-col2 { left: 100px; min-width: 150px; max-width: 210px; white-space: normal; }

tr.row-click { cursor: pointer; }
tr.row-click:hover td { background: var(--panel-2); }
.stat-card.clickable { cursor: pointer; transition: background 0.15s; }
.stat-card.clickable:hover { background: var(--panel-2); }

.kanban { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 8px; }
.kanban-col { min-width: 220px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; flex: 1; }
.kanban-col h3 { font-size: 12px; text-transform: uppercase; color: var(--text-dim); margin: 0 0 10px; display: flex; justify-content: space-between; }
.lead-card { background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px; padding: 10px; margin-bottom: 10px; font-size: 13px; }
.lead-card .name { font-weight: 600; margin-bottom: 4px; }
.lead-card .value { color: var(--teal); font-size: 12px; margin-bottom: 6px; }
.lead-card select { font-size: 11px; padding: 4px 6px; }

.modal-backdrop {
  position: fixed; inset: 0; background: rgba(6,8,16,0.7);
  display: flex; align-items: center; justify-content: center; z-index: 50;
  padding: 24px; box-sizing: border-box;
}
.modal-backdrop.hidden { display: none; }
/* While a modal is minimized, the backdrop shouldn't block the rest of the
   app -- only the small floating title bar stays clickable (to restore). */
.modal-backdrop.backdrop-minimized { background: transparent; pointer-events: none; }
.modal-backdrop.backdrop-minimized .modal { pointer-events: auto; }

.modal {
  /* Scale with the viewport instead of a fixed px width, so the dialog uses
     the space actually available on the screen rather than always opening
     at the same cramped size regardless of display. Caps keep it from
     stretching absurdly wide on large monitors. This is a starting size
     only -- the window is user-resizable (drag the bottom-right corner)
     and user-draggable (by the title bar), like a desktop window. */
  width: min(560px, 92vw);
  height: min(560px, 85vh);
  min-width: 320px;
  min-height: 200px;
  max-width: 96vw;
  max-height: 94vh;
  display: flex;
  flex-direction: column;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  box-sizing: border-box;
  overflow: hidden;
  /* Positioning context for the resize handle below. Flex items can be
     position:relative without leaving the flex layout. */
  position: relative;
}
.modal.modal-wide { width: min(820px, 94vw); height: min(640px, 88vh); }

/* Free resizing is implemented by hand (in app.js) rather than via the
   native CSS `resize` property: `.modal` is a flex item of the centering
   backdrop, and browsers don't reliably support native resize on flex
   items -- the drag handle shows but doesn't actually change the size. A
   custom handle + mousemove works consistently everywhere. */
.modal-resize-handle {
  position: absolute; right: 0; bottom: 0;
  width: 20px; height: 20px;
  cursor: nwse-resize;
  z-index: 5;
}
.modal-resize-handle::before {
  content: "";
  position: absolute; right: 5px; bottom: 5px;
  width: 9px; height: 9px;
  border-right: 2px solid var(--border);
  border-bottom: 2px solid var(--border);
}
.modal.modal-maximized .modal-resize-handle,
.modal.modal-minimized .modal-resize-handle {
  display: none;
}

.modal-titlebar {
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--panel-2);
  border-radius: var(--radius) var(--radius) 0 0;
  cursor: move;
  user-select: none;
  flex: 0 0 auto;
}
.modal-ctrl {
  width: 22px; height: 22px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 5px;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text-dim);
  font-size: 13px; line-height: 1;
  cursor: pointer;
}
.modal-ctrl:hover { background: var(--border); color: var(--text); }
.modal-ctrl-close:hover { background: #d64545; border-color: #d64545; color: #fff; }
.modal-ctrl-max::before {
  content: ""; display: block; width: 9px; height: 9px;
  border: 1.4px solid currentColor; border-radius: 1px;
}

.modal-content {
  padding: 24px;
  overflow-y: auto;
  flex: 1 1 auto;
  box-sizing: border-box;
  min-height: 0;
}
.modal-content h2 { margin-top: 0; font-size: 16px; }
.modal-actions { display: flex; gap: 10px; margin-top: 20px; }

/* Maximize: fill almost the whole viewport. app.js clears any manual
   drag/resize inline styles when engaging this, so it always resolves back
   to flex-centered at this larger size regardless of prior state. */
.modal.modal-maximized {
  width: 96vw !important; height: 94vh !important;
}

/* Minimize: collapse down to just the title bar, parked bottom-right so the
   rest of the app stays usable; click it again to restore. Form content
   underneath is only hidden, never destroyed, so nothing typed is lost. */
.modal.modal-minimized {
  position: fixed !important;
  right: 20px; bottom: 20px; left: auto !important; top: auto !important;
  width: 220px !important; height: auto !important;
  min-width: 0; min-height: 0;
  margin: 0 !important;
}
.modal.modal-minimized .modal-content { display: none; }
.modal.modal-minimized .modal-titlebar { border-radius: var(--radius); border-bottom: none; cursor: pointer; }

@media (max-width: 600px) {
  .modal-backdrop { padding: 10px; }
  .modal { width: 100%; height: 90vh; }
  .modal-resize-handle { display: none; }
  .modal-content { padding: 18px; }
}

.chart-grid { display: grid; grid-template-columns: 1.2fr 0.8fr; gap: 20px; }
@media (max-width: 900px) { .chart-grid { grid-template-columns: 1fr; } }

.leave-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px,1fr)); gap: 14px; margin-bottom: 20px; }

.tag-role {
  display: inline-block; padding: 1px 8px; border-radius: 6px; font-size: 11px;
  background: var(--panel-2); color: var(--text-dim); border: 1px solid var(--border);
}

.toast {
  position: fixed; bottom: 20px; right: 20px; background: var(--panel);
  border: 1px solid var(--border); padding: 12px 18px; border-radius: 8px; font-size: 13px;
  box-shadow: 0 6px 20px rgba(19, 26, 51, 0.14);
  z-index: 100;
}
.toast.hidden { display: none; }
.toast.error { border-color: var(--coral); color: var(--coral); }
.toast.success { border-color: var(--teal); color: var(--teal); }

.empty-state { color: var(--text-dim); font-size: 13px; padding: 20px 0; text-align: center; }

.settings-tabs { display: flex; gap: 6px; margin-bottom: 20px; border-bottom: 1px solid var(--border); }
.settings-tab {
  padding: 10px 16px; font-size: 13px; font-weight: 600; color: var(--text-dim);
  cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.settings-tab.active { color: var(--teal); border-bottom-color: var(--teal); }

.color-swatch-row { display: flex; align-items: center; gap: 12px; }
.color-swatch-row input[type="color"] {
  width: 42px; height: 42px; padding: 2px; border-radius: 8px; cursor: pointer;
}
.font-preview-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin-top: 6px; }
.font-preview-card {
  border: 1px solid var(--border); border-radius: 8px; padding: 12px; cursor: pointer;
  background: var(--panel-2);
}
.font-preview-card.selected { border-color: var(--teal); box-shadow: 0 0 0 1px var(--teal); }
.font-preview-card .sample { font-size: 15px; margin-top: 4px; }
.font-preview-card .name { font-size: 11px; color: var(--text-dim); text-transform: uppercase; }

.integration-card {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 14px; border: 1px solid var(--border); border-radius: 8px; margin-bottom: 10px;
}
.integration-card.unsupported { opacity: 0.55; }
.integration-card .meta { flex: 1; min-width: 0; }
.integration-card .meta .name { font-weight: 600; font-size: 14px; }
.integration-card .meta .desc { font-size: 12px; color: var(--text-dim); margin-top: 2px; }
.integration-card input[type="password"], .integration-card input[type="text"] { width: 220px; }
.integration-card .row { display: flex; align-items: center; gap: 8px; }
.pill-active { background: #e3f9ec; color: #16a34a; }
.pill-inactive { background: var(--panel-2); color: var(--text-dim); }

/* ---------- Contact detail page ---------- */
.contact-detail-back {
  display: inline-block; font-size: 13px; color: var(--text-dim); text-decoration: none;
  margin-bottom: 12px;
}
.contact-detail-back:hover { color: var(--ink); text-decoration: underline; }

.contact-detail-header { display: flex; align-items: flex-start; gap: 16px; padding: 18px; }
.contact-detail-avatar {
  flex: 0 0 auto; width: 48px; height: 48px; border-radius: 50%;
  background: var(--ink); color: #fff; font-size: 18px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.contact-detail-id { flex: 1; min-width: 0; }
.contact-detail-name-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.contact-detail-name { font-size: 18px; font-weight: 700; }
.contact-detail-sub { font-size: 13px; color: var(--text-dim); margin-top: 3px; }
.contact-detail-meta { display: flex; gap: 16px; font-size: 12px; color: var(--text-dim); margin-top: 6px; flex-wrap: wrap; }
.contact-detail-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.contact-detail-actions select { min-width: 130px; }

.contact-detail-stepper-panel { padding: 16px 18px; margin-top: 14px; }
.contact-detail-stepper-label { font-size: 11px; letter-spacing: 0.4px; color: var(--text-dim); margin-bottom: 12px; }
.contact-detail-stepper { display: flex; align-items: flex-start; }
.contact-detail-step { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 0 0 auto; }
.contact-detail-step-dot {
  width: 28px; height: 28px; border-radius: 50%; border: 2px solid var(--border-strong);
  display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700;
  color: var(--text-dim); background: var(--panel);
}
.contact-detail-step.done .contact-detail-step-dot { border-color: var(--ink); background: var(--ink); color: #fff; }
.contact-detail-step.current .contact-detail-step-dot { border-color: var(--ink); background: var(--panel); color: var(--ink); box-shadow: 0 0 0 3px rgba(30,58,232,0.15); }
.contact-detail-step-label { font-size: 11px; color: var(--text-dim); }
.contact-detail-step.current .contact-detail-step-label, .contact-detail-step.done .contact-detail-step-label { color: var(--ink); font-weight: 600; }
.contact-detail-step-line { flex: 1 1 auto; height: 2px; background: var(--border-strong); margin: 13px 4px 0; min-width: 12px; }
.contact-detail-step-line.done { background: var(--ink); }

.contact-detail-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 900px) { .contact-detail-cards { grid-template-columns: 1fr; } }
.contact-detail-card-title { font-size: 11px; letter-spacing: 0.4px; color: var(--text-dim); text-transform: uppercase; margin-bottom: 10px; }
.contact-detail-kv { width: 100%; font-size: 13px; }
.contact-detail-kv td { padding: 5px 0; }
.contact-detail-kv td:first-child { color: var(--text-dim); width: 42%; }
.contact-detail-kv td:last-child { text-align: right; }

.contact-detail-note-item, .contact-detail-timeline-item {
  padding: 10px 0; border-bottom: 1px solid var(--border);
}
.contact-detail-note-item:last-child, .contact-detail-timeline-item:last-child { border-bottom: none; }
.contact-detail-note-date, .contact-detail-timeline-date { font-size: 11px; color: var(--text-dim); }
.contact-detail-note-text { font-size: 13px; margin-top: 3px; white-space: pre-wrap; }
.contact-detail-timeline-label { font-size: 13px; margin-top: 2px; }
