/* ui.css — the MergeSearch UI kit. THE component layer for the whole signed-in app:
   the client portal (portal.js), the admin console (admin.js) and the support Inbox (mail.js)
   all build their screens out of exactly these pieces.

   THE CONTRACT
   ────────────
   1. Nothing here hard-codes a colour, a font or a shadow. Every value is a brand.css token
      (--paper/--raised/--ink/--line/--emerald/--display/--body/--shadow/--ease) or one of the
      layout tokens below, so light/dark and any future re-skin move in one place.
   2. A screen is composed, never styled. No `style="…"` in the JS, no per-view CSS that
      re-invents a card, a table, a pill or a button. If a screen needs something this file
      doesn't have, the component goes HERE first — then the screen uses it.
   3. The render helpers in ui.js (window.MSUI) emit exactly this markup. Prefer them over
      writing the class names by hand; that's what keeps the two portals from drifting again.

   Load order: brand.css (tokens) → ui.css (components) → portal.css (page layout).
   portal.css owns WHERE things sit on a given screen; this file owns WHAT they look like. */

/* ===========================================================================
   LAYOUT SCALE — one spacing/sizing/radius system for every surface
   =========================================================================== */
:root{
  --side-w:270px;
  --pad-x:clamp(20px,3vw,44px);
  --pad-y:clamp(26px,3vw,44px);
  --gap:20px;
  --gap-sm:14px;
  /* Three radii, one meaning each. Top-level surfaces (cards, table wraps, modals) take
     --radius-lg; boxes nested INSIDE a surface take --radius; controls and chips take
     --radius-sm. Admin used to sit a step tighter than the client portal — that mismatch
     was the most visible "these are two different products" tell. */
  --radius-lg:22px;
  --radius:16px;
  --radius-sm:12px;
  --ring:0 0 0 3px color-mix(in srgb,var(--emerald) 18%,transparent);
  /* ONE row tint. Hover is the only state that changes a row's surface — open rows keep the page
     background. Stacking an "open" shade and an "open + hover" shade on top of this meant a single
     row could be four different colours, which reads as decoration rather than as information. */
  --row-hover:color-mix(in srgb,var(--emerald) 4%,transparent);
  /* semantic status colours — the ONE place a non-brand hue is defined */
  --danger:#c0392b;
  --danger-ink:#c0392b;
  --warn:#c8890f;
  --warn-ink:#9a6a12;
}
:root[data-theme="dark"]{ --danger-ink:#f2a79c; --warn-ink:#e6b667; }

/* ===========================================================================
   BUTTONS — one action language everywhere
   =========================================================================== */
.btn-emerald{font-family:var(--body); font-size:14px; font-weight:600; letter-spacing:-.01em; text-decoration:none;
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  color:#fff; background:var(--emerald); border:1px solid var(--emerald); border-radius:999px;
  padding:11px 20px; cursor:pointer; transition:background .16s var(--ease), transform .16s var(--ease), box-shadow .16s var(--ease);}
:root[data-theme="dark"] .btn-emerald{color:#08130E;}
.btn-emerald:hover{background:var(--emerald-dark); border-color:var(--emerald-dark); box-shadow:var(--shadow);}
.btn-emerald:active{transform:translateY(1px);}
.btn-emerald:focus-visible{outline:2px solid var(--emerald); outline-offset:2px;}
.btn-emerald[disabled],.btn-ghost[disabled]{opacity:.5; cursor:default; pointer-events:none;}

.btn-ghost{font-family:var(--body); font-size:13.5px; font-weight:600; letter-spacing:-.01em; text-decoration:none;
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  color:var(--ink-soft); background:transparent; border:1px solid var(--line-strong); border-radius:999px;
  padding:10px 18px; cursor:pointer; transition:border-color .16s var(--ease), color .16s var(--ease), background .16s var(--ease);}
.btn-ghost:hover{border-color:var(--emerald); color:var(--emerald);}
.btn-ghost:focus-visible{outline:2px solid var(--emerald); outline-offset:2px;}

.btn-ghost.sm, .btn-emerald.sm{font-size:12px; padding:8px 14px; min-height:36px;}
.btn-ghost.danger{border-color:color-mix(in srgb,var(--danger) 30%,var(--line-strong)); color:color-mix(in srgb,var(--danger) 78%,var(--ink-soft));}
.btn-ghost.danger:hover{border-color:var(--danger); color:var(--danger); background:color-mix(in srgb,var(--danger) 8%,transparent);}
:root[data-theme="dark"] .btn-ghost.danger{color:#e88a7d; border-color:color-mix(in srgb,#e88a7d 34%,transparent);}
:root[data-theme="dark"] .btn-ghost.danger:hover{color:#f2a79c; border-color:#e88a7d;}

/* a quiet text-weight action inside prose or a note — no chrome, just an affordance */
.btn-link{font-family:var(--body); font-size:inherit; font-weight:600; color:inherit;
  background:none; border:0; padding:0; cursor:pointer; text-decoration:underline;
  text-underline-offset:2px;}
.btn-link:hover{opacity:.75;}

/* a row of actions (card foot, modal foot, toolbar tail) */
.btn-row{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}

/* ===========================================================================
   PAGE HEADER — the ONE title block. Every screen in both portals opens with it.
   Optional: eyebrow · back link · lede · meta strip · action slot.
   =========================================================================== */
.pg-head{display:flex; align-items:flex-end; justify-content:space-between; gap:18px 26px; flex-wrap:wrap; margin:0 0 30px;}
/* The title block takes the room it needs but yields rather than pushing the action onto its own
   line — a page's primary action belongs beside the title, not orphaned beneath a long lede. */
.pg-head-l{flex:1 1 420px; min-width:0;}
.pg-head h1{font-family:var(--display); font-size:clamp(1.9rem,3.2vw,2.6rem); font-weight:500; letter-spacing:-.02em; margin:0;}
.pg-eyebrow{display:block; font-size:11.5px; font-weight:600; letter-spacing:.13em; text-transform:uppercase;
  color:var(--emerald); margin:0 0 7px;}
.pg-back{display:inline-flex; align-items:center; gap:7px; font-size:12.5px; color:var(--muted);
  text-decoration:none; padding:0 0 12px; transition:color .16s var(--ease);}
.pg-back:hover{color:var(--emerald);}
.pg-lede{color:var(--muted); font-size:14.5px; line-height:1.6; margin:11px 0 0; max-width:66ch;}
.pg-lede b{color:var(--ink-soft); font-weight:600;}
.pg-head-act{flex:none; display:inline-flex; align-items:center; gap:8px; flex-wrap:wrap;}
/* the meta strip under a detail title — identity chips, codes, dates */
.pg-meta{margin-top:14px; display:flex; align-items:center; gap:8px 14px; flex-wrap:wrap;
  font-size:12.5px; color:var(--muted);}

/* a monospace identifier (client code, stripe ref, slug) */
.ms-code{font-family:var(--mono,ui-monospace,SFMono-Regular,Menlo,monospace); font-size:11px; color:var(--ink-soft);
  background:var(--paper); border:1px solid var(--line); border-radius:6px; padding:2px 7px;}

/* a section rule inside a long page */
.sec-title{display:flex; align-items:baseline; gap:14px; margin:0 0 20px;}
.sec-title h2{font-family:var(--display); font-size:clamp(1.25rem,2vw,1.55rem); font-weight:500; letter-spacing:-.02em;}
.sec-title .rule{flex:1; height:1px; background:var(--line); align-self:center;}

/* ===========================================================================
   CARD — the ONE surface. Everything that sits on the page background is one of these.
     .ms-card              base
     .ms-card.flush        no padding (a table or list owns the full box)
     .ms-card.accent       subtle emphasis for a primary action (NO left-edge bar — house rule)
     .ms-card.inner        a box nested inside another card (tighter radius, paper background)
   =========================================================================== */
.ms-card{background:var(--raised); border:1px solid var(--line); border-radius:var(--radius-lg);
  padding:22px 24px 20px; min-width:0;}
.ms-card.flush{padding:0; overflow:hidden;}
.ms-card.accent{border-color:var(--line);
  background:linear-gradient(180deg,color-mix(in srgb,var(--emerald) 4%,var(--raised)),var(--raised) 42%);}
:root[data-theme="dark"] .ms-card.accent{background:linear-gradient(180deg,color-mix(in srgb,var(--emerald) 8%,var(--raised)),var(--raised) 46%);}
.ms-card.inner{border-radius:var(--radius); background:var(--paper); padding:14px 16px;}

/* card header — title, optional sub, and a right-hand count/link/action */
.ms-card-head{display:flex; align-items:baseline; justify-content:space-between; gap:12px; margin:0 0 4px;}
.ms-card-head h3{font-family:var(--display); font-weight:500; font-size:1.2rem; letter-spacing:-.01em; margin:0;}
.ms-card-sub{font-size:12.5px; color:var(--muted); margin:0 0 16px; line-height:1.55; max-width:78ch;}
.ms-card-sub b{color:var(--ink-soft); font-weight:600;}
.ms-card-sub code{font-size:11.5px; background:var(--paper); border:1px solid var(--line); border-radius:6px; padding:1px 5px;}
.ms-card.flush > .ms-card-head{padding:20px 22px 0;}
.ms-card.flush > .ms-card-sub{padding:0 22px;}
.ms-card-foot{display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-top:16px; padding-top:16px;
  border-top:1px solid var(--line);}

/* the right-hand slot in a card head */
.ms-count{flex:none; font-size:11px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--muted);
  background:var(--paper); border:1px solid var(--line); border-radius:999px; padding:3px 10px; white-space:nowrap;}
.ms-cardlink{flex:none; font-size:12.5px; font-weight:600; color:var(--emerald); text-decoration:none; white-space:nowrap;}
.ms-cardlink:hover{text-decoration:underline;}

/* ===========================================================================
   SPLIT — main column + supporting rail. The ONE two-column working layout.
     .ms-split            2fr / 1fr  (a table beside a form)
     .ms-split.wide-main  1.5fr / 1fr (a detail page: substance left, actions right)
     .ms-split.even       1fr / 1fr
   Stacked children get vertical rhythm for free.
   =========================================================================== */
.ms-split{display:grid; grid-template-columns:minmax(0,2fr) minmax(300px,1fr);
  gap:clamp(20px,2.4vw,32px); align-items:start;}
.ms-split.wide-main{grid-template-columns:minmax(0,1.5fr) minmax(300px,1fr);}
.ms-split.even{grid-template-columns:minmax(0,1fr) minmax(0,1fr);}
.ms-split > *{display:flex; flex-direction:column; gap:var(--gap); min-width:0;}
@media (max-width:1000px){ .ms-split, .ms-split.wide-main, .ms-split.even{grid-template-columns:1fr;} }

/* a vertical stack of cards outside a split */
.ms-stack{display:flex; flex-direction:column; gap:var(--gap); min-width:0;}

/* ===========================================================================
   STAT — the KPI card and the thin KPI strip
   =========================================================================== */
.stat-row{display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:var(--gap); margin:0 0 34px;}
.stat{background:var(--raised); border:1px solid var(--line); border-radius:var(--radius-lg); padding:18px 20px;
  display:flex; flex-direction:column; gap:6px;}
.stat .st-k{font-size:10.5px; font-weight:600; letter-spacing:.11em; text-transform:uppercase; color:var(--muted);}
.stat .st-v{font-family:var(--display); font-weight:500; font-size:2rem; line-height:1; letter-spacing:-.02em; color:var(--ink);
  font-variant-numeric:tabular-nums;}
.stat .st-v small{font-size:14px; color:var(--muted); font-weight:400;}
.stat .st-s{font-size:12px; color:var(--ink-soft); margin-top:auto;}
.stat .st-s .up{color:var(--emerald); font-weight:700;}

/* the compact one-line variant — a dense figure strip above a working table */
.ms-kpis{display:flex; align-items:center; gap:8px 26px; flex-wrap:wrap; margin:0 0 var(--gap);
  background:var(--raised); border:1px solid var(--line); border-radius:var(--radius-lg); padding:14px 20px;}
.ms-kpi{display:inline-flex; align-items:baseline; gap:7px; white-space:nowrap;}
.ms-kpi b{font-family:var(--display); font-weight:500; font-size:1.25rem; line-height:1; color:var(--ink);
  font-variant-numeric:tabular-nums;}
.ms-kpi span{font-size:12px; color:var(--muted);}
.ms-kpi.bad b{color:var(--danger-ink);}
.ms-kpi.good b{color:var(--emerald);}

/* ===========================================================================
   PILL — the ONE status token. Tone carries the meaning; never a bare colour.
     .ms-pill            neutral   .ok emerald   .warn amber   .bad red   .info cool
     .ms-pill.dot        leading status dot
   =========================================================================== */
.ms-pill{display:inline-flex; align-items:center; gap:6px; font-size:10.5px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; border-radius:999px; padding:3px 10px; white-space:nowrap;
  background:var(--paper-2); color:var(--ink-soft);}
.ms-pill.dot::before{content:""; width:5px; height:5px; border-radius:50%; background:currentColor; flex:none;}
.ms-pill.ok{background:var(--emerald-tint); color:var(--emerald);}
.ms-pill.warn{background:color-mix(in srgb,var(--warn) 14%,transparent); color:var(--warn-ink);}
.ms-pill.bad{background:color-mix(in srgb,var(--danger) 12%,transparent); color:var(--danger-ink);}
.ms-pill.info{background:color-mix(in srgb,#3d7fa8 12%,transparent); color:#2b6a90;}
:root[data-theme="dark"] .ms-pill.info{color:#8fc3e0;}
.ms-pill.quiet{background:transparent; border:1px solid var(--line-strong); color:var(--muted);}

/* ===========================================================================
   FORM — fields, selects, textareas. One control skin across both portals.
   =========================================================================== */
.field{display:flex; flex-direction:column; gap:6px; margin-bottom:16px; min-width:0;}
.field > label{font-size:10.5px; letter-spacing:.12em; text-transform:uppercase; color:var(--muted); font-weight:600;}
.field input, .field select, .field textarea,
.ms-input, .ms-select{
  font-family:var(--body); font-size:15px; color:var(--ink); background:var(--raised);
  border:1px solid var(--line-strong); border-radius:var(--radius-sm); padding:12px 14px; min-width:0;
  transition:border-color .16s var(--ease), box-shadow .16s var(--ease);}
.field input::placeholder, .ms-input::placeholder{color:var(--muted); opacity:.7;}
.field input:focus, .field select:focus, .field textarea:focus,
.ms-input:focus, .ms-select:focus{outline:none; border-color:var(--emerald); box-shadow:var(--ring);}
.field textarea{line-height:1.55; resize:vertical; min-height:96px; font-size:14px;}

.ms-input.sm, .ms-select.sm{font-size:13.5px; padding:9px 12px;}
.ms-select.sm{padding-right:32px;}
/* a native select needs the chevron drawn in — appearance:none kills the platform one */
.field select, .ms-select{appearance:none; -webkit-appearance:none; cursor:pointer; padding-right:36px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 13px center; background-size:12px;}

/* a form laid out inside a card */
.ms-form{display:flex; flex-direction:column; gap:14px;}
.ms-form .field{margin-bottom:0;}
/* the inline status line every form writes its result into */
.ms-msg{font-size:12.5px; min-height:1em; color:var(--muted);}
.ms-msg.ok{color:var(--emerald);}
.ms-msg.ok a{color:var(--emerald); font-weight:600;}
.ms-msg.err{color:var(--danger-ink);}
/* a form appended below existing content inside the same card */
.ms-form-inline{margin-top:16px; padding-top:16px; border-top:1px solid var(--line);}

/* ===========================================================================
   TABLE — the ONE data table.
     interactive : MSUI.table(mount, cfg)   → toolbar (search · facets · count) + sortable table
     static      : MSUI.tableHTML(cfg)      → the same skin, no toolbar, for short embedded lists
   Both render .mst-table inside .mst-wrap, so a table looks identical wherever it appears.
   =========================================================================== */
.mst{display:block;}
.mst-bar{display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:14px;}
.mst-search{position:relative; display:inline-flex; align-items:center; flex:1 1 240px; max-width:340px;}
.mst-q-ic{position:absolute; left:14px; width:15px; height:15px; color:var(--muted); pointer-events:none;}
.mst-q{width:100%; font-family:var(--body); font-size:13.5px; color:var(--ink); background:var(--paper);
  border:1px solid var(--line-strong); border-radius:999px; padding:9px 16px 9px 37px; transition:border-color .15s var(--ease);}
.mst-q:focus{outline:none; border-color:var(--emerald);}
.mst-q::placeholder{color:var(--muted);}
.mst-facet{display:inline-flex;}

/* ---- MENU: the one dropdown (replaces every native select) ----------------- */
/* A native <select> draws an OS popup — macOS chrome dropped into a designed product. This is a
   real listbox, so the open state looks like the rest of the app and behaves the same everywhere. */
.ms-menu{position:relative; display:inline-flex;}
.ms-menu-btn{display:inline-flex; align-items:center; gap:8px; font-family:var(--body); font-size:12.5px;
  font-weight:500; color:var(--ink-soft); background:var(--paper); border:1px solid var(--line-strong);
  border-radius:999px; padding:9px 14px; cursor:pointer; white-space:nowrap;
  transition:border-color .15s var(--ease), color .15s var(--ease), background .15s var(--ease);}
.ms-menu-btn:hover{border-color:var(--emerald); color:var(--emerald);}
.ms-menu-btn:focus-visible{outline:2px solid var(--emerald); outline-offset:2px;}
.ms-menu.is-open .ms-menu-btn{border-color:var(--emerald); color:var(--emerald);
  background:color-mix(in srgb,var(--emerald) 6%,var(--paper));}
.ms-menu-caret{width:13px; height:13px; flex:none; opacity:.6; transition:transform .18s var(--ease);}
.ms-menu.is-open .ms-menu-caret{transform:rotate(180deg); opacity:1;}

.ms-menu-list{position:absolute; top:calc(100% + 6px); left:0; z-index:60; min-width:100%;
  max-width:340px; max-height:min(52vh,380px); overflow-y:auto; padding:6px;
  background:var(--raised); border:1px solid var(--line-strong); border-radius:var(--radius);
  box-shadow:var(--shadow); animation:ms-menu-in .14s var(--ease);}
@keyframes ms-menu-in{from{opacity:0; transform:translateY(-4px);} to{opacity:1; transform:none;}}
.ms-menu-opt{display:flex; align-items:center; gap:9px; width:100%; text-align:left;
  font-family:var(--body); font-size:13px; color:var(--ink-soft); background:none; border:0;
  border-radius:var(--radius-sm); padding:8px 10px; cursor:pointer; white-space:nowrap;
  transition:background .12s var(--ease), color .12s var(--ease);}
.ms-menu-opt:hover, .ms-menu-opt:focus-visible{outline:none; background:var(--paper-2); color:var(--ink);}
/* selection is a filled row + a tick — never a left-edge accent bar (house rule) */
.ms-menu-opt.is-on{background:var(--emerald-tint); color:var(--emerald); font-weight:600;}
.ms-menu-tick{flex:none; width:13px; height:13px; opacity:0;
  background:currentColor; -webkit-mask:var(--tick) center/contain no-repeat; mask:var(--tick) center/contain no-repeat;}
.ms-menu-opt.is-on .ms-menu-tick{opacity:1;}
:root{--tick:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 13 4 4L19 7'/%3E%3C/svg%3E");}
@media (prefers-reduced-motion:reduce){ .ms-menu-list{animation:none;} .ms-menu-caret{transition:none;} }

.mst-count{margin-left:auto; font-size:12px; color:var(--muted); white-space:nowrap;}
/* an action that rides along in the table toolbar (e.g. "+ Add client") */
.mst-bar .mst-act{margin-left:auto; display:inline-flex; gap:8px;}
.mst-bar .mst-act ~ .mst-count{margin-left:0;}

.mst-wrap{background:var(--raised); border:1px solid var(--line); border-radius:var(--radius-lg); overflow-x:auto;}
/* A wide table on a phone SCROLLS rather than squeezing every cell to one word per line. Column
   `priority` drops the least important columns first; below that floor the wrap takes over. */
.mst-table{width:100%; min-width:min(560px,100%); border-collapse:collapse; font-size:13.5px;}
.mst-th{text-align:left; font-size:10.5px; font-weight:700; letter-spacing:.1em; text-transform:uppercase;
  color:var(--muted); padding:13px 18px; border-bottom:1px solid var(--line); background:var(--paper-2); white-space:nowrap; user-select:none;}
.mst-th-in{display:inline-flex; align-items:center; gap:6px;}
.mst-sortable{cursor:pointer; transition:color .14s var(--ease);}
.mst-sortable:hover{color:var(--ink-soft);}
.mst-sortable:focus-visible{outline:2px solid var(--emerald); outline-offset:-2px;}
.mst-caret{width:0; height:0; border-left:3.5px solid transparent; border-right:3.5px solid transparent; opacity:0; transition:opacity .14s var(--ease);}
.mst-sortable:hover .mst-caret{opacity:.4; border-bottom:5px solid currentColor;}
.mst-th.is-asc .mst-caret{opacity:.9; border-bottom:5px solid currentColor; border-top:0;}
.mst-th.is-desc .mst-caret{opacity:.9; border-top:5px solid currentColor; border-bottom:0;}
.mst-table td{padding:13px 18px; border-bottom:1px solid var(--line); color:var(--ink-soft); vertical-align:middle;}
.mst-table tbody tr:last-child td{border-bottom:0;}
.mst-tr[data-href]{cursor:pointer;}
.mst-table tbody tr{transition:background .13s var(--ease);}
/* :not(.mst-detail) — an expanded detail is not a row of its own and is not clickable, so it never
   highlights. Hover belongs to things you can act on. */
.mst-table tbody tr:not(.mst-detail):hover > td{background:var(--row-hover);}
.mst-tr:focus-visible{outline:2px solid var(--emerald); outline-offset:-2px;}
.mst-table .ta-c{text-align:center;} .mst-table .ta-r{text-align:right;} .mst-table .nowrap{white-space:nowrap;}
.mst-table .num{text-align:right; font-variant-numeric:tabular-nums;}
/* THE column of a table — the one carrying the meaning. `width:100%` on one cell makes the browser
   give it every pixel the others don't need, so the metadata columns collapse to their content and
   the table stops overflowing instead of pushing its most valuable column off the screen. */
.mst-table .grow{width:100%;}
/* the primary cell — a title with an optional supporting line beneath */
.mst-title{display:block; font-weight:600; color:var(--ink); text-decoration:none;}
a.mst-title:hover{color:var(--emerald);}
.mst-sub{display:block; font-size:12px; color:var(--muted); line-height:1.45; margin-top:3px; max-width:54ch;}
.mst-code{font-family:var(--mono,ui-monospace,SFMono-Regular,Menlo,monospace); font-size:11px; color:var(--muted);}
/* the trailing affordance column */
.mst-go{width:1%; text-align:right; padding-left:0; white-space:nowrap;}
.mst-chev{color:var(--muted); font-size:20px; line-height:1; transition:color .12s var(--ease), transform .12s var(--ease);}
.mst-tr:hover .mst-chev{color:var(--emerald); transform:translateX(2px);}
.mst-none{padding:30px 18px; text-align:center; font-size:13px; color:var(--muted);
  background:var(--raised); border:1px solid var(--line); border-radius:var(--radius-lg);}
/* a table that fills a .ms-card.flush loses its own frame — the card is the frame */
.ms-card.flush > .mst-wrap, .ms-card.flush > .mst .mst-wrap{border:0; border-radius:0; background:transparent;}
/* ---- expandable rows: the summary stays scannable, the record is one click down ---- */
.mst-expandable{cursor:pointer;}
.mst-expandable > td:first-child{position:relative; padding-left:34px;}
.mst-expandable > td:first-child::before{content:""; position:absolute; left:16px; top:50%;
  width:0; height:0; margin-top:-3.5px;
  border-left:5px solid color-mix(in srgb,var(--muted) 70%,transparent);
  border-top:3.5px solid transparent; border-bottom:3.5px solid transparent;
  transition:transform .16s var(--ease); transform-origin:2px 50%;}
.mst-expandable.is-open > td:first-child::before{transform:rotate(90deg); border-left-color:var(--emerald);}
.mst-th:first-child{padding-left:34px;}

/* The open row and its detail are ONE unit, not a card floating inside a cell. The row keeps its
   tint, drops its bottom rule so the two read as continuous, and the detail is a full-bleed band on
   the same left margin as the row's first column — no inner border, no second radius. An earlier
   version nested a bordered, rounded panel inside a tinted cell and read as debris. */
/* An open row and its detail are ONE object, made continuous by removing what separates them rather
   than by painting them a shared colour: the summary drops its bottom rule, the detail carries no
   surface of its own, and a single rule under the detail closes the pair. No tint, no inner border,
   no second radius — the rotated caret and the indent already say which row is open. */
.mst-expandable.is-open > td{border-bottom-color:transparent;}
.mst-detail > td{padding:0; border-bottom:1px solid var(--line);}
.mst-detail-in{padding:2px 22px 22px 34px; animation:ms-detail-in .16s var(--ease);}
/* Hover means "this responds to a click". An open row has already answered that, so it stops
   highlighting — and the detail beneath it was never a click target to begin with. */
.mst-expandable.is-open:hover > td{background:transparent;}
@keyframes ms-detail-in{from{opacity:0; transform:translateY(-3px);} to{opacity:1; transform:none;}}
@media (prefers-reduced-motion:reduce){ .mst-detail-in{animation:none;} }

/* row emphasis — a state the row is IN, never decoration */
.mst-tr.is-urgent td{background:color-mix(in srgb,var(--danger) 5%,transparent);}
@media (max-width:640px){ .mst-p2{display:none;} .mst-count{order:5; width:100%; margin:0;} }
@media (max-width:440px){ .mst-p3{display:none;} }

/* ===========================================================================
   EMPTY STATE — what a screen says when there is nothing to show
   =========================================================================== */
.ms-empty{background:var(--raised); border:1px dashed var(--line-strong); border-radius:var(--radius-lg);
  padding:40px 26px; text-align:center;}
.ms-empty h4{font-family:var(--display); font-weight:500; font-size:1.05rem; color:var(--ink-soft); margin:0 0 6px;}
.ms-empty p{font-size:13.5px; color:var(--muted); margin:0 auto; max-width:52ch; line-height:1.6;}
.ms-empty .btn-row{justify-content:center; margin-top:18px;}
/* the quiet inline variant, for an empty region inside a card */
.ms-empty.inline{background:none; border:0; padding:20px 0 8px; font-style:italic; color:var(--muted); font-size:13px;}

/* ===========================================================================
   NOTE — a one-line contextual message. Tone matches .ms-pill.
   =========================================================================== */
.ms-note{font-size:13px; line-height:1.55; border-radius:var(--radius); padding:11px 14px; margin:0 0 20px;
  color:var(--emerald); background:var(--emerald-tint); border:1px solid color-mix(in srgb,var(--emerald) 28%,transparent);}
.ms-note.warn{color:var(--warn-ink); background:color-mix(in srgb,var(--warn) 10%,transparent);
  border-color:color-mix(in srgb,var(--warn) 30%,transparent);}
.ms-note.bad{color:var(--danger-ink); background:color-mix(in srgb,var(--danger) 8%,transparent);
  border-color:color-mix(in srgb,var(--danger) 28%,transparent);}
.ms-note.quiet{color:var(--muted); background:var(--paper-2); border-color:var(--line);}

/* ===========================================================================
   MODAL — the ONE dialog (confirm, pick-and-confirm, short flows)
   =========================================================================== */
.ms-modal-scrim{position:fixed; inset:0; z-index:70; display:flex; align-items:center; justify-content:center; padding:24px;
  background:color-mix(in srgb,var(--ink) 52%,transparent); backdrop-filter:blur(3px);}
.ms-modal{position:relative; width:100%; max-width:460px; background:var(--raised); border:1px solid var(--line-strong);
  border-radius:var(--radius-lg); box-shadow:var(--shadow); animation:ms-rise .22s var(--ease); max-height:88vh;
  display:flex; flex-direction:column;}
@keyframes ms-rise{from{opacity:0; transform:translateY(10px) scale(.99);} to{opacity:1; transform:none;}}
.ms-modal-head{display:flex; align-items:flex-start; justify-content:space-between; gap:12px; padding:24px 26px 0;}
.ms-modal-head h2, .ms-modal-head h3{font-family:var(--display); font-weight:500; font-size:1.3rem; letter-spacing:-.02em;
  margin:0; color:var(--ink);}
.ms-modal-x{font-size:24px; line-height:1; color:var(--muted); background:none; border:0; cursor:pointer; padding:0 2px;
  transition:color .14s var(--ease);}
.ms-modal-x:hover{color:var(--ink);}
.ms-modal-body{padding:12px 26px 4px; overflow-y:auto; min-height:0;}
.ms-modal-lede{font-size:14px; line-height:1.6; color:var(--ink-soft); margin:0;}
.ms-modal-lede b{color:var(--ink); font-weight:600;}
.ms-modal-foot{display:flex; justify-content:flex-end; gap:10px; padding:18px 26px 22px; flex-wrap:wrap;}
.ms-modal .field{margin:14px 0 0;}
.ms-modal.wide{max-width:640px;}

/* ===========================================================================
   FEED — a chronological list of things that happened (activity, timeline, events)
   =========================================================================== */
.ms-feed{display:flex; flex-direction:column;}
.ms-feed-row{display:flex; align-items:baseline; gap:11px; padding:11px 0; border-bottom:1px solid var(--line);}
.ms-feed-row:last-child{border-bottom:0;}
.ms-feed-dot{flex:none; width:7px; height:7px; border-radius:50%; background:var(--emerald); transform:translateY(-1px);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--emerald) 16%,transparent);}
.ms-feed-dot.warn{background:var(--warn); box-shadow:0 0 0 3px color-mix(in srgb,var(--warn) 18%,transparent);}
.ms-feed-dot.bad{background:var(--danger); box-shadow:0 0 0 3px color-mix(in srgb,var(--danger) 16%,transparent);}
.ms-feed-dot.quiet{background:var(--line-strong); box-shadow:none;}
.ms-feed-body{flex:1; min-width:0; display:flex; flex-direction:column; gap:2px;}
.ms-feed-what{font-size:13.5px; color:var(--ink); line-height:1.5;}
.ms-feed-what b{font-weight:600;}
.ms-feed-detail{font-size:12px; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.ms-feed-when{flex:none; font-size:11px; color:var(--muted); white-space:nowrap;}

/* ===========================================================================
   BARS — a labelled proportion list (top queries, lead mix, funnel steps)
   =========================================================================== */
.ms-bars{display:flex; flex-direction:column; gap:9px;}
.ms-bar{display:grid; grid-template-columns:minmax(90px,var(--bar-label,150px)) minmax(60px,1fr) auto;
  gap:12px; align-items:center;}
.ms-bar-l{font-size:12.5px; color:var(--ink-soft); font-weight:500; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.ms-bar-t{height:9px; background:color-mix(in srgb,var(--line) 72%,var(--paper)); border-radius:999px; overflow:hidden;}
.ms-bar-f{display:block; height:100%; border-radius:999px; background:var(--bar,var(--emerald)); min-width:3px;}
.ms-bar-n{font-size:12.5px; color:var(--ink); font-weight:600; font-variant-numeric:tabular-nums; text-align:right; min-width:44px;}
/* a categorised bar carries a leading dot in its own colour; the category class sets --bar */
.ms-bar-dot{display:inline-block; width:7px; height:7px; border-radius:50%; margin-right:7px;
  vertical-align:middle; background:var(--bar,var(--emerald));}

/* ===========================================================================
   DIFF — a before/after text pair (the SEO agent's page-edit proposals).
   The proposed side is marked by a tint + label, never a left-edge accent bar.
   =========================================================================== */
.ms-diff{display:flex; flex-direction:column; gap:8px; margin:10px 0 0;}
.ms-diffbox{border:1px solid var(--line); border-radius:var(--radius); padding:11px 14px; background:var(--paper);
  font-size:13px; line-height:1.55; color:var(--ink-soft);}
.ms-diffbox.proposed{border-color:color-mix(in srgb,var(--emerald) 34%,transparent); background:var(--emerald-tint);
  color:var(--emerald-ink);}
:root[data-theme="dark"] .ms-diffbox.proposed{color:var(--ink);}
.ms-difflabel{display:block; font-size:9.5px; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
  color:var(--muted); margin:0 0 5px;}
.ms-diffbox.proposed .ms-difflabel{color:var(--emerald);}

/* ===========================================================================
   PROSE — server/agent-authored copy rendered inside a card (rationales, briefs)
   =========================================================================== */
.ms-prose{font-size:13.5px; line-height:1.6; color:var(--ink-soft);}
.ms-prose > :first-child{margin-top:0;}
.ms-prose > :last-child{margin-bottom:0;}
.ms-prose p{margin:0 0 11px;}
.ms-prose h4{font-family:var(--display); font-weight:500; font-size:1.02rem; color:var(--ink); margin:16px 0 5px;}
.ms-prose ul{margin:4px 0 12px; padding-left:18px;}
.ms-prose li{margin:3px 0; line-height:1.55;}

/* ===========================================================================
   UTILITIES — the small, honest ones. Anything beyond this belongs in a component.
   =========================================================================== */
.ta-c{text-align:center;} .ta-r{text-align:right;} .nowrap{white-space:nowrap;}
.ms-muted{color:var(--muted);}
.ms-muted-i{color:var(--muted); font-style:italic;}
