/* ============================================================
   Waypenny — Design System
   Light theme, deep green accent, Playfair + Inter typography.
   ============================================================ */

/* ---------- CSS variables (Section 5) ---------- */
:root {
  --white: #ffffff;
  --off-white: #f8f9fa;
  --light-gray: #f1f3f5;
  --border: #e9ecef;
  --text-primary: #1a1a2e;
  --text-secondary: #6c757d;
  --accent: #2d6a4f;
  --accent-light: #40916c;
  --accent-pale: #d8f3dc;
  --gold: #e9c46a;
  --gold-pale: #fdf4d4;
  --danger: #e63946;
  --danger-pale: #fde8ea;
  --warning: #f4a261;
  --warning-pale: #fdecd9;
  --success: #2d6a4f;
  --info: #457b9d;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 1px 3px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 4px 14px rgba(0, 0, 0, 0.08);

  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-pill: 999px;

  --sidebar-w: 240px;
  --bottom-nav-h: 64px;
}

/* ---------- Base reset ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  color: var(--text-primary);
  background: var(--off-white);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: var(--accent);
  text-decoration: none;
}
a:hover { text-decoration: underline; }

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

img { max-width: 100%; display: block; }

/* ---------- Typography ---------- */
h1, h2, h3, h4 {
  font-family: 'Playfair Display', Georgia, serif;
  color: var(--text-primary);
  margin: 0 0 12px 0;
  font-weight: 600;
  line-height: 1.2;
}
h1 { font-size: 2.5rem; }
h2 { font-size: 1.75rem; }
h3 { font-size: 1.25rem; }
h4 { font-size: 1.0625rem; }

p { margin: 0 0 12px 0; }

.muted { color: var(--text-secondary); }
.small { font-size: 13px; }
.tiny  { font-size: 12px; }

.serif { font-family: 'Playfair Display', Georgia, serif; }

.text-success { color: var(--success); }
.text-danger  { color: var(--danger); }
.text-warning { color: var(--warning); }

.text-center { text-align: center; }
.text-right  { text-align: right; }

/* ---------- App layout (sidebar + main) ---------- */
.app-shell {
  min-height: 100vh;
}

.sidebar {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: var(--sidebar-w);
  background: var(--white);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  z-index: 50;
}

/* BUILD MOBILE-TABBAR (2026-08-13) — phone-only bottom tab bar
   (injected by injectMobileTabbar in app.js). Hidden on desktop;
   the ≤768px media block flips it on and hides the sidebar behind
   the More tab instead. */
.mobile-tabbar { display: none; }

.sidebar-brand {
  padding: 20px 20px 16px;
  border-bottom: 1px solid var(--border);
}
.brand-name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: 0.2px;
}

.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: 12px 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sidebar-nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: 14px;
  font-weight: 500;
  border-left: 3px solid transparent;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.sidebar-nav a:hover {
  background: var(--off-white);
  text-decoration: none;
}
.sidebar-nav a.active {
  background: var(--accent-pale);
  color: var(--accent);
  border-left-color: var(--accent);
  font-weight: 600;
}
.sidebar-nav a.nav-disabled {
  color: var(--text-secondary);
  cursor: not-allowed;
  opacity: 0.55;
}
.sidebar-nav a.nav-disabled:hover { background: transparent; }

.nav-section-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-secondary);
  padding: 14px 12px 6px;
}

.nav-icon {
  display: inline-flex;
  width: 18px;
  justify-content: center;
  font-size: 14px;
  opacity: 0.8;
}

/* BUILD 25 Part 4 (2026-07-27) — Team-tasks expandable group.
   Owner/mw only; shows one entry per active member. Reuses the
   sidebar-nav row look for the inner rows so it doesn't stand out
   as a separate visual pattern. */
.sidebar-nav details.nav-group {
  margin: 0;
}
.sidebar-nav details.nav-group summary.nav-group-summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  color: var(--text-primary);
  font-size: 14px;
  font-weight: 500;
  user-select: none;
}
.sidebar-nav details.nav-group summary.nav-group-summary::-webkit-details-marker {
  display: none;
}
.sidebar-nav details.nav-group summary.nav-group-summary::after {
  content: '▸';
  margin-left: auto;
  opacity: 0.55;
  font-size: 11px;
  transition: transform 0.15s ease;
}
.sidebar-nav details.nav-group[open] summary.nav-group-summary::after {
  transform: rotate(90deg);
}
.sidebar-nav details.nav-group summary.nav-group-summary:hover {
  background: var(--off-white);
}
.sidebar-nav a.nav-sublink {
  padding-left: 34px;
  font-size: 13px;
  opacity: 0.9;
}

.sidebar-footer {
  border-top: 1px solid var(--border);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sidebar-user {
  font-size: 13px;
  color: var(--text-secondary);
  text-align: center;
}
.sidebar-legal {
  display: flex;
  gap: 6px;
  justify-content: center;
  font-size: 11px;
  color: var(--text-tertiary, #8a8a8a);
  margin-top: 4px;
}
.sidebar-legal a {
  color: var(--text-tertiary, #8a8a8a);
  text-decoration: none;
}
.sidebar-legal a:hover { text-decoration: underline; }

/* ---------- Workspace switcher (MU-2) ---------- */
.ws-switcher {
  position: relative;
  padding: 10px 10px 4px;
  border-bottom: 1px solid var(--border);
}
.ws-switcher-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  background: var(--off-white);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  text-align: left;
  font-family: inherit;
  color: var(--text-primary);
  cursor: pointer;
  flex-wrap: wrap;
}
.ws-switcher-trigger:hover { background: var(--light-gray); }
.ws-switcher-name {
  font-size: 13px;
  font-weight: 600;
  flex: 1 1 100%;
  line-height: 1.25;
}
.ws-switcher-meta {
  font-size: 11px;
  color: var(--text-secondary);
  text-transform: capitalize;
  flex: 1 1 auto;
}
.ws-switcher-caret {
  font-size: 11px;
  color: var(--text-secondary);
  margin-left: auto;
}
.ws-switcher-menu {
  position: absolute;
  top: calc(100% - 2px);
  left: 10px;
  right: 10px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 60;
  max-height: 320px;
  overflow-y: auto;
  padding: 4px;
}
.ws-option {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  text-align: left;
  font-family: inherit;
  color: var(--text-primary);
  cursor: pointer;
}
.ws-option:hover { background: var(--off-white); }
.ws-option.is-active {
  background: var(--accent-pale);
  color: var(--accent);
}
.ws-option-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}
.ws-option-name {
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ws-option-meta {
  font-size: 11px;
  color: var(--text-secondary);
  text-transform: capitalize;
}
.ws-option-check {
  color: var(--accent);
  font-weight: 700;
}

.main-content {
  margin-left: var(--sidebar-w);
  padding: 32px;
  min-height: 100vh;
}

.page-header {
  margin-bottom: 24px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.page-title {
  margin: 0;
  font-size: 2rem;
}
.page-subtitle {
  color: var(--text-secondary);
  margin-top: 4px;
}

/* ---------- Cards ---------- */
.card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 20px;
}
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.card-title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 1.125rem;
  font-weight: 600;
  margin: 0;
}

/* ---------- Grid ---------- */
.grid {
  display: grid;
  gap: 20px;
}
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }

.section-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 24px 0 12px;
}

/* ---------- Stat tile (Section 5) ---------- */
.stat-tile {
  text-align: center;
}
.stat-value {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 2rem;
  font-weight: 600;
  line-height: 1.1;
  color: var(--text-primary);
}
.stat-value.muted { color: var(--text-secondary); }
.stat-label {
  color: var(--text-secondary);
  font-size: 13px;
  margin-top: 4px;
}
.stat-trend {
  font-size: 12px;
  margin-top: 6px;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 20px;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: 14px;
  border: 1.5px solid transparent;
  background: transparent;
  color: var(--text-primary);
  transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.05s;
  text-decoration: none;
  cursor: pointer;
}
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--accent);
  color: var(--white);
  border-color: var(--accent);
}
.btn-primary:hover {
  background: var(--accent-light);
  border-color: var(--accent-light);
  text-decoration: none;
}

.btn-outline {
  background: var(--white);
  color: var(--accent);
  border-color: var(--accent);
}
.btn-outline:hover {
  background: var(--accent-pale);
  text-decoration: none;
}

.btn-ghost {
  background: transparent;
  color: var(--text-primary);
  border-color: var(--border);
}
.btn-ghost:hover { background: var(--off-white); text-decoration: none; }

.btn-danger {
  background: var(--danger);
  color: var(--white);
  border-color: var(--danger);
}
.btn-danger:hover { opacity: 0.9; text-decoration: none; }

.btn-sm { padding: 6px 14px; font-size: 13px; }
.btn-lg { padding: 14px 28px; font-size: 16px; }
.btn-full { width: 100%; }

.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* ---------- Forms ---------- */
.form-group { margin-bottom: 18px; }
.form-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 6px;
  color: var(--text-primary);
}
.form-input,
.form-select,
.form-textarea {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-size: 14px;
  font-family: inherit;
  color: var(--text-primary);
  background: var(--white);
}
.form-input:focus,
.form-select:focus,
.form-textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(45, 106, 79, 0.15);
}
.form-textarea { resize: vertical; min-height: 80px; }
.form-help {
  font-size: 12px;
  color: var(--text-secondary);
  margin-top: 4px;
}
.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

/* ---------- Tables ---------- */
.table-wrapper { overflow-x: auto; }
.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.table th,
.table td {
  padding: 12px 16px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}
.table th {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  background: var(--off-white);
}
.table tbody tr:hover { background: var(--off-white); }
.table tbody tr:last-child td { border-bottom: none; }

/* ---------- Badges ---------- */
/* BUILD TASK-POLISH (2026-07-30) — badges are single-line by design;
   nowrap prevents multi-word labels like "Locked" (2-char) from
   line-breaking inside narrow table cells (which can happen when the
   cell is auto-sized against long neighbor content). */
.badge {
  display: inline-block;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  background: var(--light-gray);
  color: var(--text-secondary);
  white-space: nowrap;
}
.badge-trial   { background: var(--accent-pale); color: var(--accent); }
.badge-active  { background: var(--accent-pale); color: var(--accent); }
.badge-warning { background: var(--warning-pale); color: #b45309; }
.badge-danger  { background: var(--danger-pale);  color: var(--danger); }
.badge-gold    { background: var(--gold-pale);    color: #92740b; }
.badge-info    { background: #e6eef5;             color: var(--info); }
/* BUILD BUDGET-BILLS-MERGE Part 1 (2026-08-27) — the quietest rung of
   the due-badge scale. 'Due in 7 days' must be present without being
   loud; badge-info reads blue/informational, which is a different
   signal. Neutral gray on the default badge background. */
.badge-muted   { background: var(--light-gray);   color: var(--text-secondary); }

/* ---------- Progress bar ---------- */
.progress-bar {
  width: 100%;
  height: 8px;
  background: var(--light-gray);
  border-radius: var(--radius-pill);
  overflow: hidden;
}
.progress-fill {
  height: 100%;
  background: var(--accent);
  transition: width 0.3s ease;
}
.progress-fill.warning { background: var(--gold); }
.progress-fill.danger  { background: var(--danger); }

/* ---------- Banners / alerts ---------- */
.banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 18px;
  border-radius: var(--radius-md);
  font-size: 14px;
  margin-bottom: 20px;
}
.banner-warning { background: var(--warning-pale); color: #92400e; border: 1px solid #fcd9b6; }
.banner-danger  { background: var(--danger-pale);  color: var(--danger); border: 1px solid #f8c8cc; }
.banner-info    { background: #e6eef5;             color: var(--info); border: 1px solid #c5d6e3; }

/* WAYMARK P4 (2026-07-14) — workspace banner refined header treatment.
   Refined from the WS-UNIFY block-fill: replaced the solid green
   with a hairline rule so it reads as a page header, not a badge.
   Kept centered + serif so the workspace context is still
   impossible to miss. Tokens only — no hex, no theme drift. */
.workspace-banner {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 14px;
  padding: 4px 0 12px 0;
  border-bottom: 1px solid var(--border, #eee);
  margin-bottom: 20px;
  text-align: center;
}
.workspace-banner-label {
  /* WAYMARK P4 — the "Workspace" prefix is muted small-caps that
     defers to the workspace name. Kept for scannability but no
     longer competes visually with the name. */
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  opacity: 0.7;
}
.workspace-banner-name {
  font-family: 'Playfair Display', serif;
  font-size: 22px;
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.005em;
  line-height: 1.15;
}
.workspace-banner-type {
  /* WAYMARK P4 — small-caps muted badge, no fill. Sits alongside the
     name as an inline qualifier rather than a colored chip. */
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  opacity: 0.75;
}
/* BUILD MOBILE-TABBAR follow-up (2026-08-13) — the banner is a tap
   target on phones only (opens the More sheet with the switcher
   expanded). The caret is the affordance; hidden on desktop where
   the banner stays a static region. */
.workspace-banner-caret { display: none; }

/* ---------- Empty state ---------- */
.empty-state {
  text-align: center;
  padding: 32px 20px;
  color: var(--text-secondary);
}
.empty-state-icon {
  font-size: 32px;
  opacity: 0.5;
  margin-bottom: 8px;
}
.empty-state-title {
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 4px;
}

/* ---------- Auth pages (signup/login) ---------- */
.auth-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 16px;
  background: var(--off-white);
}
.auth-card {
  width: 100%;
  max-width: 420px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 32px;
}
.auth-card h1 {
  font-size: 1.75rem;
  margin-bottom: 8px;
  text-align: center;
}
.auth-card .auth-sub {
  text-align: center;
  color: var(--text-secondary);
  margin-bottom: 24px;
}
.auth-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 20px 0;
  color: var(--text-secondary);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 1px;
}
.auth-divider::before,
.auth-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}
.auth-footer {
  text-align: center;
  margin-top: 20px;
  font-size: 14px;
  color: var(--text-secondary);
}
.auth-error {
  background: var(--danger-pale);
  color: var(--danger);
  padding: 10px 14px;
  border-radius: var(--radius-md);
  font-size: 13px;
  margin-bottom: 16px;
  display: none;
}
.auth-error.visible { display: block; }
.auth-success {
  background: var(--accent-pale);
  color: var(--accent);
  padding: 10px 14px;
  border-radius: var(--radius-md);
  font-size: 13px;
  margin-bottom: 16px;
  display: none;
}
.auth-success.visible { display: block; }

.btn-google {
  background: var(--white);
  color: var(--text-primary);
  border-color: var(--border);
}
.btn-google:hover { background: var(--off-white); text-decoration: none; }

/* ----------------------------------------------------------------
   WAYMARK CLICKWRAP (2026-07-17) — Terms acceptance modal.
   Used by signup.html and accept-terms.html. Blocking overlay.
   ---------------------------------------------------------------- */
.terms-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.terms-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 30, 25, 0.55);
}
.terms-modal-card {
  position: relative;
  width: 100%;
  max-width: 560px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  background: var(--white, #fff);
  border-radius: var(--radius-lg, 10px);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
  padding: 32px 32px 24px;
  font-size: 15px;
  line-height: 1.55;
}
.terms-modal-title {
  font-family: 'Playfair Display', serif;
  font-weight: 600;
  font-size: 22px;
  margin-bottom: 4px;
  color: #2d6a4f;
}
.terms-modal-sub {
  font-size: 14px;
  color: #444;
  margin-bottom: 16px;
}
.terms-modal-summary {
  border: 1px solid var(--border, #eee);
  background: #fafaf7;
  border-radius: 8px;
  padding: 14px 18px;
  margin-bottom: 12px;
  font-size: 14px;
  line-height: 1.55;
  max-height: 260px;
  overflow-y: auto;
}
.terms-modal-summary strong { color: #2d6a4f; }
.terms-modal-summary ul { padding-left: 20px; margin: 8px 0; }
.terms-modal-summary li { margin-bottom: 6px; }
.terms-modal-summary-fine {
  font-size: 12px;
  color: #6b6b6b;
  margin-top: 8px;
}
.terms-modal-links {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 14px;
  font-size: 14px;
}
.terms-modal-links a {
  color: #2d6a4f;
  font-weight: 500;
  text-decoration: underline;
}
.terms-modal-check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--border, #ddd);
  border-radius: 6px;
  background: #fff;
  cursor: pointer;
  margin-bottom: 16px;
  font-size: 14px;
}
.terms-modal-check input[type="checkbox"] {
  margin-top: 3px;
  transform: scale(1.15);
  cursor: pointer;
  flex-shrink: 0;
}
.terms-modal-check span a { color: #2d6a4f; text-decoration: underline; }
.terms-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-bottom: 12px;
}
.terms-modal-version {
  font-size: 12px;
  color: #8a8a8a;
  text-align: center;
  margin-top: 6px;
}

/* ---------- Onboarding wizard ---------- */
.wizard {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 32px 16px;
  background: var(--off-white);
}
.wizard-card {
  width: 100%;
  max-width: 560px;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 36px;
}
.wizard-steps {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-bottom: 28px;
}
.wizard-dot {
  width: 32px;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
}
.wizard-dot.active { background: var(--accent); }
.wizard-dot.done   { background: var(--accent-light); }

.wizard-step { display: none; }
.wizard-step.active { display: block; }

.choice-grid {
  display: grid;
  gap: 12px;
  margin: 20px 0;
}
.choice {
  display: block;
  padding: 18px 20px;
  border: 2px solid var(--border);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
  text-align: left;
}
.choice:hover { border-color: var(--accent-light); }
.choice.selected {
  border-color: var(--accent);
  background: var(--accent-pale);
}
.choice-title {
  font-weight: 600;
  margin-bottom: 4px;
}
.choice-sub {
  font-size: 13px;
  color: var(--text-secondary);
}

.wizard-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 28px;
}

/* ---------- Landing page ---------- */
.landing-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 32px;
  border-bottom: 1px solid var(--border);
  background: var(--white);
}
.landing-nav .brand-name { font-size: 1.25rem; }
.landing-nav .nav-actions { display: flex; gap: 12px; align-items: center; }

.hero {
  padding: 80px 32px;
  text-align: center;
  background: linear-gradient(180deg, var(--white) 0%, var(--off-white) 100%);
}
.hero h1 {
  font-size: 3rem;
  max-width: 800px;
  margin: 0 auto 16px;
  line-height: 1.15;
}
.hero p {
  font-size: 1.125rem;
  color: var(--text-secondary);
  max-width: 640px;
  margin: 0 auto 28px;
}
.hero-cta {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

.section {
  padding: 64px 32px;
}
.section-inner {
  max-width: 1100px;
  margin: 0 auto;
}
.section-title {
  font-size: 2rem;
  text-align: center;
  margin-bottom: 8px;
}
.section-sub {
  text-align: center;
  color: var(--text-secondary);
  margin-bottom: 40px;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.feature {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 24px;
}
.feature-icon {
  font-size: 28px;
  margin-bottom: 12px;
}
.feature h3 {
  font-size: 1.125rem;
  margin-bottom: 6px;
}
.feature p {
  color: var(--text-secondary);
  font-size: 14px;
  margin: 0;
}

.pricing-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-top: 32px;
}
.price-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 28px;
  display: flex;
  flex-direction: column;
  text-align: center;
}
.price-card.featured {
  border-color: var(--accent);
  border-width: 2px;
  position: relative;
}
.price-card.featured::before {
  content: 'BEST VALUE';
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--accent);
  color: var(--white);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 1px;
  padding: 4px 12px;
  border-radius: var(--radius-pill);
}
.price-name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 1.5rem;
  font-weight: 600;
  margin-bottom: 4px;
}
.price-amount {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 3rem;
  font-weight: 600;
  color: var(--accent);
  line-height: 1;
}
.price-period {
  color: var(--text-secondary);
  font-size: 14px;
  margin-bottom: 18px;
}
.price-features {
  list-style: none;
  padding: 0;
  margin: 0 0 24px;
  text-align: left;
  flex: 1;
}
.price-features li {
  padding: 6px 0;
  font-size: 14px;
}
.price-features li::before {
  content: '✓ ';
  color: var(--accent);
  font-weight: 700;
}

.cta-section {
  text-align: center;
  padding: 80px 32px;
  background: var(--accent);
  color: var(--white);
}
.cta-section h2 {
  color: var(--white);
  margin-bottom: 12px;
}
.cta-section p {
  color: rgba(255,255,255,0.85);
  margin-bottom: 24px;
}
.cta-section .btn-primary {
  background: var(--white);
  color: var(--accent);
  border-color: var(--white);
}
.cta-section .btn-primary:hover {
  background: var(--accent-pale);
  border-color: var(--accent-pale);
}

.landing-footer {
  padding: 24px 32px;
  text-align: center;
  color: var(--text-secondary);
  font-size: 13px;
  border-top: 1px solid var(--border);
}

/* ---------- Loader ---------- */
.loader {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid var(--accent-pale);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.page-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 60vh;
  color: var(--text-secondary);
  gap: 10px;
}

/* ---------- Page additions (Phase 2) ---------- */
.row-flex {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.row-spread {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.stack > * + * { margin-top: 16px; }

.chart-wrap {
  position: relative;
  width: 100%;
  height: 280px;
}
.chart-wrap.tall { height: 340px; }

.btn-icon {
  background: transparent;
  border: none;
  color: var(--text-secondary);
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  cursor: pointer;
}
.btn-icon:hover { background: var(--off-white); color: var(--text-primary); }
.btn-icon.danger:hover { background: var(--danger-pale); color: var(--danger); }

.table td.amount,
.table th.amount { text-align: right; font-variant-numeric: tabular-nums; }

.table tr.row-warning td { background: var(--warning-pale); }
.table tr.row-danger  td { background: var(--danger-pale); }

.kv-list {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 6px 16px;
  font-size: 14px;
}
.kv-list dt { color: var(--text-secondary); }
.kv-list dd { margin: 0; font-weight: 600; }

.bucket-row {
  display: grid;
  grid-template-columns: 110px 1fr 140px;
  gap: 12px;
  align-items: center;
  padding: 8px 0;
}
.bucket-row .bucket-label { font-weight: 600; }
.bucket-row .bucket-meta { text-align: right; color: var(--text-secondary); font-size: 13px; }

.cat-row {
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.cat-row:last-child { border-bottom: none; }
.cat-row-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 6px;
  gap: 12px;
  flex-wrap: wrap;
}
.cat-row-name { font-weight: 600; }
.cat-row-meta { color: var(--text-secondary); font-size: 13px; }

.input-inline {
  padding: 6px 10px;
  font-size: 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  width: 100%;
  max-width: 140px;
  font-family: inherit;
  color: var(--text-primary);
  background: var(--white);
}
.input-inline:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 2px rgba(45, 106, 79, 0.15);
}

.tab-row {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
}
.tab-row button {
  background: transparent;
  border: none;
  padding: 10px 14px;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-secondary);
  border-bottom: 2px solid transparent;
  cursor: pointer;
  font-family: inherit;
}
.tab-row button.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

.divider {
  height: 1px;
  background: var(--border);
  margin: 16px 0;
}

/* ---------- Kanban (Phase 4: pipeline) ---------- */
.kanban {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  align-items: start;
}
.kanban-col {
  background: var(--off-white);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 12px;
  min-height: 200px;
}
.kanban-col-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.kanban-col-head .count {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 1px 8px;
  font-size: 11px;
  color: var(--text-primary);
}
.kanban-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px;
  margin-bottom: 10px;
  box-shadow: var(--shadow-sm);
}
.kanban-card.priority::before {
  content: '★ ';
  color: var(--gold);
}
.kanban-card h4 {
  font-family: 'Inter', sans-serif;
  font-size: 14px;
  font-weight: 600;
  margin: 0 0 4px 0;
}
.kanban-card .kc-meta {
  font-size: 12px;
  color: var(--text-secondary);
  margin-bottom: 6px;
}
.kanban-card .kc-amount {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 16px;
  font-weight: 600;
}
.kanban-card select,
.kanban-card .kc-actions {
  margin-top: 8px;
  display: flex;
  gap: 6px;
  align-items: center;
}

/* ---------- Responsive (≤768px) ---------- */
@media (max-width: 768px) {
  /* BUILD MOBILE-TABBAR (2026-08-13, pass 110) — 4-tab bottom bar +
     full-screen "More" sheet. Replaces the horizontally-scrolling
     link strip (pass 109), which broke on the Team-tasks expandable
     group and buried every destination past the first. Pattern per
     Apple HIG / Material bottom-navigation guidance: 3-5 fixed
     icon+label tabs, everything else behind a More tab.

     The desktop sidebar markup IS the More sheet on phones — same
     links, same workspace switcher (its dropdown opens downward
     inside the sheet exactly as on desktop), same wiring. The sheet
     shows when body.mobile-menu-open is set by the More tab
     (injectMobileTabbar in app.js). Desktop >768px is unchanged.
     env(safe-area-inset-bottom) clears the iPhone home indicator;
     it resolves to 0 where unsupported. */
  .sidebar {
    top: 0;
    left: 0;
    right: 0;
    bottom: calc(var(--bottom-nav-h) + env(safe-area-inset-bottom, 0px));
    width: 100%;
    border-right: none;
    display: none;
    z-index: 55;
  }
  body.mobile-menu-open .sidebar { display: flex; }
  body.mobile-menu-open { overflow: hidden; }
  /* Sheet rows get comfortable phone tap targets. */
  .sidebar-nav a { font-size: 15px; padding: 11px 12px; }
  .sidebar-nav details.nav-group summary.nav-group-summary {
    font-size: 15px;
    padding: 11px 12px;
  }

  .mobile-tabbar {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(var(--bottom-nav-h) + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--white);
    border-top: 1px solid var(--border);
    z-index: 60;
  }
  .mobile-tabbar a,
  .mobile-tabbar button {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 6px 4px;
    background: none;
    border: 0;
    font-family: inherit;
    font-size: 11px;
    font-weight: 500;
    color: var(--text-secondary);
    cursor: pointer;
  }
  .mobile-tabbar a:hover { text-decoration: none; }
  .mobile-tabbar .mtab-icon { font-size: 19px; line-height: 1; }
  .mobile-tabbar a.active,
  body.mobile-menu-open .mobile-tabbar .mtab-more {
    color: var(--accent);
    font-weight: 600;
  }

  /* Workspace banner doubles as the switcher entry point on phones:
     caret shows, whole banner is tappable (see renderWorkspaceBanner). */
  .workspace-banner { cursor: pointer; }
  .workspace-banner-caret {
    display: inline;
    font-size: 13px;
    color: var(--accent);
    align-self: center;
  }

  /* Pass 112 (Tony, 2026-08-13) — the switcher card in the More
     sheet reads as just another gray row; give it the light-green
     accent treatment so it stands out as THE workspace control. */
  .ws-switcher-trigger {
    background: var(--accent-pale);
    border-color: var(--accent);
  }
  .ws-switcher-trigger:hover { background: var(--accent-pale); }
  .ws-switcher-name,
  .ws-switcher-caret { color: var(--accent); }
  .ws-switcher-meta { color: var(--accent); opacity: 0.75; }

  /* Pass 112 — compact sheet footer. The stacked plan-chip / name /
     full-width Sign Out / legal block ate ~4 rows of the sheet; on
     phones it collapses to one row (chip · name · small Sign Out)
     with the Terms/Privacy line tucked under it. */
  .sidebar-footer {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 10px;
    padding: 10px 14px;
  }
  .sidebar-footer #trialBadge { flex: 0 0 auto; }
  .sidebar-footer .sidebar-user {
    flex: 1 1 auto;
    text-align: left;
    margin: 0;
  }
  .sidebar-footer .btn-full {
    width: auto;
    padding: 6px 16px;
    font-size: 13px;
  }
  .sidebar-footer .sidebar-legal {
    flex: 1 1 100%;
    justify-content: center;
    margin: 0;
  }

  .main-content {
    margin-left: 0;
    padding: 20px 16px;
    padding-bottom: calc(var(--bottom-nav-h) + env(safe-area-inset-bottom, 0px) + 20px);
  }

  .grid-2, .grid-3, .grid-4 {
    grid-template-columns: 1fr;
  }
  .form-row { grid-template-columns: 1fr; }
  .bucket-row { grid-template-columns: 1fr; }
  .kanban { grid-template-columns: 1fr; }

  .hero h1 { font-size: 2rem; }
  .hero { padding: 48px 20px; }
  .section { padding: 48px 20px; }
  .feature-grid,
  .pricing-grid { grid-template-columns: 1fr; }

  .auth-card,
  .wizard-card { padding: 24px; }
}

/* ============================================================
   BUILD 3 (2026-07-18) — Projects kanban board + generic modal.
   Board is a horizontally-scrolling flex layout so 1-12 columns
   all fit on the same page. Existing `.kanban` grid class is
   biz-pipeline-specific (fixed 4 columns) so a separate class
   avoids collision.
   ============================================================ */
.kanban-board {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  overflow-x: auto;
  padding-bottom: 12px;
  min-height: 320px;
}
.kanban-board .kanban-col {
  flex: 0 0 300px;
  max-width: 300px;
}
.kanban-col-name {
  font-weight: 600;
  letter-spacing: 0.05em;
}
.kanban-col-count {
  background: var(--white, #fff);
  border: 1px solid var(--border, #e5e5e5);
  border-radius: var(--radius-pill, 999px);
  padding: 1px 8px;
  font-size: 11px;
  color: var(--text-primary, #333);
}
.kanban-col-cards {
  min-height: 60px;
  padding: 4px 0;
}
.kanban-col-cards.kanban-drop-hint {
  outline: 2px dashed var(--accent, #2d6a4f);
  outline-offset: -2px;
  border-radius: var(--radius-md, 6px);
  background: var(--accent-pale, #d8f3dc);
}
.kanban-add-card-btn {
  display: block;
  width: 100%;
  padding: 8px 10px;
  margin-top: 8px;
  border: 1px dashed var(--border, #d0d0d0);
  border-radius: var(--radius-md, 6px);
  background: transparent;
  color: #666;
  font-size: 13px;
  cursor: pointer;
  transition: background 120ms, color 120ms;
}
.kanban-add-card-btn:hover,
.kanban-add-card-btn:focus {
  background: var(--accent-pale, #d8f3dc);
  color: var(--accent, #2d6a4f);
  outline: none;
}
.kanban-card {
  cursor: pointer;
  position: relative;
  transition: box-shadow 120ms, transform 60ms;
}
.kanban-card[draggable="true"]:hover {
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.09);
}
.kanban-card.dragging { opacity: 0.4; }
.kanban-card-title {
  font-family: 'Inter', sans-serif;
  font-size: 14px;
  font-weight: 600;
  color: #222;
  margin-bottom: 4px;
}
.kanban-card-desc {
  font-size: 12.5px;
  color: #555;
  line-height: 1.4;
  margin-bottom: 6px;
  white-space: pre-wrap;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}
.kanban-card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.kanban-card-tag {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11px;
  background: #f0f0f0;
  color: #555;
}

/* Generic modal shell. Same shape as .terms-modal but decoupled so
   pages that need a non-clickwrap modal can drop it in without
   dragging the clickwrap-specific inner styles. */
.cc-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.cc-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 30, 25, 0.5);
}
.cc-modal-card {
  position: relative;
  width: 100%;
  max-width: 560px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  background: var(--white, #fff);
  border-radius: var(--radius-lg, 10px);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
  padding: 28px 28px 20px;
}
.cc-modal-title {
  font-family: 'Playfair Display', serif;
  font-weight: 600;
  font-size: 20px;
  margin: 0 0 12px;
  color: var(--accent, #2d6a4f);
}
.cc-modal-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  margin-top: 18px;
  flex-wrap: wrap;
}

.col-editor-row {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 6px;
}
.col-editor-row .form-input { flex: 1; }
.col-editor-row .btn-icon { flex-shrink: 0; }

/* ============================================================
   BUILD 2 (2026-07-18) — Setup milestone journey card.
   Horizontal path of circular milestone nodes with a progress
   line. Deep green accent (--accent), warm accent-pale for the
   current-node halo + "Next up" pill.
   ============================================================ */
/* BUILD 19.1 (2026-07-26) — Get Set Up card: compact restyle.
   Nodes cluster left with fixed ~100px spacing (was: stretched
   edge-to-edge via justify-content: space-between + flex:1 per
   node). Circles 26px (was 40px). Progress line 2px (was 3px).
   Labels 11px (was 12px). Padding tightened; Next-up band
   slimmer. All behavior unchanged (chip collapse/expand, Hide
   link, per-workspace persistence, step completion logic).
*/
.setup-journey {
  padding: 14px 16px;
  --setup-progress: 0%;
}
.setup-journey-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 4px;
}
.setup-journey-header .card-title {
  font-family: 'Playfair Display', serif;
  font-size: 14px;
}
/* Pre-BUILD-19.1 ✕ dismiss button styling — BUILD 19 replaced
   the ✕ with a "Hide" text link (.dashv2-setup-hide). Rules kept
   as no-op guards in case any legacy DOM still ships. */
.setup-dismiss-btn {
  background: transparent;
  border: 0;
  padding: 0 8px;
  font-size: 24px;
  line-height: 1;
  color: #999;
  cursor: pointer;
  border-radius: 4px;
  transition: color 120ms, background 120ms;
}
.setup-dismiss-btn:hover,
.setup-dismiss-btn:focus {
  color: #333;
  background: var(--off-white, #f8f9fa);
  outline: none;
}

.milestone-track-wrap {
  /* Track sits close to header + close to Next Up band. */
  padding: 10px 6px 4px;
}
.milestone-track {
  display: flex;
  align-items: flex-start;
  /* BUILD 19.1: nodes cluster left with fixed spacing — NOT stretched.
     BUILD 19.2 (2026-07-26): personal journey grew from 4 → 11
     milestones (setup + dashboard tour). 100px gap no longer fits;
     reduced to 45px so 11 nodes @ 26px + 10 gaps ≈ 736px, comfortable
     inside the personal-dashboard column at typical widths. Business
     journey (4 milestones) still looks well-spaced at 45px. */
  justify-content: flex-start;
  gap: 45px;
  position: relative;
}
/* Base connector line — muted; sits behind the nodes.
   BUILD 19.1: 2px (was 3px). Anchored to first + last circle centers. */
.milestone-track::before {
  content: '';
  position: absolute;
  top: 12px;
  left: 13px;   /* half of circle diameter (26/2) */
  right: auto;
  /* Width from first circle center to last circle center. Each node
     is 26px wide + a 100px gap; use N-1 gaps + (N-1)*26 for a track
     that spans center-to-center. Set inline in JS if node count
     varies; static 4-node personal + 5-node business fit within
     a single computed span here (see JS if the count changes). */
  width: calc(100% - 32px);
  height: 2px;
  background: var(--wp-green-tint, #EAF3DE);
  border-radius: 999px;
  z-index: 0;
}
/* Progress fill — width driven by --setup-progress custom property
   (set by JS in dashboard.js renderSetupProgress). BUILD 19.1:
   done-portion uses --wp-green-dark; remaining uses tint above. */
.milestone-track::after {
  content: '';
  position: absolute;
  top: 12px;
  left: 13px;
  height: 2px;
  background: var(--wp-green-dark, #27500A);
  border-radius: 999px;
  z-index: 1;
  width: calc((100% - 32px) * var(--setup-progress) / 100);
  transition: width 320ms ease-out;
}

.milestone-node {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  /* BUILD 19.1: fixed width == circle width so the track math
     (gap-based center-to-center distance) stays honest. */
  flex: 0 0 26px;
  min-width: 26px;
}
.milestone-circle {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--wp-card-bg, #fff);
  border: 1.5px solid var(--wp-green-tint, #EAF3DE);
  color: #b8b6ac;
  transition: background 200ms, border-color 200ms, color 200ms, box-shadow 200ms;
}
.milestone-circle svg {
  width: 14px;
  height: 14px;
}
.milestone-node.complete .milestone-circle {
  background: var(--wp-green-dark, #27500A);
  border-color: var(--wp-green-dark, #27500A);
  color: #fff;
}
.milestone-node.current .milestone-circle {
  background: #fff;
  border-color: var(--wp-green-dark, #27500A);
  color: var(--wp-green-dark, #27500A);
  box-shadow: 0 0 0 3px var(--wp-green-tint, #EAF3DE);
}
.milestone-node.future .milestone-circle {
  /* Hollow future state — no icon dominance. */
  background: #fff;
  border-color: var(--wp-green-tint, #EAF3DE);
  color: transparent;
}
.milestone-node.future .milestone-circle svg { visibility: hidden; }

.milestone-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--wp-text-muted, #888780);
  text-align: center;
  letter-spacing: 0.01em;
  /* Center the label under its 26px circle without inheriting the
     narrow flex-basis (labels need room to breathe). */
  white-space: nowrap;
}
.milestone-node.complete .milestone-label,
.milestone-node.current  .milestone-label {
  color: var(--wp-green-dark, #27500A);
}
.milestone-node.future   .milestone-label { color: #b8b6ac; }

.setup-next-up {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px;
  background: var(--wp-green-tint, #EAF3DE);
  border-radius: 6px;
  margin-top: 8px;
  font-size: 12px;
}
.setup-next-label {
  font-weight: 500;
  color: var(--wp-green-dark, #27500A);
  flex-shrink: 0;
  font-size: 12px;
}
.setup-next-text {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--wp-green-darkest, #173404);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
}
/* Slimmer Continue pill inside the Next Up band. */
.setup-next-btn.btn {
  flex-shrink: 0;
  padding: 4px 12px;
  font-size: 12px;
  line-height: 1.3;
  min-height: 0;
}

@media (max-width: 640px) {
  .setup-journey { padding: 12px 14px; }
  .milestone-track { gap: 60px; }
  .milestone-track-wrap { padding: 8px 4px 2px; }
  .milestone-circle { width: 22px; height: 22px; }
  .milestone-circle svg { width: 12px; height: 12px; }
  .milestone-track::before,
  .milestone-track::after { top: 10px; height: 2px; left: 11px; }
  .milestone-label { font-size: 10px; }
  .setup-next-up { flex-wrap: wrap; }
  .setup-next-text { white-space: normal; }
}

/* ============================================================
   BUILD 19 (2026-07-26) — DASHBOARD REDESIGN TOKENS.

   Single source of truth for the personal-dashboard v2 palette
   and card system. Business dashboard adopts these in a follow-
   up build; the classes are designed to be reusable there.

   Scoping: page background applies ONLY when body carries the
   `dashv2` class (dashboard.js adds it on personal workspaces).
   Other pages are untouched. Card classes (.dashv2-card,
   .dashv2-tile, etc.) are class-scoped so no unrelated element
   picks them up by accident.
   ============================================================ */
:root {
  /* Page + card shell */
  --wp-page-bg:        #F0EFE9;
  --wp-card-bg:        #FFFFFF;
  --wp-card-radius:    12px;
  --wp-card-shadow:    0 1px 3px rgba(0, 0, 0, 0.07);
  --wp-card-pad:       16px;

  /* Text ramp */
  --wp-text-title:     #27500A;   /* card titles 13px/500 */
  --wp-text-label:     #5F5E5A;   /* small labels 11-12px */
  --wp-text-muted:     #888780;   /* muted 10-11px */
  --wp-text-serif:     #173404;   /* big serif numbers */

  /* Green ramp (dark → tint) */
  --wp-green-darkest:  #173404;
  --wp-green-dark:     #27500A;
  --wp-green-primary:  #3B6D11;   /* accent + bars */
  --wp-green-mid:      #97C459;
  --wp-green-light:    #C0DD97;
  --wp-green-tint:     #EAF3DE;   /* track fill for donuts / bars */

  /* Signals */
  --wp-danger:         #993C1D;   /* over-budget / short */
  /* BUILD DASHBOARD-FINAL Phase 1b (2026-09-09) — the amber
     signal finally gets a token. Three surfaces needed it in the
     same build (cash-capped verdict, under-balanced headline,
     payday-missing nudge) and all three were about to hard-code a
     hex. Same family as the action strip's text so amber means
     one thing on this page. */
  --wp-warning:        #8A5A0B;   /* attention, not failure */
  --wp-warning-bg:     #FAEEDA;

  /* Action strip (amber) */
  --wp-action-bg:      #FAEEDA;
  --wp-action-text:    #633806;
  --wp-action-btn-tx:  #854F0B;

  /* Neutral (out-of-money bars, disabled bg) */
  --wp-neutral:        #B4B2A9;

  /* Divider */
  --wp-hairline:       #E5E3DA;
}

/* Page background — dashboard v2 only (body class added by dashboard.js) */
body.dashv2,
body.dashv2 .main-content {
  background: var(--wp-page-bg);
}

/* Card — the fundamental container. Reusable class. */
.dashv2-card {
  background: var(--wp-card-bg);
  border-radius: var(--wp-card-radius);
  box-shadow: var(--wp-card-shadow);
  padding: var(--wp-card-pad);
  color: var(--wp-text-serif);
}
.dashv2-card + .dashv2-card { margin-top: 12px; }

/* Card layouts */
.dashv2-row-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-top: 12px;
}
.dashv2-row-4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-top: 12px;
}
@media (max-width: 900px) {
  .dashv2-row-2 { grid-template-columns: 1fr; }
  .dashv2-row-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .dashv2-row-4 { grid-template-columns: 1fr; }
}

/* Typography inside cards */
.dashv2-card-title {
  font-size: 13px;
  font-weight: 500;
  color: var(--wp-text-title);
  margin: 0 0 10px;
  letter-spacing: 0.01em;
}
.dashv2-label {
  font-size: 12px;
  color: var(--wp-text-label);
}
.dashv2-muted {
  font-size: 11px;
  color: var(--wp-text-muted);
}
.dashv2-serif {
  font-family: 'Playfair Display', Georgia, serif;
  color: var(--wp-text-serif);
  font-weight: 500;
}
.dashv2-num-lg {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 32px;
  line-height: 1.1;
  color: var(--wp-text-serif);
  font-weight: 500;
}
.dashv2-num-md {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 22px;
  line-height: 1.15;
  color: var(--wp-text-serif);
  font-weight: 500;
}
.dashv2-over {
  color: var(--wp-danger);
}

/* Quarter tile (small stat card) */
.dashv2-tile {
  background: var(--wp-card-bg);
  border-radius: var(--wp-card-radius);
  box-shadow: var(--wp-card-shadow);
  padding: var(--wp-card-pad);
  color: var(--wp-text-serif);
}
.dashv2-tile .dashv2-label {
  margin-top: 2px;
}

/* ── BUILD DASHBOARD-FINAL Phase 1b (2026-09-09) — KPI card scale.
   The four tier-1 cards are ONE row of four equal things, so they get
   one type scale: 24px number / 13px label / 12px subline. Before
   this they inherited .dashv2-num-md (22px) and .dashv2-label (12px)
   from the shared card ramp, which is tuned for numbers sitting
   inside a bigger card — at tile size the label read smaller than the
   subline it was labelling. Padding and radius already come from the
   same two tokens .dashv2-card uses, so the four cards and the three
   detail cards below them line up on the same grid. */
.dashv2-kpi { display: flex; flex-direction: column; }
.dashv2-kpi .dashv2-num-md { font-size: 24px; }
.dashv2-kpi .dashv2-label  { font-size: 13px; color: var(--wp-text-title); }
.dashv2-kpi .dashv2-kpi-sub {
  font-size: 12px; color: var(--wp-text-label);
  margin-top: 3px; min-height: 15px; line-height: 1.3;
}

/* Hairline divider */
.dashv2-hairline {
  height: 0.5px;
  background: var(--wp-hairline);
  margin: 10px 0;
  border: 0;
}

/* Header chips row */
.dashv2-chips {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.dashv2-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  border: 0;
  line-height: 1;
  text-decoration: none;
}
.dashv2-chip-amber {
  background: var(--wp-action-bg);
  color: var(--wp-action-btn-tx);
}
.dashv2-chip-green {
  background: var(--wp-green-tint);
  color: var(--wp-green-dark);
}
.dashv2-chip-neutral {
  background: #F1EFE8;
  color: var(--wp-text-muted);
}

/* Action strip (amber wide card) */
.dashv2-action-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-radius: var(--wp-card-radius);
  background: var(--wp-action-bg);
  color: var(--wp-action-text);
  text-decoration: none;
  margin-top: 12px;
}
.dashv2-action-strip-msg { font-size: 13px; color: var(--wp-action-text); }
.dashv2-action-btn {
  display: inline-block;
  background: #FFFFFF;
  color: var(--wp-action-btn-tx);
  padding: 6px 14px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
  border: 0;
  white-space: nowrap;
}

/* Card head — title, then its window as a suffix.

   BUILD DASHBOARD-FINAL Phase 1b (2026-09-09) — the window chip was a
   grey pill pushed to the far right by `justify-content: space-between`,
   so five cards showed five pills at five different distances from
   their own titles. It is not a status, it is the second half of the
   title: "Net worth · last 12 months". So it now sets as an inline
   muted suffix immediately after the title, and every card head reads
   the same way. The .up / .down variants keep their colours for any
   future card that genuinely reports a direction. */
.dashv2-card-head {
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
  gap: 6px;
  margin-bottom: 10px;
}
.dashv2-card-head .dashv2-card-title { margin: 0; }
.dashv2-cmp-chip {
  padding: 0;
  border-radius: 0;
  background: none;
  font-size: 12px;
  font-weight: 400;
  color: var(--wp-text-muted);
  white-space: nowrap;
}
.dashv2-cmp-chip::before { content: '· '; }
.dashv2-cmp-chip.up   { color: var(--wp-green-dark); }
.dashv2-cmp-chip.down { color: var(--wp-danger); }

/* Budget card — BARS ONLY.

   BUILD DASHBOARD-FINAL Phase 1b (2026-09-09) — the donut is gone.
   It encoded ONE number (whole-budget percent) in 84x84 pixels and
   then repeated the same three sections underneath it as text, so the
   card said everything twice and answered "which section is running
   hot?" nowhere. One bar per section answers exactly that, at a
   glance, and the bars are the same component the Budget page uses.
   The headline moves above them where the eye lands first. */
.dashv2-budget-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin-bottom: 8px;
}
.dashv2-budget-bars { display: grid; gap: 8px; }
.dashv2-bbar-head {
  display: flex; justify-content: space-between; gap: 8px;
  font-size: 12px; margin-bottom: 3px; line-height: 1.25;
}
.dashv2-bbar-head .name { color: var(--wp-text-serif); }
.dashv2-bbar-head .figs { color: var(--wp-text-label); font-variant-numeric: tabular-nums; }
.dashv2-bbar-track {
  height: 6px; border-radius: 999px;
  background: var(--wp-green-tint); overflow: hidden;
}
.dashv2-bbar-fill { height: 100%; background: var(--wp-green-primary); border-radius: 999px; }
.dashv2-bbar-fill.warning { background: var(--wp-warning); }
.dashv2-bbar-fill.danger  { background: var(--wp-danger); }
.dashv2-bbar-fill.neutral { background: var(--wp-neutral); }

/* Debt-free badge state */
.dashv2-card.debt-free {
  border: 1.5px solid var(--wp-green-mid);
}

/* Empty-state within a card */
.dashv2-empty {
  text-align: left;
  padding: 4px 0;
}
.dashv2-empty a {
  display: inline-block;
  margin-top: 6px;
  color: var(--wp-green-dark);
  font-size: 12px;
  font-weight: 500;
  text-decoration: underline;
}

/* "Hide" control inside the Get set up card. It is a <button>, so it
   does not wear a link's underline at rest — see the link-style-bleed
   note in dashboard.html (BUILD DASHBOARD-FINAL Phase 1a). */
.dashv2-setup-hide {
  background: transparent;
  border: 0;
  color: var(--wp-text-muted);
  font-size: 12px;
  text-decoration: none;
  cursor: pointer;
  padding: 0;
}
.dashv2-setup-hide:hover { text-decoration: underline; }


/* ============================================================
   BUILD TX-MOBILE-CARDS (2026-08-13) — Review & Categorize on
   phones/tablets. The 6-column transactions table forced sideways
   scrolling on anything narrower than ~900px (Tony's screenshots:
   date + logo + merchant + category + account + amount + expand
   arrow never fit one view). At ≤768px each row re-flows into a
   self-contained card via CSS grid — NO markup change, the same
   <td>s are re-placed:

     ┌───────────────────────────────┬───────────┐
     │ logo · merchant · pills       │   −$4.28  │
     │ Aug 12, 2026                  │ [Cat ▾]   │
     │ Thomas Personal Check…        │           │
     │                    Edit ✕ ▸  (actions row)│
     └───────────────────────────────┴───────────┘

   Sort-by-header goes away with the hidden thead on phones; the
   default date-DESC order + filter bar still apply. The detail
   drawer <tr> keeps its [hidden] toggle via :not([hidden]) so the
   block display override can't defeat the attribute. Desktop
   (>768px) table is untouched.
   ============================================================ */
@media (max-width: 768px) {
  #tx_tableWrap table,
  #tx_tableWrap tbody { display: block; width: 100%; }
  #tx_tableWrap thead { display: none; }
  #tx_tableWrap tr.tx-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 12px;
    row-gap: 4px;
    padding: 12px 4px;
    border-bottom: 1px solid var(--border, #eee);
  }
  #tx_tableWrap tr.tx-row td {
    display: block;
    padding: 0;
    border: none;
  }
  /* Merchant block (logo + name + pills + channel/notes) — top left. */
  #tx_tableWrap tr.tx-row td:nth-child(2) { grid-row: 1; grid-column: 1; }
  /* Amount — top right, never wraps. */
  #tx_tableWrap tr.tx-row td:nth-child(5) {
    grid-row: 1; grid-column: 2;
    text-align: right; white-space: nowrap;
  }
  /* Date + account — small muted lines under the merchant. */
  #tx_tableWrap tr.tx-row td:nth-child(1) {
    grid-row: 2; grid-column: 1;
    font-size: 12px; color: var(--text-secondary, #6b6b6b);
  }
  #tx_tableWrap tr.tx-row td:nth-child(4) {
    grid-row: 3; grid-column: 1;
    font-size: 12px; color: var(--text-secondary, #6b6b6b);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* Category picker — right side, centered against date+account. */
  #tx_tableWrap tr.tx-row td:nth-child(3) {
    grid-row: 2 / span 2; grid-column: 2;
    align-self: center; justify-self: end;
  }
  #tx_tableWrap tr.tx-row td:nth-child(3) select {
    max-width: 150px; font-size: 13px;
  }
  /* Actions (Edit/Delete on manual rows; details ▸ on all) — own
     bottom line, right-aligned, full card width. */
  #tx_tableWrap tr.tx-row td:nth-child(6) {
    grid-row: 4; grid-column: 1 / -1;
    text-align: right;
  }
  /* Detail drawer spans the card; [hidden] still wins. */
  #tx_tableWrap tr.tx-drawer:not([hidden]) { display: block; }
  #tx_tableWrap tr.tx-drawer:not([hidden]) td { display: block; }
}

/* ============================================================
   BUILD M-STACK (2026-08-13) — shared phone card pattern for list
   tables + iOS font-boost pin (Tony: "everything needs to fit
   nicely within the view on any size device").

   text-size-adjust: Mobile Safari "font boosting" was randomly
   inflating text inside wide blocks (the transaction drawer looked
   huge on some rows, normal on others — Tony's Railway vs Amazon
   screenshots). 100% pins every page to its authored sizes.

   .m-stack (opt-in, on the .table-wrapper OR the <table>): at
   ≤768px the table becomes per-row cards on the same markup —
   first cell bold, the FIRST .amount cell pinned top-right,
   further .amount cells back in the left flow, .text-right action
   cells bottom-right, empty cells hidden. Number-heavy tables add
   a scope class (.m-stack--sales etc.) whose ::before labels name
   the ambiguous columns. Desktop (>768px) unchanged everywhere.
   ============================================================ */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

@media (max-width: 768px) {
  .table-wrapper.m-stack { overflow-x: visible; }
  .m-stack table, table.m-stack { display: block; width: 100%; }
  .m-stack tbody { display: block; width: 100%; }
  .m-stack thead { display: none; }
  .m-stack tbody tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 12px;
    row-gap: 3px;
    padding: 12px 4px;
    border-bottom: 1px solid var(--border, #eee);
  }
  .m-stack tbody tr td {
    display: block;
    border: none;
    padding: 0;
    min-width: 0;
    grid-column: 1;
    overflow-wrap: anywhere;
  }
  .m-stack tbody tr td:first-child { font-weight: 600; }
  .m-stack tbody tr td:empty { display: none; }
  .m-stack tbody tr td.amount {
    grid-column: 2;
    grid-row: 1;
    text-align: right;
    white-space: nowrap;
    align-self: start;
  }
  /* Second-and-later amount cells return to the left flow (a grid
     can't stack several cells in the same top-right slot). */
  .m-stack tbody tr td.amount ~ td.amount {
    grid-column: 1;
    grid-row: auto;
    text-align: left;
    white-space: normal;
  }
  .m-stack tbody tr td.text-right {
    grid-column: 2;
    grid-row: 2;
    text-align: right;
    align-self: end;
    white-space: nowrap;
  }
  /* Column labels — render only where a scope class sets content. */
  .m-stack tbody td::before {
    display: block;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-secondary, #6b6b6b);
  }
  .m-stack--invoices td:nth-child(3)::before { content: 'Total'; }
  .m-stack--invoices td:nth-child(4)::before { content: 'Balance'; }
  .m-stack--invoices td:nth-child(5)::before { content: 'Due'; }
  .m-stack--sales td:nth-child(4)::before { content: 'Revenue'; }
  .m-stack--sales td:nth-child(5)::before { content: 'COGS'; }
  .m-stack--sales td:nth-child(6)::before { content: 'Shipping'; }
  .m-stack--sales td:nth-child(7)::before { content: 'Fees'; }
  .m-stack--sales td:nth-child(8)::before { content: 'Profit'; }
  .m-stack--expenses td:nth-child(4)::before { content: 'Amount'; }
  .m-stack--expenses td:nth-child(5)::before { content: 'Monthly equiv.'; }
  .m-stack--bills td:nth-child(4)::before { content: 'Next due'; }
  .m-stack--income td:nth-child(4)::before { content: 'Amount'; }
  .m-stack--income td:nth-child(5)::before { content: 'Monthly equiv.'; }
  .m-stack--debt td:nth-child(2)::before { content: 'Balance'; }
  .m-stack--debt td:nth-child(3)::before { content: 'APR'; }
  .m-stack--debt td:nth-child(4)::before { content: 'Min payment'; }
  .m-stack--paylog td:nth-child(3)::before { content: 'Gross'; }
  .m-stack--paylog td:nth-child(4)::before { content: 'Federal'; }
  .m-stack--paylog td:nth-child(5)::before { content: 'FICA'; }
  .m-stack--paylog td:nth-child(6)::before { content: 'State'; }
  .m-stack--paylog td:nth-child(7)::before { content: 'Net'; }
}

/* ============================================================
   BUILD MOBILE-SWEEP (2026-08-13, pass 118) — device-width fixes
   from the 4-agent audit of every user-facing page. ALL rules are
   phone/tablet-scoped; desktop is untouched. Selectors that also
   exist in page-local style blocks are prefixed with `body ` —
   page blocks load AFTER styles.css, so an unprefixed rule of
   equal specificity would lose on source order.
   ============================================================ */
@media (max-width: 768px) {
  /* ---- global hardening ---- */
  .banner { flex-wrap: wrap; }
  .banner > .btn { flex: 1 1 100%; justify-content: center; }
  .card-header { flex-wrap: wrap; gap: 8px; }
  body .save-bar { flex-wrap: wrap; }
  .card, .auth-card, .mfa-card { overflow-wrap: anywhere; }
  .row-flex > select, .row-flex > input,
  .row-flex > .form-select, .row-flex > .form-input { min-width: 0; }
  .stat-value { font-size: 1.6rem; }
  .dashv2-num-lg { font-size: 26px; }
  /* backstop — real fixes below; this guarantees no page pans */
  html, body { overflow-x: hidden; }

  /* ---- overlay chrome: reclaim ~36px on every modal ---- */
  div[id$="Overlay"] { padding: 12px !important; }
  div[id$="Overlay"] > .card,
  div[id$="Overlay"] > .modal-card { padding: 14px !important; max-width: 100% !important; }
  body .modal-overlay { padding: 20px 10px; }
  body .modal-card { padding: 16px; }
  body .cc-modal { padding: 12px; }
  body .cc-modal-card { padding: 20px 16px 16px; }
  /* settings delete modal: reachable buttons on short screens */
  #wsDeleteModal { align-items: flex-start !important; padding: 16px !important; overflow-y: auto !important; }

  /* ---- fixed-px grid rows become single-column stacks ---- */
  body .li-row, body .sched-row,
  body .dv-li, body .dv-sc, body .dv-pay,
  body .rep-list-row, body .rep-grid {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 4px;
  }
  body .li-row > *, body .sched-row > * { min-width: 0; }
  body .dv-head { display: none; }
  body .rep-agediv { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  body .rep-list-row .row-flex { justify-content: flex-start; }
  #rp_body ul { padding-left: 20px; }
  body .rep-table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; font-size: 12px; }
  body .rep-table th, body .rep-table td { white-space: nowrap; }

  /* ---- documents list: 2-col card, header row hidden ---- */
  body .doc-row {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 8px; row-gap: 2px;
  }
  body .doc-row > * { min-width: 0; overflow-wrap: anywhere; }
  body .doc-row > :nth-child(1) { grid-column: 1; grid-row: 1; }
  body .doc-row > :nth-child(2),
  body .doc-row > :nth-child(3),
  body .doc-row > :nth-child(4) { grid-column: 1; font-size: 12px; color: var(--text-secondary, #6b6b6b); }
  body .doc-row > :nth-child(5) { grid-column: 2; grid-row: 1; text-align: right; }
  #listCard > .doc-row:first-child,
  #docList > .doc-row:first-child { display: none; }
  .doc-upload { padding: 12px; }
  #f_file { flex: 1 1 100% !important; min-width: 0; max-width: 100%; }

  /* ---- social media list: card rows, header hidden ---- */
  body .sm-row {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 8px; row-gap: 4px;
  }
  #listHead { display: none !important; }
  body .sm-row > :nth-child(1) { grid-column: 1; grid-row: 2; font-size: 12px; }
  body .sm-row > :nth-child(2) { grid-column: 1; grid-row: 1; min-width: 0; }
  body .sm-row > :nth-child(3) { grid-column: 1; grid-row: 3; }
  body .sm-row > :nth-child(4) { grid-column: 2; grid-row: 1; justify-self: end; }
  body .sm-row > :nth-child(5) { grid-column: 2; grid-row: 2; justify-self: end; }
  #filtersCard > .row-flex { min-width: 0 !important; flex: 1 1 100%; flex-wrap: wrap; }
  #filtersCard > .form-group { min-width: 0 !important; flex: 1 1 100%; }
  #f_campaignLabel { min-width: 0; max-width: 100%; }
  body .sm-cmt-head { flex-wrap: wrap; gap: 4px; }

  /* ---- members: invite module matrix + action cells ---- */
  body .module-matrix-head,
  body .module-matrix-row { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; padding: 8px 10px; }
  body .module-matrix-head > span:first-child { display: none; }
  body .module-matrix-row > div:first-child { grid-column: 1 / -1; }
  body .module-matrix-head > span { font-size: 10px; text-align: center; }
  body .module-matrix-row > label { text-align: center; font-size: 12px; }
  #membersBody td.text-right,
  #invitesBody td.text-right,
  #suggestedIncomeBody td.text-right {
    grid-column: 1 / -1; grid-row: auto;
    white-space: normal; text-align: left;
    display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px;
  }
  .m-stack--members td:nth-child(2)::before { content: 'Email'; }
  .m-stack--members td:nth-child(3)::before { content: 'Access'; }
  .m-stack--members td:nth-child(4)::before { content: 'Joined'; }
  .m-stack--invites td:nth-child(2)::before { content: 'Access'; }
  .m-stack--invites td:nth-child(3)::before { content: 'Sent'; }
  .m-stack--invites td:nth-child(4)::before { content: 'Expires'; }

  /* ---- purchasing (resources) rows ---- */
  body .res-item { grid-template-columns: minmax(0, 1fr) auto; column-gap: 10px; row-gap: 4px; padding: 12px; }
  body .res-item > * { grid-column: 1; min-width: 0; overflow-wrap: anywhere; }
  body .res-item > .res-drag { display: none; }
  body .res-item > :nth-child(3) { grid-row: 1; }
  body .res-item > .res-item-size { grid-row: 2; font-size: 12px; }
  body .res-item > .res-actions { grid-column: 2; grid-row: 1; align-self: start; white-space: normal; flex-wrap: wrap; }
  body .res-item > div:empty { display: none; }
  #itemOverlay .row-flex > .form-select,
  #itemOverlay .row-flex > .form-input { flex: 1 1 100%; min-width: 0; }

  /* ---- feedback board + feedback ---- */
  body .fb-post { grid-template-columns: 52px minmax(0, 1fr); gap: 10px; padding: 12px; }
  body .fb-post > div { min-width: 0; }
  body .fb-post-vote { min-width: 0; }
  body .fb-post-actions { grid-column: 1 / -1; flex-wrap: wrap; }
  body .fb-post-desc, body .fb-reply-body, #fb_historyBody div { overflow-wrap: anywhere; }
  #composeCard .form-group > div > label { display: block; margin-right: 0 !important; margin-bottom: 6px; }

  /* ---- clients: detail rows + search ---- */
  body .tag-detail-row { flex-direction: column; gap: 0; }
  body .tag-detail-row > div:first-child { width: auto !important; }
  #cli_search { min-width: 0 !important; }

  /* ---- pipeline + projects: kanban text + linked-task rows ---- */
  body .kanban { grid-template-columns: minmax(0, 1fr); }
  .kanban-card { overflow-wrap: anywhere; }
  .kanban-card .kc-actions { flex-wrap: wrap; }
  .lt-row > div { min-width: 0; overflow-wrap: anywhere; }
  .col-editor-row .form-input { min-width: 0; }

  /* ---- products import wizard ---- */
  #importOverlay .stepper { flex-wrap: wrap; }
  .import-stats { flex-wrap: wrap !important; }
  body #importMapTable, body #importValidateTable { display: block; overflow-x: auto; font-size: 12px; }
  .cat-group-header { flex-wrap: wrap; gap: 8px; }
  .cat-group-header > :first-child { min-width: 0; overflow-wrap: anywhere; }
  /* any bare table dropped straight in a card scrolls itself */
  .card > table.table:not(.m-stack) { display: block; overflow-x: auto; }

  /* ---- CSV import (biz-import): review rows become cards ---- */
  #step3Card .table-wrapper { max-height: none; overflow: visible; }
  #reviewTable, #reviewTable tbody { display: block; width: 100%; }
  #reviewTable thead { display: none; }
  #reviewTable tbody tr {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    gap: 6px 10px; padding: 12px 4px;
    border-bottom: 1px solid var(--border, #eee);
  }
  #reviewTable tbody td { display: block; border: none; padding: 0; min-width: 0; }
  #reviewTable td:nth-child(1) { grid-column: 1; grid-row: 1; font-size: 12px; color: var(--text-secondary, #6b6b6b); }
  #reviewTable td:nth-child(3) { grid-column: 2; grid-row: 1; text-align: right; white-space: nowrap; font-weight: 600; }
  #reviewTable td:nth-child(2),
  #reviewTable td:nth-child(4),
  #reviewTable td:nth-child(5) { grid-column: 1 / -1; }
  #reviewTable td:nth-child(6) { grid-column: 2; text-align: right; }
  #mapTable th, #mapTable td { padding: 6px 8px; font-size: 12px; }
  #mapTable .form-select { padding: 6px 8px; font-size: 12px; }

  /* ---- settings: access matrix + workspace rows + platforms ---- */
  #ma_matrix .mod-row, #pMaBody .mod-row { flex-direction: column; align-items: stretch; gap: 8px; }
  #ma_matrix .mod-row > .row-flex, #pMaBody .mod-row > .row-flex {
    flex-shrink: 1 !important; width: 100%; justify-content: space-between; gap: 8px;
  }
  #ma_matrix .mod-row > .row-flex > label,
  #pMaBody .mod-row > .row-flex > label { flex: 1 1 auto; font-size: 12px; white-space: nowrap; }
  .ws-row { flex-wrap: wrap; }
  .ws-row-actions { flex: 1 1 100%; justify-content: flex-end; }
  #salesPlatformsList .form-row { grid-template-columns: 1fr 1fr; column-gap: 8px; align-items: end; }
  #salesPlatformsList .form-row > .form-group:first-child { grid-column: 1 / -1; }

  /* ---- dashboard: milestone track scrolls inside its card ---- */
  .milestone-track-wrap {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    margin: 0 -6px; padding-left: 6px; padding-right: 6px;
  }
  .milestone-track { gap: 34px; width: max-content; min-width: 100%; }
  .milestone-label { font-size: 9px; }
  .dashv2-split { flex-wrap: wrap; }
  .dashv2-action-strip { flex-wrap: wrap; }
  .dashv2-action-btn { flex-shrink: 0; }

  /* ---- retirement key-value list ---- */
  .kv-list { grid-template-columns: 1fr; gap: 2px 0; }
  .kv-list dd { margin-bottom: 8px; }

  /* ---- tasks: table becomes cards (drag hidden; arrows + status
          select + Review Now survive) ---- */
  body #tTable, body #tTable tbody { display: block; width: 100%; }
  body #tTable thead { display: none; }
  body #tTable tbody tr.t-row {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    gap: 4px 10px; padding: 12px 4px;
    border-bottom: 1px solid var(--border, #eee);
  }
  body #tTable tbody tr.t-row td { display: block; border: none; padding: 0; min-width: 0; grid-column: 1; }
  body #tTable tr.t-row td:nth-child(1) { display: none; }
  body #tTable tr.t-row td:nth-child(5) { grid-row: 1; grid-column: 1 / -1; font-weight: 600; overflow-wrap: anywhere; }
  body #tTable tr.t-row td:nth-child(2),
  body #tTable tr.t-row td:nth-child(3),
  body #tTable tr.t-row td:nth-child(8) { font-size: 11px; color: var(--text-secondary, #6b6b6b); }
  body #tTable tr.t-row td:nth-child(9) { grid-column: 1 / -1; }
  body #tTable tr.t-row td:nth-child(10) { grid-column: 1 / -1; text-align: right; }
  body .t-actions-cell { white-space: normal !important; }
  #filterBar select { min-width: 0; }

  /* ---- auth/legal misc ---- */
  #codeInput { width: 100%; }
  #qrHolder img { max-width: 100%; height: auto; }
  .mfa-card { margin: 20px 12px; padding: 24px 20px; }
  body .legal-container { margin: 16px 10px; padding: 24px 18px; }
  body .legal-container .legal-toc ol { columns: 1; }
  body .legal-container h1 { font-size: 26px; }
}
