@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; }
/* The browser's own [hidden] rule is display:none at the lowest possible
   specificity, so any class that sets display — .btn-chip, .btn, a flex
   row — silently beats it and the element stays on screen. Every
   hidden="" in this app depends on this line. */
[hidden]{ display:none !important; }
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; }
/* The logo, painted over the mark. If the image cannot be loaded the
   square shows through, so the corner is never simply empty. A wide
   wordmark still shows at its own width: the square is a minimum, not
   a cage. */
.auth-mark-logo{ display:inline-block; width:auto; min-width:28px; height:28px; overflow:hidden; }
.auth-mark-logo img{ display:block; height:100%; width:auto; max-width:150px; border-radius:8px; }
.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; }
img.avatar, img.gear-avatar, img.presence-avatar{ object-fit:cover; display:block; }
.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 ----------------------------------------------
   Four dropdowns rather than seventeen flat links. The flat bar wrapped
   onto a second row, and a menu you cannot take in at a glance has
   stopped being a menu. Each button is one job somebody does. */
.admin-nav{ display:flex; align-items:center; gap:2px; margin-left:16px; }
.admin-menu{ position:relative; }
.admin-menu-btn{
  display:inline-flex; align-items:center; gap:6px;
  font-family:inherit; font-size:12.5px; font-weight:500;
  padding:7px 10px 7px 12px; border-radius:8px; border:none;
  background:none; color:var(--text-soft); cursor:pointer; white-space:nowrap;
}
.admin-menu-btn:hover{ background:var(--panel); color:var(--text); }
.admin-menu-btn.active{ background:var(--gold-soft); color:var(--gold); }
.admin-menu-btn:focus-visible{ outline:2px solid var(--gold); outline-offset:1px; }
/* The icons carry width and height attributes too — see admin_icons.php.
   These rules refine them; they are not what stops an unstyled SVG
   expanding to 300x150. */
.admin-menu-icon{ width:16px; height:16px; flex-shrink:0; opacity:0.75; }
.admin-menu-btn.active .admin-menu-icon,
.admin-menu-item.active .admin-menu-icon{ opacity:1; }
.admin-menu-chevron{ width:14px; height:14px; opacity:0.5; flex-shrink:0; transition:transform .15s ease; }
.admin-menu.open .admin-menu-chevron{ transform:rotate(180deg); }
.admin-menu-text{ flex:1; }

/* Closed by default. Three things open it: the .open class app.js sets,
   or — only while app.js has not claimed the nav — hover and focus-within,
   so the admin stays navigable if the script fails to load. */
.admin-menu-drop{
  display:none; position:absolute; top:calc(100% + 6px); left:0; z-index:120;
  min-width:216px; padding:6px;
  background:var(--panel-alt); border:1px solid var(--border-soft);
  border-radius:12px; box-shadow:0 12px 32px rgba(0,0,0,0.35);
}
.admin-menu.open > .admin-menu-drop{ display:block; }
.admin-nav:not(.js-menus) .admin-menu:hover > .admin-menu-drop,
.admin-nav:not(.js-menus) .admin-menu:focus-within > .admin-menu-drop{ display:block; }

.admin-menu-item{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:8px 10px; border-radius:8px;
  font-size:13px; text-decoration:none; color:var(--text-soft);
}
.admin-menu-item:hover{ background:var(--panel); color:var(--text); }
.admin-menu-item.active{ background:var(--gold-soft); color:var(--gold); }
.admin-menu-item:focus-visible{ outline:2px solid var(--gold); outline-offset:-2px; }
.admin-nav-badge{
  background:var(--coral); color:#1a0d0d; font-size:10px; font-weight:700;
  border-radius:9px; padding:1px 6px; line-height:1.5;
}
/* The working area.
 *
 * This was a flat 1000px, left-aligned, which on a wide monitor left half
 * the window empty — most visibly on the inbox, where a 300px list and a
 * message pane were crammed into two thirds of the screen with nothing
 * beside them.
 *
 * Wider, but not edge to edge: prose past roughly 100 characters a line
 * is harder to read, so text-heavy pages keep their own narrower cap
 * (set inline, per page), and everything else gets the room. */
.dash-content{ padding:26px; max-width:1500px; }

/* For layouts that genuinely want the whole window — an inbox, a table of
 * records, a board. Nothing in these is prose. */
.dash-content.dash-wide{ max-width:none; }
.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){
  /* !important because several pages set their own desktop columns as an
     inline style — "minmax(260px, 340px) 1fr" is fine on a monitor and is
     94px wider than an iPhone. An inline style beats a stylesheet, so on a
     phone this has to say so outright. */
  .dash-cols{ grid-template-columns:1fr !important; }
  .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-menu-btn{ min-height:44px; }
  .admin-menu-item{ min-height:44px; }
  /* Four buttons plus a logout outrun a phone, so the bar wraps to two
     rows of two. Scrolling it sideways would have been tidier but
     overflow-x:auto forces overflow-y to compute as auto too, which
     clips the dropdown — wrapping keeps the menus visible. */
  .admin-nav{ margin-left:8px; flex-wrap:wrap; }
  /* Right-hand menus open leftwards so they don't run off the screen. */
  .admin-menu:nth-child(even) > .admin-menu-drop{ left:auto; right:0; }
  .admin-menu-drop{ min-width:200px; max-width:min(280px, 84vw); }
  .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)); }
  /* The bell sits in the middle of the bar on a phone, so a panel hung
     off its right edge ran off the left of the screen with half of every
     line cut away. On a phone it hangs off the bar itself instead, edge
     to edge. */
  .dash-top{ position:relative; }
  /* Two selectors, because the base rules are declared later in this
     file and would otherwise win the tie. */
  .dash-top .bell-menu{ position:static; }
  .dash-top .bell-dropdown{ left:12px; right:12px; width:auto; max-width:none; top:calc(100% + 6px); }
}

.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'; }

/* min-width:0 on a flex item is what lets it be narrower than its own
   content. Without it one long unbroken string — a pasted URL in a task
   title, a reference number, an email address with no spaces — makes the
   row as wide as the string, which makes the panel that wide, which makes
   the page that wide, and the whole dashboard scrolls sideways on a phone
   because of one task. overflow-wrap:anywhere then breaks the string
   rather than the layout. */
.row{ display:flex; align-items:center; gap:10px; padding:9px 0; border-top:1px solid var(--border-soft); min-width:0; }
.row > *{ min-width:0; }
.row-title, .row-sub{ overflow-wrap:anywhere; }
.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);
}
/* Person or program: the verdict beside the name, with its reason on
   hover. A row judged a bot is greyed rather than hidden when shown. */
.visitor-verdict{ font-weight:500; cursor:help; }
.visitor-verdict.tone-moss{ background:var(--moss-soft); color:var(--moss); }
.visitor-verdict.tone-coral{ background:var(--coral-soft); color:var(--coral); }
.visitor-verdict.tone-mute{ background:rgba(255,255,255,.06); color:var(--text-mute); }
.visitor-row.is-bot{ opacity:.55; }
/* 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; }
}

/* --- Who's here ------------------------------------------------------
   A strip rather than a fifth headline card: this is not a number you
   compare against last month, it is a glance at who is around right now.
   Same icon disc as the cards above so it reads as part of them, in moss
   rather than gold because it is a live state and not a total. */
.presence-strip{
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  background:var(--panel); border:1px solid var(--border-soft); border-radius:14px;
  padding:14px 16px; margin-bottom:18px;
}
.presence-strip .kpi-icon{
  background:color-mix(in srgb, var(--moss) 18%, var(--panel-alt));
  color:var(--moss);
}
.presence-copy{ display:flex; flex-direction:column; gap:2px; min-width:0; }
.presence-title{ font-size:14px; font-weight:600; display:flex; align-items:center; gap:8px; }
.presence-sub{ font-size:12px; color:var(--text-soft); }
.presence-people{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-left:auto; }
.presence-person{
  display:flex; align-items:center; gap:7px;
  background:var(--panel-alt); border:1px solid var(--border-soft);
  border-radius:999px; padding:4px 12px 4px 4px;
  font-size:12.5px; white-space:nowrap;
}
.presence-person.is-you{ border-color:color-mix(in srgb, var(--moss) 45%, transparent); }
.presence-avatar{
  width:26px; height:26px; border-radius:50%; flex-shrink:0;
  display:flex; align-items:center; justify-content:center;
  font-size:10.5px; font-weight:600; letter-spacing:.02em;
  background:color-mix(in srgb, var(--moss) 22%, var(--panel));
  color:var(--moss);
}
.presence-you{ color:var(--text-mute); }
@media (max-width: 720px){
  .presence-people{ margin-left:0; width:100%; }
}

/* --- The support ticket link, in the help panel ----------------------
   Set apart from the articles above it, because it is the thing to do
   when none of them helped. */
.help-ticket{
  margin:14px 0 4px; padding:12px;
  background:var(--panel-alt); border:1px solid var(--border-soft); border-radius:10px;
}
.help-ticket-note{ font-size:11.5px; color:var(--text-mute); margin-top:8px; line-height:1.45; }
.help-ticket-note strong{ color:var(--text-soft); }

/* --- Mail tabs -------------------------------------------------------
   Above the conversation list: Primary, Promotions, Updates, Social.
   An underline rather than pills, because these are one list seen four
   ways and not four places to go. */
.mail-tabs{
  display:flex; gap:2px; align-items:stretch; flex-wrap:wrap;
  border-bottom:1px solid var(--border-soft); margin:0 2px 6px; padding:0 4px;
}
.mail-tab{
  display:inline-flex; align-items:center; gap:6px;
  padding:8px 10px; font-size:12px; text-decoration:none;
  color:var(--text-mute); border-bottom:2px solid transparent;
  margin-bottom:-1px; white-space:nowrap;
}
.mail-tab:hover{ color:var(--text-soft); }
.mail-tab.is-on{ color:var(--text); border-bottom-color:var(--gold); font-weight:600; }
.mail-tab:focus-visible{ outline:2px solid var(--focus); outline-offset:-2px; border-radius:4px; }
.mail-tab-n{
  font-size:10.5px; color:var(--text-mute);
  background:var(--panel-alt); border-radius:999px; padding:1px 6px;
}
.mail-tab.is-on .mail-tab-n{ color:var(--text-soft); }

/* --- 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;
    /* overflow-x:auto alone is not enough here. A grid or flex item is
       sized by its own content unless it is told it may be smaller, so
       past a certain number of stages the board grew wider than the
       screen and took the whole page with it — a sideways scrollbar on
       the phone instead of inside the board. It only appears once a
       workspace has enough stages to overflow, which is how it survived
       this long. */
    min-width:0;
    max-width:100%;
  }
  .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 team scorecard.

   Eleven numbers per person, and the whole point of the page is reading
   them side by side. It used to sit in a scrolling box, which meant the
   comparison a manager came for was the half they had to drag into view.

   Two things fix that. The columns nobody has a figure for are dropped
   server-side, and what is left is packed tighter and grouped under the
   channel it belongs to, so the eye finds "the email ones" as a block
   rather than reading eleven headings.

   Below the width where even that would scroll, the table is replaced by
   one card per person. Not a table pretending to be cards: the same
   figures, laid out the way a narrow screen can actually show them.
   ------------------------------------------------------------------- */
.scorecard{ table-layout:auto; font-size:12.5px; }
.scorecard th, .scorecard td{ padding:8px 9px; }
/* Numbers line up on their digits, so a column compares at a glance. */
.scorecard .num{ font-variant-numeric:tabular-nums; font-size:12.5px; }
.scorecard thead th{ font-size:10px; letter-spacing:.04em; }
/* The person's name holds the row together, so it gets the room. */
.scorecard tbody th{ white-space:nowrap; padding-right:14px; }

/* The channel headings above the metric names. */
.scorecard-groups th{
  padding-bottom:2px; text-align:center; color:var(--text-soft);
  font-size:10px; letter-spacing:.08em;
}
.scorecard-groups th:not(:first-child){
  border-left:1px solid var(--border-soft); border-bottom:1px solid var(--border-soft);
}
.scorecard thead tr:last-child th{ border-top:none; padding-top:6px; }

.scorecard-cards{ display:none; }
.scorecard-card{
  border:1px solid var(--border-soft); border-radius:10px;
  padding:12px 14px; margin-bottom:10px; background:var(--panel-alt);
}
.scorecard-person{
  display:block; font-weight:600; color:var(--text);
  font-size:14px; margin-bottom:10px; text-decoration:none;
}
.scorecard-group + .scorecard-group{
  margin-top:10px; padding-top:10px; border-top:1px solid var(--border-soft);
}
.scorecard-group-name{
  color:var(--text-mute); font-size:10px; text-transform:uppercase;
  letter-spacing:.08em; margin-bottom:6px;
}
.scorecard-metrics{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(88px, 1fr)); gap:10px 12px;
}
.scorecard-value{
  font-family:'IBM Plex Mono', monospace; font-variant-numeric:tabular-nums;
  font-size:16px; color:var(--text); line-height:1.2;
}
.scorecard-label{ color:var(--text-mute); font-size:10.5px; margin-top:2px; }

/* The switch. A little before the table would actually overflow, so
   nobody meets the scrollbar on the way to the cards. */
@media (max-width: 1180px){
  .scorecard{ display:none; }
  .scorecard-cards{ display:block; }
}

/* 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; }
/* The "?" mark. This used to be a filled circle — background:currentColor
   with the glyph in the panel colour — but currentColor there is the
   span's own colour, which is the panel colour, so the whole thing
   rendered as a dark blob with an invisible question mark, and in some
   browsers stretched into an oval. A ring in the button's own text
   colour follows hover and open states without any of that. */
.help-btn span[aria-hidden]{
  display:inline-flex; align-items:center; justify-content:center; flex:none;
  width:16px; height:16px; border-radius:50%; box-sizing:border-box;
  border:1.5px solid currentColor; background:transparent; color:inherit;
  font-size:10.5px; font-weight:700; line-height:1;
}

/* --- The phone button in the top bar --------------------------------
   Same footprint as the gear beside it. The dot is the only thing that
   moves: it says a call is up in the window, which may be behind the
   browser somewhere. */
.call-btn{
  position:relative;
  display:inline-flex; align-items:center; justify-content:center;
  width:34px; height:34px; padding:0; margin-right:8px;
  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;
}
.call-btn svg{ width:17px; height:17px; display:block; }
.call-btn:hover{ color:var(--text); border-color:var(--gold); }
.call-btn:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.call-btn.is-live{ color:var(--moss); border-color:var(--moss); background:var(--moss-soft); }
.call-btn-dot{
  position:absolute; top:-3px; right:-3px;
  width:9px; height:9px; border-radius:50%;
  background:var(--moss); border:2px solid var(--ink);
  animation:call-pulse 1.6s ease-in-out infinite;
}
.call-btn-dot[hidden]{ display:none; }
@keyframes call-pulse{ 0%,100%{ opacity:1; } 50%{ opacity:.35; } }
@media (prefers-reduced-motion: reduce){ .call-btn-dot{ animation:none; } }

.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;
}

/* --- Single sign-on buttons on the login screen ----------------------
   Sat above the password form: for anyone whose workspace requires SSO
   this is the only door, and a door below a form you cannot fill in is
   a door people miss. */
.sso-buttons{ display:flex; flex-direction:column; gap:9px; margin-bottom:18px; }
.sso-form{ margin:0; }
.btn-sso{
  display:flex; align-items:center; justify-content:center; gap:10px;
  width:100%; min-height:44px; padding:11px 14px;
  font-family:inherit; font-size:14px; font-weight:500;
  background:var(--panel-alt); color:var(--text);
  border:1px solid var(--border); border-radius:10px; cursor:pointer;
}
.btn-sso:hover{ background:var(--panel); border-color:var(--border-strong, var(--border)); }
.btn-sso:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.sso-mark{ width:18px; height:18px; flex-shrink:0; }

.sso-divider{
  display:flex; align-items:center; gap:12px;
  margin:0 0 18px; font-size:12px; color:var(--text-mute);
}
.sso-divider::before, .sso-divider::after{
  content:""; flex:1; height:1px; background:var(--border-soft);
}

/* The address the provider vouched for, on the last step of an SSO
   signup. Shown rather than put in an input, because it is not something
   the person may change here — the workspace is created from it. */
.sso-identity{
  display:flex; align-items:center; gap:12px;
  padding:12px 14px; margin:0 0 18px;
  background:var(--panel-alt); border:1px solid var(--border); border-radius:10px;
}
.sso-identity-email{ font-size:14px; font-weight:500; word-break:break-all; }
.sso-identity-note{ font-size:12px; color:var(--text-mute); margin-top:2px; }

/* --- Custom field values on a record page ---------------------------
   A definition list, because that is what it is: a label and the thing
   it labels. Kept visually identical to the built-in fields around it so
   a custom field never looks bolted on. */
.cf-list{ display:flex; flex-direction:column; gap:10px; margin:0; }
.cf-row{ display:grid; grid-template-columns:150px 1fr; gap:14px; align-items:baseline; }
.cf-row dt{ font-size:12px; color:var(--text-soft); font-weight:500; }
.cf-row dd{ margin:0; font-size:13.5px; color:var(--text); word-break:break-word; }
/* A section of custom fields: a small heading in the form and on the detail page. */
.cf-section{ font-size:11.5px; text-transform:uppercase; letter-spacing:.06em; color:var(--text-mute); margin:18px 0 8px; padding-top:12px; border-top:1px solid var(--border-soft); }
.cf-section-head{ font-size:11.5px; text-transform:uppercase; letter-spacing:.06em; color:var(--text-mute); margin-top:6px; padding-top:8px; border-top:1px solid var(--border-soft); }
.cf-section-head:first-child{ margin-top:0; padding-top:0; border-top:0; }
@media (max-width:600px){
  .cf-row{ grid-template-columns:1fr; gap:2px; }
}

/* --- Import progress -------------------------------------------------
   Deliberately text, not a bar. A percentage would be a lie until the
   whole extract has been counted, and a migration is exactly the moment
   somebody needs to trust what they are being told. */
.import-progress{
  display:flex; flex-direction:column; gap:8px;
  padding:16px; border:1px solid var(--border-soft); border-radius:10px;
  background:var(--panel-alt);
}
.import-status{ font-size:14px; color:var(--text); }
.import-counts{ font-size:12px; color:var(--text-soft); white-space:pre-wrap; }

/* --- Audio setup, on the profile page --------------------------------
   A status block rather than a card: it reports one thing, and the
   colour of the dot is the report. Three states — unknown, ready and
   blocked — each with a matching border so it reads at a glance without
   relying on the dot's colour alone. */
.audio-setup{
  border:1px solid var(--border-control); border-radius:10px;
  padding:14px; margin-bottom:16px; background:var(--panel-alt);
}
.audio-setup[data-state="ready"]{ border-color:var(--moss); background:var(--moss-soft); }
.audio-setup[data-state="blocked"]{ border-color:var(--coral); background:var(--coral-soft); }

.audio-setup-head{ display:flex; align-items:center; gap:9px; font-size:13.5px; color:var(--text); }
.audio-dot{
  width:9px; height:9px; border-radius:50%; flex-shrink:0;
  background:var(--text-mute); box-shadow:0 0 0 3px rgba(157,178,204,0.15);
}
.audio-setup[data-state="ready"] .audio-dot{ background:var(--moss); box-shadow:0 0 0 3px var(--moss-soft); }
.audio-setup[data-state="blocked"] .audio-dot{ background:var(--coral); box-shadow:0 0 0 3px var(--coral-soft); }

.audio-setup-detail{
  font-size:12px; color:var(--text-soft); line-height:1.55; margin:8px 0 0;
}
.audio-setup-detail strong{ color:var(--text); }

.audio-setup-actions{ display:flex; gap:8px; flex-wrap:wrap; margin-top:12px; }

/* The live input level. Deliberately not animated with a transition —
   a meter that lags is a meter that lies about whether you are audible. */
.audio-meter{
  height:6px; border-radius:3px; background:var(--ink);
  overflow:hidden; margin-top:12px;
}
.audio-meter > span{
  display:block; height:100%; width:0%;
  background:linear-gradient(90deg, var(--moss), var(--gold));
}
@media (prefers-reduced-motion: reduce){
  .audio-meter > span{ transition:none; }
}

/* --- "Remember this browser", on the 2FA screen ----------------------
   The caveat sits under the label rather than in a tooltip, because the
   thing somebody needs to know before ticking it — that the password is
   still required, and that this should not be a shared machine — is the
   whole basis on which they should decide. */
.remember-device{
  display:flex; align-items:flex-start; gap:10px;
  margin:0 0 14px; padding:11px 12px;
  border:1px solid var(--border-soft); border-radius:9px;
  cursor:pointer; text-align:left;
}
.remember-device:hover{ border-color:var(--border-control); }
.remember-device input{ margin-top:2px; }
.remember-device-title{ display:block; font-size:13px; color:var(--text); }
.remember-device-note{ display:block; font-size:11.5px; color:var(--text-mute); margin-top:3px; line-height:1.5; }

/* =====================================================================
   The calling window (softphone.php)
   =====================================================================
   Its own window, roughly 400px wide, so everything is one column and
   nothing depends on the CRM shell being around it. Sizes are a little
   larger than the app's: this is used while holding a phone conversation,
   and a mis-tapped Mute during a call is worse than a wide button. */

.sp-body{ margin:0; background:var(--ink); color:var(--text); }
.sp{ display:flex; flex-direction:column; gap:14px; padding:14px 14px 20px; min-height:100vh; box-sizing:border-box; }

.sp-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:10px; }
.sp-title{ font-size:17px; line-height:1.2; }
.sp-from{ font-size:12px; color:var(--text-mute); margin-top:2px; }
.sp-badges{ display:flex; flex-direction:column; align-items:flex-end; gap:5px; }
.sp-chip{
  font-size:10.5px; text-transform:uppercase; letter-spacing:.04em;
  padding:3px 7px; border-radius:999px; border:1px solid var(--border-control); color:var(--text-mute);
}
.sp-chip.is-browser{ color:var(--gold); border-color:var(--gold); background:var(--gold-soft); }
.sp-chip.is-phone{ color:var(--text-soft); }
.sp-chip.is-rec{ color:var(--coral); border-color:var(--coral); background:var(--coral-soft); }

.sp-note{
  font-size:12px; line-height:1.55; color:var(--text-soft);
  padding:9px 11px; border:1px solid var(--border-soft); border-radius:9px; background:var(--panel-alt);
}
.sp-note a{ color:var(--gold); }

.sp-empty{ padding:24px 4px; text-align:center; color:var(--text-soft); font-size:13.5px; line-height:1.6; }

/* ---- The call itself ---- */
.sp-live{
  padding:14px; border-radius:12px;
  background:var(--panel); border:1px solid var(--border-control);
}
.sp-live.is-ringing{ border-color:var(--gold); }
.sp-live.is-live{ border-color:var(--moss); }
.sp-live-name{ font-size:16px; font-weight:600; word-break:break-word; }
.sp-live-number{ font-size:12px; color:var(--text-mute); margin-top:2px; }
.sp-live-meta{ display:flex; align-items:baseline; justify-content:space-between; gap:8px; margin-top:8px; }
.sp-live-status{ font-size:12.5px; color:var(--text-soft); }
.sp-live-timer{ font-size:15px; color:var(--text); }
.sp-live-actions{ display:flex; flex-wrap:wrap; gap:8px; margin-top:12px; }

.sp-btn{
  flex:1 1 auto; min-height:40px; padding:9px 14px;
  font-family:inherit; font-size:13.5px; font-weight:600;
  background:var(--panel-alt); color:var(--text);
  border:1px solid var(--border-control); border-radius:10px; cursor:pointer;
}
.sp-btn:hover{ border-color:var(--gold); }
.sp-btn:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.sp-btn[hidden]{ display:none !important; }
.sp-btn[aria-pressed="true"]{ background:var(--gold-soft); border-color:var(--gold); color:var(--gold); }
.sp-answer{ background:var(--moss-soft); border-color:var(--moss); color:var(--moss); }
.sp-end{ background:var(--coral-soft); border-color:var(--coral); color:var(--coral); }
.sp-go{ flex:0 0 auto; background:var(--gold-btn-bg); border-color:var(--gold-btn-bg); color:#fff; }
.sp-go:hover{ filter:brightness(1.08); }
.sp-save{ background:var(--gold-btn-bg); border-color:var(--gold-btn-bg); color:#fff; }

/* ---- Keypads. The dial pad and the tone pad are the same object in
   two places, so they are one class. ---- */
.sp-pad{ display:grid; grid-template-columns:repeat(3, 1fr); gap:7px; margin-top:12px; }
.sp-pad[hidden]{ display:none !important; }
.sp-key{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px;
  min-height:46px; padding:4px;
  background:var(--panel-alt); color:var(--text);
  border:1px solid var(--border-soft); border-radius:10px; cursor:pointer;
  font-family:inherit; font-size:17px; line-height:1;
}
.sp-key:hover{ border-color:var(--border-control); }
.sp-key:active{ background:var(--gold-soft); }
.sp-key:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.sp-key-num{ font-size:17px; }
.sp-key-sub{ font-size:8.5px; letter-spacing:.14em; color:var(--text-mute); }
.sp-pad-dtmf .sp-key{ min-height:38px; font-size:15px; }

/* ---- Dialling ---- */
.sp-label{ display:block; font-size:11px; text-transform:uppercase; letter-spacing:.05em; color:var(--text-mute); margin-bottom:5px; }
.sp-q-row{ display:flex; gap:7px; }
.sp-q-row input{
  flex:1 1 auto; min-width:0; min-height:40px; padding:9px 11px;
  font-family:inherit; font-size:14px;
  background:var(--panel-alt); color:var(--text);
  border:1px solid var(--border-control); border-radius:10px;
}
.sp-q-row input:focus{ outline:2px solid var(--gold); outline-offset:1px; }
.sp-hint{ font-size:11px; color:var(--text-mute); margin-top:5px; }

.sp-results{ display:flex; flex-direction:column; gap:4px; margin-top:8px; }
.sp-results[hidden]{ display:none !important; }
.sp-result{
  display:flex; flex-direction:column; align-items:flex-start; gap:1px;
  width:100%; padding:8px 10px; text-align:left;
  background:var(--panel); color:var(--text);
  border:1px solid var(--border-soft); border-radius:9px; cursor:pointer; font-family:inherit;
}
.sp-result:hover{ border-color:var(--gold); }
.sp-result:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.sp-result-name{ font-size:13px; }
.sp-result-number{ font-size:11.5px; color:var(--text-mute); }

/* ---- Wrap-up ---- */
.sp-wrap{
  padding:13px; border-radius:12px;
  background:var(--panel); border:1px solid var(--gold);
}
.sp-wrap[hidden]{ display:none !important; }
.sp-wrap-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:10px; font-size:13.5px; }
.sp-link{ background:none; border:0; padding:0; color:var(--text-mute); font-family:inherit; font-size:12px; cursor:pointer; text-decoration:underline; }
.sp-link:hover{ color:var(--text); }
.sp-outcomes{ display:flex; flex-wrap:wrap; gap:6px; margin-bottom:10px; }
.sp-outcome{
  padding:6px 10px; font-family:inherit; font-size:12px;
  background:var(--panel-alt); color:var(--text-soft);
  border:1px solid var(--border-soft); border-radius:999px; cursor:pointer;
}
.sp-outcome:hover{ border-color:var(--border-control); color:var(--text); }
.sp-outcome.is-on{ background:var(--gold-soft); border-color:var(--gold); color:var(--gold); }
.sp-outcome:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.sp-wrap textarea{
  width:100%; box-sizing:border-box; padding:9px 11px; margin-bottom:10px;
  font-family:inherit; font-size:13px; line-height:1.5; resize:vertical;
  background:var(--panel-alt); color:var(--text);
  border:1px solid var(--border-control); border-radius:9px;
}
.sp-check{ display:flex; align-items:center; gap:7px; font-size:12.5px; color:var(--text-soft); margin-bottom:11px; }
.sp-check select{
  font-family:inherit; font-size:12.5px; padding:4px 6px;
  background:var(--panel-alt); color:var(--text);
  border:1px solid var(--border-control); border-radius:7px;
}

/* ---- Recent ---- */
.sp-recent-head{
  display:flex; align-items:baseline; justify-content:space-between;
  font-size:11px; text-transform:uppercase; letter-spacing:.05em; color:var(--text-mute);
  margin-bottom:6px;
}
.sp-recent-head a{ color:var(--gold); text-transform:none; letter-spacing:0; font-size:11.5px; }
.sp-recent-list{ display:flex; flex-direction:column; gap:2px; }
.sp-recent-empty{ font-size:12.5px; color:var(--text-mute); padding:6px 2px; }
.sp-recent-row{
  display:flex; align-items:center; gap:9px;
  width:100%; padding:7px 8px; text-align:left;
  background:none; color:var(--text); border:1px solid transparent; border-radius:8px;
  cursor:pointer; font-family:inherit; font-size:13px;
}
.sp-recent-row:hover{ background:var(--panel); border-color:var(--border-soft); }
.sp-recent-row:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.sp-recent-dir{ color:var(--text-mute); font-size:13px; flex:0 0 auto; }
.sp-recent-row.is-missed .sp-recent-dir{ color:var(--coral); }
.sp-recent-who{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.sp-recent-when{ flex:0 0 auto; font-size:11px; color:var(--text-mute); }

.sp-foot{ min-height:16px; font-size:12px; line-height:1.5; color:var(--text-soft); }
.sp-foot.is-error{ color:var(--coral); }
.sp-foot.is-warn{ color:var(--gold); }
.sp-foot.is-ok{ color:var(--moss); }

/* --- The notification bell -------------------------------------------
   Next to the name, where somebody looks when they wonder whether
   anything happened while they were on another screen. The count is
   rendered by the server, so it is right the moment the page paints. */
.bell-menu{ position:relative; margin-right:8px; }
.bell-btn{
  position:relative;
  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;
}
.bell-btn:hover{ color:var(--text); border-color:var(--gold); }
.bell-btn:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.bell-btn[aria-expanded="true"]{ color:var(--gold); background:var(--gold-soft); border-color:var(--gold); }
.bell-count{
  position:absolute; top:-6px; right:-6px;
  min-width:17px; height:17px; padding:0 4px; box-sizing:border-box;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--coral); color:#fff; border:2px solid var(--ink);
  border-radius:999px; font-size:10px; font-weight:700; line-height:1;
}
.bell-count[hidden]{ display:none !important; }

.bell-dropdown{
  position:absolute; top:calc(100% + 8px); right:0; z-index:300;
  width:330px; max-width:calc(100vw - 24px);
  background:var(--panel); border:1px solid var(--border); border-radius:12px;
  box-shadow:0 14px 34px rgba(0,0,0,0.45); overflow:hidden;
}
.bell-dropdown[hidden]{ display:none !important; }
.bell-head{
  display:flex; align-items:center; justify-content:space-between;
  padding:10px 12px; border-bottom:1px solid var(--border-soft);
  font-size:12px; text-transform:uppercase; letter-spacing:.05em; color:var(--text-mute);
}
.bell-readall{
  background:none; border:0; padding:0; cursor:pointer; font-family:inherit;
  font-size:11.5px; color:var(--gold); text-transform:none; letter-spacing:0;
}
.bell-readall:hover{ text-decoration:underline; }
.bell-list{ max-height:min(60vh, 420px); overflow-y:auto; }
.bell-empty{ padding:18px 12px; text-align:center; font-size:12.5px; color:var(--text-mute); }
.bell-item{
  display:flex; align-items:flex-start; gap:9px;
  padding:10px 12px; border-bottom:1px solid var(--border-soft);
  color:var(--text); text-decoration:none;
}
.bell-item:last-child{ border-bottom:0; }
.bell-item:hover{ background:var(--panel-alt); }
.bell-item.is-unread{ background:var(--gold-soft); }
.bell-item.is-unread:hover{ background:var(--gold-soft); filter:brightness(1.15); }
.bell-icon{ flex:0 0 auto; width:18px; text-align:center; font-size:13px; color:var(--text-mute); }
.bell-text{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:2px; }
.bell-title{ font-size:13px; line-height:1.35; }
.bell-body{
  font-size:11.5px; color:var(--text-mute); line-height:1.45;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.bell-when{ flex:0 0 auto; font-size:10.5px; color:var(--text-mute); padding-top:2px; }

/* --- Audio setup, inside the calling window --------------------------
   The microphone prompt belongs where the call happens. This panel is
   the first thing in the window until it is satisfied, and collapses to
   a single green line once it is. */
.sp-audio{
  padding:12px; border-radius:12px;
  background:var(--panel); border:1px solid var(--border-control);
}
.sp-audio.is-ready{ border-color:var(--moss); background:var(--moss-soft); }
.sp-audio.is-blocked{ border-color:var(--coral); background:var(--coral-soft); }
.sp-audio-head{ display:flex; align-items:center; gap:8px; }
.sp-audio-head strong{ font-size:13.5px; font-weight:600; flex:1 1 auto; }
.sp-audio-dot{
  width:9px; height:9px; border-radius:50%; flex:0 0 auto;
  background:var(--text-mute);
}
.sp-audio.is-ready .sp-audio-dot{ background:var(--moss); }
.sp-audio.is-blocked .sp-audio-dot{ background:var(--coral); }
.sp-audio-detail{ font-size:11.5px; line-height:1.55; color:var(--text-soft); margin:6px 0 0; }
.sp-allow{ margin-top:10px; background:var(--gold-btn-bg); border-color:var(--gold-btn-bg); color:#fff; }
.sp-audio-pickers{ margin-top:12px; }
.sp-audio-pickers[hidden]{ display:none !important; }
.sp-audio-pickers select{
  width:100%; box-sizing:border-box; min-height:38px; padding:8px 10px; margin-bottom:8px;
  font-family:inherit; font-size:13px;
  background:var(--panel-alt); color:var(--text);
  border:1px solid var(--border-control); border-radius:9px;
}
.sp-audio-pickers select:focus{ outline:2px solid var(--gold); outline-offset:1px; }
.sp-meter{
  height:6px; margin:0 0 10px; border-radius:999px;
  background:var(--panel-alt); border:1px solid var(--border-soft); overflow:hidden;
}
.sp-meter > span{
  display:block; height:100%; width:0%;
  background:var(--moss); transition:width .1s linear;
}
.sp-test{ min-height:34px; padding:7px 12px; font-size:12.5px; flex:0 0 auto; }

/* ---------------------------------------------------------------------
   Legal pages — the privacy policy, terms and the rest.

   They share the knowledge base's reading shell; what they need on top of
   it is a contents list, a version line, and the two places a policy is
   referred to from a form: the signup tick-box and the small print under
   an auth card.
   ------------------------------------------------------------------ */
.legal-meta{
  font-size:12.5px; color:var(--text-mute); margin:-6px 0 20px;
}
.legal-toc{
  border:1px solid var(--border-soft); border-radius:12px;
  padding:14px 18px 6px; margin:0 0 26px; background:var(--panel-alt);
}
.legal-toc-label{
  display:block; font-size:11px; text-transform:uppercase; letter-spacing:.06em;
  color:var(--text-mute); margin-bottom:6px;
}
.legal-toc ol{ margin:0; padding-left:20px; font-size:13px; }
.legal-toc li{ padding:3px 0; }
.legal-toc a{ color:#6FB6F0; }
/* A policy is read in long runs rather than skimmed, so it gets more line
   height and more air around headings than a help article does. */
.legal-body{ font-size:13.5px; line-height:1.72; }
.legal-body h3{ font-size:15px; margin:28px 0 8px; scroll-margin-top:20px; }
.legal-body h4{ font-size:13.5px; margin:18px 0 6px; }
.legal-body li{ margin:3px 0; }

/* The signup tick-box. Bigger than the browser default because it is the
   one control on the form that has to be pressed deliberately. */
.consent-check{
  display:flex; align-items:flex-start; gap:9px;
  font-size:12.5px; color:var(--text-soft); line-height:1.5;
  margin:2px 0 16px; cursor:pointer;
}
.consent-check input{ width:16px; height:16px; margin:1px 0 0; flex-shrink:0; cursor:pointer; }
.consent-check a{ color:#6FB6F0; text-decoration:underline; }

.legal-footlinks{
  margin-top:18px; padding-top:12px; border-top:1px solid var(--border-soft);
  display:flex; flex-wrap:wrap; gap:4px 14px; justify-content:center;
  font-size:11.5px;
}
.legal-footlinks a{ color:var(--text-mute); }
.legal-footlinks a:hover{ color:var(--text-soft); }

@media print{
  .kb-head, .kb-top, .kb-crumb, .kb-article-foot, .legal-toc{ display:none; }
  .legal-body{ color:#000; }
}

/* The line picker in the softphone header — only drawn when a workspace
   has more than one number, so a single-line workspace looks unchanged. */
.sp-fromline{ display:block; margin-top:2px; }
.sp-from-select{
  background:var(--panel-alt); border:1px solid var(--border-control); color:var(--text-soft);
  border-radius:7px; padding:3px 6px; font-size:12px; max-width:210px;
}
.sp-from-select:focus-visible{ outline:2px solid var(--gold); outline-offset:1px; }

/* ---------------------------------------------------------------------
   An email rendered in a conversation.

   Somebody else's HTML on our page, so everything here is about keeping
   it inside its own box: widths capped, tables scrolling in their own
   strip rather than stretching the thread, and colours forced back to
   something readable — a message designed for a white background is
   otherwise black text on a dark panel.
   ------------------------------------------------------------------ */
.email-html{
  font-size:13px; line-height:1.6; color:var(--text-soft);
  max-width:100%; overflow-x:auto; overflow-y:hidden;
}
.email-html *{ max-width:100% !important; box-sizing:border-box; }
/* Marketing email is built as fixed-width tables — typically 600px —
 * centred inside whatever window opens them. Dropped into this pane that
 * leaves a column of empty panel down one side, which is what somebody
 * sees and calls "empty space in the middle". The table structure is kept
 * (it is what holds the layout together); only the fixed width and the
 * centring are overridden, so the message fills the space it is given. */
.email-html table{
  width:100% !important; max-width:100% !important;
  margin-left:0 !important; margin-right:0 !important; float:none !important;
  table-layout:auto !important;
}
.email-html td, .email-html th{ width:auto !important; }
/* Images keep their aspect ratio when their width attribute is overridden. */
.email-html img{ height:auto !important; }
/* The sender's own colours cannot be trusted against this background. */
.email-html [style]{ background:transparent !important; }
.email-html, .email-html p, .email-html span, .email-html div,
.email-html td, .email-html th, .email-html li{ color:var(--text-soft) !important; }
.email-html h1, .email-html h2, .email-html h3,
.email-html h4, .email-html h5, .email-html h6{
  color:var(--text) !important; font-size:14.5px; margin:12px 0 6px; line-height:1.35;
}
.email-html p{ margin:0 0 9px; }
.email-html a{ color:#6FB6F0 !important; text-decoration:underline; word-break:break-word; }
.email-html img{ height:auto; border-radius:6px; }
.email-html table{ border-collapse:collapse; width:auto !important; max-width:100%; }
.email-html td, .email-html th{ padding:4px 6px; vertical-align:top; }
.email-html hr{ border:0; border-top:1px solid var(--border-soft); margin:12px 0; }
.email-html blockquote{
  margin:8px 0; padding:2px 0 2px 12px; border-left:2px solid var(--border-soft); color:var(--text-mute) !important;
}
.email-html pre{ white-space:pre-wrap; word-break:break-word; font-size:12px; }
.email-html ul, .email-html ol{ margin:0 0 9px; padding-left:20px; }
.email-html li{ margin:2px 0; }
/* Font tags from a 2004 template, neutralised. */
.email-html font{ color:inherit !important; font-size:inherit !important; }

.email-images-note{
  font-size:11.5px; color:var(--text-mute); background:var(--panel-alt);
  border:1px solid var(--border-soft); border-radius:8px;
  padding:6px 9px; margin:0 0 8px;
}
.email-images-note a{ color:#6FB6F0; text-decoration:underline; margin-left:4px; }

/* =====================================================================
 * On a phone, as an app
 *
 * The CRM has always worked on a phone in a browser. What this adds is
 * the difference between that and something a client can keep on their
 * home screen and answer a call from: the notch and home bar accounted
 * for, touch targets that survive a thumb on a building site, and — when
 * it is running as an installed app — a bottom bar for the four things
 * anybody opens it to do, because a hamburger at the top of a phone
 * screen is the hardest place on the device to reach.
 * ================================================================== */

/* The install offer. One line, dismissible, above everything. */
.install-bar{
  position:fixed; left:12px; right:12px; z-index:400;
  bottom:calc(12px + env(safe-area-inset-bottom, 0px));
  display:flex; align-items:center; gap:10px;
  background:var(--panel); border:1px solid var(--border-control);
  border-radius:12px; padding:10px 12px;
  box-shadow:0 12px 30px rgba(0,0,0,.35);
  font-size:13px; color:var(--text);
}
.install-bar-text{ flex:1; min-width:0; line-height:1.4; }
.install-bar-close{
  background:none; border:0; color:var(--text-mute);
  font-size:20px; line-height:1; cursor:pointer; padding:0 4px;
}
@media (min-width:861px){
  /* Nobody installs a CRM on a desktop from a banner. */
  .install-bar{ display:none; }
}

/* Safe areas: the iPhone's home bar sits on top of whatever is at the
 * bottom of the screen, and the notch over whatever is at the top. */
@supports (padding: max(0px)){
  .dash-content{
    padding-left:max(26px, env(safe-area-inset-left));
    padding-right:max(26px, env(safe-area-inset-right));
    padding-bottom:max(26px, env(safe-area-inset-bottom));
  }
  /* The bar keeps its own 16px above the buttons; the notch, when there
     is one, adds to that rather than replacing it. "max(0px, …)" here
     was replacing it: on every browser that understands max() the bar
     lost its top padding and the buttons sat against the browser chrome. */
  .dash-top{ padding-top:max(16px, env(safe-area-inset-top)); }
}

@media (max-width:860px){
  /* A thumb is about 9mm across. Anything smaller than 44px is a target
   * people miss, and missing "call" is worse than missing most things. */
  .btn, .btn-chip, .row-actions a, .row-actions button{ min-height:40px; }
  .dash-content{ padding:16px; }
  .panel{ padding:14px; }
  /* 16px or iOS zooms the whole page in when a field is focused, and
   * never quite zooms back out. */
  input, select, textarea{ font-size:16px; }
  table.table{ font-size:12.5px; }
}

/* Running as an installed app, on a phone. */
html[data-app="installed"] .dash-top-help,
html[data-app="installed"] .dash-top-settings{ display:none; }

@media (max-width:860px){
  html[data-app="installed"] body{ padding-bottom:64px; }

  /* The four things somebody opens a CRM on their phone to do. Built from
   * the existing sidebar links by app.js, so it can never list a page the
   * workspace does not have. */
  .app-tabbar{
    position:fixed; left:0; right:0; bottom:0; z-index:300;
    display:flex; justify-content:space-around; align-items:stretch;
    background:var(--panel); border-top:1px solid var(--border-soft);
    padding-bottom:env(safe-area-inset-bottom, 0px);
  }
  .app-tabbar a{
    flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center;
    gap:2px; padding:9px 4px 7px; font-size:10.5px; color:var(--text-mute); text-decoration:none;
    min-height:56px;
  }
  .app-tabbar a.active{ color:var(--gold); }
  .app-tabbar svg{ width:20px; height:20px; }
}
@media (min-width:861px){
  .app-tabbar{ display:none; }
}

/* ---------------------------------------------------------------------
   The emoji picker, and the "what will this text cost" note.

   The picker sits inside the field's own box rather than beside it, so
   adding one never reflows the form around it. Everything is drawn by the
   operating system's own emoji font — no sprite sheet, no web font, and
   nothing to go stale when a new Unicode release lands.
   ------------------------------------------------------------------- */
.emoji-wrap { position: relative; display: block; }
.emoji-wrap > input,
.emoji-wrap > textarea,
/* A rich editor is a contenteditable div rather than a textarea, and it
   gets the same room on the right so the toggle never sits on top of
   what somebody is writing. */
.emoji-wrap > [data-rte] { padding-right: 40px; }

.emoji-toggle {
  position: absolute; top: 6px; right: 8px;
  width: 28px; height: 28px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: 0; border-radius: 7px;
  font-size: 16px; line-height: 1; cursor: pointer; opacity: .6;
}
.emoji-toggle:hover, .emoji-toggle:focus-visible { opacity: 1; background: var(--panel-alt); }

.emoji-panel {
  position: absolute; right: 0; bottom: calc(100% + 6px); z-index: 40;
  width: 280px; max-height: 260px; overflow-y: auto;
  padding: 10px; border-radius: 12px;
  background: var(--panel); border: 1px solid var(--line);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .28);
}
.emoji-panel-title {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-mute); margin: 8px 0 5px;
}
.emoji-panel-title:first-child { margin-top: 0; }
.emoji-grid { display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px; }
.emoji-item {
  background: transparent; border: 0; border-radius: 6px; padding: 3px 0;
  font-size: 17px; line-height: 1.25; cursor: pointer;
}
.emoji-item:hover, .emoji-item:focus-visible { background: var(--panel-alt); }

.sms-count { font-size: 11.5px; color: var(--text-mute); margin-top: 5px; }
/* Amber, not red: two segments is a cost, not a mistake. */
.sms-count-warn { color: var(--amber, #C98A2E); }

@media (max-width: 560px) {
  .emoji-panel { width: min(280px, calc(100vw - 40px)); }
  .emoji-grid { grid-template-columns: repeat(8, 1fr); }
}

/* ---------------------------------------------------------------------
 * The rich-text editor (assets/editor.js)
 *
 * Sized and spaced like the app's other inputs, so a composer does not
 * look like a widget bolted onto the page. The editing area itself is
 * deliberately plain and light: it is showing an email, and an email is
 * black text on white wherever it is finally read, so previewing it on a
 * dark panel would be a lie about what the recipient sees.
 * ------------------------------------------------------------------ */

.rte {
  border: 1px solid var(--border-control);
  border-radius: 9px;
  background: var(--panel-alt);
  overflow: hidden;
}
.rte:focus-within { border-color: var(--accent, #2E93E0); }

.rte-bar {
  display: flex; align-items: center; gap: 2px; flex-wrap: wrap;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border-soft);
  background: var(--panel);
}

.rte-btn {
  background: transparent; border: 0; border-radius: 6px;
  color: var(--text-soft); cursor: pointer;
  min-width: 28px; height: 28px; padding: 0 6px;
  font-size: 13px; line-height: 1;
}
.rte-btn:hover, .rte-btn:focus-visible { background: var(--panel-alt); color: var(--text); }
.rte-btn b, .rte-btn i, .rte-btn u, .rte-btn s { font-size: 13px; }

.rte-sep {
  width: 1px; height: 18px; margin: 0 4px;
  background: var(--border-soft); display: inline-block;
}

.rte-select {
  background: var(--panel-alt); border: 1px solid var(--border-control);
  color: var(--text); border-radius: 6px;
  font-size: 12px; padding: 4px 6px; max-width: 120px;
}

/* A native colour input is a chunky control by default; this trims it to
   the size of the buttons beside it without hiding what it is. */
.rte-colour {
  width: 26px; height: 26px; padding: 0;
  border: 1px solid var(--border-control); border-radius: 6px;
  background: transparent; cursor: pointer;
}
.rte-colour::-webkit-color-swatch-wrapper { padding: 2px; }
.rte-colour::-webkit-color-swatch { border: 0; border-radius: 4px; }
.rte-colour::-moz-color-swatch { border: 0; border-radius: 4px; }

.rte-area {
  min-height: 160px; max-height: 460px; overflow-y: auto;
  padding: 12px 14px;
  background: #ffffff; color: #1b1725;
  font-family: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: 14px; line-height: 1.5;
  outline: none;
}
.rte-area:empty::before {
  content: attr(data-placeholder);
  color: #9a94a6;
}
.rte-area a { color: #1a56b8; }
.rte-area img { max-width: 100%; height: auto; }
.rte-area table { border-collapse: collapse; }
.rte-area td, .rte-area th { padding: 4px 8px; }
.rte-area hr { border: 0; border-top: 1px solid #e5e0ef; margin: 12px 0; }
.rte-area p { margin: 0 0 10px; }
.rte-area ul, .rte-area ol { margin: 0 0 10px; padding-left: 22px; }

.rte-note {
  font-size: 11.5px; color: var(--text-mute);
  padding: 6px 10px; border-top: 1px solid var(--border-soft);
  background: var(--panel);
}
.rte-note.is-error { color: var(--coral); }

/* The signature preview: a real email is white, so the preview is too. */
.sig-preview {
  background: #ffffff; color: #1b1725;
  border: 1px solid var(--border-soft); border-radius: 9px;
  padding: 14px; overflow-x: auto;
  font-family: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: 14px; line-height: 1.5;
}
.sig-preview img { max-width: 100%; height: auto; }
.sig-preview a { color: #1a56b8; }

@media (max-width: 560px) {
  .rte-bar { gap: 1px; padding: 5px 6px; }
  .rte-btn { min-width: 26px; height: 26px; padding: 0 4px; }
  .rte-select { max-width: 92px; }
  .rte-area { min-height: 140px; font-size: 13.5px; }
}

/* ---------------------------------------------------------------------
   The contact type-ahead.

   Replaces a dropdown that held 500 names and cut off silently at the
   five-hundredth. The list floats over the form rather than pushing it
   about, because a form that jumps as you type is worse than the problem
   being solved.
   ------------------------------------------------------------------- */
.contact-search{ position:relative; }
.contact-search-input{ width:100%; }
.contact-search-list{
  position:absolute; z-index:40; left:0; right:0; top:calc(100% + 4px);
  max-height:260px; overflow-y:auto;
  background:var(--panel); border:1px solid var(--border-control);
  border-radius:10px; box-shadow:0 8px 24px rgba(0,0,0,.35); padding:4px;
}
.contact-search-item{
  display:flex; flex-direction:column; gap:2px; width:100%; text-align:left;
  background:none; border:none; color:var(--text); cursor:pointer;
  padding:8px 10px; border-radius:7px; font-size:13px; font-family:inherit;
}
.contact-search-item:hover, .contact-search-item.is-active{ background:var(--panel-alt); }
.contact-search-name{ font-weight:500; }
.contact-search-detail{ font-size:11.5px; color:var(--text-mute); }
.contact-search-empty{ padding:10px; font-size:12.5px; color:var(--text-mute); }

/* ── Team Chat dock ──────────────────────────────────────────────────
   Chat in the corner of every page, so a colleague's message does not
   wait for somebody to navigate to it. Bottom left, away from the call
   launcher and the toasts, which both live on the right. */
#staff-dock { position: fixed; left: 16px; bottom: 16px; z-index: 60;
  font-size: 13px; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }

.dock-tab { display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  background: var(--panel); color: var(--text); border: 1px solid var(--border-control);
  border-radius: 999px; padding: 9px 14px; font-size: 12.5px; font-family: inherit;
  box-shadow: 0 6px 20px rgba(0,0,0,.28); }
.dock-tab:hover { border-color: var(--gold); }

.dock-badge { background: var(--coral); color: #fff; border-radius: 999px;
  padding: 1px 6px; font-size: 10.5px; font-weight: 600; line-height: 1.6; }

/* Closed by default: it must never cover the page somebody is working on
   until they ask for it. */
.dock-panel { display: none; width: 320px; max-width: calc(100vw - 32px);
  background: var(--panel); border: 1px solid var(--border-control); border-radius: 12px;
  box-shadow: 0 14px 40px rgba(0,0,0,.38); }
/* Not overflow:hidden — the emoji picker opens upward out of the compose
   row, and a clipped picker looks open while its buttons take no clicks.
   The list clips its own corners instead, since a hovered row has a
   background of its own. */
#staff-dock.is-open .dock-panel { display: block; }
#staff-dock.is-open .dock-tab { order: 2; }

.dock-head { display: flex; align-items: center; gap: 8px; padding: 10px 12px;
  border-bottom: 1px solid var(--border-soft); }
.dock-title { flex: 1; min-width: 0; font-size: 12.5px; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dock-head button, .dock-head a { background: none; border: 0; cursor: pointer;
  color: var(--text-mute); font-size: 14px; padding: 0 3px; text-decoration: none;
  font-family: inherit; line-height: 1; }
.dock-head button:hover, .dock-head a:hover { color: var(--text); }

/* The back arrow is only meaningful inside a conversation, and the list
   and the thread are never both on screen — 320px is not enough room to
   pretend otherwise. */
.dock-back { display: none; }
#staff-dock.in-thread .dock-back { display: inline; }
.dock-list { max-height: 300px; overflow: auto; border-radius: 0 0 11px 11px; }
.dock-thread { display: none; max-height: 300px; min-height: 160px; overflow: auto; padding: 10px 12px; }
#staff-dock.in-thread .dock-list { display: none; }
#staff-dock.in-thread .dock-thread { display: block; }

.dock-row { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: none; border: 0; border-top: 1px solid var(--border-soft); cursor: pointer;
  padding: 10px 12px; color: var(--text); font-family: inherit; font-size: 12.5px; }
.dock-row:hover { background: var(--panel-alt); }
.dock-row-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dock-row-when { font-size: 10.5px; color: var(--text-mute); white-space: nowrap; }
.dock-row-avatar { width: 26px; height: 26px; border-radius: 50%; flex: none; }
.dock-msg-who { display: flex; align-items: center; gap: 5px; }
.dock-msg-avatar { width: 18px; height: 18px; border-radius: 50%; flex: none; }
.staff-avatar { width: 30px; height: 30px; border-radius: 50%; flex: none; object-fit: cover; }
/* Pictures and files in a message, and the reactions under it. */
.staff-att-img { display: inline-block; margin-top: 6px; }
.staff-att-img img { display: block; max-width: 260px; max-height: 240px; border-radius: 10px; border: 1px solid var(--border-soft); }
.staff-att-file { display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; padding: 7px 10px; border-radius: 9px;
  background: var(--panel-alt); border: 1px solid var(--border-soft); color: var(--text); font-size: 12.5px; }
.staff-att-file small { color: var(--text-mute); }
.staff-reacts { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin-top: 4px; position: relative; }
.react-chip { background: var(--panel-alt); border: 1px solid var(--border-soft); color: var(--text-soft); border-radius: 999px;
  padding: 1px 8px; font-size: 12px; cursor: pointer; font-family: inherit; line-height: 1.6; }
.react-chip b { font-weight: 600; font-size: 11px; }
.react-chip.mine { border-color: var(--gold); background: var(--gold-soft); color: var(--text); }
.react-add { background: transparent; border: 1px dashed var(--border); color: var(--text-mute); border-radius: 999px;
  width: 24px; height: 22px; font-size: 13px; cursor: pointer; line-height: 1; opacity: 0; transition: opacity .15s; }
.staff-msg:hover .react-add, .dock-msg:hover .react-add, .react-add:focus-visible { opacity: 1; }
.react-picker { display: inline-flex; gap: 2px; background: var(--panel); border: 1px solid var(--border); border-radius: 999px; padding: 2px 4px;
  box-shadow: 0 8px 22px rgba(0,0,0,.35); }
.react-picker button { background: transparent; border: 0; font-size: 16px; cursor: pointer; padding: 2px 4px; border-radius: 6px; line-height: 1; }
.react-picker button:hover { background: var(--panel-alt); }
.staff-attach { padding: 0 10px; font-size: 15px; }
.dock-att-img { display: block; max-width: 200px; max-height: 180px; border-radius: 9px; margin-top: 4px; }
.dock-att-file { display: inline-flex; gap: 5px; align-items: center; font-size: 12px; margin-top: 4px; color: var(--text); text-decoration: underline; }
.dock-attach { background: transparent; border: 0; cursor: pointer; font-size: 16px; padding: 0 4px; opacity: .75; }
.dock-attach:hover { opacity: 1; }
.staff-avatar-sm { width: 22px; height: 22px; border-radius: 50%; flex: none; object-fit: cover; }
.dock-row-pip { background: var(--coral); color: #fff; border-radius: 999px;
  padding: 0 6px; font-size: 10px; font-weight: 600; }
.dock-empty { padding: 14px 12px; margin: 0; color: var(--text-mute); font-size: 12px; }

.dock-msg { margin-bottom: 8px; display: flex; flex-direction: column; align-items: flex-start; max-width: 88%; }
.dock-msg.is-you { align-self: flex-end; align-items: flex-end; margin-left: auto; }
.dock-msg.is-run { margin-top: -4px; }
.dock-msg.is-run .dock-msg-who { display: none; }
.dock-thread { display: none; flex-direction: column; }
#staff-dock.in-thread .dock-thread { display: flex; }
.dock-msg-who { display: block; font-size: 10.5px; color: var(--text-mute); margin: 0 4px 2px; }
.dock-msg.is-you .dock-msg-who { color: var(--gold); }
/* Bubbles: theirs on the left in the panel colour, yours on the right in
   the accent. pre-wrap, so a message typed over several lines keeps them
   without any markup being involved — the text is written with textContent. */
.dock-msg-body { font-size: 12.5px; color: var(--text); word-break: break-word; white-space: pre-wrap;
  background: var(--panel-alt); border: 1px solid var(--border-soft); border-radius: 12px 12px 12px 4px; padding: 6px 10px; }
.dock-msg.is-you .dock-msg-body { background: var(--gold); color: #fff; border-color: transparent; border-radius: 12px 12px 4px 12px; }
.dock-msg.is-pending .dock-msg-body { opacity: .6; }
.dock-msg-body.is-big { font-size: 28px; line-height: 1.2; background: transparent; border-color: transparent; padding: 0 4px; }
.dock-warn { color: var(--coral); font-size: 12px; max-width: 100%; }
.dock-typing { font-size: 11px; color: var(--text-mute); padding: 0 12px 6px; font-style: italic; }
.dock-typing::after { content: ''; display: inline-block; width: 1em; text-align: left; animation: dock-dots 1.2s steps(4, end) infinite; }
@keyframes dock-dots { 0% { content: ''; } 25% { content: '.'; } 50% { content: '..'; } 75% { content: '...'; } }
/* The full Team Chat page shares the rules: a lone emoji is large, and
   "… is typing" sits under the thread in the same quiet italic. */
.staff-msg-body.is-big { font-size: 30px !important; line-height: 1.2; }
.staff-typing { font-size: 11.5px; color: var(--text-mute); padding: 0 16px 6px; font-style: italic; }
/* The picker wraps the box in a block of its own; the box keeps its full
   width of the row all the same. */
#staff-send .emoji-wrap { flex: 1; min-width: 0; }
.staff-typing::after { content: ''; display: inline-block; width: 1em; text-align: left; animation: dock-dots 1.2s steps(4, end) infinite; }
.dock-badge.is-pulse { animation: dock-pulse .6s ease-out 1; }
@keyframes dock-pulse { 0% { transform: scale(1); } 40% { transform: scale(1.45); } 100% { transform: scale(1); } }

.dock-compose { display: flex; gap: 6px; padding: 10px 12px; border-top: 1px solid var(--border-soft); align-items: center; }
.dock-compose .emoji-wrap { flex: 1; min-width: 0; }
.dock-compose input { width: 100%; min-width: 0; background: var(--panel-alt); color: var(--text);
  border: 1px solid var(--border-control); border-radius: 8px; padding: 8px 10px; font-size: 12.5px; }
.dock-compose input:disabled { opacity: .5; }
.dock-compose .emoji-toggle { right: 4px; }
.dock-compose .emoji-panel { right: 0; width: 260px; }
.dock-compose [data-dock-send] { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; padding: 0; border-radius: 50%; }

/* On a phone the dock spans the width, because a 320px panel pinned to
   one corner of a 360px screen is neither one thing nor the other. */
@media (max-width: 520px) {
  #staff-dock { left: 10px; right: 10px; bottom: 10px; }
  .dock-panel { width: 100%; }
}

/* ── Reactions on a conversation ───────────────────────────────────────
   Theirs: a small chip hanging off the bottom corner of the bubble, the
   way every chat app draws it. Ours: a row of buttons under a customer's
   message; the one that is on is lit. */
.msg-reaction { display: table; margin-top: 6px; padding: 1px 7px; border-radius: 999px;
  background: var(--panel); border: 1px solid var(--border-control); font-size: 13px; line-height: 1.5;
  box-shadow: 0 2px 6px rgba(0,0,0,.18); }
.msg-react { display: flex; align-items: center; gap: 2px; margin: 6px 0 0; }
.msg-react button { background: transparent; border: 1px solid transparent; border-radius: 7px; padding: 1px 5px;
  font-size: 14px; line-height: 1.4; cursor: pointer; opacity: .55; }
.msg-react button:hover, .msg-react button:focus-visible { opacity: 1; background: var(--panel); border-color: var(--border-control); }
.msg-react button.is-on { opacity: 1; background: var(--gold-soft); border-color: var(--gold); }
.msg-react-note { font-size: 10.5px; color: var(--text-mute); margin-left: 4px; }

/* ── WhatsApp calls ─────────────────────────────────────────────────────
   The ring: a bar across the top of whatever page is open, green like the
   app people expect it from, with Answer where the thumb lands. */
.wa-ring { position: fixed; top: 12px; left: 50%; transform: translateX(-50%); z-index: 1300;
  display: flex; align-items: center; gap: 12px; max-width: calc(100vw - 24px);
  padding: 10px 14px; border-radius: 999px; background: var(--panel); color: var(--text);
  border: 1px solid #25D366; box-shadow: 0 14px 40px rgba(0,0,0,.4); font-size: 13px;
  animation: wa-ring-in .3s ease-out; }
.wa-ring[hidden] { display: none; }
.wa-ring-icon { font-size: 18px; animation: wa-ring-shake 1.2s ease-in-out infinite; }
.wa-ring-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wa-ring-answer { background: #25D366; border-color: #25D366; color: #fff; }
.wa-ring-answer:hover { background: #1fb457; }
@keyframes wa-ring-in { from { transform: translate(-50%, -20px); opacity: 0; } to { transform: translate(-50%, 0); opacity: 1; } }
@keyframes wa-ring-shake { 0%, 100% { transform: rotate(0); } 10% { transform: rotate(-14deg); } 20% { transform: rotate(12deg); } 30% { transform: rotate(-10deg); } 40% { transform: rotate(8deg); } 50% { transform: rotate(0); } }
.wa-call-btn { border-color: #25D366; color: #25D366; }
.wa-call-btn:hover { background: rgba(37, 211, 102, .12); }
.sp-chip.wa-chip { border-color: #25D366; color: #25D366; }
.sp-audio-dot[data-state="ok"] { background: var(--moss); }
.sp-audio-dot[data-state="bad"] { background: var(--coral); }
.sp-audio-dot[data-state="wait"] { background: var(--gold); }
