/* Page-to-page nav (hx-boost, see body[hx-swap] in each page template) cross-
   fades instead of hard-cutting old content out for new content in. Browser
   default view-transition duration (~250ms) reads as sluggish next to this
   app's other transitions (0.12s elsewhere in this file) -- matched here.
   No-ops entirely in browsers without View Transitions support. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.12s;
}

:root {
  /* Surfaces */
  --bg: #f7f7f8;
  --surface: #ffffff;
  --surface-alt: #fafafa;

  /* Borders — whisper-thin, Twenty style */
  --border: #ececee;
  --border-strong: #dcdce0;

  /* Text */
  --text: #18181b;
  --text-muted: #52525b;
  --text-subtle: #a1a1aa;

  /* Accent — monochrome */
  --accent: #18181b;
  --accent-hover: #000000;
  --accent-soft: rgba(0, 0, 0, 0.06);
  --accent-ring: rgba(0, 0, 0, 0.10);

  /* Topbar — slightly lighter dark grey */
  --topbar-bg: #3a3a3e;
  --topbar-bg-hover: #4d4d52;
  --topbar-text: #e4e4e7;
  --topbar-text-hover: #ffffff;
  --topbar-border: #27272a;

  /* Hover/row states */
  --hover: #f4f4f6;
  --row-hover: #f7f7f9;

  /* Layered, subtle shadows */
  --shadow-xs: 0 1px 1px rgba(16, 24, 40, 0.03);
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.04);
  --shadow-md: 0 4px 8px -2px rgba(16, 24, 40, 0.06), 0 2px 4px -2px rgba(16, 24, 40, 0.04);
  --shadow-lg: 0 12px 24px -6px rgba(16, 24, 40, 0.08), 0 4px 8px -2px rgba(16, 24, 40, 0.04);

  --radius: 8px;
  --radius-sm: 6px;
  --radius-lg: 10px;
}

* { box-sizing: border-box; }

body {
  font-family: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", system-ui, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  margin: 0;
  padding: 0;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* TOP BAR — dark grey, flat, no heavy shadow */
.topnav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 32px;
  background: var(--topbar-bg);
  border-bottom: 1px solid var(--topbar-border);
  margin-bottom: 32px;
  width: 100%;
}

.nav-hamburger {
  display: none;
}

.topnav .links a {
  color: var(--topbar-text);
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  padding: 6px 12px;
  margin-right: 4px;
  border-radius: var(--radius-sm);
  transition: color 0.12s ease, background 0.12s ease;
}

.topnav .links a:hover {
  color: var(--topbar-text-hover);
  background: var(--topbar-bg-hover);
}

.topnav a.active {
  color: var(--topbar-bg);
  background: var(--surface);
  border-radius: 4px;
}

tr.deleting {
  opacity: 0;
  transition: opacity 0.2s ease;
}

.brand {
  font-weight: 600;
  font-size: 15px;
  letter-spacing: -0.01em;
  color: var(--topbar-text-hover);
}

/* MAIN CONTENT WRAPPER */
main {
  max-width: 1600px;
  margin: 0 auto;
  padding: 0 12px 40px;
}

/* Deals and Leads pages only — their rows carry enough columns (deals:
   scheduled date, estimated hours, job address; leads: address, city,
   service type, urgency, follow up) that the standard 1600px cap crowds
   them and forces long fields like email to wrap onto several lines.
   Every other page keeps the normal width. */
body.wide-page main {
  max-width: none;
}

/* TYPOGRAPHY */
h1 {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0 0 24px;
  padding-bottom: 0;
  border-bottom: none;
}

/* Title + actions row */
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 20px;
}

.page-header h1 {
  margin: 0;
}

h2 {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 12px;
}

/* TABLES — Twenty look: barely-visible borders, soft surface */
table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

th {
  text-align: left;
  padding: 10px 16px;
  background: #ebebef;
  border-bottom: 1px solid var(--border-strong);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  cursor: pointer;
  user-select: none;
  transition: background 0.12s ease, color 0.12s ease;
}

th:hover {
  background: #e0e0e5;
  color: var(--text);
}

td {
  padding: 11px 16px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  vertical-align: middle;
  overflow-wrap: anywhere;
  word-break: break-word;
}

tr:last-child td {
  border-bottom: none;
}

/* Reserve a full page's worth of row height up front on the five paginated
   list pages. Each table starts with an empty <tbody hx-trigger="load">
   that only fills in once its rows finish loading -- without a reserved
   height the table renders at just-the-header size for that ~150-200ms
   and then visibly grows as rows stream in, which is the "grows from the
   top down" flash left over after the page-nav cross-fade fix.

   This has to live on a wrapping <div>, not on the <table> itself: a
   <table>'s row-height distribution algorithm stretches EXISTING rows to
   fill a min-height when there aren't enough rows to reach it naturally,
   instead of just leaving blank space below the last row. On a page with
   a near-full 20-row table that's invisible; on a page with only a
   handful of real rows (e.g. Notes, most of the time) it turns every row
   huge. A plain block-level wrapper div reserves the same vertical space
   in normal flow without touching the table's internal layout at all --
   the table renders at its natural height inside it, and any leftover
   space is just blank space in the div below it. See the .table-min-h
   wrapper in each list page's HTML template.

   Estimate: (per_page=20 rows * ~42.5px row height) + ~38px header,
   rounded up -- a visual estimate, not a computed value; re-tune if
   per_page in crm.conf changes from the default, or if this over/
   undershoots. */
.table-min-h {
  min-height: 890px;
}

tbody tr {
  transition: background 0.1s ease;
}

tbody tr:hover {
  background: var(--row-hover);
}

tbody {
  transition: opacity 0.15s ease;
}

tbody.htmx-request {
  opacity: 0;
  transition: opacity 0.08s ease;
}

/* BUTTONS — primary now blue, ghost secondary */
.btn {
  background: var(--accent);
  color: #ffffff;
  border: 1px solid var(--accent);
  padding: 7px 14px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  display: inline-block;
  text-decoration: none;
  transition: background 0.12s ease, border-color 0.12s ease, transform 0.05s ease, box-shadow 0.12s ease;
  font-family: inherit;
  box-shadow: var(--shadow-xs);
}

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

.btn:active {
  transform: translateY(1px);
}

.btn-danger {
  background: var(--surface);
  color: var(--text-muted);
  border: 1px solid var(--border-strong);
  padding: 5px 10px;
  font-size: 12px;
  font-weight: 500;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all 0.12s ease;
  font-family: inherit;
}

.btn-danger:hover {
  color: #ffffff;
  background: var(--accent);
  border-color: var(--accent);
}

.btn-email {
  text-decoration: none;
  margin-right: 4px;
  display: inline-block;
}

/* Mobile-only — see the @media (max-width: 600px) override below */
.btn-call {
  text-decoration: none;
  margin-right: 4px;
  display: none;
}

.btn-notes {
  margin-right: 4px;
}

.btn-to-contact {
  margin-right: 4px;
}

/* FORMS */
.form {
  margin-top: 32px;
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  box-shadow: var(--shadow-sm);
}

.form h2 {
  width: 100%;
  margin-bottom: 12px;
}

.form > form {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  width: 100%;
  align-items: center;
}

.form-footer {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  margin-top: 4px;
}

.form .form-footer input,
.form .form-footer select {
  flex: 0 0 auto;
}

.form-row-centered {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
}

.form .form-row-centered input,
.form .form-row-centered select {
  flex: 0 0 auto;
}

.form textarea {
  flex: 0 0 100%;
  width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  resize: vertical;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.form textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.form textarea::placeholder {
  color: var(--text-subtle);
}

.form input, .form select {
  padding: 8px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  flex: 1 1 160px;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.form input:focus, .form select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.form input::placeholder {
  color: var(--text-subtle);
}

/* CONTROLS BAR */
.controls {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
  gap: 12px;
}

.controls input[type="file"] {
  font-size: 13px;
  padding: 6px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-family: inherit;
  color: var(--text-muted);
}

.controls form {
  display: flex;
  gap: 8px;
  align-items: center;
}

/* IO actions block — right-justified, Export + Import inline */
.io-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.io-actions .import-form {
  display: inline-flex;
  align-items: center;
}

/* CSV dropdown menu */
.csv-menu {
  position: relative;
  display: inline-flex;
}

.csv-dropdown {
  display: none;
  flex-direction: column;
  gap: 8px;
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  white-space: nowrap;
  z-index: 100;
  box-shadow: var(--shadow-sm);
  min-width: 160px;
}

.csv-dropdown.open {
  display: flex;
}

.csv-dropdown .import-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* NAV "MORE" DROPDOWN (Flowstate, Profile) — .nav-more-btn intentionally has
   no styling overrides here; it inherits .topnav .links a as-is so it reads
   as just another nav link, not a distinct control. */
.nav-more {
  position: relative;
  display: inline-block;
}

.nav-more-dropdown {
  display: none;
  flex-direction: column;
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  min-width: 140px;
  z-index: 100;
  overflow: hidden;
}

.nav-more-dropdown.open {
  display: flex;
}

.nav-more-dropdown a {
  padding: 8px 14px;
  white-space: nowrap;
  color: var(--text) !important;
  font-size: 13px;
}

.nav-more-dropdown a:hover {
  background: var(--hover);
}

/* PAGER */
.pager {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  margin-top: 16px;
  font-size: 13px;
  color: var(--text-muted);
}

.pager a {
  color: var(--text-muted);
  text-decoration: none;
  padding: 5px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-weight: 500;
  background: var(--surface);
  transition: all 0.12s ease;
}

.pager a:hover {
  background: var(--accent);
  color: #ffffff;
  border-color: var(--accent);
}

.pager-info {
  font-weight: 500;
  min-width: 100px;
  text-align: center;
  color: var(--text-muted);
}

.pager-placeholder {
  display: inline-block;
  width: 72px;
}

/* LOGIN */
.login-card {
  max-width: 380px;
  margin: 80px auto;
  padding: 36px 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.login-card h2 {
  font-size: 18px;
  font-weight: 600;
  text-transform: none;
  letter-spacing: -0.01em;
  color: var(--text);
  margin: 0 0 24px;
  text-align: center;
}

.login-card input {
  display: block;
  width: 100%;
  padding: 10px 12px;
  margin-bottom: 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.login-card input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

/* PROFILE PAGE — centered narrow column */
.profile-page {
  max-width: 420px;
  margin: 0 auto;
  text-align: center;
}

.profile-page .profile-info {
  margin-bottom: 24px;
}

.profile-page .profile-info h2 {
  text-align: center;
  margin-top: 20px;
}

.profile-page .profile-info p {
  text-align: center;
  margin: 0 0 8px;
}

.profile-page .profile-info ul {
  list-style: none;
  padding-left: 0;
  margin: 0;
}

.profile-page .profile-info li {
  margin-bottom: 4px;
}

.profile-page .actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 8px;
}

.profile-page .actions form {
  margin: 0;
}

.profile-page .actions .btn {
  width: 100%;
}

.profile-page .actions p {
  font-size: 12px;
  margin-top: 4px;
  color: var(--text-muted);
  text-align: center;
}

/* DASHBOARD STAT CARDS */
.stats-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 16px;
  margin-bottom: 32px;
}

.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 18px;
  box-shadow: var(--shadow-sm);
}

.stat-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-subtle);
  margin-bottom: 4px;
}

.stat-value {
  font-size: 24px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.02em;
  line-height: 1.2;
}

@media (max-width: 900px) {
  .stats-row {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* DASHBOARD: cap visible rows to 5 */
.dashboard-row tbody tr:nth-child(n+6),
.dashboard-section tbody tr:nth-child(n+6) {
  display: none;
}

/* DASHBOARD LAYOUT */
.dashboard-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  margin-bottom: 32px;
  width: 100%;
}

.dashboard-half {
  min-width: 0;
}

.dashboard-half h2,
.dashboard-section h2 {
  margin-bottom: 12px;
}

.dashboard-section {
  width: 100%;
  margin-bottom: 32px;
}

/* Recent Leads dashboard table: First, Last, Company, Phone, Email via the
   dedicated /api/leads/recent endpoint (routes.lisp) -- a fixed, explicit
   field list, not a reuse of the full Leads page's render-lead-row, so this
   widget's column set can't drift out of sync with its <thead> the way it
   did when it shared markup with the main page.
   First/Last/Company (nth-child(2)/(3)/(4)) have no width of their own, so
   they're the columns auto-layout squeezes first once Phone/Email claim
   their protected space below. white-space: nowrap alone isn't enough to
   stop that: the base td rule's overflow-wrap: anywhere + word-break:
   break-word (needed elsewhere so long emails/URLs don't blow out their
   columns) will still force a break *inside* a name — "Whitmore" becoming
   "Whit"/"more" on two lines — even though nowrap has suppressed breaking
   at spaces. Resetting overflow-wrap/word-break back to normal here is what
   actually stops that; nowrap then makes the table (already wrapped in
   .table-wrap, which is overflow-x: auto unconditionally, same as every
   non-dashboard list page) grow wider and scroll instead of wrapping a
   name. */
.dashboard-row-top .dashboard-half:first-child th:nth-child(2),
.dashboard-row-top .dashboard-half:first-child td:nth-child(2),
.dashboard-row-top .dashboard-half:first-child th:nth-child(3),
.dashboard-row-top .dashboard-half:first-child td:nth-child(3),
.dashboard-row-top .dashboard-half:first-child th:nth-child(4),
.dashboard-row-top .dashboard-half:first-child td:nth-child(4) {
  white-space: nowrap;
  overflow-wrap: normal;
  word-break: normal;
}

.dashboard-row-top .dashboard-half:first-child th:nth-child(5),
.dashboard-row-top .dashboard-half:first-child td:nth-child(5) {
  width: 160px;
  min-width: 160px;
  max-width: 160px;
  white-space: nowrap;
}

.dashboard-row-top .dashboard-half:first-child th:nth-child(6),
.dashboard-row-top .dashboard-half:first-child td:nth-child(6) {
  min-width: 200px;
}

/* Recent Deals dashboard table: hide Contact + Phone columns */
.dashboard-row-top .dashboard-half:last-child th:nth-child(6),
.dashboard-row-top .dashboard-half:last-child td:nth-child(6),
.dashboard-row-top .dashboard-half:last-child th:nth-child(7),
.dashboard-row-top .dashboard-half:last-child td:nth-child(7) {
  display: none;
}

/* Explicit widths for the remaining visible columns (Title/Value/Stage/Company).
   Without these, an empty table (no rows to size against) can leave the header
   row narrower than the container instead of stretching to fill it. */
.dashboard-row-top .dashboard-half:last-child th:nth-child(2),
.dashboard-row-top .dashboard-half:last-child td:nth-child(2) {
  width: 40%;
}

.dashboard-row-top .dashboard-half:last-child th:nth-child(3),
.dashboard-row-top .dashboard-half:last-child td:nth-child(3) {
  width: 18%;
}

.dashboard-row-top .dashboard-half:last-child th:nth-child(4),
.dashboard-row-top .dashboard-half:last-child td:nth-child(4) {
  width: 20%;
}

.dashboard-row-top .dashboard-half:last-child th:nth-child(5),
.dashboard-row-top .dashboard-half:last-child td:nth-child(5) {
  width: 22%;
}

/* Notes page table column widths. Body (nth-child(2)) intentionally has no
   explicit width — it's the only unconstrained column, so auto table layout
   already gives it the space left over after Type/Phone/Email below. A
   previous "width: 100%" here fought with those columns' own widths, and
   once td got overflow-wrap: anywhere (which lets auto-layout shrink a
   column's minimum content width to near zero), that conflict collapsed
   Body down to almost nothing, wrapping ordinary note text into many lines. */
.notes-table th:nth-child(3),
.notes-table td:nth-child(3) {
  width: 90px;
  white-space: nowrap;
}

.notes-table th:nth-child(4),
.notes-table td:nth-child(4) {
  max-width: 160px;
  white-space: nowrap;
}

.notes-table th:nth-child(5),
.notes-table td:nth-child(5) {
  min-width: 300px;
}

/* Without this, the Delete column has no protected width the way ID/Type/Phone
   do above, so when Email's min-width squeezes the row, auto table layout
   shrinks Delete instead and wraps its button text mid-word ("dele"/"te"). */
.notes-table th:nth-child(6),
.notes-table td:nth-child(6) {
  white-space: nowrap;
}

/* Phone columns are capped to fit the longest value formatPhone (app.js)
   ever produces -- "+1 (123) 123-1232" -- so they never grow wider than
   that just because a table has spare horizontal room. */
.leads-table th:nth-child(4),
.leads-table td:nth-child(4),
.contacts-table th:nth-child(5),
.contacts-table td:nth-child(5),
.companies-table th:nth-child(4),
.companies-table td:nth-child(4),
.deals-table th:nth-child(7),
.deals-table td:nth-child(7) {
  max-width: 160px;
  white-space: nowrap;
}

.table-wrap {
  overflow-x: auto;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  background: var(--surface);
}

.table-wrap table {
  border: none;
  border-radius: 0;
  box-shadow: none;
  margin: 0;
}

.dashboard-half table,
.dashboard-section table {
  font-size: 12px;
}

/* ANALYTICS SHEET — grouped line items instead of a stat-card grid */
.analytics-sheet {
  max-width: 640px;
  margin: 0 auto;
}

.analytics-group {
  margin-bottom: 28px;
}

.analytics-group h2 {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-subtle);
  margin: 0 0 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-strong);
}

.analytics-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 8px 2px;
  border-bottom: 1px solid var(--border);
}

.analytics-row:last-child {
  border-bottom: none;
}

.analytics-label {
  color: var(--text-muted);
  font-size: 14px;
}

.analytics-value {
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  white-space: nowrap;
}

.analytics-row-total {
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
  margin-top: 4px;
  padding-top: 12px;
}

.analytics-row-total .analytics-label {
  color: var(--text);
  font-weight: 600;
}

.analytics-row-total .analytics-value {
  font-size: 16px;
}

/* Hide ID (first column) on the main list-page tables, at every viewport
   width — not just mobile. :not([colspan]) excludes the single-cell
   "no X yet" empty-state row, which is simultaneously first-child and
   last-child of its own row. */
.leads-table th:nth-child(1),
.leads-table td:nth-child(1):not([colspan]),
.contacts-table th:nth-child(1),
.contacts-table td:nth-child(1):not([colspan]),
.companies-table th:nth-child(1),
.companies-table td:nth-child(1):not([colspan]),
.deals-table th:nth-child(1),
.deals-table td:nth-child(1):not([colspan]),
.notes-table th:nth-child(1),
.notes-table td:nth-child(1):not([colspan]) {
  display: none;
}

/* Keep the injected email/call/notes/delete buttons on one line at every
   viewport width. The actions cell has no width of its own, so once the
   Tags column (or anything else) claims enough of the row's width, auto
   table layout can squeeze the actions cell below what its buttons need,
   wrapping them into a stack and inflating row height. :not([colspan])
   excludes the single-cell "no X yet" empty-state row, which must stay
   free to wrap. */
main > table td:last-child:not([colspan]) {
  white-space: nowrap;
}

/* Hide ID (first column) and delete button (last column) on all dashboard tables.
   :not([colspan]) excludes the single-cell "no X yet" empty-state row — that
   lone <td colspan="N"> is simultaneously first-child AND last-child of its
   row, so without this exclusion it gets hidden entirely instead of just ID/delete. */
.dashboard-row table td:first-child:not([colspan]),
.dashboard-row table th:first-child,
.dashboard-row table td:last-child:not([colspan]),
.dashboard-row table th:last-child,
.dashboard-section table td:first-child:not([colspan]),
.dashboard-section table th:first-child,
.dashboard-section table td:last-child:not([colspan]),
.dashboard-section table th:last-child {
  display: none;
}

/* Safety net: wherever columns are conditionally hidden (here, and in the
   mobile column-hiding below), the empty-state placeholder's colspan can no
   longer be trusted to match the table's actual visible column count. Taking
   it out of table layout entirely avoids any resulting blank space. */
table td[colspan] {
  display: block;
}

/* Hide Phone and Email columns on the dashboard's Notes widget. Scoped via
   .notes-table plus a .dashboard-half/.dashboard-section ancestor check so
   the main Notes list page's real Phone/Email columns are untouched. */
.dashboard-half .notes-table tr td:nth-child(4),
.dashboard-half .notes-table tr td:nth-child(5),
.dashboard-half .notes-table tr th:nth-child(4),
.dashboard-half .notes-table tr th:nth-child(5),
.dashboard-section .notes-table tr td:nth-child(4),
.dashboard-section .notes-table tr td:nth-child(5),
.dashboard-section .notes-table tr th:nth-child(4),
.dashboard-section .notes-table tr th:nth-child(5) {
  display: none;
}

/* Explicit widths for the remaining visible Upcoming Dates columns, same
   reasoning as the Recent Deals rule above — an empty table has no row
   content to size the header against. */
.dashboard-row-bottom .dashboard-half:last-child th:nth-child(2),
.dashboard-row-bottom .dashboard-half:last-child td:nth-child(2) {
  width: 36%;
}

.dashboard-row-bottom .dashboard-half:last-child th:nth-child(3),
.dashboard-row-bottom .dashboard-half:last-child td:nth-child(3) {
  width: 22%;
}

.dashboard-row-bottom .dashboard-half:last-child th:nth-child(4),
.dashboard-row-bottom .dashboard-half:last-child td:nth-child(4) {
  width: 22%;
}

.dashboard-row-bottom .dashboard-half:last-child th:nth-child(5),
.dashboard-row-bottom .dashboard-half:last-child td:nth-child(5) {
  width: 20%;
}

/* Explicit widths for the To Be Contacted columns, same reasoning as the
   Recent Leads/Deals rules above — an empty table has no row content to
   size the header against. */
.dashboard-row-bottom .dashboard-half:first-child th:nth-child(2),
.dashboard-row-bottom .dashboard-half:first-child td:nth-child(2) {
  width: 25%;
}

.dashboard-row-bottom .dashboard-half:first-child th:nth-child(3),
.dashboard-row-bottom .dashboard-half:first-child td:nth-child(3) {
  width: 25%;
}

.dashboard-row-bottom .dashboard-half:first-child th:nth-child(4),
.dashboard-row-bottom .dashboard-half:first-child td:nth-child(4) {
  width: 160px;
  min-width: 160px;
  max-width: 160px;
  white-space: nowrap;
}

.dashboard-row-bottom .dashboard-half:first-child th:nth-child(5),
.dashboard-row-bottom .dashboard-half:first-child td:nth-child(5) {
  width: 25%;
}

/* To Be Contacted row tints — server picks the class based on how the
   next-contact date compares to today. Set on <tr> (not <td>) since td has
   no background-color of its own, matching how tbody tr:hover already works. */
tr.row-overdue {
  background: #fee2e2;
}

tr.row-due-today {
  background: #ffedd5;
}

tr.row-due-tomorrow {
  background: #fef9c3;
}

@media (max-width: 900px) {
  .dashboard-row {
    grid-template-columns: 1fr;
  }
}

/* CALENDAR ==================================== */
/* Desktop gets the real month grid with spanning event bars; mobile gets a
   plain date input + a simple day list instead of trying to shrink a 7-column
   grid onto a narrow screen — see .cal-mobile-only below. */

.cal-mobile-only {
  display: none;
}

.cal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.cal-month-label {
  font-weight: 600;
  font-size: 16px;
}

.cal-weekday-labels {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  margin-bottom: 4px;
}

.cal-weekday {
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.cal-week {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 6px;
  margin-bottom: 10px;
}

.cal-day {
  grid-row: 1;
  font-size: 13px;
  color: var(--text-muted);
  padding: 12px 8px;
  min-height: 44px;
  border-top: 1px solid var(--border);
}

.cal-day-out {
  opacity: 0.35;
}

.cal-day-num {
  font-weight: 500;
}

.cal-event-bar {
  font-size: 11px;
  color: #ffffff;
  padding: 1px 6px;
  border-radius: 3px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  cursor: pointer;
  margin-top: 1px;
}

.cal-contact-chip {
  font-size: 11px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid #2563eb;
  border-radius: 3px;
  padding: 1px 6px;
  margin-top: 4px;
  line-height: 1.3;
}

.cal-contact-chip-name {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-weight: 600;
}

.cal-contact-chip-phone {
  color: var(--text-muted);
  white-space: normal;
  word-break: break-word;
}

.event-color-0 { background: #2563eb; }
.event-color-1 { background: #16a34a; }
.event-color-2 { background: #d97706; }
.event-color-3 { background: #dc2626; }
.event-color-4 { background: #7c3aed; }
.event-color-5 { background: #0891b2; }

@media (max-width: 600px) {
  .cal-desktop-only {
    display: none;
  }
  .cal-mobile-only {
    display: block;
  }
}

/* MISC */
.error {
  color: var(--text);
  font-size: 13px;
  text-align: center;
  margin-top: 12px;
  font-weight: 500;
}

ul {
  padding-left: 20px;
  color: var(--text);
}

ul li {
  margin-bottom: 6px;
  font-weight: 500;
}

p {
  color: var(--text-muted);
  margin: 0 0 12px;
}

/* SELECTION */
::selection {
  background: var(--accent-soft);
  color: var(--text);
}

/* SEARCH BAR */
.search {
  padding: 7px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  background: var(--surface);
  flex: 1 1 auto;
  max-width: 280px;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.search:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

/* INVALID FORM INPUT — only flag after user has typed something */
.form input:required:invalid:not(:placeholder-shown) {
  border-color: #8b1f1f;
}

/* STICKY TABLE HEADERS */
thead th {
  position: sticky;
  top: 0;
  z-index: 1;
}

/* MAIN PAGE TABLE OVERFLOW (excludes dashboard tables) — only on narrow viewports,
   since display:block on a <table> breaks its width-fill behavior on wider screens. */
@media (max-width: 900px) {
  main > table {
    display: block;
    overflow-x: auto;
    max-width: 100%;
  }
}

/* TOPNAV — hamburger (left) + centered brand, both on one row. Tapping the
   hamburger reveals .links as a dropdown panel instead of the desktop's
   inline row of links. Shares the 900px breakpoint above (not the 600px
   one below) so there's no gap where the table is already in narrow-screen
   mode but the nav still shows the full, un-hamburgered desktop link row. */
@media (max-width: 900px) {
  .topnav {
    flex-direction: row;
    align-items: center;
    padding: 12px 16px;
    position: relative;
  }

  .nav-hamburger {
    display: inline-block;
    order: -1;
    background: none;
    border: none;
    color: var(--topbar-text);
    font-size: 22px;
    line-height: 1;
    padding: 4px 8px;
    cursor: pointer;
  }

  .brand {
    font-size: 14px;
    flex: 1;
    text-align: center;
  }

  .topnav .links {
    display: none;
    flex-direction: column;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--topbar-bg);
    padding: 8px 16px 16px;
    z-index: 100;
    overflow-x: visible;
    white-space: normal;
  }

  .topnav .links.open {
    display: flex;
  }
}

/* TABLET — the gap between the 900px hamburger-nav breakpoint above and the
   600px mobile breakpoint below (which starts hiding columns and forcing
   horizontal scroll). Without this, a table at e.g. 750px wide keeps full
   desktop font-size/padding and just grows a horizontal scrollbar instead of
   scaling down — readable text, but nothing else fits. Tightening density
   here first means most tables still fit without scrolling at all. */
@media (max-width: 900px) and (min-width: 601px) {
  h1 {
    font-size: 20px;
  }

  main {
    padding: 0 12px 32px;
  }

  td, th {
    padding: 7px 12px;
    font-size: 12px;
  }

  td.tags-cell {
    max-width: 200px;
  }
}

/* PRINT */
/* Password change modal */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
}

.modal-box {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 24px;
  width: 100%;
  max-width: 360px;
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.modal-box h2 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  text-align: left;
}

.modal-box input[type="password"] {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.modal-box input[type="password"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-ring);
}

/* Wider variant for modals showing more than a couple of stacked inputs —
   the contact notes modal needs room for the info block + textarea. */
.modal-box-wide {
  max-width: 480px;
}

.contact-detail p {
  margin: 0 0 6px;
  font-size: 13px;
  color: var(--text);
}

.modal-box textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  resize: vertical;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.modal-box textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-ring);
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 4px;
}

.btn-secondary {
  background: var(--surface);
  color: var(--text-muted);
  border: 1px solid var(--border-strong);
  padding: 7px 14px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  transition: background 0.12s ease;
}

.btn-secondary:hover {
  background: var(--hover);
}

.form-error {
  color: #dc2626;
  font-size: 12px;
}

/* Dark mode — invert lightness, rotate hue 180deg to preserve original colors */
html.dark-mode {
  filter: invert(1) hue-rotate(180deg);
}

html.dark-mode img,
html.dark-mode video,
html.dark-mode iframe {
  filter: invert(1) hue-rotate(180deg);
}

@media print {
  .topnav,
  .controls,
  .pager,
  .form,
  .btn-danger {
    display: none !important;
  }

  table {
    color: #000;
    box-shadow: none;
    border: none;
  }

  th,
  td {
    color: #000;
  }
}

/* AI WIDGET */
.ai-float-btn {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 1000;
  background: var(--topbar-bg);
  color: var(--topbar-text);
  border: none;
  padding: 8px 18px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  box-shadow: var(--shadow-md);
  transition: background 0.12s ease, color 0.12s ease;
}

.ai-float-btn:hover {
  background: var(--topbar-bg-hover);
  color: var(--topbar-text-hover);
}

.ai-widget {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 1000;
  width: 360px;
  height: 480px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.ai-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 11px 16px;
  background: var(--topbar-bg);
  flex-shrink: 0;
}

.ai-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--topbar-text-hover);
}

.ai-close-btn {
  background: none;
  border: none;
  color: var(--topbar-text);
  cursor: pointer;
  font-size: 16px;
  padding: 0 2px;
  line-height: 1;
  font-family: inherit;
  transition: color 0.12s ease;
}

.ai-close-btn:hover {
  color: var(--topbar-text-hover);
}

.ai-messages {
  flex: 1;
  overflow-y: auto;
  padding: 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.ai-msg-user {
  align-self: flex-end;
  background: var(--accent);
  color: #ffffff;
  padding: 8px 12px;
  border-radius: 12px 12px 2px 12px;
  max-width: 82%;
  font-size: 13px;
  line-height: 1.45;
  word-break: break-word;
  white-space: pre-wrap;
}

.ai-msg-assistant {
  align-self: flex-start;
  background: var(--surface-alt);
  color: var(--text);
  padding: 8px 12px;
  border-radius: 12px 12px 12px 2px;
  max-width: 82%;
  font-size: 13px;
  line-height: 1.45;
  word-break: break-word;
  white-space: pre-wrap;
  border: 1px solid var(--border);
}

.ai-msg-error {
  color: #dc2626;
}

.ai-no-key {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
  padding: 24px;
  line-height: 1.5;
}

.ai-input-area {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  align-items: center;
}

.ai-input {
  flex: 1;
  padding: 7px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  outline: none;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

.ai-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-ring);
}

.ai-spinner {
  width: 30px;
  height: 30px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: ai-spin 0.65s linear infinite;
  flex-shrink: 0;
}

@keyframes ai-spin {
  to { transform: rotate(360deg); }
}

/* AI CONFIG MODAL */
.ai-provider-toggle {
  display: flex;
  gap: 8px;
}

.ai-provider-btn {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  transition: all 0.12s ease;
}

.ai-provider-btn.active {
  background: var(--accent);
  color: #ffffff;
  border-color: var(--accent);
}

.ai-provider-btn:hover:not(.active) {
  background: var(--hover);
  color: var(--text);
}

.ai-disclaimer {
  font-size: 11px;
  color: var(--text-subtle);
  margin: -4px 0 0;
  line-height: 1.5;
}

/* MOBILE */
@media (max-width: 600px) {
  /* 1. BODY AND LAYOUT */
  body {
    padding: 0;
  }

  main {
    padding: 0 12px 24px;
  }

  /* 3. TYPOGRAPHY */
  h1 {
    font-size: 20px;
  }

  /* 4. TABLES */
  td, th {
    padding: 5px 10px;
    font-size: 12px;
  }

  /* > not a plain descendant selector — dashboard tables are nested inside
     .dashboard-half/.dashboard-row, not direct children of main, so they're
     excluded here the same way the 900px rule above already excludes them.
     Without this, display:block breaks their percentage-width column sizing. */
  main > table {
    display: block;
    overflow-x: auto;
    max-width: 100%;
    -webkit-overflow-scrolling: touch;
  }

  /* Hide low-priority columns on the main list pages so most rows fit
     without horizontal scrolling. ID (nth-child(1)) is already hidden at
     every viewport width by the global rule above the dashboard tables —
     City/Date, Contact/Phone, and Phone/Email are the droppable columns
     for leads/deals/notes respectively, mobile-only. */
  .leads-table th:nth-child(6),
  .leads-table td:nth-child(6),
  .leads-table th:nth-child(7),
  .leads-table td:nth-child(7) {
    display: none;
  }

  .contacts-table th:nth-child(6),
  .contacts-table td:nth-child(6) {
    display: none;
  }

  .companies-table th:nth-child(3),
  .companies-table td:nth-child(3) {
    display: none;
  }

  .deals-table th:nth-child(6),
  .deals-table td:nth-child(6),
  .deals-table th:nth-child(7),
  .deals-table td:nth-child(7) {
    display: none;
  }

  .notes-table th:nth-child(4),
  .notes-table td:nth-child(4),
  .notes-table th:nth-child(5),
  .notes-table td:nth-child(5) {
    display: none;
  }

  /* Explicit widths for the remaining visible columns on each table above.
     Without these, an empty table (no rows to size against) can leave the
     header row narrower than the container instead of stretching to fill it —
     same issue as the dashboard's mini-tables, fixed the same way. Delete
     (always the last column, still shown here unlike on the dashboard) is
     left unconstrained since it just needs to fit its own button. */
  /* white-space: nowrap keeps rows single-line on mobile — without it, td's
     overflow-wrap: anywhere lets long names/emails wrap mid-word to fit
     these narrow percentage widths, inflating row height. main > table's
     overflow-x: auto (above) already handles any resulting horizontal
     overflow via side-scroll instead. */
  .leads-table th:nth-child(2), .leads-table td:nth-child(2) { width: 20%; white-space: nowrap; }
  .leads-table th:nth-child(3), .leads-table td:nth-child(3) { width: 20%; white-space: nowrap; }
  .leads-table th:nth-child(4), .leads-table td:nth-child(4) { width: 24%; white-space: nowrap; }
  .leads-table th:nth-child(5), .leads-table td:nth-child(5) { width: 26%; white-space: nowrap; }
  .leads-table th:nth-child(8), .leads-table td:nth-child(8) { width: 20%; white-space: nowrap; }

  .contacts-table th:nth-child(2), .contacts-table td:nth-child(2) { width: 18%; white-space: nowrap; }
  .contacts-table th:nth-child(3), .contacts-table td:nth-child(3) { width: 18%; white-space: nowrap; }
  .contacts-table th:nth-child(4), .contacts-table td:nth-child(4) { width: 22%; white-space: nowrap; }
  .contacts-table th:nth-child(5), .contacts-table td:nth-child(5) { width: 18%; white-space: nowrap; }
  .contacts-table th:nth-child(7), .contacts-table td:nth-child(7) { width: 20%; white-space: nowrap; }

  .companies-table th:nth-child(2), .companies-table td:nth-child(2) { width: 30%; white-space: nowrap; }
  .companies-table th:nth-child(4), .companies-table td:nth-child(4) { width: 26%; white-space: nowrap; }
  .companies-table th:nth-child(5), .companies-table td:nth-child(5) { width: 32%; white-space: nowrap; }

  .deals-table th:nth-child(2), .deals-table td:nth-child(2) { width: 28%; white-space: nowrap; }
  .deals-table th:nth-child(3), .deals-table td:nth-child(3) { width: 16%; white-space: nowrap; }
  .deals-table th:nth-child(4), .deals-table td:nth-child(4) { width: 18%; white-space: nowrap; }
  .deals-table th:nth-child(5), .deals-table td:nth-child(5) { width: 24%; white-space: nowrap; }

  .notes-table th:nth-child(2), .notes-table td:nth-child(2) { width: 55%; }
  .notes-table th:nth-child(3), .notes-table td:nth-child(3) { width: 25%; }

  /* 5. FORMS */
  .form {
    flex-direction: column;
  }

  .form input,
  .form select {
    width: 100%;
    flex: none;
  }

  /* 16px, not 13px — under 16px, iOS Safari zooms the whole page in on focus */
  .form input,
  .form select,
  .search {
    font-size: 16px;
  }

  /* 6. CONTROLS — search + CSV button share one row, CSV right-justified
     in the space left over (base .controls already has justify-content:
     space-between/align-items:center; only the column stacking needs undoing). */
  .controls {
    flex-direction: row;
    flex-wrap: nowrap;
    gap: 8px;
  }

  .controls .search {
    flex: 1 1 auto;
    max-width: none;
    width: auto;
  }

  /* 7. PAGER */
  .pager {
    font-size: 12px;
    gap: 8px;
  }

  /* 8. LOGIN CARD */
  .login-card {
    max-width: none;
    width: 90%;
    margin: 24px auto;
    padding: 24px 20px;
  }

  /* 9. BUTTONS — bigger tap targets than desktop, not smaller */
  .btn {
    padding: 10px 16px;
  }

  .btn-danger {
    padding: 8px 14px;
    font-size: 13px;
  }

  /* 10. CALL BUTTONS — mobile only, hidden on desktop by the base .btn-call rule */
  .btn-call {
    display: inline-block;
  }
}

/* COLUMN HIDING — right-click a column header to collapse it (app.js).
   Scoped to min-width so it never fights the mobile column rules above,
   which already decide what's visible under 600px on their own terms.
   A "hidden" column isn't removed — it collapses to a narrow strip with just
   the header's first letter (app.js swaps the th's text) and blank cells, so
   there's still a sliver to right-click again to bring it back.
   :not([colspan]) on nth-child(1) excludes the single-cell "no X yet"
   empty-state row, same reason as the mobile rules above. */
@media (min-width: 601px) {
  table.hide-col-1 th:nth-child(1),
  table.hide-col-1 td:nth-child(1):not([colspan]),
  table.hide-col-2 th:nth-child(2),
  table.hide-col-2 td:nth-child(2),
  table.hide-col-3 th:nth-child(3),
  table.hide-col-3 td:nth-child(3),
  table.hide-col-4 th:nth-child(4),
  table.hide-col-4 td:nth-child(4),
  table.hide-col-5 th:nth-child(5),
  table.hide-col-5 td:nth-child(5),
  table.hide-col-6 th:nth-child(6),
  table.hide-col-6 td:nth-child(6),
  table.hide-col-7 th:nth-child(7),
  table.hide-col-7 td:nth-child(7),
  table.hide-col-8 th:nth-child(8),
  table.hide-col-8 td:nth-child(8),
  table.hide-col-9 th:nth-child(9),
  table.hide-col-9 td:nth-child(9),
  table.hide-col-10 th:nth-child(10),
  table.hide-col-10 td:nth-child(10) {
    width: 28px;
    max-width: 28px;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    padding-left: 6px;
    padding-right: 6px;
    text-align: center;
  }

  /* Header keeps its (now single-letter) text visible; only the data cells
     go blank. color: transparent (not font-size: 0) so row height is
     unaffected — the box still clips to 28px via overflow: hidden above,
     regardless of how long the real value underneath actually is. */
  table.hide-col-1 td:nth-child(1):not([colspan]),
  table.hide-col-2 td:nth-child(2),
  table.hide-col-3 td:nth-child(3),
  table.hide-col-4 td:nth-child(4),
  table.hide-col-5 td:nth-child(5),
  table.hide-col-6 td:nth-child(6),
  table.hide-col-7 td:nth-child(7),
  table.hide-col-8 td:nth-child(8),
  table.hide-col-9 td:nth-child(9),
  table.hide-col-10 td:nth-child(10) {
    color: transparent;
  }

  /* Tags is column 8 on the contacts table and column 9 on the leads table
     (leads has the extra follow-up column contacts doesn't). color:
     transparent above only blanks text — it does nothing for the pills' own
     background/border or the tag-remove/tag-add spans' explicit colors, so
     collapsing the column would otherwise still show pill fragments and the
     "+" button poking out of the 28px strip. Hide those elements outright
     instead. */
  table.hide-col-8 td.tags-cell .tag-pill,
  table.hide-col-8 td.tags-cell .tag-add,
  table.hide-col-9 td.tags-cell .tag-pill,
  table.hide-col-9 td.tags-cell .tag-add {
    display: none;
  }

  /* The Actions column (email/call/notes/to-contact/delete buttons -- every
     one shares the base .btn-danger class) is always the last column, at a
     different index per table depending on how many fields that table has.
     Same reasoning as the tags-pill rule above: color: transparent doesn't
     touch a button's own background, so the buttons would otherwise still
     poke out of the collapsed 28px strip. */
  .leads-table.hide-col-10 td:last-child .btn-danger,
  .contacts-table.hide-col-9 td:last-child .btn-danger,
  .deals-table.hide-col-8 td:last-child .btn-danger,
  .companies-table.hide-col-6 td:last-child .btn-danger,
  .notes-table.hide-col-6 td:last-child .btn-danger {
    display: none;
  }
}

/* TAGS (contacts, leads) */
.tag-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: #e8e8e8;
  border: 1px solid #c4c4c4;
  border-radius: 12px;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
  margin: 2px;
  white-space: nowrap;
}

.tag-pill .tag-remove {
  cursor: pointer;
  font-size: 10px;
  color: #666;
  line-height: 1;
  padding: 0 2px;
}

.tag-pill .tag-remove:hover {
  color: #000;
}

.tag-add {
  display: inline-block;
  cursor: pointer;
  color: var(--text-subtle);
  font-size: 12px;
  padding: 2px 6px;
}

.tag-input {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 4px 8px;
  font-size: 12px;
  font-family: inherit;
  width: 140px;
  margin: 2px;
}

.tag-input:focus {
  outline: none;
  border-color: #000;
}

/* No min-width: an empty row (just the "+" add control) should size to
   fit the "Tags" header, not force a wide empty-looking column. max-width
   is the cap that makes a row with several tags wrap its pills onto
   additional lines within the cell instead of growing the column further
   -- the td's own overflow-wrap/word-break (see base td rule above) already
   wraps ordinary inline content the same way once a max-width is set. */
td.tags-cell {
  max-width: 280px;
}
