@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,600&family=Inter:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap');

:root{
  --ink:#0A1526;
  --panel:#101E33;
  --panel-alt:#0C1A2C;
  --border:#223550;        /* decorative rules and dividers */
  --border-soft:#182840;
  /* Control boundaries are held to WCAG's 3:1 non-text minimum — the old
     --border was 1.35:1 against a panel, so every input edge was
     effectively invisible. Dividers keep the softer colours above,
     because purely decorative lines are exempt. */
  --border-control:#4A6A9E;
  --text:#EAF1FB;
  --text-soft:#93A7C4;
  --text-mute:#9DB2CC;     /* was #7691AD — 5.1:1, and used at 10-11px */
  --gold:#2E93E0;
  --gold-btn-bg:#1F6FBF;   /* white on this is 5.1:1; the old #2376CA was 4.65 */
  --focus:#7CC4FF;
  --gold-soft:rgba(46,147,224,0.16);
  --coral:#F0576B;
  --coral-soft:rgba(240,87,107,0.14);
  --moss:#34D399;
  --moss-soft:rgba(52,211,153,0.14);
}
*{ box-sizing:border-box; }
body{
  margin:0;
  background:var(--ink);
  color:var(--text);
  font-family:'Inter',sans-serif;
  -webkit-font-smoothing:antialiased;
}
a{ color:inherit; text-decoration:none; }
.serif{ font-family:'Fraunces',serif; font-weight:600; letter-spacing:-0.01em; }
.mono{ font-family:'IBM Plex Mono',monospace; }

.auth-shell{ min-height:100vh; display:flex; align-items:center; justify-content:center; padding:20px; }
.auth-card{ width:100%; max-width:380px; background:var(--panel); border:1px solid var(--border-soft); border-radius:16px; padding:32px; }
.auth-brand{ display:flex; align-items:center; gap:10px; margin-bottom:24px; }
.auth-mark{ width:28px; height:28px; border-radius:8px; background:linear-gradient(155deg,var(--gold),#124A78); flex-shrink:0; }
.auth-title{ font-size:22px; margin-bottom:4px; }
.auth-sub{ font-size:13px; color:var(--text-soft); margin-bottom:22px; }

label{ display:block; font-size:12px; color:var(--text-soft); margin-bottom:6px; font-weight:500; }
.field{ margin-bottom:14px; }
.field-hint{ font-size:11.5px; color:var(--text-mute); margin-top:5px; }
/* Visible to screen readers, not on screen — for the handful of controls
   whose purpose is obvious visually but has no on-screen label text. */
.visually-hidden{
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0;
}
/* Skip to content. Off-screen until it takes focus, which is the first
   thing a keyboard lands on — otherwise reaching the page content means
   tabbing past the whole sidebar on every single page. */
.skip-link{
  position:absolute; left:-9999px; top:0; z-index:200;
  background:var(--panel); color:var(--text); border:1px solid var(--border-control);
  border-radius:0 0 10px 0; padding:14px 18px; min-height:44px; font-size:13.5px; font-weight:600; text-decoration:none;
}
.skip-link:focus{ left:0; outline:2px solid #6FB6F0; outline-offset:2px; }
/* The skip link moves focus here; the ring on a whole page region is
   noise, and the heading underneath is what the reader wants. */
main[tabindex="-1"]:focus{ outline:none; }
.req{ color:var(--coral); }

/* Every text-entry control shares one border colour, so the edge of a
   field is always visible rather than implied by a slight fill change. */
input, select, textarea{
  width:100%; background:var(--panel-alt); border:1px solid var(--border-control); border-radius:9px;
  padding:10px 12px; color:var(--text); font-size:14px; font-family:'Inter',sans-serif;
}
textarea{ resize:vertical; }
input::placeholder, textarea::placeholder{ color:var(--text-mute); opacity:1; }
input[type="checkbox"], input[type="radio"]{
  width:18px; height:18px; padding:0; flex-shrink:0;
  accent-color:var(--gold);
  /* An unchecked native checkbox on a dark background is nearly
     invisible, so the box gets its own outline. */
  outline:1px solid var(--border-control); outline-offset:-1px; border-radius:4px;
}
input[type="radio"]{ border-radius:50%; }
input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible{
  outline:2px solid var(--focus); outline-offset:2px;
}
input[type="color"]{ padding:2px; height:38px; }
input[type="file"]{ padding:8px 10px; }
input:disabled, select:disabled, textarea:disabled{
  color:var(--text-mute); background:var(--ink); border-color:var(--border); cursor:not-allowed;
}
input[aria-invalid="true"], textarea[aria-invalid="true"], select[aria-invalid="true"]{
  border-color:var(--coral);
}

/* One focus style for everything focusable, not just inputs. */
:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; border-radius:6px; }
input:focus-visible, select:focus-visible, textarea:focus-visible{ outline-offset:1px; }

.btn{
  width:100%; background:var(--gold-btn-bg); color:#FFFFFF; font-weight:600; font-size:14px;
  padding:11px; border-radius:9px; border:1px solid transparent; cursor:pointer; margin-top:6px;
  min-height:40px; display:inline-flex; align-items:center; justify-content:center; gap:8px;
}
.btn:hover:not(:disabled){ filter:brightness(1.08); }
.btn:disabled{ opacity:0.75; cursor:default; }
/* A ghost button is a real button, so it gets a real edge. */
.btn-ghost{ background:var(--panel-alt); color:var(--text); border-color:var(--border-control); }
/* Primary buttons that shouldn't span the panel. */
.btn-inline{ width:auto; padding:11px 22px; }
.btn-sm{ width:auto; padding:8px 14px; font-size:12.5px; min-height:36px; }

/* Small row actions — the "Delete", "Retry", "On/Off" chips that used to
   be one-off inline styles with no border and a 24px tap target. */
.btn-chip{
  display:inline-flex; align-items:center; justify-content:center; gap:6px;
  background:var(--panel-alt); color:var(--text-soft);
  border:1px solid var(--border-control); border-radius:8px;
  padding:7px 12px; font-size:12px; font-family:inherit; font-weight:500;
  cursor:pointer; text-decoration:none; min-height:34px; white-space:nowrap;
}
.btn-chip:hover:not(:disabled){ background:var(--panel); color:var(--text); }
.btn-chip:disabled{ opacity:0.75; cursor:default; }
.btn-chip.danger{ background:var(--coral-soft); color:var(--coral); border-color:var(--coral); }
.btn-chip.ok{ background:var(--moss-soft); color:var(--moss); border-color:var(--moss); }
.btn-chip.off{ background:var(--panel-alt); color:var(--text-mute); border-color:var(--border-control); }
.btn-chip.primary{ background:var(--gold-soft); color:var(--gold); border-color:var(--gold); }

/* Bare icon buttons (the ▲▼ reorder controls). */
.btn-icon{
  display:inline-flex; align-items:center; justify-content:center;
  width:30px; height:26px; padding:0;
  background:none; border:1px solid transparent; border-radius:6px;
  color:var(--text-mute); cursor:pointer; font-size:11px; font-family:inherit;
}
.btn-icon:hover{ background:var(--panel); color:var(--text); border-color:var(--border-control); }

.error-box{ background:var(--coral-soft); color:var(--coral); font-size:12.5px; padding:9px 11px; border-radius:8px; margin-bottom:14px; }
/* "You've used every line your plan includes" — a fact about the plan, not a
   mistake the person made, so it reads in the accent colour rather than red. */
.notice{
  background:var(--gold-soft); border:1px solid var(--gold);
  color:var(--text); font-size:12.5px; line-height:1.55;
  padding:10px 12px; border-radius:9px;
}
/* The accent blue only reaches 4:1 against the tinted panel this box sits
   on — under the 4.5:1 body text needs — so links inside it get a lighter
   shade and an underline to carry the meaning without relying on colour. */
.notice a{ color:#6FB6F0; text-decoration:underline; font-weight:500; }
.foot-link{ text-align:center; font-size:12.5px; color:var(--text-mute); margin-top:18px; }
.foot-link a{ color:var(--gold); font-weight:500; }

/* dashboard */
.dash-shell{ min-height:100vh; display:flex; }
.dash-sidebar{ width:220px; flex-shrink:0; background:var(--panel-alt); border-right:1px solid var(--border-soft); padding:20px 12px; display:flex; flex-direction:column; }
.dash-nav{ display:flex; flex-direction:column; gap:2px; margin-top:18px; }
.dash-nav-item{ display:flex; align-items:center; gap:10px; padding:9px 12px; border-radius:9px; font-size:13.5px; color:var(--text-soft); font-weight:500; }
.dash-nav-item:hover{ background:var(--panel); color:var(--text); }
.dash-nav-item.active{ background:var(--gold-soft); color:var(--gold); }
.dash-nav-item.disabled{ color:var(--text-mute); cursor:default; }
.dash-nav-item.disabled:hover{ background:none; color:var(--text-mute); }
.dash-nav-item svg{ width:16px; height:16px; flex-shrink:0; }
.soon-tag{ margin-left:auto; font-size:9.5px; text-transform:uppercase; letter-spacing:0.04em; background:var(--panel); color:var(--text-mute); padding:2px 6px; border-radius:5px; }

/* --- Grouped sidebar -------------------------------------------------
   The nav is bucketed into collapsible groups (CRM / Outreach / Records)
   so it reads as a few sections rather than one long list. The group
   holding the current page is forced open on render by header.php; the
   others restore whatever the person last left them at (see app.js). */
.nav-group{ margin-top:10px; }
.nav-group-head{
  display:flex; align-items:center; width:100%; gap:6px;
  background:none; border:none; cursor:pointer;
  padding:6px 12px; margin:0 0 2px; border-radius:8px;
  font-family:inherit; font-size:10.5px; font-weight:600;
  letter-spacing:0.08em; text-transform:uppercase;
  color:var(--text-mute); text-align:left;
}
.nav-group-head:hover{ color:var(--text-soft); background:var(--panel); }
.nav-group-head:focus-visible{ outline:2px solid var(--gold); outline-offset:-2px; }
.nav-group-head .nav-chevron{
  width:14px; height:14px; margin-left:auto; flex-shrink:0;
  transition:transform .16s ease; transform:rotate(-90deg);
}
.nav-group-head[aria-expanded="true"] .nav-chevron{ transform:rotate(0deg); }
/* A collapsed group still signals that it holds the current page. */
.nav-group-head.has-active{ color:var(--gold); }
.nav-group-body{ display:flex; flex-direction:column; gap:2px; }
.nav-group-body[hidden]{ display:none; }

.dash-main{ flex:1; min-width:0; }
.dash-top{ display:flex; align-items:center; gap:14px; padding:16px 26px; border-bottom:1px solid var(--border-soft); }
.dash-top .auth-brand{ margin:0; }
.dash-top-spacer{ flex:1; }
.dash-top-tenant{ font-size:12.5px; color:var(--text-mute); }
.dash-top-greeting{ font-size:12.5px; color:var(--text-soft); }
.logout-btn{ font-size:12.5px; color:var(--text-soft); background:var(--panel); padding:7px 12px; border-radius:8px; border:1px solid var(--border-control); cursor:pointer; }
.logout-btn:hover{ color:var(--text); }

/* --- Gear menu (profile / account / workspace settings) --------------
   Everything configuration-shaped was pulled out of the sidebar and now
   hangs off this single control in the top-right corner. */
.gear-menu{ position:relative; }
.gear-btn{
  display:inline-flex; align-items:center; justify-content:center;
  width:34px; height:34px; padding:0;
  background:var(--panel); border:1px solid var(--border-control); border-radius:9px;
  color:var(--text-soft); cursor:pointer; transition:color .15s ease, background .15s ease;
}
.gear-btn svg{ width:17px; height:17px; display:block; }
.gear-btn:hover{ color:var(--text); border-color:var(--border); }
.gear-btn.active,
.gear-btn[aria-expanded="true"]{ color:var(--gold); background:var(--gold-soft); border-color:var(--gold); }
.gear-btn:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }

.gear-dropdown{
  position:absolute; top:calc(100% + 8px); right:0; z-index:300;
  width:236px; padding:6px;
  background:var(--panel); border:1px solid var(--border); border-radius:12px;
  box-shadow:0 14px 34px rgba(0,0,0,0.45);
}
.gear-dropdown[hidden]{ display:none; }
.gear-id{ display:flex; align-items:center; gap:10px; padding:8px 10px 10px; }
.gear-avatar{
  width:30px; height:30px; flex-shrink:0; border-radius:9px;
  background:linear-gradient(155deg,var(--gold),#124A78); color:#fff;
  display:flex; align-items:center; justify-content:center;
  font-size:13px; font-weight:600;
}
.gear-id-name{ font-size:13.5px; font-weight:600; }
.gear-id-sub{
  font-size:11px; color:var(--text-mute); margin-top:1px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.gear-section-label{
  font-size:10px; font-weight:600; letter-spacing:0.08em; text-transform:uppercase;
  color:var(--text-mute); padding:8px 10px 4px;
}
.gear-item{
  display:flex; align-items:center; gap:10px; width:100%;
  padding:8px 10px; border-radius:8px; border:none;
  background:none; font-family:inherit; font-size:13px; font-weight:500;
  color:var(--text-soft); text-align:left; cursor:pointer;
}
.gear-item svg{ width:16px; height:16px; flex-shrink:0; }
.gear-item:hover{ background:var(--panel-alt); color:var(--text); }
.gear-item.active{ background:var(--gold-soft); color:var(--gold); }
.gear-item:focus-visible{ outline:2px solid var(--gold); outline-offset:-2px; }
.gear-item-danger{ color:var(--coral); }
.gear-item-danger:hover{ background:var(--coral-soft); color:var(--coral); }
.gear-divider{ height:1px; background:var(--border-soft); margin:6px 4px; }

/* --- Platform admin nav ----------------------------------------------
   Grouped and wrapping, because the admin bar now covers workspaces,
   selling and platform-wide settings rather than one flat list. */
.admin-nav{ display:flex; flex-wrap:wrap; align-items:center; gap:3px; margin-left:16px; }
.admin-nav-group{
  font-size:9.5px; font-weight:600; letter-spacing:0.08em; text-transform:uppercase;
  color:var(--text-mute); padding:0 8px 0 10px; border-left:1px solid var(--border-soft); margin-left:6px;
}
.admin-nav-group:first-child{ border-left:none; margin-left:0; padding-left:0; }
.admin-nav-item{
  display:inline-flex; align-items:center; gap:6px;
  font-size:12.5px; padding:7px 11px; border-radius:8px;
  text-decoration:none; color:var(--text-soft);
}
.admin-nav-item:hover{ background:var(--panel); color:var(--text); }
.admin-nav-item.active{ background:var(--gold-soft); color:var(--gold); }
.admin-nav-badge{
  background:var(--coral); color:#1a0d0d; font-size:10px; font-weight:700;
  border-radius:9px; padding:1px 6px; line-height:1.5;
}
.dash-content{ padding:26px; max-width:1000px; }
.dash-cols{ display:grid; grid-template-columns:1.1fr 1fr; gap:18px; margin-top:20px; }

.stat-grid-4{ display:grid; grid-template-columns:repeat(4,1fr); gap:14px; margin-bottom:20px; }

/* Hamburger toggle — hidden on desktop, shown only inside the mobile media query below. */
.hamburger-btn{ display:none; background:none; border:none; color:var(--text); padding:6px; cursor:pointer; }
.hamburger-btn svg{ width:22px; height:22px; display:block; }
.sidebar-backdrop{ display:none; }

@media (max-width:860px){
  .dash-cols{ grid-template-columns:1fr; }
  .stat-grid-4{ grid-template-columns:repeat(2,1fr); }
  .quick-add{ flex-direction:column; }
  .quick-add button{ width:100%; }

  .hamburger-btn{ display:inline-flex; align-items:center; }

  /* Sidebar becomes an off-canvas drawer instead of vanishing entirely. */
  .dash-sidebar{
    position:fixed; top:0; left:0; bottom:0; z-index:200;
    transform:translateX(-100%); transition:transform .2s ease;
    box-shadow:2px 0 24px rgba(0,0,0,0.4);
  }
  .dash-sidebar.open{ transform:translateX(0); }

  .sidebar-backdrop.open{
    display:block; position:fixed; inset:0; z-index:190;
    background:rgba(0,0,0,0.5);
  }

  /* Real tap targets. This used to match on inline style attributes,
     which only worked for buttons that happened to be written a certain
     way; the small actions are proper classes now, so the rule can be
     about the control itself. 44px is the WCAG 2.2 target-size minimum. */
  /* .btn sets its own min-height, and a class beats an element selector,
     so the mobile minimum has to be at least as specific to win. */
  button, a.btn, input[type="submit"], select,
  .btn, .btn-chip, .btn-icon, .btn-sm, .logout-btn, .gear-btn{
    min-height:44px;
    /* Height alone left a column of 24-34px-wide icon buttons — the
       hamburger, the gear, the ✕ on a row — which are exactly the ones a
       thumb misses. A target has two dimensions. */
    min-width:44px;
  }
  .hamburger-btn, .gear-btn{ justify-content:center; }
  .btn-chip{ padding:10px 14px; font-size:13px; }
  /* The channel filters on Conversations are links, so the button rule
     above skips them. Two classes deep because .channel-chip's own rule
     is further down the file and would otherwise win on order. */
  .channel-filters .channel-chip{ min-height:44px; }
  .btn-icon{ width:44px; height:44px; }
  input[type="checkbox"], input[type="radio"]{ width:24px; height:24px; }
  /* A checkbox in a label needs the whole row to be tappable, not just
     the box — these are the "enable X" toggles throughout settings. */
  label:has(> input[type="checkbox"]), label:has(> input[type="radio"]){
    min-height:44px; display:flex; align-items:center;
  }
  .admin-nav-item{ min-height:44px; }
  .gear-item{ min-height:44px; }
  .dash-nav-item{ min-height:44px; }
  .toast-stack{ left:16px; right:16px; bottom:16px; max-width:none; }

  /* The greeting is the first thing to go when the top bar gets tight —
     the gear menu repeats the name anyway. */
  .dash-top-greeting{ display:none; }
  .dash-top-tenant{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:45vw; }
  /* Keep the dropdown on-screen on narrow phones. */
  .gear-dropdown{ width:min(268px, calc(100vw - 28px)); }
}

.panel{ background:var(--panel); border:1px solid var(--border-soft); border-radius:14px; padding:18px 20px; }
.panel h2{ font-size:15px; margin:0 0 12px; }
.panel-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:12px; }
.count-pill{ font-size:11px; color:var(--text-mute); background:var(--panel-alt); padding:3px 8px; border-radius:6px; font-family:'IBM Plex Mono'; }

.row{ display:flex; align-items:center; gap:10px; padding:9px 0; border-top:1px solid var(--border-soft); }
.row:first-child{ border-top:none; padding-top:0; }
.row-title{ font-size:13.5px; font-weight:500; }
.row-sub{ font-size:11.5px; color:var(--text-mute); margin-top:1px; }
.row-spacer{ flex:1; }
.pill{ font-size:11px; font-weight:600; padding:3px 9px; border-radius:20px; }
.pill-gold{ background:var(--gold-soft); color:var(--gold); }
.pill-moss{ background:var(--moss-soft); color:var(--moss); }
.pill-coral{ background:var(--coral-soft); color:var(--coral); }
/* An empty state should say what to do next and give you the control to
   do it, rather than just reporting that there is nothing here. */
.empty-state{
  display:flex; flex-direction:column; align-items:center; gap:10px;
  font-size:13px; color:var(--text-soft); padding:26px 18px; text-align:center;
}
.empty-state .empty-icon{ color:var(--text-mute); }
.empty-state .empty-icon svg{ width:30px; height:30px; display:block; }
.empty-state .empty-title{ font-size:14.5px; color:var(--text); font-weight:600; }
.empty-state .empty-sub{ font-size:12.5px; color:var(--text-mute); max-width:44ch; line-height:1.5; }
.empty-state .empty-actions{ display:flex; gap:8px; flex-wrap:wrap; justify-content:center; margin-top:4px; }
/* Compact variant for empty states inside a small panel. */
.empty-state.tight{ padding:16px 12px; gap:7px; }

.quick-add{ display:flex; gap:8px; margin-top:14px; }
.quick-add input{ flex:1; }
.quick-add button{ width:auto; padding:10px 16px; margin-top:0; }

/* Conversations: side-by-side on desktop, single full-width view on mobile.
   .convo-shell gets a data-selected attribute (set in conversations.php)
   so CSS alone decides which pane shows, no JS required. */
@media (max-width:860px){
  .convo-shell{ grid-template-columns:1fr !important; }
  .convo-shell[data-selected="0"] .convo-thread{ display:none; }
  .convo-shell[data-selected="1"] .convo-list{ display:none; }
  .convo-shell[data-selected="1"] .convo-back-link{ display:inline-block !important; }
}


/* --- Billing ---------------------------------------------------------
   The plan cards double as radio labels, so the whole card is the click
   target rather than a 14px radio dot. */
.plan-option{
  display:flex; align-items:flex-start; gap:10px; cursor:pointer;
  background:var(--panel-alt); border:2px solid var(--border-soft);
  border-radius:12px; padding:14px;
}
.plan-option:hover{ border-color:var(--border); }
.plan-option:has(input:checked){ border-color:var(--gold); background:var(--gold-soft); }
.plan-option.current{ cursor:default; border-color:var(--moss); }
.plan-option input{ margin-top:3px; }

/* Card brand badge beside the saved payment method. */
.card-chip{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:52px; height:34px; padding:0 10px;
  background:var(--panel-alt); border:1px solid var(--border);
  border-radius:7px; font-size:10.5px; font-weight:700; letter-spacing:0.04em;
  color:var(--text-soft);
}

/* A button that reads as a link — used for inline billing actions. */
.link-btn{
  background:none; border:none; padding:0; cursor:pointer;
  font-family:inherit; font-size:inherit; text-decoration:underline;
}
.link-btn:disabled{ opacity:0.5; cursor:default; }


/* --- Feedback states -------------------------------------------------
   Four things a person needs to be told, each with one way of saying it:
   something is happening, it worked, it didn't, and you have unsaved
   work. Previously only the first existed, and confirmation was a native
   confirm() box that couldn't be styled or read out sensibly. */

/* Toasts: transient success/error confirmations. Announced politely to
   screen readers via aria-live on the container. */
.toast-stack{
  position:fixed; z-index:1000; bottom:20px; right:20px;
  display:flex; flex-direction:column; gap:8px; max-width:min(380px, calc(100vw - 32px));
}
.toast{
  display:flex; align-items:flex-start; gap:10px;
  background:var(--panel); border:1px solid var(--border-control); border-left-width:3px;
  border-radius:10px; padding:12px 14px; font-size:13px; color:var(--text);
  box-shadow:0 10px 28px rgba(0,0,0,0.45);
  animation:toast-in .18s ease-out;
}
.toast.success{ border-left-color:var(--moss); }
.toast.error{ border-left-color:var(--coral); }
.toast.info{ border-left-color:var(--gold); }
.toast-icon{ flex-shrink:0; margin-top:1px; }
.toast-icon svg{ width:16px; height:16px; display:block; }
.toast.success .toast-icon{ color:var(--moss); }
.toast.error .toast-icon{ color:var(--coral); }
.toast.info .toast-icon{ color:var(--gold); }
.toast-close{
  background:none; border:none; color:var(--text-mute); cursor:pointer;
  font-size:16px; line-height:1; padding:2px 4px; margin-left:auto;
}
.toast-close:hover{ color:var(--text); }
@keyframes toast-in{ from{ opacity:0; transform:translateY(8px); } to{ opacity:1; transform:none; } }

/* Loading: a spinner for buttons mid-request, and a page-level bar. */
.spinner{
  width:14px; height:14px; flex-shrink:0;
  border:2px solid currentColor; border-right-color:transparent; border-radius:50%;
  display:inline-block; animation:spin .6s linear infinite;
}
@keyframes spin{ to{ transform:rotate(360deg); } }
.is-loading{ cursor:progress; }

.route-progress{
  position:fixed; top:0; left:0; height:3px; width:0; z-index:1200;
  background:var(--gold); transition:width .2s ease, opacity .3s ease;
}

/* Inline validation, sitting with the field it's about. */
.field-error{
  display:flex; align-items:flex-start; gap:6px;
  font-size:12px; color:var(--coral); margin-top:6px;
}
.field-error svg{ width:13px; height:13px; flex-shrink:0; margin-top:1px; }

/* Unsaved changes: the form says so, and the button says what's pending. */
.dirty-badge{
  display:none; align-items:center; gap:6px;
  font-size:11.5px; color:var(--gold); background:var(--gold-soft);
  border-radius:20px; padding:3px 10px; margin-left:8px;
}
.dirty-badge::before{ content:''; width:6px; height:6px; border-radius:50%; background:var(--gold); }
form.is-dirty .dirty-badge{ display:inline-flex; }

/* Confirmation dialog — replaces window.confirm(), which can't be styled,
   can't explain consequences, and reads out the page URL first. */
.confirm-backdrop{
  position:fixed; inset:0; z-index:1100;
  background:rgba(5,10,20,0.66); backdrop-filter:blur(2px);
  display:flex; align-items:center; justify-content:center; padding:20px;
}
.confirm-dialog{
  width:100%; max-width:420px;
  background:var(--panel); border:1px solid var(--border-control); border-radius:14px;
  padding:22px; box-shadow:0 24px 60px rgba(0,0,0,0.5);
}
.confirm-title{ font-size:16px; font-weight:600; margin:0 0 8px; }
.confirm-body{ font-size:13.5px; color:var(--text-soft); line-height:1.55; margin:0 0 18px; }
.confirm-actions{ display:flex; gap:8px; justify-content:flex-end; flex-wrap:wrap; }
.confirm-actions .btn{ width:auto; margin-top:0; padding:10px 18px; }

@media (prefers-reduced-motion: reduce){
  .toast, .spinner, .route-progress{ animation:none !important; transition:none !important; }
}

/* --- Setup checklist -------------------------------------------------
   Each step is derived from the workspace's own data, so the tick is a
   statement of fact rather than a box someone remembered to check. */
.progress-track{
  height:8px; background:var(--panel-alt); border:1px solid var(--border-control);
  border-radius:20px; overflow:hidden;
}
.progress-fill{
  height:100%; background:var(--gold); border-radius:20px;
  transition:width .3s ease;
}
.setup-step{
  display:flex; align-items:flex-start; gap:12px;
  padding:14px 0; border-top:1px solid var(--border-soft);
}
.setup-check{
  width:22px; height:22px; flex-shrink:0; margin-top:1px;
  border:2px solid var(--border-control); border-radius:50%;
  display:flex; align-items:center; justify-content:center; color:transparent;
}
.setup-step.done .setup-check{ border-color:var(--moss); color:var(--moss); }
.setup-check svg{ width:13px; height:13px; }
.setup-title{ font-size:14px; font-weight:600; }
.setup-step.done .setup-title{ color:var(--text-soft); font-weight:500; }
.setup-body{ font-size:12.5px; color:var(--text-mute); margin-top:3px; line-height:1.5; }
.setup-step .btn-chip{ flex-shrink:0; }

/* The dashboard nudge — the same checklist, condensed to the next step. */
.setup-callout{
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  background:var(--panel); border:1px solid var(--gold);
  border-radius:14px; padding:16px 18px; margin-bottom:20px;
}
.setup-callout .progress-track{ max-width:260px; }

@media (max-width:860px){
  .setup-step{ flex-wrap:wrap; }
  .setup-step .btn-chip{ margin-left:34px; }
}

/* --- Rows that go somewhere -------------------------------------------
   A dashboard list of tasks or deals is a list of things you want to open,
   so the whole row is the link rather than a hidden hotspot on the title.
   Being an <a> keeps it one tab stop, keyboard-activatable, and announced
   as a link. */
.row-link{
  text-decoration:none; color:inherit; cursor:pointer;
  border-radius:8px; margin:0 -8px; padding-left:8px; padding-right:8px;
  transition:background .12s ease;
}
.row-link:hover{ background:var(--panel-alt); }
.row-link:hover .row-title{ color:var(--gold); }
.row-link:focus-visible{ outline:2px solid var(--focus); outline-offset:-2px; }
.row-go{
  display:flex; align-items:center; color:var(--text-mute);
  opacity:0; transition:opacity .12s ease, transform .12s ease; transform:translateX(-3px);
}
.row-go svg{ width:15px; height:15px; }
.row-link:hover .row-go, .row-link:focus-visible .row-go{ opacity:1; transform:none; }
/* Touch devices have no hover, so the affordance is always visible. */
@media (hover:none){ .row-go{ opacity:1; transform:none; } }

/* The row you arrived at, marked briefly so it can be found in a long
   list. :target alone would leave it highlighted forever. */
@keyframes arrive-highlight{
  0%, 55% { background:var(--gold-soft); box-shadow:inset 3px 0 0 var(--gold); }
  100% { background:transparent; box-shadow:inset 3px 0 0 transparent; }
}
/* The negative margin pays back the padding, so the marker bar gets space
   of its own instead of sitting on the first letter, while the row's text
   stays lined up with the rows above and below it. */
.row:target, .kanban-card:target{
  animation:arrive-highlight 3.2s ease-out forwards;
  border-radius:8px; scroll-margin-top:90px;
  padding-left:12px; margin-left:-12px;
}
@media (prefers-reduced-motion: reduce){
  .row:target, .kanban-card:target{
    animation:none; background:var(--gold-soft); box-shadow:inset 3px 0 0 var(--gold);
  }
}

/* --- The call bar -----------------------------------------------------
   Fixed to the bottom, above everything, because a live call outranks
   whatever page you happen to be on. It follows you between pages by
   being re-created from the same state on each load. */
.call-bar{
  position:fixed; left:50%; transform:translateX(-50%); bottom:18px; z-index:1200;
  display:flex; align-items:center; gap:14px;
  min-width:min(420px, calc(100vw - 32px)); max-width:calc(100vw - 32px);
  padding:12px 16px; border-radius:14px;
  background:var(--panel); border:1px solid var(--border-control);
  box-shadow:0 12px 34px rgba(0,0,0,.45);
}
.call-bar-who{ display:flex; align-items:center; gap:10px; flex:1; min-width:0; }
.call-bar-name{ font-size:13.5px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.call-bar-status{ font-size:11.5px; color:var(--text-soft); }
.call-bar-timer{ font-size:13px; color:var(--text-soft); }
.call-bar-actions{ display:flex; gap:8px; flex-shrink:0; }
.call-bar .btn-icon{ min-height:34px; padding:0 12px; font-size:12.5px; }
.call-bar .call-hangup{ background:var(--coral-soft); color:var(--coral); border-color:var(--coral); }
.call-bar .call-answer{ background:var(--moss-soft); color:var(--moss); border-color:var(--moss); }

/* The status dot: steady when connected, pulsing while it rings. */
.call-bar-dot{
  width:10px; height:10px; border-radius:50%; flex-shrink:0;
  background:var(--text-mute);
}
.call-bar.is-live .call-bar-dot{ background:var(--moss); }
.call-bar.is-ringing .call-bar-dot{ background:var(--gold); animation:call-pulse 1.1s ease-in-out infinite; }
@keyframes call-pulse{ 0%,100%{ opacity:1; transform:scale(1); } 50%{ opacity:.35; transform:scale(.8); } }
@media (prefers-reduced-motion: reduce){
  .call-bar.is-ringing .call-bar-dot{ animation:none; opacity:1; }
}
@media (max-width: 640px){
  .call-bar{ left:16px; right:16px; transform:none; min-width:0; }
}

/* --- Live visitors ---------------------------------------------------- */
.visitor-row{ align-items:center; gap:10px; }
.visitor-status{
  width:8px; height:8px; border-radius:50%; flex-shrink:0;
  background:var(--text-mute);
}
.visitor-status.is-active{
  background:var(--moss);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--moss) 22%, transparent);
}
/* The header's "is this list actually live" indicator. */
.live-dot{
  width:8px; height:8px; border-radius:50%; background:var(--text-mute);
  display:inline-block; flex-shrink:0;
}
.live-dot.is-live{ background:var(--moss); animation:live-breathe 2.4s ease-in-out infinite; }
@keyframes live-breathe{ 0%,100%{ opacity:1; } 50%{ opacity:.4; } }
@media (prefers-reduced-motion: reduce){ .live-dot.is-live{ animation:none; } }

/* =====================================================================
   Dashboard
   ===================================================================== */

/* --- The four headline numbers ---------------------------------------
   Cards, not bare panels: each one is a link into the list it counts,
   because the first thing you want after reading "64 qualified" is to
   see which 64. */
.kpi-grid{
  display:grid; grid-template-columns:repeat(4, minmax(0, 1fr));
  gap:14px; margin-bottom:18px;
}
.kpi-card{
  display:flex; align-items:center; gap:14px;
  background:var(--panel); border:1px solid var(--border-soft); border-radius:14px;
  padding:16px; text-decoration:none; color:inherit;
  transition:border-color .12s ease, transform .12s ease;
}
.kpi-card:hover{ border-color:var(--border-control); transform:translateY(-1px); }
.kpi-card:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.kpi-icon{
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  width:44px; height:44px; border-radius:50%;
  background:var(--gold-btn-bg); color:#FFFFFF;
}
.kpi-icon svg{ width:21px; height:21px; }
.kpi-body{ display:flex; flex-direction:column; min-width:0; gap:1px; }
.kpi-label{ font-size:12px; color:var(--text-soft); }
.kpi-value{ font-size:25px; line-height:1.1; }
.kpi-delta{ font-size:11px; display:flex; gap:5px; flex-wrap:wrap; align-items:baseline; }
.kpi-up{ color:var(--moss); font-weight:600; }
.kpi-down{ color:var(--coral); font-weight:600; }

@media (max-width: 1100px){ .kpi-grid{ grid-template-columns:repeat(2, minmax(0,1fr)); } }
@media (max-width: 560px){
  .kpi-grid{ grid-template-columns:1fr; }
  .kpi-card{ padding:14px; }
}

/* --- The pipeline board ----------------------------------------------
   Scrolls sideways rather than squeezing. Squeezing eight stages into a
   fixed width makes every card unreadable; scrolling keeps them legible
   and the shape of the pipeline obvious. */
/* A grid, not a scroller: however many stages a workspace has, they all
   fit across the panel. A sideways scrollbar on the dashboard hides half
   the pipeline behind a gesture, which defeats the point of a board you
   are meant to take in at a glance. Columns get narrow rather than
   hidden, and the card text truncates to suit. */
.pipeline-board{
  display:grid;
  grid-auto-flow:column;
  grid-auto-columns:minmax(0, 1fr);
  gap:10px;
  padding:4px 0 4px;
}
.pipeline-col{ min-width:0; display:flex; flex-direction:column; }
.pipeline-head{
  display:flex; flex-direction:column; gap:4px;
  padding:10px 12px; border-radius:10px 10px 0 0;
  text-decoration:none; font-weight:600;
}
.pipeline-head:focus-visible{ outline:2px solid var(--focus); outline-offset:-2px; }
.pipeline-stage-name{ font-size:12.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.pipeline-stage-figures{ display:flex; gap:10px; font-size:12px; font-weight:500; }
.pipeline-cards{
  background:var(--panel-alt); border:1px solid var(--border-soft); border-top:none;
  border-radius:0 0 10px 10px; padding:8px; display:flex; flex-direction:column; gap:6px;
  flex:1; min-height:120px;
}
.pipeline-card{
  display:flex; align-items:center; gap:8px;
  background:var(--panel); border:1px solid var(--border-soft); border-radius:8px;
  padding:8px 9px; text-decoration:none; color:inherit;
}
.pipeline-card:hover{ border-color:var(--border-control); }
.pipeline-card:focus-visible{ outline:2px solid var(--focus); outline-offset:1px; }
.pipeline-avatar{
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  width:26px; height:26px; border-radius:50%;
  font-size:10.5px; font-weight:600; letter-spacing:.02em;
}
.pipeline-card-title{
  display:block; font-size:12.5px; font-weight:500;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.pipeline-card-sub{
  display:block; font-size:11px; color:var(--text-mute);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.pipeline-more{
  display:block; text-align:center; font-size:11.5px; color:var(--text-soft);
  padding:6px; border-radius:7px; text-decoration:none;
}
.pipeline-more:hover{ background:var(--panel); color:var(--text); }
.pipeline-empty{
  font-size:11.5px; color:var(--text-mute); text-align:center; padding:14px 6px;
}

/* Under about 700px the columns would be narrower than a name, so the
   board falls back to scrolling — a deliberate trade at the point where
   fitting everything stops being legible. */
@media (max-width: 700px){
  .pipeline-board{
    grid-auto-flow:column;
    grid-auto-columns:minmax(150px, 1fr);
    overflow-x:auto;
    scroll-snap-type:x proximity;
  }
  .pipeline-col{ scroll-snap-align:start; }
}

/* --- Lead source donut ------------------------------------------------
   A conic-gradient, so there is no chart library to load and nothing to
   fail on a blocked CDN. */
.donut-row{ display:flex; gap:16px; align-items:center; flex-wrap:wrap; }
.donut{
  width:128px; height:128px; border-radius:50%; flex-shrink:0;
  display:flex; align-items:center; justify-content:center;
}
.donut-hole{
  width:78px; height:78px; border-radius:50%; background:var(--panel);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px;
}
.donut-legend{ list-style:none; margin:0; padding:0; flex:1; min-width:150px; display:flex; flex-direction:column; gap:7px; }
.donut-legend li{ display:flex; align-items:center; gap:8px; font-size:12.5px; }
.donut-swatch{ width:9px; height:9px; border-radius:2px; flex-shrink:0; }

/* --- Leads over time --------------------------------------------------
   Six numbers do not need a charting library. */
.trend-chart{ display:flex; align-items:flex-end; gap:10px; padding:8px 0 0; }
.trend-col{ flex:1; min-width:0; display:flex; flex-direction:column; align-items:center; gap:5px; }
.trend-value{ font-size:11px; color:var(--text-soft); }
/* The bar's percentage height needs a track of its own to resolve
   against. Sizing it against the column instead let the tallest bar
   push the month label out of the panel. */
.trend-track{ height:120px; width:100%; display:flex; align-items:flex-end; justify-content:center; }
.trend-bar{
  width:100%; max-width:46px;
  background:linear-gradient(180deg, var(--gold), color-mix(in srgb, var(--gold) 45%, transparent));
  border-radius:5px 5px 2px 2px;
}
.trend-label{ font-size:11px; color:var(--text-mute); }

/* --- Lifecycle strip -------------------------------------------------- */
.lifecycle-strip{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.lifecycle-step{
  display:flex; align-items:center; gap:10px; flex:1; min-width:170px;
  padding:10px 12px; border-radius:10px; text-decoration:none; color:inherit;
  border:1px solid var(--border-soft);
}
.lifecycle-step:hover{ border-color:var(--border-control); background:var(--panel-alt); }
.lifecycle-step:focus-visible{ outline:2px solid var(--focus); outline-offset:1px; }
.lifecycle-icon{
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  width:34px; height:34px; border-radius:50%;
  background:var(--gold-soft); color:var(--gold);
}
.lifecycle-icon svg{ width:17px; height:17px; }
.lifecycle-label{ display:block; font-size:13px; font-weight:600; }
.lifecycle-sub{ display:block; font-size:11px; color:var(--text-mute); }
.lifecycle-arrow{ color:var(--text-mute); flex-shrink:0; font-size:15px; }
@media (max-width: 720px){
  .lifecycle-arrow{ display:none; }
  .lifecycle-step{ min-width:100%; }
}

/* The deal name on a kanban card opens the deal. The card itself stays a
   drag handle, so only the title is the link. */
.deal-card-link{ color:inherit; text-decoration:none; }
.deal-card-link:hover{ color:var(--gold); text-decoration:underline; }
.deal-card-link:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; border-radius:4px; }

/* --- The unified inbox ------------------------------------------------
   Four channels in one list, so each row has to say which one it is at a
   glance — a coloured dot for scanning, a badge in the thread header for
   certainty. */
.channel-filters{ display:flex; gap:8px; flex-wrap:wrap; margin-bottom:14px; }
.channel-chip{
  display:inline-flex; align-items:center; gap:7px;
  padding:7px 13px; border-radius:999px; font-size:12.5px; font-weight:500;
  background:var(--panel); border:1px solid var(--border-control); color:var(--text-soft);
  text-decoration:none; min-height:34px;
}
.channel-chip:hover{ color:var(--text); border-color:var(--gold); }
.channel-chip.active{ background:var(--gold-soft); border-color:var(--gold); color:var(--gold); }
.channel-chip:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.channel-chip-count{ font-size:11px; opacity:.75; font-family:'IBM Plex Mono',monospace; }

.channel-dot{ width:8px; height:8px; border-radius:50%; flex-shrink:0; }
.channel-badge{
  display:inline-block; padding:2px 9px; border-radius:999px;
  font-size:10.5px; font-weight:600; border:1px solid transparent;
}

.convo-row{
  display:flex; align-items:center; gap:4px; border-radius:9px;
  border:1px solid transparent;
}
.convo-row:hover{ background:var(--panel-alt); }
.convo-row.is-selected{ background:var(--panel-alt); border-color:var(--border-control); }

/* An unread count has to survive being glanced at, so it carries a real
   background rather than just a colour on the text. */
.unread-pill{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:19px; height:19px; padding:0 6px; border-radius:999px;
  background:var(--gold-btn-bg); color:#FFFFFF;
  font-size:10.5px; font-weight:700; flex-shrink:0;
}

/* Revenue chart — inline SVG, no library. The columns stretch to the panel
   while the labels stay upright, which is why the bars and their labels are
   two elements rather than text inside the SVG. */
.revenue-chart-wrap{ margin-top:4px; }
.revenue-chart{ display:block; width:100%; height:150px; }
.revenue-chart-labels{
  display:flex; margin-top:4px;
  font-size:11px; color:var(--text-mute); font-family:'IBM Plex Mono', monospace;
}
.revenue-chart-labels span{ flex:1; text-align:center; }

.revenue-table{ margin-top:12px; }
.revenue-table > summary{
  cursor:pointer; font-size:12px; color:var(--gold);
  padding:6px 2px; min-height:24px;
}
.revenue-table table{ width:100%; border-collapse:collapse; margin-top:6px; font-size:12.5px; }
.revenue-table th, .revenue-table td{
  text-align:left; padding:6px 4px; border-top:1px solid var(--border-soft);
}
.revenue-table thead th{ color:var(--text-mute); font-weight:500; font-size:11px;
  text-transform:uppercase; letter-spacing:.05em; }
.revenue-table tbody th{ font-weight:400; color:var(--text-soft); }
.revenue-table td{ text-align:right; }

/* Reports */
.report-controls{
  display:flex; gap:12px; align-items:flex-end; flex-wrap:wrap; margin-bottom:16px;
}
.report-controls select{
  background:var(--panel-alt); border:1px solid var(--border-control);
  color:var(--text); border-radius:9px; padding:10px 12px; width:100%;
}
/* A wide report scrolls inside its own box rather than pushing the page
   sideways — a horizontally scrolling page loses the navigation. */
.table-scroll{ overflow-x:auto; }
.report-table{ width:100%; border-collapse:collapse; font-size:13px; }
.report-table th, .report-table td{
  padding:9px 12px; text-align:left; border-top:1px solid var(--border-soft);
  white-space:nowrap;
}
.report-table thead th{
  border-top:none; color:var(--text-mute); font-weight:500;
  font-size:11px; text-transform:uppercase; letter-spacing:.05em;
}
.report-table tbody th{ font-weight:500; color:var(--text); }
.report-table td{ color:var(--text-soft); }
.report-table .num{ text-align:right; font-family:'IBM Plex Mono', monospace; }
.report-table tbody tr:hover{ background:var(--panel-alt); }

/* The "who is asking" block on the platform admin's feedback inbox.
   A grid of label/value pairs rather than a table, because it is a
   handful of facts about one thing, not rows of records.

   Labels sit above their values rather than beside them: side by side,
   a fixed label column ate half of every cell and pushed email addresses
   and "1 open deal" onto a second line. Stacked, the value gets the full
   width, and the grid still collapses to one column on a phone. */
.feedback-facts{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(175px, 1fr));
  gap:11px 20px; font-size:12.5px; color:var(--text-soft);
}
.feedback-facts > div{ min-width:0; }
.feedback-facts span{
  display:block; color:var(--text-mute); font-size:10.5px; font-weight:600;
  text-transform:uppercase; letter-spacing:0.05em; margin-bottom:2px;
}
.feedback-facts a{ color:#6FB6F0; text-decoration:underline; overflow-wrap:anywhere; }

/* ---------------------------------------------------------------------
   The help panel.

   A drawer on the right rather than a modal, because somebody following
   instructions needs to see the page the instructions are about. On a
   phone there is no room for both, so it becomes a sheet over the page.
   ------------------------------------------------------------------- */
.help-btn{
  display:inline-flex; align-items:center; gap:6px; margin-right:8px;
  background:var(--panel-alt); border:1px solid var(--border-control); color:var(--text-soft);
  border-radius:9px; padding:7px 12px; font-size:12.5px; font-weight:500;
  font-family:inherit; cursor:pointer; min-height:34px;
}
.help-btn:hover{ color:var(--text); border-color:var(--gold); }
.help-btn[aria-expanded="true"]{ background:var(--gold-soft); color:var(--gold); border-color:var(--gold); }
.help-btn:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.help-btn span[aria-hidden]{
  display:inline-flex; align-items:center; justify-content:center;
  width:16px; height:16px; border-radius:50%; background:currentColor; color:var(--panel);
  font-size:11px; font-weight:700;
}

.help-backdrop{ display:none; }

/* With the panel open on a wide screen the page shifts left rather than
   being covered. The whole point of a side panel is following steps while
   looking at the thing the steps are about — a panel that hides the
   button it is telling you to press is worse than no panel. */
body.help-open .dash-main{ padding-right:380px; }
body.help-open .dash-main{ transition:padding-right .18s ease; }

.help-panel{
  position:fixed; top:0; right:0; bottom:0; width:380px; max-width:92vw; z-index:210;
  background:var(--panel); border-left:1px solid var(--border-control);
  box-shadow:-2px 0 24px rgba(0,0,0,0.35);
  display:flex; flex-direction:column;
}
.help-panel[hidden]{ display:none; }
.help-panel-head{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:16px 18px; border-bottom:1px solid var(--border-soft); flex-shrink:0;
}
.help-panel-head h2{ margin:0; font-size:15px; }
.help-close{
  background:none; border:none; color:var(--text-mute); font-size:22px; line-height:1;
  cursor:pointer; padding:4px 8px; border-radius:8px; min-width:44px; min-height:44px;
}
.help-close:hover{ color:var(--text); }
.help-close:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }

.help-panel-body{ overflow-y:auto; padding:14px 18px 22px; }
.help-article{ border-bottom:1px solid var(--border-soft); padding:10px 0; }
.help-article > summary{
  cursor:pointer; font-size:13.5px; font-weight:600; color:var(--text);
  padding:6px 0; list-style:none;
}
.help-article > summary::-webkit-details-marker{ display:none; }
.help-article > summary::before{ content:'▸ '; color:var(--text-mute); }
.help-article[open] > summary::before{ content:'▾ '; }
.help-article > summary:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.help-summary{ font-size:12.5px; color:var(--text-mute); margin:2px 0 8px; }

/* Article prose, shared by the panel and the public knowledge base. */
.help-body{ font-size:13px; color:var(--text-soft); line-height:1.62; }
.help-body h3{ font-size:13.5px; color:var(--text); margin:14px 0 5px; }
.help-body h4{ font-size:12.5px; color:var(--text); margin:12px 0 4px; }
.help-body p{ margin:0 0 9px; }
.help-body ul, .help-body ol{ margin:0 0 10px; padding-left:20px; }
.help-body li{ margin-bottom:5px; }
.help-body code{
  background:var(--panel-alt); border:1px solid var(--border-soft); border-radius:5px;
  padding:1px 5px; font-family:'IBM Plex Mono',monospace; font-size:11.5px;
}
.help-body a{ color:#6FB6F0; text-decoration:underline; }
.help-body .help-note{
  border-left:2px solid var(--gold); background:var(--gold-soft); color:var(--gold);
  padding:8px 11px; border-radius:0 8px 8px 0; margin:10px 0; font-size:12.5px;
}
.help-foot{ font-size:12px; color:var(--text-mute); margin:16px 0 0; }
.help-foot a{ color:#6FB6F0; text-decoration:underline; }

@media (max-width: 1200px){
  /* Not enough width left to be worth squeezing the page into. */
  body.help-open .dash-main{ padding-right:0; }
}

@media (max-width: 860px){
  /* No room for the page and the panel at once, so the panel takes over
     and the page behind is dimmed and made inert by the script. */
  .help-panel{ width:100%; max-width:100%; }
  .help-backdrop.open{
    display:block; position:fixed; inset:0; z-index:205; background:rgba(0,0,0,0.5);
  }
  .help-btn span:not([aria-hidden]){ display:none; }
  .help-btn{ padding:7px 9px; }
}

/* ---------------------------------------------------------------------
   The public knowledge base at /help.php.

   Readable without an account on purpose — somebody locked out is the
   person who most needs the article about getting in — so it stands on
   its own rather than inside the app shell.
   ------------------------------------------------------------------- */
.kb-shell{ max-width:780px; margin:0 auto; padding:26px 20px 60px; }
.kb-head{
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  padding-bottom:18px; border-bottom:1px solid var(--border-soft); margin-bottom:28px; flex-wrap:wrap;
}
.kb-brand{ display:inline-flex; align-items:center; gap:10px; color:var(--text); text-decoration:none; font-size:17px; }
.kb-top{ display:flex; gap:16px; }
.kb-top a{ color:var(--text-soft); text-decoration:none; font-size:13px; padding:8px 0; }
.kb-top a:hover{ color:var(--text); text-decoration:underline; }

.kb-intro h1{ font-size:30px; margin:0 0 6px; }
.kb-intro p{ color:var(--text-soft); font-size:14px; margin:0 0 18px; }
.kb-search{ display:flex; gap:8px; margin-bottom:30px; }
.kb-search input{ flex:1; }
.kb-search .btn{ width:auto; padding:10px 22px; }
.kb-result-count{ font-size:13px; color:var(--text-soft); margin:0 0 20px; }
.kb-result-count a{ color:#6FB6F0; text-decoration:underline; }
.kb-empty{ color:var(--text-mute); font-size:13.5px; padding:30px 0; }

.kb-category{ margin-bottom:30px; }
.kb-category h2{
  font-size:11.5px; text-transform:uppercase; letter-spacing:0.07em; color:var(--text-mute);
  margin:0 0 10px; font-weight:600;
}
.kb-item{
  display:block; padding:13px 15px; margin-bottom:8px; text-decoration:none;
  background:var(--panel); border:1px solid var(--border-soft); border-radius:10px;
}
.kb-item:hover{ border-color:var(--gold); }
.kb-item:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.kb-item-title{ display:block; color:var(--text); font-size:14px; font-weight:500; }
.kb-item-sub{ display:block; color:var(--text-mute); font-size:12.5px; margin-top:3px; }

.kb-crumb{ font-size:12px; color:var(--text-mute); margin:0 0 8px; }
.kb-crumb a{ color:#6FB6F0; text-decoration:underline; }
.kb-article h1{ font-size:27px; margin:0 0 8px; }
.kb-summary{ color:var(--text-soft); font-size:14.5px; margin:0 0 22px; }
/* The article body is a little larger here than in the side panel: this
   is a page somebody reads, not a reference they glance at. */
.kb-article .help-body{ font-size:14px; }
.kb-article .help-body h3{ font-size:16px; margin:22px 0 7px; }
.kb-article .help-body h4{ font-size:14px; margin:16px 0 5px; }
.kb-article-foot{
  display:flex; justify-content:space-between; gap:14px; flex-wrap:wrap;
  margin-top:34px; padding-top:16px; border-top:1px solid var(--border-soft);
  font-size:13px; color:var(--text-mute);
}
.kb-article-foot a{ color:#6FB6F0; text-decoration:underline; }
.kb-foot{
  margin-top:44px; padding-top:16px; border-top:1px solid var(--border-soft);
  font-size:12px; color:var(--text-mute);
}
.kb-foot a{ color:#6FB6F0; text-decoration:underline; }

/* The page-tagging grid on the knowledge base editor — 27 checkboxes
   need to be scannable in columns, not a list you scroll past. */
.help-pagegrid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(165px, 1fr)); gap:2px 14px;
  max-height:260px; overflow-y:auto; padding:10px 12px;
  background:var(--panel-alt); border:1px solid var(--border-control); border-radius:9px;
}
.help-pagegrid label{
  display:flex; align-items:center; gap:8px; margin:0; padding:5px 0;
  font-size:12.5px; color:var(--text-soft); cursor:pointer; min-height:32px;
}
/* Size is deliberately left to the shared rule, which grows checkboxes
   to 24px on a phone. Pinning them at 16px here overrode that and put
   them under the minimum touch size — the audit caught it. */
.help-pagegrid input{ flex-shrink:0; margin:0; }
.field-label-standalone{
  display:block; font-size:12px; color:var(--text-soft); margin-bottom:6px; font-weight:500;
}
