/* GENERATED brand tokens, scripts/apply-config.mjs */
:root{
  --brand-primary: #0B996E;
  --brand-ink: #1F2937;
  --brand-accent: #F5A623;
  --brand-surface: #FFFFFF;
}
/* Partner Voices - design tokens sourced from Brevo's own design-token file
   (designsystem.www.brevo.com) and live www.brevo.com CSS. Semantic layer re-derived to pass
   WCAG 2.2 AA in both themes. */

:root {
  /* brand primitives (verbatim Brevo) */
  --forest-100:#effaf7; --forest-200:#d8efe8; --forest-300:#b3dfd2; --forest-400:#71c4ab;
  --forest-500:#48ac8e; --forest-600:#0b996f; --forest-700:#02835c; --forest-800:#006a43;
  --forest-900:#004227; --forest-950:#002e1e;
  --mint-100:#f9fff6; --mint-200:#e8fedf; --mint-300:#d7fec8; --mint-400:#c6efb6;
  --grey-25:#fafafa; --grey-50:#f5f5f5; --grey-100:#f0f0f0; --grey-200:#e3e3e3;
  --grey-300:#cfcfcf; --grey-400:#b5b5b5; --grey-500:#858585; --grey-600:#696969;
  --grey-700:#474747; --grey-800:#2c2c2c; --grey-900:#1b1b1b;
  --iris-100:#efeefc; --iris-200:#dbd9f7; --iris-300:#b3aeef; --iris-400:#8b83e7;
  --iris-500:#6358de; --iris-700:#4f46b2; --iris-900:#3c3585;
  --tulip-100:#ffecee; --tulip-200:#ffd6db; --tulip-400:#ff8d9a; --tulip-700:#e72448;
  --tulip-800:#cf1a3b; --tulip-900:#b81735;
  --coral-100:#fff4f0; --coral-200:#ffdfd1; --coral-400:#ff976b; --coral-700:#d9592e;
  --coral-900:#a24428;
  --sun-100:#fffbeb; --sun-300:#fee89a; --sun-400:#fedd67; --sun-900:#8e6f01;
  --chart-1:#6459de; --chart-2:#159e9e; --chart-3:#eb4280; --chart-4:#5aa3e7;
  --chart-5:#deaf02; --chart-6:#96834a; --chart-7:#ef6639; --chart-8:#0b996e;
  --chart-9:#89af79; --chart-10:#ff384f; --chart-11:#948d7a;

  --font-heading:'Bricolage Grotesque', Verdana, ui-sans-serif, system-ui, sans-serif;
  --font-body:'Inter', Arial, ui-sans-serif, system-ui, -apple-system, sans-serif;

  --r-sm:.25rem; --r-md:.5rem; --r-lg:1rem; --r-xl:1.5rem; --r-pill:10rem;
  --bw:2px;
  --sp-1:.5rem; --sp-2:1rem; --sp-3:1.5rem; --sp-4:2rem;

  --shadow-xs:0 1px 2px rgba(28,28,28,.08);
  --shadow-sm:0 4px 8px -2px rgba(28,28,28,.14), 0 2px 4px -2px rgba(28,28,28,.1);
  --shadow-md:0 10px 16px -4px rgba(28,28,28,.1), 0 4px 6px -2px rgba(28,28,28,.04);
  --shadow-lg:0 20px 24px -4px rgba(28,28,28,.08), 0 8px 8px rgba(28,28,28,.03);
  --gloss:inset -1px -3px 7.8px 0 rgba(27,27,27,.25), inset 1px 3px 8px 0 rgba(255,255,255,.2),
          0 4px 8px -2px rgba(27,27,27,.14), 0 2px 4px -2px rgba(27,27,27,.1);

  /* semantic - light */
  --bg:#ffffff; --bg-subtle:var(--grey-25); --bg-muted:var(--grey-50);
  --rail:var(--mint-100); --rail-border:var(--forest-200);
  --surface:#ffffff; --overlay:rgba(92,109,85,.4);
  --border:var(--grey-200); --border-strong:var(--grey-300);
  --text:var(--grey-900); --text-secondary:var(--grey-700); --text-muted:var(--grey-600);
  --action:var(--grey-900); --action-hover:var(--grey-800); --on-action:#ffffff;
  --accent:var(--forest-800); --accent-hover:var(--forest-900); --on-accent:#ffffff;
  --accent-graphic:#0b996e; --link:var(--forest-800);
  --focus:var(--iris-700); --focus-offset:#ffffff;
  --ok:var(--forest-800); --ok-bg:var(--forest-100); --ok-border:var(--forest-200);
  --warn:var(--coral-900); --warn-bg:var(--coral-100); --warn-border:var(--coral-200);
  --err:var(--tulip-800); --err-bg:var(--tulip-100); --err-border:var(--tulip-200);
  --info:var(--iris-700); --info-bg:var(--iris-100); --info-border:var(--iris-200);
  --hold:var(--sun-900); --hold-bg:var(--sun-100); --hold-border:var(--sun-300);
  --pill-bg:var(--mint-200); --pill-text:var(--forest-900);
}

:root[data-theme="dark"], :root:not([data-theme="light"]) {
  --bg:var(--grey-900); --bg-subtle:#232323; --bg-muted:var(--grey-800);
  --rail:#12251d; --rail-border:var(--forest-900);
  --surface:var(--grey-800); --overlay:rgba(0,0,0,.6);
  --border:var(--grey-700); --border-strong:var(--grey-600);
  --text:#fafafa; --text-secondary:var(--grey-300); --text-muted:var(--grey-400);
  --action:var(--mint-300); --action-hover:var(--mint-200); --on-action:var(--forest-900);
  --accent:var(--mint-300); --accent-hover:var(--mint-200); --on-accent:var(--forest-900);
  --accent-graphic:var(--forest-600); --link:var(--forest-400);
  --focus:var(--iris-400); --focus-offset:var(--grey-900);
  --ok:var(--forest-400); --ok-bg:#0d2a22; --ok-border:var(--forest-900);
  --warn:var(--coral-400); --warn-bg:#33180f; --warn-border:var(--coral-900);
  --err:var(--tulip-400); --err-bg:#33161b; --err-border:var(--tulip-900);
  --info:var(--iris-300); --info-bg:#22203d; --info-border:var(--iris-900);
  --hold:var(--sun-400); --hold-bg:#2e2607; --hold-border:var(--sun-900);
  --pill-bg:var(--forest-900); --pill-text:var(--mint-300);
  --shadow-xs:0 1px 2px rgba(0,0,0,.16);
  --shadow-sm:0 4px 8px -2px rgba(0,0,0,.24), 0 2px 4px -2px rgba(0,0,0,.16);
  --shadow-md:0 10px 16px -4px rgba(0,0,0,.2), 0 4px 6px -2px rgba(0,0,0,.16);
  --shadow-lg:0 20px 24px -4px rgba(0,0,0,.2), 0 8px 8px rgba(0,0,0,.16);
  --gloss:inset -1px -3px 7.8px 0 rgba(0,0,0,.35), inset 1px 3px 8px 0 rgba(255,255,255,.18),
          0 4px 8px -2px rgba(0,0,0,.24);
}
:root[data-theme="light"] {
  --bg:#ffffff; --bg-subtle:var(--grey-25); --bg-muted:var(--grey-50);
  --rail:var(--mint-100); --rail-border:var(--forest-200);
  --surface:#ffffff; --overlay:rgba(92,109,85,.4);
  --border:var(--grey-200); --border-strong:var(--grey-300);
  --text:var(--grey-900); --text-secondary:var(--grey-700); --text-muted:var(--grey-600);
  --action:var(--grey-900); --action-hover:var(--grey-800); --on-action:#ffffff;
  --accent:var(--forest-800); --accent-hover:var(--forest-900); --on-accent:#ffffff;
  --accent-graphic:#0b996e; --link:var(--forest-800);
  --focus:var(--iris-700); --focus-offset:#ffffff;
  --ok:var(--forest-800); --ok-bg:var(--forest-100); --ok-border:var(--forest-200);
  --warn:var(--coral-900); --warn-bg:var(--coral-100); --warn-border:var(--coral-200);
  --err:var(--tulip-800); --err-bg:var(--tulip-100); --err-border:var(--tulip-200);
  --info:var(--iris-700); --info-bg:var(--iris-100); --info-border:var(--iris-200);
  --hold:var(--sun-900); --hold-bg:var(--sun-100); --hold-border:var(--sun-300);
  --pill-bg:var(--mint-200); --pill-text:var(--forest-900);
}

*{margin:0;padding:0;box-sizing:border-box}
html{color-scheme:light dark}
body{background:var(--bg);color:var(--text);font-family:var(--font-body);font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased}
h1,h2,h3,h4{font-family:var(--font-heading);font-weight:600;color:var(--text);line-height:1.25}
a{color:var(--link)}
:focus-visible{outline:none;box-shadow:0 0 0 2px var(--focus-offset),0 0 0 4px var(--focus)}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:var(--r-pill);border:3px solid var(--bg)}

/* ---------- shell ---------- */
.shell{display:flex;min-height:100vh}
.rail{width:232px;flex:0 0 232px;background:var(--rail);border-right:var(--bw) solid var(--rail-border);
  border-bottom:var(--bw) solid var(--rail-border);border-bottom-right-radius:30px;
  padding:var(--sp-2) .75rem;position:sticky;top:0;height:100vh;overflow-y:auto;display:flex;flex-direction:column;gap:2px}
.brand{display:flex;align-items:center;gap:.5rem;padding:.375rem .5rem .75rem}
.mark{height:26px;width:26px;flex:0 0 26px;display:block}
.brand .brand-name{font-family:var(--font-heading);font-weight:700;font-size:15px;line-height:1.1;color:var(--text)}
.brand .sub{font-size:11px;color:var(--text-muted);font-weight:600;letter-spacing:.04em;text-transform:uppercase}
.login-brand{display:flex;align-items:center;gap:.5rem;margin-bottom:1.25rem}
.login-brand .mark{height:30px;width:30px;flex:0 0 30px}
.login-brand .wordmark{font-family:var(--font-heading);font-weight:700;font-size:22px;letter-spacing:-.02em;
  color:var(--accent-graphic)}
#login h1{font-size:20px;margin-bottom:.25rem}
.navitem{display:flex;align-items:center;gap:.5rem;padding:.375rem .625rem;border-radius:var(--r-md);font-size:13px;
  border:var(--bw) solid transparent;color:var(--text-secondary);font-weight:500;cursor:pointer;
  background:none;font:inherit;font-weight:500;width:100%;text-align:left;transition:background .2s}
.navitem:hover{background:var(--mint-200)}
:root[data-theme="dark"] .navitem:hover,:root:not([data-theme="light"]) .navitem:hover{background:rgba(255,255,255,.06)}
.navitem[aria-current="page"]{background:var(--surface);border-color:var(--rail-border);color:var(--text);font-weight:600;font-size:13px;box-shadow:var(--shadow-xs)}
.navitem .ic{width:16px;height:16px;flex:0 0 16px;stroke:currentColor;fill:none;stroke-width:2}
.navitem .count{margin-left:auto;font-size:10px;font-weight:700;background:var(--pill-bg);color:var(--pill-text);padding:1px 7px;border-radius:var(--r-pill)}
.nav-section{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--text-muted);padding:.5rem .625rem .125rem;margin-top:.25rem}
.rail-foot{margin-top:auto;padding-top:var(--sp-2);border-top:var(--bw) solid var(--rail-border);display:flex;flex-direction:column;gap:.5rem}

.main{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{height:56px;display:flex;align-items:center;gap:var(--sp-2);padding:0 var(--sp-4);
  border-bottom:var(--bw) solid var(--border);background:var(--bg);position:sticky;top:0;z-index:20}
.topbar h1{font-size:18px;font-weight:600}
.topbar .right{margin-left:auto;display:flex;align-items:center;gap:.75rem}
.page{padding:var(--sp-4);max-width:1400px;width:100%}
@media(max-width:1000px){.page{padding:var(--sp-2)}}
/* The topbar is one non-wrapping flex row, so a page that adds a control to .right (Sent
   adds "Sync delivery" next to the date range) pushed the row 22px past a 375px viewport
   and the whole document scrolled sideways. The row keeps its shape and gives up padding,
   title width and select width instead. */
@media(max-width:520px){
  .topbar{padding:0 var(--sp-2)}
  .topbar h1{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .topbar .right{min-width:0;gap:.4rem}
  .topbar .right select{min-width:0;max-width:38vw}
  /* The earlier fix shrank the title and the select but left the action button at its full
     desktop padding, so Sent still pushed the document 12px sideways at 375px. The button
     gives up padding and a point of type rather than its label: a truncated "Sync deliv..."
     would be worse than a slightly smaller one. */
  .topbar .right .btn{padding:.4rem .5rem;font-size:12.5px;white-space:nowrap;flex:0 0 auto}
}

/* ---------- primitives ---------- */
.card{background:var(--surface);border:var(--bw) solid var(--border);border-radius:var(--r-lg);padding:var(--sp-3)}
.card.tight{padding:var(--sp-2)}
.card h2{font-size:15px;margin-bottom:.75rem}
.card .hint{color:var(--text-muted);font-size:12.5px;margin-bottom:.75rem}
.grid{display:grid;gap:var(--sp-2)}
.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:.625rem}
.tile{background:var(--surface);border:var(--bw) solid var(--border);border-radius:var(--r-lg);padding:.75rem .875rem;transition:border-color .2s}
.tile[role=button]:hover{border-color:var(--border-strong)}
.tile .n{font-family:var(--font-heading);font-size:23px;font-weight:700;line-height:1.15;letter-spacing:-.02em}
.tile .l{font-size:10.5px;color:var(--text-muted);font-weight:600;text-transform:uppercase;letter-spacing:.04em;margin-top:2px;line-height:1.25}
.tile .d{font-size:11.5px;color:var(--text-secondary);margin-top:.3rem;line-height:1.3}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;min-height:38px;padding:.4rem .9rem;
  border:var(--bw) solid transparent;border-radius:.75rem;font:inherit;font-weight:600;cursor:pointer;
  white-space:nowrap;transition:.2s;background:var(--surface);color:var(--text-secondary);border-color:var(--border)}
.btn:hover{border-color:var(--border-strong);color:var(--text)}
.btn.primary{background:var(--action);border-color:var(--action);color:var(--on-action);box-shadow:var(--gloss)}
.btn.primary:hover{background:var(--action-hover);border-color:var(--action-hover)}
.btn.accent{background:transparent;border-color:var(--accent);color:var(--accent);box-shadow:var(--shadow-xs)}
.btn.accent:hover{background:var(--mint-100);box-shadow:var(--shadow-sm)}
:root[data-theme="dark"] .btn.accent:hover,:root:not([data-theme="light"]) .btn.accent:hover{background:rgba(255,255,255,.06)}
.btn.ghost{background:transparent;border-color:transparent;color:var(--accent)}
.btn.ghost:hover{background:var(--mint-100)}
:root[data-theme="dark"] .btn.ghost:hover,:root:not([data-theme="light"]) .btn.ghost:hover{background:rgba(255,255,255,.06)}
.btn.danger{color:var(--err);border-color:var(--err-border)}
.btn.danger:hover{background:var(--err-bg);border-color:var(--err)}
.btn.sm{min-height:30px;padding:.2rem .6rem;font-size:12.5px;border-radius:var(--r-md)}
.btn[disabled]{opacity:.5;cursor:not-allowed}

.pill{display:inline-flex;align-items:center;gap:.25rem;padding:2px 9px;border-radius:var(--r-pill);
  font-size:11px;font-weight:700;background:var(--pill-bg);color:var(--pill-text);white-space:nowrap}
.pill.ok{background:var(--ok-bg);color:var(--ok)}
.pill.warn{background:var(--warn-bg);color:var(--warn)}
.pill.err{background:var(--err-bg);color:var(--err)}
.pill.info{background:var(--info-bg);color:var(--info)}
.pill.hold{background:var(--hold-bg);color:var(--hold)}
.pill.muted{background:var(--bg-muted);color:var(--text-secondary)}
.dot{width:8px;height:8px;border-radius:50%;flex:0 0 8px;display:inline-block}

input[type=text],input[type=number],input[type=search],input[type=url],input[type=email],select,textarea{
  width:100%;background:var(--surface);border:var(--bw) solid var(--border-strong);border-radius:var(--r-md);
  padding:.45rem .7rem;font:inherit;color:var(--text)}
input:focus,select:focus,textarea:focus{border-color:var(--text);outline:none}
textarea{min-height:120px;resize:vertical;line-height:1.6}
label.field{display:block;margin-bottom:var(--sp-2)}
label.field>.lab{display:block;font-weight:600;font-size:12.5px;margin-bottom:.25rem}
label.field>.desc{display:block;color:var(--text-muted);font-size:12px;margin-bottom:.375rem}
label.field>.eg{display:block;color:var(--text-muted);font-size:11.5px;margin-top:.25rem;font-style:italic}
.row{display:flex;gap:.5rem;align-items:center;flex-wrap:wrap}
.spread{display:flex;gap:.5rem;align-items:center;justify-content:space-between;flex-wrap:wrap}

table{width:100%;border-collapse:collapse;font-size:13px}
th{text-align:left;padding:.6rem .75rem;font-weight:600;font-size:11.5px;text-transform:uppercase;
  letter-spacing:.05em;color:var(--text-secondary);background:var(--bg-muted);border-bottom:var(--bw) solid var(--border);white-space:nowrap}
td{padding:.7rem .75rem;border-bottom:1px solid var(--border);vertical-align:top}
tbody tr:hover td{background:var(--bg-subtle)}
tbody tr.clickable{cursor:pointer}
.tablewrap{overflow-x:auto;border:var(--bw) solid var(--border);border-radius:var(--r-lg);background:var(--surface)}
/* A narrow table does not want .tablewrap's 820px floor, but it still has to scroll inside
   its own box rather than pushing the page sideways on a phone. */
.tablescroll{overflow-x:auto;max-width:100%}
.tablewrap table{min-width:820px}
.tablewrap th:first-child,.tablewrap td:first-child{position:sticky;left:0;background:var(--surface)}
.tablewrap th:first-child{background:var(--bg-muted)}
tbody tr:hover td:first-child{background:var(--bg-subtle)}

.tabs{display:flex;gap:.25rem;border-bottom:var(--bw) solid var(--border);margin-bottom:var(--sp-2);overflow-x:auto}
.tab{padding:.5rem .875rem;border:0;border-bottom:3px solid transparent;background:none;font:inherit;
  font-weight:600;color:var(--text-muted);cursor:pointer;white-space:nowrap;margin-bottom:-2px}
.tab:hover{color:var(--text)}
.tab[aria-selected="true"]{color:var(--text);border-bottom-color:var(--accent-graphic)}

/* ---------- filter chips ----------
   These carry real weight: they are how a person answers "who has never replied to me".
   So they are sized and coloured as a primary control, not as incidental metadata. Each
   chip states its own count, and the count keeps its contrast in both the resting and the
   selected state. */
.filterbar{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
.filterbar>.flab{display:inline-flex;align-items:center;font-size:10.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);flex:0 0 auto;padding-right:.125rem}
.chips{display:flex;gap:.375rem;flex-wrap:wrap;align-items:center}
.chip{display:inline-flex;align-items:center;gap:.4rem;padding:.32rem .5rem .32rem .7rem;
  border:var(--bw) solid var(--border);border-radius:var(--r-pill);background:var(--surface);
  font:inherit;font-size:12.5px;font-weight:600;color:var(--text-secondary);cursor:pointer;
  transition:background .15s ease,border-color .15s ease,color .15s ease,transform .15s ease,box-shadow .15s ease}
.chip .n{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:17px;
  padding:0 5px;border-radius:var(--r-pill);background:var(--bg-muted);color:var(--text-secondary);
  font-size:11px;font-weight:700;line-height:1;transition:background .15s ease,color .15s ease}
/* HOVER SAYS "THIS IS A BUTTON", NOT JUST "THE CURSOR IS HERE". The resting chip and the
   page share the same surface, so a border-only hover was invisible against the sticky
   header. The fill changes too, which is the part the eye actually catches. */
.chip:hover{background:var(--bg-subtle);border-color:var(--border-strong);color:var(--text);
  transform:translateY(-1px);box-shadow:var(--shadow-xs)}
.chip:hover .n{background:var(--pill-bg);color:var(--text)}
.chip:active{transform:translateY(0);box-shadow:none;transition-duration:.05s}
/* SELECTED IS A FILL PLUS A HALO, so a chosen filter still reads as chosen at the edge of
   vision, where a fill swap alone does not survive against a busy row. The halo is drawn in
   a page tone rather than an accent, so it separates the selected chip from its neighbours
   without adding a fourth colour, and it works unchanged for every tone below. */
.chip[aria-pressed="true"]{background:var(--action);border-color:var(--action);color:var(--on-action);
  box-shadow:var(--shadow-sm),0 0 0 3px var(--bg-subtle)}
.chip[aria-pressed="true"]:hover{transform:translateY(-1px);box-shadow:var(--shadow-md),0 0 0 3px var(--bg-subtle)}
/* The focus ring must outrank both of those. The global :focus-visible rule sets box-shadow,
   and every .chip rule above sets box-shadow too, so a keyboard user lost the ring entirely
   on the one control row that is hardest to reach any other way. Restated here, last. */
.chip:focus-visible{outline:none;
  box-shadow:0 0 0 2px var(--focus-offset),0 0 0 4px var(--focus)}
/* The badge on a selected chip is a solid cutout in the page surface, not a translucent
   overlay. A selected chip is dark in the light theme and light in the dark theme, so the
   surface pair inverts with it and stays legible for every tone below without needing a
   separate token per tone. Solid also means the contrast is measurable rather than an
   artifact of alpha compositing. */
.chip[aria-pressed="true"] .n{background:var(--surface);color:var(--text)}
/* A tone tints the resting chip so the important states read at a glance, and fills on
   select. Identity is never colour alone: every chip is also labelled. */
.chip.t-ok{border-color:var(--ok-border);color:var(--ok)}
.chip.t-ok .n{background:var(--ok-bg);color:var(--ok)}
.chip.t-ok[aria-pressed="true"]{background:var(--ok);border-color:var(--ok);color:var(--on-accent)}
.chip.t-hold{border-color:var(--hold-border);color:var(--hold)}
.chip.t-hold .n{background:var(--hold-bg);color:var(--hold)}
.chip.t-hold[aria-pressed="true"]{background:var(--hold);border-color:var(--hold);color:var(--focus-offset)}
.chip.t-info{border-color:var(--info-border);color:var(--info)}
.chip.t-info .n{background:var(--info-bg);color:var(--info)}
.chip.t-info[aria-pressed="true"]{background:var(--info);border-color:var(--info);color:var(--focus-offset)}
.chip.t-err{border-color:var(--err-border);color:var(--err)}
.chip.t-err .n{background:var(--err-bg);color:var(--err)}
.chip.t-err[aria-pressed="true"]{background:var(--err);border-color:var(--err);color:var(--focus-offset)}
/* A compact variant for dense columns. The inbox list is 320px wide, so full-size chips
   cost four rows of vertical space that the conversation list needs more. */
.chip.sm{padding:.2rem .4rem .2rem .55rem;font-size:11.5px;gap:.3rem}
.chip.sm .n{min-width:17px;height:15px;font-size:10px;padding:0 4px}
.chip.is-quiet{border-color:var(--border);color:var(--text-muted)}
.chip .caret{font-size:7px;opacity:1;margin-left:.05rem}

/* Overflow menu holding the filters that are rarely the thing you are looking for. */
.moremenu{position:relative;display:inline-flex}
.moremenu .menu{position:absolute;top:calc(100% + 5px);left:0;z-index:40;background:var(--surface);
  border:var(--bw) solid var(--border);border-radius:var(--r-md);padding:.4rem;
  box-shadow:var(--shadow-md);display:flex;flex-direction:column;gap:.3rem;min-width:190px}
.moremenu .menu .chip{justify-content:space-between;width:100%}
/* Near the right edge of a narrow column the menu would overflow, so it flips. */
@media(max-width:760px){.moremenu .menu{left:auto;right:0}}

/* Clear rides along with the chips rather than wrapping to a row of its own, which in the
   narrow conversation column costs list height for one word. */
.chip-clear{min-height:24px;padding:.15rem .5rem;font-size:11.5px}

.datefilter{display:inline-flex;align-items:center;margin-left:auto}
.datefilter select{width:auto;min-width:112px;padding:.2rem .45rem;font-size:11.5px;
  border-width:1px;border-radius:var(--r-md);cursor:pointer}
.datefilter select:hover{border-color:var(--border-strong)}
/* A filter that currently matches nothing stays visible so the taxonomy never shifts
   under the cursor, but it recedes and stops inviting a click. */
/* A filter chip with a count of zero is still a control a person has to read, so the
   "nothing here" cue is a muted colour rather than transparency. Dimming the whole chip
   with opacity dragged the toned variants (.t-hold on white was 1.85:1) far under 4.5:1,
   and no amount of opacity fixes that for every tone at once. */
.chip.is-zero{opacity:1;color:var(--text-muted);border-color:var(--border)}
.chip.is-zero .n{background:transparent;color:var(--text-muted)}
/* An empty filter is still clickable, so it still answers the pointer. It just answers more
   quietly: the fill and border move, the chip does not lift. Killing every hover response
   made these read as disabled controls, which they are not. */
.chip.is-zero:hover{background:var(--bg-subtle);border-color:var(--border-strong);
  color:var(--text-secondary);transform:none;box-shadow:none}
.chip.is-zero:hover .n{background:transparent;color:var(--text-secondary)}

.empty{padding:var(--sp-4);text-align:center;color:var(--text-muted)}
.empty .big{font-family:var(--font-heading);font-size:16px;color:var(--text);margin-bottom:.25rem}
.skel{background:linear-gradient(90deg,var(--bg-muted) 25%,var(--bg-subtle) 50%,var(--bg-muted) 75%);
  background-size:200% 100%;animation:sk 1.2s infinite;border-radius:var(--r-md);height:14px}
@keyframes sk{0%{background-position:200% 0}100%{background-position:-200% 0}}
.banner{border:var(--bw) solid var(--border);border-radius:var(--r-lg);padding:.75rem 1rem;display:flex;
  gap:.625rem;align-items:flex-start;font-size:13px}
.banner.warn{background:var(--warn-bg);border-color:var(--warn-border);color:var(--warn)}
.banner.err{background:var(--err-bg);border-color:var(--err-border);color:var(--err)}
.banner.info{background:var(--info-bg);border-color:var(--info-border);color:var(--info)}
.banner.ok{background:var(--ok-bg);border-color:var(--ok-border);color:var(--ok)}
.banner.hold{background:var(--hold-bg);border-color:var(--hold-border);color:var(--hold)}

/* The HTML `hidden` attribute only carries `display:none` at user-agent weight, so any
   component rule that sets its own display (.shell, .drawer) silently beat it and the
   element stayed painted and tab-reachable while marked hidden. This restores it once
   for every element rather than per component. */
[hidden]{display:none !important}

/* ---------- drawer (right side panel) ---------- */
.scrim{position:fixed;inset:0;background:var(--overlay);z-index:60;opacity:0;pointer-events:none;transition:opacity .25s}
.scrim.open{opacity:1;pointer-events:auto}
.drawer{position:fixed;top:0;right:0;bottom:0;width:min(680px,92vw);background:var(--surface);
  border-left:var(--bw) solid var(--border);z-index:61;transform:translateX(100%);transition:transform .3s cubic-bezier(.4,0,.2,1);
  display:flex;flex-direction:column;box-shadow:var(--shadow-lg)}
.drawer.open{transform:translateX(0)}
.drawer-head{padding:var(--sp-2) var(--sp-3);border-bottom:var(--bw) solid var(--border);display:flex;
  align-items:flex-start;gap:.75rem;position:sticky;top:0;background:var(--surface);z-index:2}
.drawer-body{padding:var(--sp-3);overflow-y:auto;flex:1}
.drawer h2{font-size:19px}
@media(max-width:680px){.drawer{width:100vw;border-left:0}}

.kv{display:grid;grid-template-columns:150px 1fr;gap:.4rem 1rem;font-size:13px}
.kv .k{color:var(--text-muted)}
.kv .v{word-break:break-word}
@media(max-width:680px){.kv{grid-template-columns:110px 1fr}}

.scorebar{display:grid;grid-template-columns:120px 1fr 44px;gap:.5rem;align-items:center;margin-bottom:.4rem;font-size:12.5px}
.scorebar .track{height:8px;background:var(--bg-muted);border-radius:var(--r-pill);overflow:hidden}
.scorebar .fill{height:100%;border-radius:var(--r-pill)}

.post{border:var(--bw) solid var(--border);border-radius:var(--r-lg);padding:.75rem;margin-bottom:.625rem}
.post .meta{display:flex;gap:.4rem;align-items:center;flex-wrap:wrap;margin-bottom:.4rem;font-size:11.5px;color:var(--text-muted)}
.post .cap{white-space:pre-wrap;font-size:13px}
.post details{margin-top:.4rem}
.post summary{cursor:pointer;font-size:12px;color:var(--link);font-weight:600}
.post .tx{margin-top:.4rem;font-size:12.5px;color:var(--text-secondary);white-space:pre-wrap;
  background:var(--bg-subtle);padding:.5rem;border-radius:var(--r-md);max-height:220px;overflow:auto}

/* ---------- inbox 3-pane ---------- */
.inbox{display:grid;grid-template-columns:320px minmax(0,1fr) 300px;gap:0;height:calc(100vh - 56px);
  border-top:0}
.inbox>*{overflow-y:auto;overflow-x:hidden;min-width:0}
.inbox .list{border-right:var(--bw) solid var(--border)}
.inbox .ctx{border-left:var(--bw) solid var(--border);padding:var(--sp-2)}
.inbox .thread{display:flex;flex-direction:column;height:100%}
.conv{padding:.7rem .875rem;border-bottom:1px solid var(--border);cursor:pointer;display:flex;gap:.625rem}
.conv:hover{background:var(--bg-subtle)}
.conv[aria-selected="true"]{background:var(--mint-100);border-left:3px solid var(--accent-graphic);padding-left:calc(.875rem - 3px)}
:root[data-theme="dark"] .conv[aria-selected="true"],:root:not([data-theme="light"]) .conv[aria-selected="true"]{background:rgba(255,255,255,.05)}
.conv .av{width:34px;height:34px;flex:0 0 34px;border-radius:50%;background:var(--pill-bg);color:var(--pill-text);
  display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px}
.conv .body{min-width:0;flex:1}
.conv .nm{font-weight:600;font-size:13px;display:flex;gap:.35rem;align-items:center}
.conv .pv{color:var(--text-muted);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px}
.conv .tm{font-size:11px;color:var(--text-muted);margin-left:auto;white-space:nowrap}
.conv.unread .nm::before{content:'';width:7px;height:7px;border-radius:50%;background:var(--accent-graphic);display:inline-block}
.msgs{flex:1;overflow-y:auto;overflow-x:hidden;padding:var(--sp-2);min-width:0}
/* white-space:pre-wrap preserves the newlines a real email carries, but it also preserves
   one enormous unbreakable token. A support auto-reply containing a 300-character tracking
   URL pushed the whole thread pane sideways. Long tokens now wrap inside the bubble. */
.bub{max-width:76%;padding:.6rem .8rem;border-radius:var(--r-lg);margin-bottom:.625rem;font-size:13px;
  white-space:pre-wrap;position:relative;overflow-wrap:anywhere;word-break:break-word;min-width:0}
.bub a{overflow-wrap:anywhere;word-break:break-all}
.bub.in{background:var(--bg-muted);border:var(--bw) solid var(--border);border-bottom-left-radius:var(--r-sm)}
.bub.out{background:var(--pill-bg);color:var(--pill-text);margin-left:auto;border-bottom-right-radius:var(--r-sm)}
.bub .m{font-size:10.5px;opacity:.75;margin-bottom:.25rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em}
.bub .subj{font-weight:700;margin-bottom:.25rem}
.composer{border-top:var(--bw) solid var(--border);padding:var(--sp-2);background:var(--surface)}
@media(max-width:1100px){.inbox{grid-template-columns:280px minmax(0,1fr)}.inbox .ctx{display:none}}
@media(max-width:760px){
  /* Master-detail on small screens. Trapping the conversation list inside a short
     scroller hides almost all of it behind a nested scrollbar, so instead the list gets
     the whole screen and opening a thread replaces it. */
  .inbox{grid-template-columns:1fr;height:auto}
  .inbox .list{border-right:0;max-height:none;overflow:visible}
  .inbox .thread,.inbox .ctx{display:none}
  .inbox[data-view="thread"] .list{display:none}
  .inbox[data-view="thread"] .thread{display:flex;min-height:calc(100vh - 120px)}
  .backlist{display:inline-flex!important}
}
.backlist{display:none}

/* charts */
.bars{display:flex;align-items:flex-end;gap:3px;height:110px}
.bars .b{flex:1;background:var(--chart-8);border-radius:3px 3px 0 0;min-height:2px;position:relative}
.bars .b:hover{opacity:.8}
.funnel .step{display:grid;grid-template-columns:130px 1fr 60px;gap:.625rem;align-items:center;margin-bottom:.4rem;font-size:12.5px}
.funnel .track{height:20px;background:var(--bg-muted);border-radius:0 var(--r-sm) var(--r-sm) 0;overflow:hidden}
.funnel .fill{height:100%;border-radius:0 var(--r-sm) var(--r-sm) 0}

.tip{position:relative;cursor:help;border-bottom:1px dotted var(--text-muted)}
.tip:hover::after{content:attr(data-tip);position:absolute;bottom:calc(100% + 6px);left:0;z-index:50;
  background:var(--grey-900);color:#fff;padding:.5rem .625rem;border-radius:var(--r-md);font-size:11.5px;
  font-weight:400;line-height:1.45;width:280px;box-shadow:var(--shadow-md);white-space:normal;text-transform:none;letter-spacing:normal}
:root[data-theme="dark"] .tip:hover::after,:root:not([data-theme="light"]) .tip:hover::after{background:#000}

/* ---------- info affordance ----------
   A circled "i" that explains a term the interface cannot define in the space it has:
   what "unresponsive" actually means, how a payout becomes committed, why a lead is held.
   It is a real <button> so it opens on keyboard focus and on tap, not on hover alone. */
.ii{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;flex:0 0 15px;
  border-radius:50%;border:1.5px solid var(--text-muted);background:none;color:var(--text-muted);
  font:inherit;font-size:9.5px;font-weight:700;line-height:1;cursor:help;padding:0;
  position:relative;vertical-align:middle;margin-left:.3rem;transition:.16s;text-transform:none;letter-spacing:0}
.ii:hover,.ii:focus-visible{border-color:var(--accent-graphic);color:var(--accent-graphic);transform:scale(1.14)}
/* The bubble is generated only while it is actually shown. Kept permanently in the box tree
   (opacity:0) it still took layout, and a 250px bubble hanging past the right edge gave the
   whole page a horizontal scrollbar at phone width. Same idiom as .tip below. */
.ii::after{position:absolute;bottom:calc(100% + 8px);left:50%;
  transform:translateX(-50%);z-index:80;background:var(--grey-900);color:#fff;
  padding:.55rem .7rem;border-radius:var(--r-md);font-size:11.5px;font-weight:400;line-height:1.45;
  width:250px;box-shadow:var(--shadow-md);white-space:normal;text-align:left;text-transform:none;
  letter-spacing:normal;pointer-events:none}
.ii:hover::after,.ii:focus-visible::after{content:attr(data-tip)}
/* Near a container edge a centred tooltip would be clipped, so it anchors to one side. */
.ii[data-align="start"]::after{left:-6px;transform:translateX(0)}
.ii[data-align="end"]::after{left:auto;right:-6px;transform:translateX(0)}
:root[data-theme="dark"] .ii::after,:root:not([data-theme="light"]) .ii::after{background:#000;border:1px solid var(--border)}
@media(max-width:680px){.ii::after{width:200px}}

/* ---------- motion polish ----------
   Every hover here is a 1px lift with a shadow, nothing that moves layout. */
.tile[role=button]{cursor:pointer;transition:border-color .16s,transform .16s,box-shadow .16s}
.tile[role=button]:hover{border-color:var(--border-strong);transform:translateY(-2px);box-shadow:var(--shadow-sm)}
.tile[role=button]:active{transform:translateY(0);box-shadow:var(--shadow-xs)}
.btn{transition:background .16s,border-color .16s,color .16s,transform .16s,box-shadow .16s}
.btn:not([disabled]):hover{transform:translateY(-1px)}
.btn:not([disabled]):active{transform:translateY(0)}
.card{transition:border-color .16s,box-shadow .16s}
.navitem{transition:background .16s,color .16s,border-color .16s,transform .16s}
.navitem:not([aria-current="page"]):hover{transform:translateX(2px)}
.conv{transition:background .16s,border-left-color .16s}
tbody tr.clickable{transition:background .16s}

.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}
.muted{color:var(--text-muted)}
.small{font-size:12px}
.mt2{margin-top:var(--sp-2)}.mt3{margin-top:var(--sp-3)}.mb2{margin-bottom:var(--sp-2)}
.leaf{border-radius:2.5rem 0 2.5rem 0}

#login{max-width:400px;margin:12vh auto;padding:var(--sp-4)}
#login .card{border-radius:2.5rem 0 2.5rem 0}
@media(max-width:900px){
  .rail{position:fixed;left:0;top:0;z-index:70;transform:translateX(-100%);transition:transform .25s}
  .rail.open{transform:translateX(0)}
  .menubtn{display:inline-flex!important}
}
.menubtn{display:none}

/* Motion is decoration only. Layout state must never depend on a transition finishing:
   a background tab, a paused compositor or a reduced-motion preference would otherwise
   leave a panel stranded mid-slide. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
}

/* ---------- agent feed ----------
   A single chronological stream carrying both directions: what the agent asked, and what
   it was told. Open items are tinted so the things waiting on a person never sink below
   the ones already handled. */
.feeditem{border:var(--bw) solid var(--border);border-radius:var(--r-md);padding:.6rem .7rem;
  margin-bottom:.5rem;background:var(--surface);transition:border-color .16s,box-shadow .16s}
.feeditem:hover{border-color:var(--border-strong);box-shadow:var(--shadow-xs)}
.feeditem.open{border-color:var(--hold-border);background:var(--hold-bg)}
.feeditem .fbody{font-size:13px;line-height:1.45;color:var(--text);overflow-wrap:anywhere}
/* AN INCIDENT DETAIL IS FULL OF THINGS THAT DO NOT BREAK: campaign uuids, api paths, email
   addresses, `src/index.js:2723`. Without a wrap rule one of those props the whole card open
   and the PAGE scrolls sideways, which is the one thing a layout must never do. Measured at
   375px on 2026-09-01: the Activity page had a document scrollWidth of 628 against a 375
   viewport, and every other page was clean, because only this card renders raw operational
   prose. Same rule the feed and the rules list already use. */
.incrow{padding:.45rem 0;border-bottom:1px solid var(--border);overflow-wrap:anywhere;min-width:0}
.feeditem .fctx{font-size:11.5px;color:var(--text-muted);margin-top:.25rem;overflow-wrap:anywhere}
.feeditem .fans{font-size:12.5px;color:var(--text-secondary);margin-top:.4rem;padding-top:.4rem;
  border-top:1px solid var(--border);overflow-wrap:anywhere}
.feeditem input[type=text]{min-height:32px;font-size:12.5px}

/* The inbox composer competes with the thread for a fixed column height. A full-size
   textarea left only a sliver of conversation visible on a short screen, so it starts
   compact and grows when focused. */
.composer textarea{min-height:64px}
.composer textarea:focus{min-height:120px}
.inbox .thread .msgs{min-height:180px}

/* ---------- teach the agent: the feedback box that sits under every reply box ---------- */
/* Same border, radius and type scale as .feeditem on the Overview, because it is the same
   act: telling the agent something. It reads as part of the composer, not as a new panel. */
.teach{border-top:var(--bw) solid var(--border);padding:var(--sp-2);background:var(--bg-subtle)}
.teach .th{display:flex;align-items:center;gap:.4rem;font-size:10.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted);margin-bottom:.4rem}
/* Fixed height on purpose. The composer above grows on focus, and copying that here meant
   the box shrank the instant focus left it on mousedown, which moved the Teach button up by
   32px between mousedown and mouseup: a real click landed under the button and did nothing.
   Found by clicking it, not by reading it, because node --check cannot see a layout shift. */
.teach textarea{min-height:64px;font-size:12.5px}
.teach select{width:auto;min-width:150px;font-size:12.5px}
.note{border:var(--bw) solid var(--border);border-radius:var(--r-md);padding:.45rem .6rem;
  background:var(--surface);margin-top:.4rem;font-size:12.5px;line-height:1.45;overflow-wrap:anywhere}
.note .nm{display:flex;align-items:center;gap:.35rem;margin-bottom:.2rem}
/* Scoped to the timestamp, not to .muted. `.pill.muted` also carries the class, so the
   looser selector pushed the topic pill and the "you chose" pill to the right edge too and
   the note header rendered as four widely spaced fragments instead of a row of pills. */
.note .nm .when{margin-left:auto}
.bub .attr{font-size:10.5px;opacity:.8;margin-top:.35rem;padding-top:.3rem;
  border-top:var(--bw) solid currentColor;line-height:1.35}
.rule{border:var(--bw) solid var(--border);border-radius:var(--r-lg);padding:.7rem .85rem;
  background:var(--surface);margin-bottom:.6rem}
.rule.is-superseded{opacity:.72;border-style:dashed}
.rule .rt{font-size:13.5px;line-height:1.5;overflow-wrap:anywhere}
.rule .prov{font-size:11.5px;color:var(--text-muted);margin-top:.45rem;line-height:1.5;overflow-wrap:anywhere}
.rule .verbatim{font-size:12px;color:var(--text-secondary);margin-top:.35rem;padding-left:.6rem;
  border-left:2px solid var(--border-strong);overflow-wrap:anywhere}
.rule textarea{min-height:64px;font-size:13px}

/* ---- Thread dock -------------------------------------------------------
   Reply and Teach were permanently expanded under the message stream and took
   about three quarters of the pane, so the conversation itself was reduced to a
   letterbox. They are tabs now: closed by default, one open at a time. Collapsed
   the dock is a single row of controls, so the stream keeps its height until you
   actually want to type. Uses the existing tokens; nothing here is a new look. */
.dock{border-top:var(--bw) solid var(--border);background:var(--surface);flex:0 0 auto}
.dock-tabs{display:flex;align-items:center;gap:6px;padding:.5rem var(--sp-2)}
.dock-tab{
  appearance:none;background:transparent;border:var(--bw) solid var(--border);
  color:var(--text-muted);font:inherit;font-size:11.5px;font-weight:600;
  padding:.3rem .7rem;border-radius:var(--r-sm);cursor:pointer;
  display:inline-flex;align-items:center;gap:.35rem;
}
.dock-tab:hover{color:var(--text);border-color:var(--text-muted)}
.dock-tab.on{background:var(--pill-bg);border-color:var(--accent);color:var(--accent)}
.dock-tab:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.dock-tab .dot{width:5px;height:5px;border-radius:50%;background:var(--accent);display:inline-block}
.dock-note{
  margin-left:auto;font-size:10.5px;color:var(--text-muted);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:46%;
}
.dock-panel{padding:0 var(--sp-2) var(--sp-2);border-top:var(--bw) solid var(--border)}
.dock-panel[hidden]{display:none}
/* the composer is roomy only once it is open, so the closed state costs one row */
.dock-panel #cmp-body{min-height:84px}
/* the teach box brought its own top border and background; inside the dock that
   would draw a second rule directly under the panel's own. */
.dock-panel .teach{border-top:0;background:transparent;padding:.6rem 0 0}
@media(max-width:720px){.dock-note{display:none}}

/* ── FUNNEL BANDS ───────────────────────────────────────────────────────────────
   Five colours carrying the five stages of the funnel, so its shape is legible
   before a single number is read: sourced, contacted, engaged, deal, onboarded.

   The two sets below are CHOSEN, not flipped. The obvious dark-mode values
   (#48ac8e forest and #deaf02 amber) measure 2.78 and 2.05 against white, under
   the 3.0 a 3px rule needs, so light mode gets its own darker steps. Both sets
   were computed rather than eyeballed: every adjacent pair clears dE 15 in normal
   vision and dE 8 under simulated protanopia and deuteranopia, and every colour
   clears 3.0 contrast on its own surface.

   Colour is a GROUPING cue only. Every tile still carries its own text label, so
   nothing here is identified by colour alone. */
:root{
  --band-a:#767676; --band-b:#5348c9; --band-c:#2b7460; --band-d:#b08800; --band-e:#0a6f50;
}
:root[data-theme="dark"], :root:not([data-theme="light"]){
  --band-a:#8b8b8b; --band-b:#6358de; --band-c:#48ac8e; --band-d:#deaf02; --band-e:#12a878;
}
:root[data-theme="light"]{
  --band-a:#767676; --band-b:#5348c9; --band-c:#2b7460; --band-d:#b08800; --band-e:#0a6f50;
}
.tiles.funnel .tile{position:relative;padding-left:.9rem}
.tiles.funnel .tile::before{
  content:"";position:absolute;left:0;top:.55rem;bottom:.55rem;width:3px;
  border-radius:0 3px 3px 0;background:var(--band,var(--border));
}
.tile.band-a{--band:var(--band-a)} .tile.band-b{--band:var(--band-b)}
.tile.band-c{--band:var(--band-c)} .tile.band-d{--band:var(--band-d)}
.tile.band-e{--band:var(--band-e)}
/* The North Star earns a little more weight than a rule: it is the number the whole
   system exists to move, and it sat at the far end of a 16 tile grid. */
.tile.band-e{background:color-mix(in srgb,var(--band-e) 6%,var(--surface))}
.tile.band-e .n{color:var(--band-e)}

/* Feed priority. Reuses the existing status hues rather than inventing a fourth scale:
   these mean the same thing here as everywhere else in the app. */
.pill.prio-high{background:var(--tulip-100);color:var(--tulip-800);border-color:transparent;font-weight:700}
.pill.prio-mid{background:var(--sun-100);color:var(--coral-900);border-color:transparent}
.pill.prio-low{background:var(--pill-bg);color:var(--text-muted);border-color:transparent}
:root[data-theme="dark"] .pill.prio-high,:root:not([data-theme="light"]) .pill.prio-high{background:rgba(207,26,59,.18);color:#ff8a9c}
:root[data-theme="dark"] .pill.prio-mid,:root:not([data-theme="light"]) .pill.prio-mid{background:rgba(222,175,2,.16);color:#e8c65a}
