/* Core's component CSS — tables, cards, pills, drawers and the rest of the furniture its screens
   are built from.
 *
 * ## This file no longer defines the design tokens, and that is the consolidation's doing
 *
 * It used to open with a full `:root` and a full `:root[data-theme="dark"]` — a TRIMMED COPY of
 * `/components/design-foundation.css`, made back when Core was its own deployment and did not link
 * the foundation. Both are deleted. The foundation is linked ahead of this file by `index.html` and
 * is the one source now.
 *
 * **The dark block had to go, not merely ought to have.** It selected
 * `:root[data-theme="dark"]` (specificity 0,2,0) where the foundation's selects `html.dark`
 * (0,1,1). With one theme controller setting BOTH — which is what lets 579 hand-written rules in
 * this file keep selecting on `data-theme` — Core's copy won every collision, so merely putting the
 * three apps in one page would have silently repainted every Agent screen's dark mode in Core's
 * palette. Nobody would have chosen that; nobody would have noticed it either.
 *
 * What survives is the two things Core genuinely owns rather than inherited.
 */

/* **The WCAG AA correction, kept and now platform-wide.** The foundation carries #0e8a6c and
   #b76b00, which measure 3.97:1 and 3.77:1 as text on their own tints — under the 4.5:1 AA floor,
   and both are used AS TEXT on those tints by every pill and banner. These clear it at 4.51 and are
   visually indistinguishable. Flagged in the signed-off Emails mock-up.

   It was Core's alone before the merge, which meant Agent and Commercial shipped the failing pair.
   Applying it here now applies it everywhere, which is the argument the original comment already
   made — "a token fixed in one place is a token that has drifted" — finally taken to its end.

   Light only. The foundation's dark steps clear AA on their tints (6.7–7.8:1) and are unchanged. */
:root {
  --status-green: #0d8064;
  --status-amber: #a56000;
}

/* Core's rail is 252px where the foundation says 248px. Kept because this file's own chrome rules
   measure against it. The PORTAL's rail reads `--rail-w` from `src/styles/tokens.css`. */
:root { --nav-w: 252px; }

/* the topbar's lavender wash becomes a dark surface */
:root[data-theme="dark"] .topbar { background: #14111c; }
/* the sidebar is already dark — nudge it a touch darker than the content */
:root[data-theme="dark"] .nav { background: #100e17; }

/* Theme toggle control (top-right) */
.theme-toggle { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); cursor: pointer; padding: 0; font-size: 15px; line-height: 1; }
.theme-toggle:hover { color: var(--text); border-color: var(--accent); }

* { box-sizing: border-box; }
/* `body`'s own background, colour and font are set ONCE, in `src/styles/tokens.css`. What stays
   here is the pair this file's screens measure against — a 16px root and the antialiasing — which
   the foundation does not set. */
body {
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
.mono { font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 12px; }

/* ===== APP SHELL — mirrored VERBATIM from the canonical Commercial chrome
   (commercial-module @ 4906fd7, Roger's ruling 2026-07-26). Adapted only for
   Core's accent pair (ink #5B3FD1 / vivid #8B7CF8; dark #8B7CF8) and our
   data-theme attribute (Commercial toggles html.dark). ===== */
:root { --core-ink: #5B3FD1; --core-vivid: #8B7CF8; }
:root[data-theme="dark"] { --core-ink: #8B7CF8; --core-vivid: #8B7CF8; }
.shell { display: grid; grid-template-columns: var(--nav-w) 1fr; min-height: 100vh; }
/* rail stays INK in both themes (canonical phase-1 rule) */
.rail { position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column;
  background: #100E16; color: #EDEAF5; border-right: 1px solid rgba(255,255,255,0.06); }
.rail-head { height: 73px; box-sizing: border-box; flex: 0 0 auto; display: flex; align-items: center; padding: 0 20px; border-bottom: 1px solid rgba(255,255,255,0.08); }
.rail-head img { height: 56px; width: auto; max-width: 212px; display: block; }
.rail-nav { flex: 1 1 auto; overflow-y: auto; padding: 65px 6px 14px; } /* first item level with the page title */
.nav-grp-head { padding: 16px 16px 8px; font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 10px; text-transform: uppercase; letter-spacing: 0.14em; font-weight: 500; color: #5B5470; }
.nav-item { position: relative; display: flex; align-items: center; gap: 11px; padding: 9px 16px; margin: 1px 0; border-radius: 8px; font-size: 15px; color: inherit; cursor: pointer; text-decoration: none; opacity: 0.72; }
.nav-item:hover { opacity: 1; background: rgba(255,255,255,0.05); }
.nav-item.active { opacity: 1; font-weight: 500; background: color-mix(in oklab, var(--core-vivid) 15%, transparent); }
.nav-item.active::before { content: ""; position: absolute; left: 0; top: 6px; bottom: 6px; width: 2px; border-radius: 2px; background: var(--core-vivid); }
.nav-item .ico { width: 17px; height: 17px; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; }
.nav-item .ico svg { width: 16px; height: 16px; display: block; }
.nav-item .lbl { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-item.soon { opacity: 0.5; }
.nav-item.soon:hover { opacity: 0.72; }
.soon-tag { flex: 0 0 auto; font-size: 9.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; padding: 2px 6px; border-radius: 8px; background: rgba(255,255,255,0.14); color: rgba(255,255,255,0.85); }
/* rail collapse — canonical 64px icon-only, persisted */
.rail-toggle { position: absolute; right: 6px; top: 88px; width: 26px; height: 26px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.22); background: #221c38; color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer; opacity: 0; transition: opacity .15s, border-color .15s; z-index: 60; font-size: 13px; line-height: 1; padding: 0; }
.rail { position: sticky; }
.rail:hover .rail-toggle { opacity: 1; }
.rail-toggle:hover { border-color: #fff; }
html.railc { --nav-w: 64px; }
html.railc .nav-item .lbl, html.railc .soon-tag, html.railc .nav-grp-head, html.railc .nav-foot .who, html.railc .nav-foot .avatar { display: none; }
html.railc .rail-head { padding: 0 6px; overflow: hidden; justify-content: flex-start; }
html.railc .rail-head img { width: 52px; max-width: none; object-fit: cover; object-position: left; }
html.railc .nav-item { justify-content: center; padding: 11px 0; }
html.railc .nav-foot { justify-content: center; padding: 12px 6px; }
html.railc .nav-foot .railtheme { margin-left: 0; }
/* rail foot: avatar + who + theme */
.nav-foot { flex: 0 0 auto; display: flex; align-items: center; gap: 10px; padding: 12px; border-top: 1px solid rgba(255,255,255,0.08); }
.nav-foot .avatar { flex: 0 0 auto; width: 32px; height: 32px; border-radius: 99px; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600; color: #C4B5FD; background: rgba(255,255,255,0.07); border: 1px solid rgba(255,255,255,0.13); }
.nav-foot .who { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; cursor: pointer; }
.nav-foot .who b { font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav-foot .who span { font-size: 11px; color: #6E6684; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav-foot .railtheme { margin-left: auto; flex: 0 0 auto; width: 34px; height: 34px; border-radius: 9px; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 15px; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.14); color: #fff; }
.nav-foot .railtheme:hover { border-color: rgba(255,255,255,0.4); }

/* 72px top bar — accent wash (dark) / white + 2px vivid rule (light) */
.main { min-width: 0; display: flex; flex-direction: column; }
.topbar { height: 72px; flex: 0 0 auto; display: flex; align-items: center; padding: 0 16px 0 26px; gap: 14px;
  background: linear-gradient(180deg, rgba(139,124,248,0.13), rgba(139,124,248,0.05)), var(--surface);
  border-bottom: 1px solid rgba(139,124,248,0.34); }
:root[data-theme="light"] .topbar { background: var(--surface); border-bottom: 2px solid var(--core-vivid); }
.topbar .right { margin-left: auto; display: flex; align-items: center; gap: 14px; }
.mod-chip { display: inline-flex; align-items: center; gap: 9px; height: 44px; padding: 0 15px; border-radius: 10px; font-size: 15.5px; font-weight: 700; letter-spacing: -0.01em; color: var(--core-ink); background: rgba(139,124,248,0.16); flex: none; }
:root[data-theme="dark"] .mod-chip { background: rgba(139,124,248,0.13); }
.mod-chip svg { width: 17px; height: 17px; flex: none; }
.bar-ctl { height: 44px; display: inline-flex; align-items: center; gap: 9px; padding: 0 15px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); font-family: inherit; font-size: 13px; font-weight: 600; color: var(--text); cursor: pointer; transition: border-color .12s; flex: none; white-space: nowrap; }
.bar-ctl:hover { border-color: var(--core-vivid); }
.bar-ctl .cdiv { width: 1px; height: 20px; background: var(--border); }
.bar-ctl .chev { font-size: 10px; color: var(--core-vivid); }
:root[data-theme="dark"] .bar-ctl { background: rgba(255,255,255,0.05); border-color: rgba(255,255,255,0.15); color: #ece8f5; }
:root[data-theme="dark"] .bar-ctl .cdiv { background: rgba(255,255,255,0.18); }
.bar-div { width: 1px; height: 28px; background: var(--border); margin: 0 2px; flex: none; }
:root[data-theme="dark"] .bar-div { background: rgba(255,255,255,0.16); }
.ninedots { width: 44px; height: 44px; border: 1px solid transparent; border-radius: 10px; background: transparent; color: var(--core-ink); cursor: pointer; display: flex; align-items: center; justify-content: center; flex: none; transition: background .12s, border-color .12s; }
.ninedots:hover { background: rgba(139,124,248,0.14); border-color: rgba(139,124,248,0.4); }
:root[data-theme="dark"] .ninedots:hover { background: rgba(139,124,248,0.12); }
/* nine-dots module list — fixed pvt tiles */
.mod-list { position: fixed; z-index: 9999; width: 604px; background: var(--surface); border: 1px solid var(--border); border-radius: 16px; display: none; grid-template-columns: 1fr 1fr; gap: 12px; padding: 14px; box-shadow: 0 20px 54px rgba(0,0,0,0.32); }
.mod-list.open { display: grid; }
.pvt { padding: 16px; border-radius: 14px; border: 1px solid var(--border); background: var(--surface-2); display: flex; flex-direction: column; gap: 11px; cursor: default; text-decoration: none; }
a.pvt { cursor: pointer; }
a.pvt:hover { border-color: var(--accent); }
.pvt.dis { opacity: 0.55; }
.pvt-id { display: flex; align-items: center; gap: 12px; min-width: 0; }
.pvt-ico { width: 38px; height: 38px; border-radius: 10px; flex: none; display: flex; align-items: center; justify-content: center; }
.pvt-t { font-size: 17px; font-weight: 600; line-height: 1.1; color: var(--text); display: block; }
.pvt-s { font-family: "JetBrains Mono", monospace; font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; display: block; margin-top: 4px; }
.pvt-d { margin: 0; font-size: 13px; line-height: 1.6; color: var(--text-soft); }
/* state control + panel */
#state-ctl .sdot { width: 8px; height: 8px; border-radius: 50%; background: #26b47a; flex: none; }
/* .state-panel / .sp-h / .ver-seg / .envseg dressed the version-and-environment panel behind
   the status chip. Both sections went on 2026-07-31 — Core has one version, and each
   deployment is its own environment — so the panel went with them. `#state-ctl .sdot` above
   stays: the chip is now purely the backend health indicator it was already carrying. */
/* breadcrumb — its own 42px row, no border */
.crumbrow { height: 42px; flex: 0 0 auto; display: flex; align-items: center; padding: 0 24px 0 32px; font-size: 13px; color: var(--text-soft); }
.crumb b { font-weight: 600; color: var(--text); }
.crumb .sep { margin: 0 8px; color: var(--text-soft); }
.page { padding: 22px 32px 44px; max-width: 1500px; width: 100%; }

/* Page header */
h1.page-title { font-size: 26px; font-weight: 500; letter-spacing: -0.015em; margin: 0 0 4px; }
.subtitle { color: var(--text-soft); font-size: 15px; line-height: 1.55; margin: 0 0 18px; }
.page-lead { color: var(--text-soft); font-size: 14px; line-height: 1.55; max-width: 660px; margin: 0 0 22px; }
.page-lead a { color: var(--accent); text-decoration: none; }
.page-lead a:hover { text-decoration: underline; }

/* Product Evolution — mock-up launcher cards */
.mk-grouphead { font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-soft); margin: 26px 0 12px; }
.mk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 14px; }
a.mk-card { display: block; padding: 18px; border-radius: 12px; background: var(--surface); border: 1px solid var(--grey-200); text-decoration: none; color: var(--text); transition: border-color .15s, transform .15s, box-shadow .15s; }
a.mk-card:hover { border-color: var(--accent); transform: translateY(-1px); box-shadow: var(--shadow-card); }
a.mk-card .mk-t { font-weight: 600; font-size: 15px; }
a.mk-card .mk-d { font-size: 12.5px; color: var(--text-soft); line-height: 1.5; margin-top: 5px; }
a.mk-card .mk-tag { display: inline-block; font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; padding: 3px 7px; border-radius: 6px; margin-top: 10px; background: var(--grey-100); color: var(--text-soft); }

/* Users & roles — styled to the signed-off mock-up: pill counts, accent
   chips, role list + editor, 15px type (house rule: no text under 14px). */
.ur-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--grey-200); margin: 4px 0 20px; }
.ur-tab { padding: 12px 20px; font: inherit; font-size: 15px; font-weight: 600; color: var(--text-soft); background: none; border: 0; border-bottom: 3px solid transparent; margin-bottom: -1px; cursor: pointer; display: inline-flex; align-items: center; gap: 9px; }
.ur-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.ur-count { font-size: 14px; font-weight: 700; min-width: 24px; text-align: center; padding: 2px 9px; border-radius: 999px; background: var(--surface-2); color: var(--text-soft); border: 1px solid var(--grey-200); }
.ur-tab.active .ur-count { background: var(--accent); color: #fff; border-color: var(--accent); }
.ur-toolbar { display: flex; align-items: flex-end; justify-content: space-between; gap: 14px; margin: 0 0 14px; flex-wrap: wrap; }
.ur-filters { display: flex; gap: 16px; flex-wrap: wrap; }
.ur-filters label { display: flex; flex-direction: column; gap: 6px; font-size: 14px; color: var(--text-soft); font-weight: 600; }
.ur-filters select { padding: 10px 12px; border: 1px solid var(--grey-300); border-radius: 9px; font: inherit; font-size: 15px; background: var(--surface); color: var(--text); }
.ur-actions { display: flex; gap: 8px; flex-wrap: wrap; }
table.dt th.sortable { cursor: pointer; user-select: none; }
table.dt th.sortable:hover { color: var(--text); }
.chk-cell { width: 44px; }
table.dt input[type=checkbox] { width: 17px; height: 17px; accent-color: var(--accent); cursor: pointer; }
.stat { display: inline-flex; align-items: center; gap: 7px; font-size: 14px; font-weight: 600; }
.stat .dot { width: 8px; height: 8px; border-radius: 50%; }
.ur-ghost { color: var(--text-soft); font-size: 14px; }
.ur-chip { font-size: 14px; font-weight: 600; padding: 5px 12px; border-radius: 999px; background: var(--accent-soft); color: var(--accent); display: inline-flex; gap: 7px; align-items: center; white-space: nowrap; }
.ur-chip .x { cursor: pointer; opacity: 0.7; font-weight: 700; }
.ur-bulk { display: flex; align-items: center; gap: 14px; padding: 12px 16px; background: var(--accent-soft); border: 1px solid var(--accent); border-radius: 12px; margin-bottom: 12px; font-size: 15px; font-weight: 600; }
.ur-bulk select { padding: 9px 11px; border: 1px solid var(--grey-300); border-radius: 9px; font: inherit; font-size: 14px; background: var(--surface); color: var(--text); }
/* roles: list + editor */
.ur-cols { display: grid; grid-template-columns: 296px 1fr; gap: 22px; align-items: start; }
@media (max-width: 1050px) { .ur-cols { grid-template-columns: 1fr; } }
.ur-rolelist { background: var(--surface); border: 1px solid var(--grey-200); border-radius: 14px; padding: 10px; }
.ur-rl-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 8px 10px 12px; font-size: 15px; font-weight: 600; }
.ur-role { padding: 12px 13px; border-radius: 10px; cursor: pointer; border: 1px solid transparent; margin-bottom: 4px; }
.ur-role:hover { background: var(--surface-2); }
.ur-role.on { background: var(--accent-soft); border-color: var(--accent); }
.ur-role .rn { font-weight: 600; font-size: 15px; }
.ur-role .rd { font-size: 14px; color: var(--text-soft); margin-top: 2px; }
.ur-editor { background: var(--surface); border: 1px solid var(--grey-200); border-radius: 14px; overflow: hidden; }
.ur-ed-line { padding: 16px 22px; border-bottom: 1px solid var(--grey-200); display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.ur-ed-line .et { font-size: 19px; font-weight: 600; }
.ur-ed-line .es { font-size: 14px; color: var(--text-soft); margin-left: 10px; }
.ur-sec { padding: 20px 22px; border-bottom: 1px solid var(--grey-200); }
.ur-sec:last-of-type { border-bottom: 0; }
.ur-sec-h { font-weight: 600; font-size: 16px; }
.ur-sec-sub { font-size: 14px; color: var(--text-soft); margin: 3px 0 14px; }
.ur-lbl { display: block; font-size: 14px; color: var(--text-soft); font-weight: 600; margin-bottom: 5px; }
.ur-modgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
@media (max-width: 1250px) { .ur-modgrid { grid-template-columns: 1fr; } }
.ur-modrow { display: flex; align-items: center; gap: 12px; padding: 11px 13px; border: 1px solid var(--grey-200); border-radius: 10px; background: var(--surface-2); }
.ur-modrow .mn { font-weight: 600; font-size: 15px; flex: 1; }
.ur-seg { display: inline-flex; border: 1px solid var(--grey-300); border-radius: 9px; overflow: hidden; background: var(--surface); }
.ur-seg button { border: 0; background: transparent; color: var(--text-soft); font: inherit; font-size: 14px; font-weight: 600; padding: 7px 13px; cursor: pointer; }
.ur-seg button.on { background: var(--accent); color: #fff; }
.ur-chips { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }
.ur-group { display: flex; align-items: center; gap: 10px; padding: 8px 0; font-size: 15px; cursor: pointer; border-bottom: 1px dashed var(--grey-200); }
.ur-group:last-child { border-bottom: 0; }
.ur-group input[type=checkbox] { width: 17px; height: 17px; accent-color: var(--accent); }
.ur-foot { display: flex; align-items: center; gap: 14px; justify-content: flex-end; padding: 16px 22px; background: var(--surface-2); }
/* areas */
.ur-areas { display: grid; grid-template-columns: 220px 1fr; gap: 22px; align-items: start; }
@media (max-width: 900px) { .ur-areas { grid-template-columns: 1fr; } }
.ur-modmenu { background: var(--surface); border: 1px solid var(--grey-200); border-radius: 14px; padding: 10px; }
.ur-mm { padding: 11px 13px; border-radius: 9px; cursor: pointer; font-size: 15px; font-weight: 600; color: var(--text-soft); margin-bottom: 3px; }
.ur-mm:hover { background: var(--surface-2); }
.ur-mm.on { background: var(--accent-soft); color: var(--accent); }
.ur-cat { background: var(--surface); border: 1px solid var(--grey-200); border-radius: 14px; padding: 20px 22px; }
.ur-acols { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 16px; }
.ur-acol { background: var(--surface-2); border: 1px solid var(--grey-200); border-radius: 12px; padding: 14px; }
.ur-acol-h { font-size: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-soft); font-weight: 600; margin-bottom: 10px; }
.ur-aitem { padding: 8px 0; border-bottom: 1px dashed var(--grey-200); font-size: 15px; }
.ur-aitem:last-child { border-bottom: 0; }
.ur-sens { font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--status-amber); background: var(--tint-amber); padding: 2px 8px; border-radius: 6px; margin-left: 8px; }

/* Section card */
.section { background: var(--surface); border: 1px solid var(--grey-200); border-radius: 8px; margin-bottom: 18px; box-shadow: var(--shadow-card); }
.section-head { display: flex; align-items: center; gap: 12px; padding: 24px 28px; border-bottom: 1px solid var(--grey-200); }
.section-head h2 { font-size: 18px; font-weight: 500; margin: 0; }
.section-head .right { margin-left: auto; display: flex; gap: 8px; align-items: center; }
.section-body.nopad { padding: 0; }

/* Data table */
table.dt { width: 100%; border-collapse: collapse; font-size: 15px; }
table.dt thead th { text-align: left; font-weight: 600; font-size: 14px; color: var(--text-soft); padding: 14px 18px; background: var(--surface-2); border-bottom: 1px solid var(--grey-200); white-space: nowrap; }
table.dt tbody td { padding: 16px 18px; border-bottom: 1px solid var(--grey-200); vertical-align: middle; }
table.dt tbody tr { cursor: pointer; }
table.dt tbody tr:hover { background: var(--grey-100); }
table.dt tbody tr:last-child td { border-bottom: none; }
table.dt .ctr { text-align: center; font-variant-numeric: tabular-nums; }
.dt-empty { padding: 28px; text-align: center; color: var(--text-soft); font-size: 15px; }

/* Buttons */
.btn { display: inline-flex; align-items: center; gap: 6px; background: var(--surface); border: 1px solid var(--grey-300); color: var(--text); font-size: 14px; font-weight: 500; padding: 10px 18px; border-radius: 4px; cursor: pointer; font-family: inherit; line-height: 1.2; min-height: 44px; }
.btn.primary { background: var(--btn-primary); color: #fff; border-color: var(--btn-primary); }
.btn.primary:hover { background: var(--btn-primary-hover); }
.btn.danger { color: var(--status-red); }
.btn.sm { padding: 9px 15px; font-size: 14px; min-height: 38px; }
.btn:disabled { opacity: 0.5; cursor: default; }

/* Pills */
.pill { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: 999px; font-size: 14px; font-weight: 600; background: var(--grey-100); color: var(--text-soft); white-space: nowrap; }
.pill.dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pill.success { background: var(--tint-mint); color: var(--status-green); }
.pill.muted { background: var(--grey-100); color: var(--text-soft); }

/* Forms */
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 14px; color: var(--text-muted); margin-bottom: 8px; font-weight: 600; }
.field input, .field select { width: 100%; padding: 10px 12px; border: 1px solid var(--grey-300); border-radius: 4px; font: inherit; font-size: 14px; color: var(--text); background: var(--surface); }
.field input:focus, .field select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.field .help { font-size: 14px; color: var(--text-soft); margin-top: 6px; }
.form-error { background: var(--tint-rose); color: var(--status-red); border-radius: var(--radius); padding: 10px 14px; font-size: 14px; margin-bottom: 14px; }
.form-error:empty { display: none; }

/* Drawer */
.drawer { position: fixed; top: 0; right: 0; width: 700px; max-width: calc(100vw - 24px); height: 100vh; background: var(--surface); border-left: 1px solid var(--border); box-shadow: var(--shadow-lg); z-index: 60; transform: translateX(100%); transition: transform 0.22s ease; display: flex; flex-direction: column; }
.drawer.open { transform: translateX(0); }
.drawer-backdrop { position: fixed; inset: 0; background: rgba(15, 15, 20, 0.35); z-index: 50; display: none; }
.drawer-backdrop.open { display: block; }
.drawer-head { padding: 16px 20px; border-bottom: 1px solid var(--border); }
.drawer-head h2 { font-size: 18px; font-weight: 600; margin: 0; }
.drawer-head .sub { font-size: 14px; color: var(--text-soft); margin-top: 3px; }
.drawer-body { flex: 1; overflow-y: auto; padding: 18px 20px; overscroll-behavior: contain; }
/* drawer open = the page behind must not scroll */
body.drawer-open { overflow: hidden; }
.drawer-x { position: absolute; top: 14px; right: 14px; width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); font-size: 16px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.drawer-x:hover { color: var(--text); border-color: var(--accent); }
.drawer-head { position: relative; }
.drawer-foot { padding: 14px 20px; border-top: 1px solid var(--border); display: flex; gap: 8px; justify-content: flex-end; background: var(--surface-2); }

/* Outcome banners (sync / provision / offboard results). Family adopted
   verbatim from Commercial's component-library submission — Core previously
   emitted .banner markup with no styles at all. */
.banner { padding: 11px 16px; border-radius: 8px; font-size: 14px; margin: 0 0 16px; background: var(--grey-100); color: var(--text-muted); border: 1px solid var(--grey-200); }
.banner b { font-weight: 600; }
.banner.success, .banner.ok { background: var(--tint-mint); color: var(--status-green); border-color: transparent; }
.banner.warn { background: var(--tint-amber); color: var(--status-amber); border-color: transparent; }
.banner.danger { background: var(--tint-rose); color: var(--status-red); border-color: transparent; }
.banner.info { background: var(--tint-sky); color: var(--status-blue); border-color: transparent; }

/* Copy-phase provenance banner (inbox rule 3): visible until cutover */
.copy-phase-note { background: var(--tint-amber); color: var(--status-amber); border-radius: 6px; padding: 9px 14px; font-size: 12.5px; margin: 0 0 16px; }

/* bar dropdown menus, nine-dot popover, home headline */
.ctl-menu { position: absolute; top: 52px; right: 0; min-width: 230px; padding: 8px; border-radius: 12px; background: var(--surface); border: 1px solid var(--grey-200); box-shadow: var(--shadow-lg); z-index: 90; display: none; text-align: left; }
.ctl-menu.on { display: block; }
.ctl-menu-head { font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-soft); padding: 8px 12px 6px; }
/* canonical brand menu: the PARCELHERO GROUP header row IS the All-brands control */
.ctl-menu-head-click { cursor: pointer; border-radius: 8px; margin-top: 4px; }
.ctl-menu-head-click:hover { background: var(--surface-2); color: var(--text); }
.ctl-menu-head-click.onhead { color: var(--accent); }
.ctl-item { display: flex; align-items: center; gap: 9px; padding: 10px 12px; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; color: var(--text); }
.ctl-item:hover { background: var(--surface-2); }
.ctl-item.on { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.ctl-item.dis { color: var(--text-soft); cursor: default; font-weight: 400; }
.ctl-item.dis:hover { background: none; }
.ctl-row { display: flex; gap: 6px; flex-wrap: wrap; padding: 2px 10px 8px; }
.ctl-chip { font: inherit; font-size: 14px; font-weight: 600; padding: 7px 13px; border-radius: 9px; border: 1px solid var(--grey-200); background: var(--surface); color: var(--text-soft); cursor: pointer; }
.ctl-chip.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.dots-wrap { position: relative; }
.switch-pop { position: absolute; top: 52px; right: 0; width: 660px; max-width: calc(100vw - 300px); padding: 16px; border-radius: 14px; background: var(--pv-bg, var(--surface)); border: 1px solid var(--grey-200); box-shadow: var(--shadow-lg); z-index: 90; }
.switch-pop .pv-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.home-head { margin: 4px 0 30px; }
.home-eyebrow { font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-soft); }
.home-title { margin: 8px 0 0; font-size: 26px; font-weight: 500; letter-spacing: -0.02em; line-height: 1.2; color: var(--text); }
/* capability toggle chips — pick, don't type */
.ur-capchip { font: inherit; font-size: 14px; font-weight: 600; padding: 7px 15px; border-radius: 999px; border: 1px solid var(--grey-300); background: var(--surface); color: var(--text-soft); cursor: pointer; }
.ur-capchip:hover { border-color: var(--accent); }
.ur-capchip.on { background: var(--accent); border-color: var(--accent); color: #fff; }
/* editable role name + description at the head of the editor */
.ur-name-input { font: inherit; font-size: 19px; font-weight: 600; color: var(--text); background: transparent; border: 1px solid transparent; border-radius: 8px; padding: 6px 10px; margin-left: -10px; width: 100%; }
.ur-desc-input { font: inherit; font-size: 15px; color: var(--text-soft); background: transparent; border: 1px solid transparent; border-radius: 8px; padding: 6px 10px; margin-left: -10px; width: 100%; }
.ur-name-input:hover, .ur-desc-input:hover { border-color: var(--grey-200); }
.ur-name-input:focus, .ur-desc-input:focus { outline: none; border-color: var(--accent); background: var(--surface); color: var(--text); }

/* switcher popover — compact tiles that keep the design tokens */
.switch-pop .pv-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.switch-pop .pv-tile { padding: 16px; gap: 10px; }
.switch-pop .pv-tile__head { gap: 10px; }
.switch-pop .pv-tile__id { gap: 10px; }
.switch-pop .pv-tile__id > span:last-child { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.switch-pop .pv-tile__title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.switch-pop .pv-tile__sub { white-space: nowrap; }
.switch-pop .pv-badge { flex: 0 0 auto; }
/* native form controls follow the theme (fixes dark dropdowns in light mode) */
:root { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }
/* role editor sub-tabs */
.ur-edtabs { display: flex; gap: 6px; padding: 14px 22px; border-bottom: 1px solid var(--grey-200); background: var(--surface-2); }
.ur-edtab { padding: 9px 16px; font: inherit; font-size: 14px; font-weight: 600; border-radius: 10px; border: 1px solid var(--grey-300); background: var(--surface); color: var(--text-soft); cursor: pointer; }
.ur-edtab.active { background: var(--accent); border-color: var(--accent); color: #fff; }
/* capability pick cards — name + what it grants */
.ur-capgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 10px; }
.ur-capcard { text-align: left; font: inherit; border: 1px solid var(--grey-300); background: var(--surface); border-radius: 12px; padding: 12px 14px; cursor: pointer; display: flex; flex-direction: column; gap: 4px; }
.ur-capcard b { font-size: 15px; color: var(--text); }
.ur-capcard span { font-size: 14px; color: var(--text-soft); line-height: 1.45; }
.ur-capcard:hover { border-color: var(--accent); }
.ur-capcard.on { background: var(--accent-soft); border-color: var(--accent); }
.ur-capcard.on b { color: var(--accent); }
/* custom dropdown — opens below, white in light mode */
.udd { position: relative; min-width: 172px; }
.udd-btn { width: 100%; display: flex; justify-content: space-between; align-items: center; gap: 8px; font: inherit; font-size: 15px; padding: 10px 12px; border: 1px solid var(--grey-300); border-radius: 9px; background: var(--surface); color: var(--text); cursor: pointer; }
.udd-btn:hover { border-color: var(--accent); }
.udd-caret { color: var(--text-soft); font-size: 10px; }
.udd-menu { position: absolute; top: calc(100% + 5px); left: 0; right: 0; background: var(--surface); border: 1px solid var(--grey-300); border-radius: 10px; box-shadow: var(--shadow-lg); z-index: 70; display: none; padding: 5px; max-height: 260px; overflow: auto; }
.udd-menu.on { display: block; }
.udd-opt { padding: 9px 11px; border-radius: 7px; font-size: 14px; cursor: pointer; color: var(--text); }
.udd-opt:hover { background: var(--surface-2); }
.udd-opt.sel { color: var(--accent); font-weight: 600; }
/* approvals config cards */
.ap-subtabs { display: flex; gap: 6px; margin: 0 0 18px; }
.ap-subtab { padding: 9px 16px; font: inherit; font-size: 15px; font-weight: 600; border-radius: 10px; border: 1px solid var(--grey-300); background: var(--surface); color: var(--text-soft); cursor: pointer; }
.ap-subtab.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.ap-card { background: var(--surface); border: 1px solid var(--grey-200); border-radius: 14px; padding: 18px 20px; margin-bottom: 14px; max-width: 1000px; }
.ap-top { display: flex; justify-content: space-between; gap: 14px; align-items: flex-start; flex-wrap: wrap; }
.ap-remove { color: var(--status-red); border-color: var(--status-red); }
.ap-row { display: grid; grid-template-columns: 150px 1fr; gap: 14px; align-items: start; margin-top: 14px; }
.ap-lbl { font-size: 14px; color: var(--text-soft); font-weight: 600; padding-top: 9px; }
.ap-lbl2 { font-size: 14px; color: var(--text-soft); }
.ap-tier { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; flex-wrap: wrap; }
.ap-tier input { width: 92px; padding: 9px 11px; border: 1px solid var(--grey-300); border-radius: 8px; font: inherit; font-size: 15px; background: var(--surface); color: var(--text); }
.ap-tier .udd { min-width: 210px; }
.ap-arrow { color: var(--text-soft); }
.ap-tierdel { border: 0; background: none; color: var(--status-red); font-size: 17px; cursor: pointer; }
.ap-addtier { font: inherit; font-size: 14px; font-weight: 600; color: var(--accent); background: none; border: 0; padding: 4px 0; cursor: pointer; }
.ap-addreq .udd { min-width: 160px; }
.ap-addreq .udd-btn { border-style: dashed; color: var(--text-soft); }
.ap-foot { display: flex; justify-content: flex-end; align-items: center; gap: 14px; margin-top: 14px; }

/* ── API integrations ──────────────────────────────────────────────────────
   The ParcelHero (PVR) handshake surface. `ai-` prefixed so it cannot collide
   with the shared component classes above. */
/* 16px — body. **Every size in this block was raised on 2026-08-03**, and the reason is recorded
   at `.ai-hrow` below: the whole screen had been ported at the MOCK-UP's scale, which Roger's
   ruling of 2026-08-02 supersedes. */
.ai-lede { color: var(--text-soft); font-size: 16px; max-width: 78ch; margin: -6px 0 20px;
  line-height: 1.55; }
/* The link out to Swagger, in the Engineering lede. Underlined rather than colour-only: the lede
   is already --text-soft, so a colour change alone against it is the weakest possible affordance
   and fails a contrast check on the ratio that matters. */
.ai-docs-link { color: var(--accent); font-weight: 600; text-decoration: underline; }
.ai-docs-link:hover { text-decoration-thickness: 2px; }

/* Four cards, identical geometry — the name and state are fixed height so the
   three rows below start at the same y whatever the name's length. Cards that
   each find their own layout cannot be compared down a column. */
.ai-health { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 12px; margin-bottom: 20px; }
.ai-card { display: block; width: 100%; text-align: left; font: inherit; color: inherit;
  background: var(--surface); border: 1px solid var(--border); border-radius: 13px;
  padding: 14px 16px; box-shadow: var(--shadow-card); cursor: pointer; }
.ai-card:hover { border-color: var(--accent); }
.ai-card-bad { border-color: var(--status-amber); background: var(--tint-amber); }
.ai-cname { display: block; font-size: 16px; font-weight: 700; line-height: 20px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ai-card > .pill { margin-top: 4px; }
.ai-cupd { display: block; font-size: 14.5px; color: var(--text-soft); min-height: 17px;
  margin: 6px 0 10px; }
.ai-hrow { display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  padding: 5px 0; border-top: 1px solid var(--border); font-size: 14.5px; color: var(--text-soft); }
/* ── the type scale on this screen, and why it changed ──────────────────────────────────────
   **Every `.ai-` size was raised on 2026-08-03.** 50 of the 53 sat below 14.5px, because the screen
   was ported from `public/mock-ups/api-integrations.html` and inherited that page's scale — a
   standalone document with a 15px body, where 10.5px badges and 12.5px table rows hang together.

   Inside Core they do not, and Roger's ruling of 2026-08-02 already said so: **legacy typography —
   16px body, 14.5px tables, 26px/800 titles — supersedes the signed-off token guide.** Matching the
   mock-up was the wrong target; this is the right one. Three sizes, and nothing between:

     16px    body-level content — ledes, card names, tab labels, step and section headings
     14.5px  table and row text — every figure label, path, note, field and control
     13px    the FLOOR, and only for true badges (POST, REQUIRED, LIVE) and counts

   Roger, 2026-08-03: *"the average calls per day … is not size 15, looks more like 13. You have a
   hard rule to not use that text size … everything is very significantly smaller. Even the tabs,
   the handshake, and endpoints. You've got plenty of space to play with."*

   The figure and its working, in the same sitting: *"the 96.8 and the 302 of 312 are too close to
   each other, and the 96.8 should be bigger."* They were one string with a single space in it, so
   the reader had to separate them by eye. Now a flex pair — baseline-aligned so the digits sit on
   one line rather than the fraction floating, with a real gap between them. */
.ai-hval { display: inline-flex; align-items: baseline; gap: 12px; }
.ai-hrow b, .ai-hnum { font-size: 20px; font-weight: 800; color: var(--text); }
.ai-hsub { font-size: 14.5px; font-weight: 600; color: var(--text-soft); }

.ai-urgent { border: 1px solid var(--status-amber); background: var(--tint-amber);
  color: var(--status-amber); border-radius: 11px; padding: 12px 16px; font-size: 14.5px;
  line-height: 1.55; margin: 0 0 20px; }

/* ~0.5cm clear of the health cards above — Roger, 2026-08-03: *"the handshake and endpoints,
   maybe about half a centimetre at the moment, are too close to the boxes above."* Half a
   centimetre is ~19px at 96dpi, on top of the 20px the card grid already leaves. */
.ai-tabs { margin-top: 20px; display: flex; gap: 2px; border-bottom: 1px solid var(--border);
  margin-bottom: 18px;
  flex-wrap: wrap; }
.ai-tab { border: 0; background: none; font: inherit; font-size: 16px; font-weight: 600;
  color: var(--text-soft); padding: 11px 16px; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px; }
.ai-tab:hover { color: var(--text); }
.ai-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
.ai-tabn { font-size: 13px; font-weight: 800; border-radius: 999px; padding: 1px 8px;
  margin-left: 8px; background: var(--surface-2); color: var(--text-soft); }
.ai-tab.on .ai-tabn { background: var(--accent-soft); color: var(--accent); }

/* The handshake: two party panels and the steps between them, as a grid rather
   than one SVG, so every control in it is a real focusable element. */
/* ~72px above the diagram. Roger, 2026-08-03: *"about an inch worth of space, slightly less than
   on legacy but definitely more than what you have here."* An inch is 96px; this is a shade under,
   which is what he asked for. */
.ai-diagram {
  margin-top: 72px; display: grid; grid-template-columns: 178px 1fr 178px; gap: 18px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 18px;
  padding: 20px; box-shadow: var(--shadow-card); }
.ai-party { background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  padding: 18px 12px; text-align: center; }
.ai-party b { display: block; font-size: 18px; font-weight: 700; }
.ai-party span { display: block; font-size: 14.5px; color: var(--text-soft); margin-top: 4px; }
.ai-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column;
  justify-content: space-around; gap: 6px; }
.ai-step { padding: 4px 0; }
.ai-step-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.ai-step-name { border: 0; background: none; font: inherit; font-size: 18px; font-weight: 700;
  padding: 0; cursor: pointer; text-align: left; }
.ai-step-name:hover { text-decoration: underline; }
.ai-step-tag { font-size: 13px; font-weight: 800; letter-spacing: .6px; color: var(--text-soft); }
/* A real button, not a hover target: hover is unreachable without a mouse. */
.ai-info { width: 24px; height: 24px; border-radius: 50%; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-soft); font: inherit; font-size: 13px;
  font-weight: 800; cursor: pointer; padding: 0; line-height: 1; }
.ai-info:hover, .ai-info[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }
/* ── the connector: legacy's values, ported rather than reinvented ──────────────────────────
   **Every number here is read out of `public/mock-ups/api-integrations.html`**, which is the
   mock-up Roger signed off. It is CSS rather than SVG only because the SVG stretched — it was
   `viewBox="0 0 200 12"` with `preserveAspectRatio="none"`, so the arrowhead polygon scaled
   horizontally with the row while the line escaped through `vectorEffect`. That is the only thing
   that needed to change. The geometry and the timing did not, and I spent three rounds of Roger's
   time inventing replacements for them — 60s, then 90s; 9px, then 14px, then 11px — before going
   back and reading what legacy actually does:

       dashed line   stroke-dasharray="3 7"  stroke-width="2"  opacity=".5"
       arrowhead     polygon 10 long × 5 half-height
       packet        circle r="4.5"  → 9px across
       travel        animateMotion dur="8s", CONTINUOUS
       stagger       begin="i * 0.6s", so the lanes do not pulse in unison
       fade          values="0;1;1;0"  keyTimes="0;0.05;0.9;1"

   One packet per lane, crossing every 8 seconds, always. Roger, 2026-08-03: *"the mockup works
   perfectly — the speed of the dots, the formatting, everything is good."* */
.ai-conn { position: relative; width: 100%; height: 14px; margin: 6px 0; overflow: hidden; }

/* `stroke-dasharray="3 7"` — a repeating gradient, because a CSS dashed border is drawn to the
   browser's own rhythm and will not hold a 3-on/7-off pattern. */
.ai-track { position: absolute; top: 50%; left: 0; right: 0; height: 2px; margin-top: -1px;
  opacity: .5;
  background-image: repeating-linear-gradient(to right,
    currentColor 0 3px, transparent 3px 10px); }

/* The polygon, as borders: 10 long, 5 either side of the line. */
.ai-arrow { position: absolute; top: 50%; right: 0; margin-top: -5px; width: 0; height: 0;
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
  border-left: 10px solid currentColor; }
.ai-conn-back .ai-arrow { right: auto; left: 0; border-left: 0;
  border-right: 10px solid currentColor; }

/* `r="4.5"` is 9px across — legacy's size, kept.
   **The TIMING is not legacy's, and that is deliberate.** Legacy crosses every 8s, continuously.
   Roger, 2026-08-03: *"the dots are only supposed to go once every 90 seconds. Currently, they're
   continually running."* So the cycle is 90s and the crossing is legacy's ~8s inside it: the
   packet moves at the speed it always did, and then the lane is quiet for the rest of the minute
   and a half. Slowing the crossing itself is what made it read as stuck last time. */
.ai-pkt { position: absolute; top: 50%; margin-top: -4.5px; width: 9px; height: 9px;
  border-radius: 50%; left: 0; opacity: 0; animation: ai-travel 90s linear infinite; }
.ai-conn-back .ai-pkt { animation-name: ai-travel-back; }

/* `values="0;1;1;0"` at `keyTimes="0;0.05;0.9;1"`, exactly. */
@keyframes ai-travel {
  0%    { left: 0; opacity: 0; }
  0.4%  { opacity: 1; }
  8%    { opacity: 1; }
  8.9%  { left: calc(100% - 9px); opacity: 0; }
  100%  { left: calc(100% - 9px); opacity: 0; }
}
@keyframes ai-travel-back {
  0%    { left: calc(100% - 9px); opacity: 0; }
  0.4%  { opacity: 1; }
  8%    { opacity: 1; }
  8.9%  { left: 0; opacity: 0; }
  100%  { left: 0; opacity: 0; }
}
}
/* Legacy's `words`: the short description in lighter grey, above the call in bold. Dropped in
   the React port and asked back for on 2026-08-03. */
.ai-step-words { font-size: 14.5px; color: var(--text-soft); margin: 2px 0 4px; line-height: 1.5; }

.ai-step-foot { display: flex; align-items: baseline; gap: 12px; }
.ai-call { font-family: ui-monospace, Menlo, monospace; font-size: 14.5px; font-weight: 700;
  color: var(--text); opacity: .75; }
.ai-contract { margin-left: auto; border: 0; background: none; font: inherit; font-size: 14.5px;
  font-weight: 700; color: var(--accent); cursor: pointer; padding: 0; white-space: nowrap; }
.ai-detail { margin: 8px 0 0; font-size: 14.5px; color: var(--text-soft); line-height: 1.5;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  padding: 9px 12px; max-width: 70ch; }
.ai-note { font-size: 14.5px; color: var(--text-soft); line-height: 1.6; max-width: 92ch;
  margin: 14px 2px 0; }
.ai-note-hint { margin-top: 8px; }
/* The packets stop. The arrowhead and the dotted track both STAY: one says which way and the other
   says there is a connection at all, and neither is motion. */
@media (prefers-reduced-motion: reduce) { .ai-pkt { display: none; } }
/* One column when the two end panels no longer fit beside the steps. The top margin is inherited
   from the rule above rather than restated. */
@media (max-width: 860px) { .ai-diagram { grid-template-columns: 1fr; } }

.ai-toolbar { display: flex; gap: 9px; align-items: center; flex-wrap: wrap; font-size: 14.5px;
  color: var(--text-soft); margin: 0 0 14px; }
.ai-toolbar .ai-btn:first-of-type { margin-left: auto; }
.ai-btn { display: inline-flex; align-items: center; gap: 6px; background: var(--surface);
  border: 1px solid var(--grey-300); color: var(--text); font: inherit; font-size: 14.5px;
  font-weight: 600; padding: 7px 13px; border-radius: 6px; cursor: pointer; text-decoration: none; }
.ai-btn-primary { background: var(--btn-primary); color: #fff; border-color: var(--btn-primary); }
.ai-link { border: 0; background: none; font: inherit; color: var(--accent); font-weight: 700;
  cursor: pointer; padding: 0; text-decoration: underline; }

.ai-ep { border: 1px solid var(--border); border-radius: 14px; background: var(--surface);
  box-shadow: var(--shadow-card); margin-bottom: 12px; overflow: hidden; }
.ai-ep-open { border-color: var(--accent); }
.ai-ephd { display: flex; align-items: center; gap: 12px; padding: 14px 17px; width: 100%;
  background: none; border: 0; font: inherit; color: inherit; text-align: left; cursor: pointer;
  flex-wrap: wrap; }
.ai-meth { font-family: ui-monospace, Menlo, monospace; font-size: 13px; font-weight: 800;
  color: #fff; border-radius: 6px; padding: 4px 9px; min-width: 46px; text-align: center; }
.ai-meth-post { background: var(--accent); }
.ai-meth-get { background: var(--status-blue); }
.ai-meth-put { background: var(--status-amber); }
.ai-path { font-family: ui-monospace, Menlo, monospace; font-size: 14.5px; font-weight: 700; }
.ai-eptitle { font-size: 14.5px; color: var(--text-soft); }
.ai-epright { margin-left: auto; font-size: 14.5px; color: var(--text-soft); }
.ai-epbody { padding: 0 17px 16px; border-top: 1px solid var(--border); }
.ai-seg { display: inline-flex; background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; padding: 3px; margin: 14px 0 4px; }
.ai-seg button { border: 0; background: none; font: inherit; font-size: 14.5px; font-weight: 600;
  color: var(--text-soft); padding: 5px 13px; border-radius: 6px; cursor: pointer; }
.ai-seg button.on { background: var(--surface); color: var(--accent); box-shadow: var(--shadow-card); }
.ai-plain { font-size: 16px; line-height: 1.6; max-width: 78ch; margin: 12px 0 0; }
.ai-grp, .ai-colh { font-size: 13px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase;
  color: var(--text-soft); margin: 16px 0 4px; }
.ai-kv { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.ai-kv td { padding: 7px 0; border-top: 1px solid var(--border); vertical-align: top; }
.ai-kv td:first-child { width: 230px; color: var(--text-soft); }
.ai-chips { display: flex; gap: 6px; flex-wrap: wrap; margin: 6px 0 0; }
.ai-plainpill { background: var(--surface-2); color: var(--text-soft); font-weight: 600;
  font-size: 14.5px; padding: 3px 10px; }
/* State modifiers for the shared pill. Named `ai-` because the shared set only ships `success`
   and `muted`, and the Emails screen is adding variants of its own on another branch. */
.pill.ai-ok { background: var(--tint-mint); color: var(--status-green); }
.pill.ai-warn { background: var(--tint-amber); color: var(--status-amber); }
.pill.ai-bad { background: var(--tint-rose); color: var(--status-red); }
.ai-card .pill { font-size: 14.5px; padding: 3px 10px; }
.ai-errs { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.ai-errs td { padding: 8px 0; border-top: 1px solid var(--border); vertical-align: top;
  color: var(--text-soft); }
.ai-errs td:first-child { width: 140px; font-family: ui-monospace, Menlo, monospace;
  font-weight: 800; color: var(--text); }
.ai-seemore { font-size: 14.5px; color: var(--text-soft); margin: 8px 0 0; }
.ai-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; margin-top: 12px; }
@media (max-width: 900px) { .ai-cols { grid-template-columns: 1fr; } }
.ai-field { padding: 9px 0; border-top: 1px solid var(--border); }
.ai-field-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ai-fname { font-family: ui-monospace, Menlo, monospace; font-size: 14.5px; font-weight: 700; }
.ai-ftype { font-size: 14.5px; color: var(--text-soft); }
.ai-freq { font-size: 13px; font-weight: 800; letter-spacing: .4px; color: var(--status-amber); }
.ai-maps { margin-left: auto; font-size: 13px; font-weight: 700; color: var(--accent);
  background: var(--accent-soft); border-radius: 7px; padding: 2px 8px; }
.ai-maps-gap { color: var(--status-amber); background: var(--tint-amber); }
.ai-fdesc { font-size: 14.5px; color: var(--text-soft); margin: 3px 0 0; line-height: 1.45; }
.ai-pre { margin: 10px 0 0; padding: 13px 15px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 9px; overflow: auto; max-height: 340px;
  font: 11.5px/1.6 ui-monospace, Menlo, monospace; color: var(--text); }

.ai-subtabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.ai-subtab { border: 1px solid var(--border); background: var(--surface); font: inherit;
  font-size: 14.5px; font-weight: 600; color: var(--text-soft); padding: 6px 13px;
  border-radius: 999px; cursor: pointer; }
.ai-subtab.on { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.ai-subn { font-size: 13px; font-weight: 800; margin-left: 6px; opacity: .75; }
.ai-tx { border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
  margin-bottom: 7px; overflow: hidden; }
.ai-tx-open { border-color: var(--accent); }
.ai-txhd { display: flex; align-items: center; gap: 12px; padding: 11px 15px; width: 100%;
  background: none; border: 0; font: inherit; color: inherit; text-align: left; cursor: pointer;
  flex-wrap: wrap; }
.ai-code { font-family: ui-monospace, Menlo, monospace; font-size: 13px; font-weight: 800;
  border-radius: 6px; padding: 3px 8px; min-width: 40px; text-align: center; }
.ai-code-ok { color: var(--status-green); background: var(--tint-mint); }
.ai-code-err { color: var(--status-amber); background: var(--tint-amber); }
.ai-code-bad { color: var(--status-red); background: var(--tint-rose); }
.ai-txgroup { font-size: 14.5px; font-weight: 700; }
.ai-txdir, .ai-txsum { font-size: 14.5px; }
.ai-txdir { color: var(--text-soft); }
.ai-txwhen { margin-left: auto; font-size: 14.5px; color: var(--text-soft); white-space: nowrap; }
.ai-txbody { padding: 0 15px 15px; border-top: 1px solid var(--border); }
.ai-txactions { display: flex; gap: 9px; flex-wrap: wrap; margin: 12px 0 0; }
.ai-empty { font-size: 14.5px; color: var(--text-soft); }

/* 14.5px — table text, per the scale above. It carried no font-size at all until 2026-08-03. */
.ai-conv { font-size: 13px; border: 1px solid var(--border); border-radius: 14px;
  background: var(--surface);
  box-shadow: var(--shadow-card); padding: 4px 17px 14px; }
.ai-convrow { display: grid; grid-template-columns: 170px 1fr; gap: 14px; padding: 9px 0;
  border-top: 1px solid var(--border); font-size: 14.5px; }
.ai-convrow span { color: var(--text-soft); }
.ai-gap { border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  padding: 14px 16px; margin-bottom: 10px; }
.ai-gap h4 { margin: 0 0 5px; font-size: 16px; font-family: ui-monospace, Menlo, monospace; }
.ai-gap p { margin: 0; font-size: 14.5px; color: var(--text-soft); line-height: 1.55; }

/* Visually hidden, still read aloud and still found by search-in-page. */
.ai-vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ----- the engineering tab: live API traffic -----------------------------
   Still `ai-` because it is a tab of this screen and not a new shell
   primitive. The filter row reuses the Emails screen's control surface
   (`--input-bg`) rather than declaring a third one: a form control that looks
   different on two Core screens reads as two different kinds of control. */
/* ── the integration chips, from the prototype ──────────────────────────────────────────────
   Roger, 2026-08-03: *"the transactions design is completely different … align with the
   prototype."* The prototype's own note gives the reason and it still holds: *"a select box to
   choose between five things you can see the counts of is a click that buys nothing."*
   The counts on them are the server's, over the whole log rather than the current page. */
/* Roger, 2026-08-03: the pills want *"3 or 4 mm further away from the menu above, just to give
   the thing room to breathe"*, and *"a big gap between the pills and [the row] above"*. At 96dpi
   4mm is ~15px, so 16 above and 24 below. */
.ai-subtabs { display: flex; gap: 8px; flex-wrap: wrap; margin: 16px 0 24px; }
/* Taller — *"this whole row should be a bit taller"*. */
.ai-subtab { border: 1px solid var(--border); background: var(--surface); font: inherit;
  font-size: 14.5px; font-weight: 600; color: var(--text-soft); border-radius: 999px;
  padding: 10px 18px; cursor: pointer; }
.ai-subtab:hover { color: var(--text); }
.ai-subtab.on { background: var(--tint-accent, var(--surface-2)); color: var(--accent);
  border-color: var(--accent); }
.ai-subn { font-size: 13px; font-weight: 800; margin-left: 7px; opacity: .75; }

/* The search box carries the prototype's magnifier. Absolutely positioned inside the wrapper so
   the icon does not change the input's own metrics. */
/* **On the right**, as the mock-up has it. `margin-left: auto` rather than a fixed order, so it
   holds the far edge whether the row carries three controls or five. */
.ai-searchwrap { position: relative; display: inline-flex; align-items: center;
  margin-left: auto; }
.ai-searchwrap svg { position: absolute; left: 11px; width: 15px; height: 15px; fill: none;
  stroke: var(--text-soft); stroke-width: 2; stroke-linecap: round; pointer-events: none; }
.ai-searchwrap .ai-search { padding-left: 34px; }

.ai-filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.ai-ctl { font: inherit; font-size: 14.5px; color: var(--text); background: var(--input-bg);
  border: 1px solid var(--input-border); border-radius: 8px; padding: 6px 10px; }
.ai-lab { font-size: 14.5px; color: var(--text-soft); }
/* Never more than half the row: the reference box is one of seven controls, and a search field
   that dominates the row reads as the primary action when it is not. */
.ai-search { flex: 1 1 190px; max-width: 320px; }
/* Present whenever there is anything at all, not only when there is a second page — "1 to 50 of
   41,204" is the sentence that says the screen is a window rather than everything there is. */
.ai-pager { display: flex; align-items: center; gap: 10px; margin: 14px 0 0; font-size: 14.5px;
  color: var(--text-soft); }
.ai-pager span { margin-right: auto; }
.ai-pager .ai-btn[disabled] { opacity: .45; cursor: default; }
/* Amber, not red. A redacted field is the system working correctly; nothing here is an incident. */
.ai-redacted { color: var(--status-amber); }
.ai-redacted code { font-family: ui-monospace, Menlo, monospace; font-size: 14.5px; }
.ai-refused { line-height: 1.6; }
.ai-refused code { font-family: ui-monospace, Menlo, monospace; font-size: 14.5px;
  background: var(--surface-2); border-radius: 5px; padding: 1px 5px; }
/* ===== Emails (Core ▸ Platform ▸ Emails) — the sending-health monitor =====
   Per the signed-off mock-up public/mock-ups/emails.html. Prefixed `em-` because
   these are one screen's pieces, not new shell primitives: the tiles, the trend
   and the filter row have no second caller yet, and a component library is
   earned by a second use, not by a first one. */

/* Form controls carry their own surface. On the dark theme the page surface and
   the input surface were within a shade of each other, so the search box read as
   text floating on the panel rather than as a box. */
:root { --input-bg: #ffffff; --input-border: var(--grey-300); }
:root[data-theme="dark"] { --input-bg: #2a2536; --input-border: #413a56; }

/* three counts, three tiles — deliberately NOT a chart: each is a single
   headline number, and a bar chart of three unrelated totals reads slower than
   the number itself */
.em-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 18px; }
.em-tile { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 15px 18px; box-shadow: var(--shadow-card); }
.em-tile .k { font-size: 12.5px; color: var(--text-soft); font-weight: 500; }
.em-tile .v { font-size: 30px; font-weight: 800; letter-spacing: -0.02em; margin-top: 6px; line-height: 1.1; }
.em-tile .f { font-size: 12.5px; color: var(--text-soft); margin-top: 3px; }
/* the outbox count is the only coloured number on the screen, and it is amber:
   nothing here is red */
.em-tile.watch .v { color: var(--status-amber); }

/* 14-day trend. Two series, so a legend is always present and the fills carry a
   2px surface gap. Rounded 4px data-ends, anchored to the baseline. */
.em-trend { padding: 16px 28px 20px; }
.em-legend { display: flex; gap: 16px; font-size: 13px; color: var(--text-soft); margin-bottom: 12px; }
.em-legend i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; margin-right: 6px; vertical-align: -1px; }
.em-chart { display: flex; align-items: flex-end; gap: 7px; height: 132px; padding: 4px 0 0; }
.em-day { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; gap: 2px; cursor: default; }
.em-seg { border-radius: 2px; }
.em-seg.top { border-radius: 4px 4px 2px 2px; }
.em-seg.ok { background: var(--status-green); }
.em-seg.bad { background: var(--status-amber); }
.em-day:hover .em-seg { outline: 2px solid var(--surface); outline-offset: -1px; }
.em-xaxis { display: flex; gap: 7px; margin-top: 7px; }
.em-xaxis span { flex: 1; text-align: center; font-size: 11px; color: var(--text-soft); }

/* filters — ONE row: date range, two dropdowns, search */
.em-filters { display: flex; gap: 10px; align-items: center; padding: 13px 28px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.em-group { display: flex; align-items: center; gap: 6px; }
.em-lab { font-size: 12.5px; color: var(--text-soft); white-space: nowrap; }
.em-ctl { font: inherit; font-size: 13.5px; color: var(--text); background: var(--input-bg); border: 1px solid var(--input-border); border-radius: 6px; padding: 7px 10px; height: 36px; }
.em-ctl:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
select.em-ctl { padding-right: 26px; cursor: pointer; }
input[type="date"].em-ctl { min-width: 140px; }
/* the search box: half the row at most, a magnifying glass inside it, and its
   own lighter surface so it reads as a box in both themes */
.em-searchwrap { position: relative; margin-left: auto; width: 290px; max-width: 50%; }
.em-searchwrap svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); width: 15px; height: 15px; stroke: var(--text-soft); fill: none; stroke-width: 2; pointer-events: none; }
.em-search { width: 100%; padding-left: 32px; }
.em-search::placeholder { color: var(--text-soft); opacity: 1; }
.em-use { font-size: 13px; color: var(--text-soft); }

/* the table. Every column sorts, so every header IS a control and is a button. */
table.dt.em-dt { table-layout: fixed; font-size: 14.5px; }
table.dt.em-dt thead th { padding: 0; }
table.dt.em-dt thead th button { width: 100%; text-align: left; font: inherit; font-size: 13px; font-weight: 600; color: var(--text-soft); background: none; border: 0; padding: 12px 18px; cursor: pointer; display: flex; align-items: center; gap: 5px; }
table.dt.em-dt thead th button:hover { color: var(--text); }
table.dt.em-dt thead th button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
table.dt.em-dt thead th button .ar { font-size: 9px; opacity: 0.35; }
table.dt.em-dt thead th.sorted button { color: var(--text); }
table.dt.em-dt thead th.sorted button .ar { opacity: 1; color: var(--accent); }
table.dt.em-dt tbody td { padding: 13px 18px; vertical-align: top; overflow-wrap: break-word; }
/* rows are not clickable here — there is nothing to open yet */
table.dt.em-dt tbody tr { cursor: default; }
table.dt.em-dt tbody tr:hover { background: transparent; }
.em-who b { display: block; overflow-wrap: break-word; }
.em-who span { font-size: 12.5px; color: var(--text-soft); }
.em-ref { white-space: nowrap; }
.em-sm { font-size: 12.5px; line-height: 1.45; }
.em-soft { color: var(--text-soft); }
.em-na { color: var(--text-soft); font-style: italic; font-size: 12.5px; }
/* prose, not identifiers: break it between words or not at all */
.em-reason { overflow-wrap: normal; }

/* status pills. Every one carries a glyph AND a word — colour is the third
   encoding, never the only one. */
.em-dt .pill { padding: 3px 9px; font-size: 12.5px; }
.pill.warn { background: var(--tint-amber); color: var(--status-amber); }
.pill.info { background: var(--tint-sky); color: var(--status-blue); }

@media (max-width: 1000px) {
  .em-tiles { grid-template-columns: 1fr; }
  .em-searchwrap { margin-left: 0; width: 100%; max-width: 100%; }
}

/* ── sortable headers and the pager, for any .dt ─────────────────────────────
   The Emails screen wrote the sortable header first, scoped to its own .em-dt.
   Every converted list screen sorts and pages, so the rules are generalised
   here. `button.th-sort` rather than every header button: a table with a button
   in a header cell for some other reason must not silently become a sort
   control. `.em-dt`'s copy is left alone — it also lays out that table's fixed
   columns, and a screen not in this PR is not a screen to restyle. */
table.dt thead th:has(> button.th-sort) { padding: 0; }
table.dt thead th button.th-sort { width: 100%; text-align: inherit; font: inherit; font-size: 14px; font-weight: 600; color: var(--text-soft); background: none; border: 0; padding: 14px 18px; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; }
table.dt thead th.ctr button.th-sort { justify-content: center; }
table.dt thead th button.th-sort:hover { color: var(--text); }
table.dt thead th button.th-sort:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
table.dt thead th button.th-sort .ar { font-size: 9px; opacity: 0.35; }
table.dt thead th.sorted button.th-sort { color: var(--text); }
table.dt thead th.sorted button.th-sort .ar { opacity: 1; color: var(--accent); }

/* One list envelope, so one pager. */
.pager { border-top: 1px solid var(--grey-200); }

/* ── Product Evolution ───────────────────────────────────────────────────────
   Ported from the `<style>` block `modules/evolution.js` injected into the page
   on every single render. It lives here for the same reason every other screen's
   rules do: a stylesheet the browser can cache, and one place to read when
   something looks wrong. House rule from the original, kept: no text below 14px
   anywhere on this screen. */
.evo-screen { max-width: 1320px; }
.evo-toptabs { display: flex; gap: 10px; margin: 0 0 22px; }
.evo-toptab { padding: 11px 20px; font-size: 15px; font-weight: 600; color: var(--text-soft);
  cursor: pointer; border: 1px solid var(--grey-200); border-radius: 10px;
  background: var(--surface); text-decoration: none; }
.evo-toptab.active { color: #fff; background: var(--accent); border-color: var(--accent); }

.evo-controls { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap;
  margin: 0 0 20px; }
.evo-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--grey-200); flex-wrap: wrap;
  flex: 1; }
.evo-tab { padding: 12px 18px; font-size: 15px; font-weight: 600; color: var(--text-soft);
  cursor: pointer; border: 0; border-bottom: 3px solid transparent; margin-bottom: -1px;
  background: none; font-family: inherit; display: inline-flex; align-items: center; gap: 9px; }
.evo-tab:hover { color: var(--text); }
.evo-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.evo-tcount { font-size: 14px; font-weight: 700; min-width: 24px; text-align: center;
  padding: 2px 9px; border-radius: 999px; background: var(--surface-2); color: var(--text-soft);
  border: 1px solid var(--grey-200); }
.evo-tab.active .evo-tcount { background: var(--accent); color: #fff; border-color: var(--accent); }
.evo-field { display: flex; flex-direction: column; gap: 5px; }
.evo-flabel { font-size: 14px; font-weight: 600; color: var(--text-soft); }
.evo-field select, .evo-field input { font: inherit; font-size: 14px; padding: 9px 12px;
  border: 1px solid var(--grey-200); border-radius: 9px; background: var(--surface);
  color: var(--text); }
.evo-search input { min-width: 260px; }

/* The row is a DIV wrapping a link and some buttons, not one big anchor. A `<button>` inside an
   `<a>` is invalid HTML — see `Evolution.tsx:MockupRow`. The link still fills the row, so clicking
   the title still opens the mock-up; only the buttons sit outside it. */
.evo-row { display: flex; align-items: center; gap: 20px; padding: 20px 24px;
  border: 1px solid var(--grey-200); border-radius: 14px; margin-bottom: 14px;
  background: var(--surface); transition: box-shadow .12s, border-color .12s;
  color: inherit; }
.evo-row:hover { box-shadow: var(--shadow-card); border-color: var(--accent); }
.evo-rowlink { flex: 1; min-width: 0; text-decoration: none; color: inherit; }
.evo-rowchev { display: inline-flex; align-items: center; text-decoration: none; }
.evo-rowmain { flex: 1; min-width: 0; }
.evo-row .evo-title { display: block; font-weight: 700; font-size: 17px; line-height: 1.35; }
.evo-row .evo-meta { display: block; font-size: 14px; color: var(--text-soft); margin-top: 5px;
  line-height: 1.5; }
.evo-btn { border: 1px solid var(--grey-200); background: var(--surface); color: var(--text);
  font: inherit; font-size: 14px; font-weight: 600; border-radius: 9px; padding: 9px 15px;
  cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; }
.evo-btn:hover { border-color: var(--accent); }
.evo-btn:disabled { opacity: .55; cursor: default; }
.evo-btn.primary { background: var(--status-green, #1a7f4b); color: #fff;
  border-color: var(--status-green, #1a7f4b); }
.evo-btn.danger { color: #c62828; border-color: rgba(198, 40, 40, .35); }
.evo-btn.ghost { color: var(--text-soft); }
[data-theme="dark"] .evo-btn.danger { color: #ff8a8a; border-color: rgba(255, 138, 138, .35); }

/* The sign-off buttons — on the row and again on the detail, which is what the legacy screen did
   and is what stops somebody navigating back to the list to approve what they just read. */
.evo-acts { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; flex: none; }
.evo-decide { display: flex; justify-content: flex-end; margin: 0 0 18px; }

/* How many are still waiting on somebody. Counted over the whole catalogue, from the facets. */
.evo-awaiting { font-size: 15px; margin: 0 0 16px; color: var(--text-soft); }
.evo-awaiting b { color: var(--accent); }

/* Who decided what, and when. On the screen rather than only in the table, because an approval
   nobody can see is only checkable by whoever can open a database (`PLATFORM.md` §4). */
.evo-hist { list-style: none; margin: 0; padding: 0; }
.evo-histrow { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 0; border-bottom: 1px solid var(--grey-200); }
.evo-histrow:last-child { border-bottom: 0; }
.evo-histwho { font-size: 14px; color: var(--text-soft); }
.evo-histnote { flex-basis: 100%; margin: 4px 0 0; font-size: 14px; line-height: 1.5; }
.evo-hist-empty { font-size: 14px; color: var(--text-soft); margin: 0; }

/* Every chip carries a word as well as a colour — colour is the third encoding, never
   the only one. The word is the SERVER's (`status_label`); the class only picks a palette. */
.evo-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 700;
  border-radius: 999px; padding: 5px 13px; white-space: nowrap; }
.evo-chip .evo-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.evo-chip.pending { color: #b76b00; background: rgba(183, 107, 0, .12); }
.evo-chip.approved { color: #1a7f4b; background: rgba(26, 127, 75, .12); }
.evo-chip.rejected { color: #c62828; background: rgba(198, 40, 40, .12); }
.evo-chip.cancelled { color: var(--text-soft); background: rgba(138, 138, 150, .14); }
.evo-chip.completed { color: #3457d5; background: rgba(52, 87, 213, .12); }
[data-theme="dark"] .evo-chip.pending { color: #e7a33e; background: rgba(231, 163, 62, .16); }
[data-theme="dark"] .evo-chip.approved { color: #4cc98a; background: rgba(76, 201, 138, .16); }
[data-theme="dark"] .evo-chip.rejected { color: #ff8a8a; background: rgba(255, 138, 138, .16); }
[data-theme="dark"] .evo-chip.completed { color: #7ea0ff; background: rgba(126, 160, 255, .16); }

.evo-daily { border-left: 2px solid var(--grey-200); padding-left: 22px; margin-left: 6px;
  max-width: 1000px; }
.evo-daily .d-item { margin-bottom: 24px; position: relative; }
.evo-daily .d-item::before { content: ""; position: absolute; left: -29px; top: 6px; width: 10px;
  height: 10px; border-radius: 50%; background: var(--accent); }
.evo-daily .d-date { font-size: 14px; color: var(--text-soft); font-weight: 600; }
.evo-daily .d-title { font-weight: 700; font-size: 17px; margin: 3px 0 6px; }
.evo-daily .d-body { font-size: 15px; color: var(--text-soft); line-height: 1.6; }

/* the in-app mock-up viewer */
.evo-detailhead { display: flex; align-items: center; justify-content: space-between; gap: 14px;
  flex-wrap: wrap; margin-bottom: 14px; }
.evo-back { cursor: pointer; color: var(--accent); font-size: 15px; font-weight: 600;
  text-decoration: none; }
.evo-context { max-width: 1000px; border: 1px solid var(--grey-200); border-radius: 14px;
  padding: 22px 26px; background: var(--surface); margin-bottom: 18px; }
.evo-context .lbl { font-size: 14px; text-transform: uppercase; letter-spacing: .05em;
  font-weight: 700; color: var(--text-soft); }
.evo-context p { font-size: 15px; line-height: 1.6; margin: 8px 0 16px; }
.mkpv-bar { display: flex; align-items: center; justify-content: space-between; gap: 14px;
  flex-wrap: wrap; padding: 13px 18px; margin-bottom: 14px; border: 1px solid var(--grey-200);
  border-radius: 12px; background: var(--surface-2); }
.mkpv-bar span { font-size: 14px; color: var(--text-soft); }
.mkpv-frame { width: 100%; height: 1200px; border: 1px solid var(--grey-200); border-radius: 12px;
  background: var(--surface); display: block; }

/* ── the sign-in screen ────────────────────────────────────────────────────────────────────────
   The whole page a signed-out visitor gets (src/screens/sign-in). It is deliberately NOT inside
   .shell: there is no rail, no topbar and no breadcrumb behind it, because there is nothing behind
   it to reach. Every value is a semantic token, so the card follows the theme toggle like the rest
   of the app rather than carrying the mock-up's own hard-coded palette. */
.pv-signin { min-height: 100vh; display: flex; align-items: center; justify-content: center;
  background: var(--bg); padding: 24px; }
.pv-signin__theme { position: fixed; top: 18px; right: 18px; }
.pv-signin__card { width: 380px; max-width: 100%; background: var(--surface);
  border: 1px solid var(--border); border-radius: 18px; padding: 40px 34px 34px;
  text-align: center; box-shadow: var(--shadow-lg); }
.pv-signin__logo { height: 34px; margin-bottom: 26px; }
.pv-signin__title { font-size: 21px; font-weight: 600; margin: 0 0 6px; letter-spacing: -0.01em;
  color: var(--text); }
.pv-signin__sub { color: var(--text-soft); font-size: 13.5px; line-height: 1.5; margin: 0 0 26px; }
/* White in BOTH themes, and that is Google's brand requirement rather than an oversight: their
   sign-in button has a fixed appearance and a themed one is not a compliant use of the mark. */
.pv-signin__google { display: flex; align-items: center; justify-content: center; gap: 11px;
  width: 100%; padding: 12px 16px; border: 1px solid #dcd7e6; background: #ffffff; color: #1b1729;
  border-radius: 11px; font: inherit; font-size: 14.5px; font-weight: 600; cursor: pointer;
  text-decoration: none; transition: box-shadow .15s; }
.pv-signin__google:hover { box-shadow: 0 3px 12px rgba(0, 0, 0, .14); }
.pv-signin__foot { margin-top: 22px; font-size: 12px; color: var(--text-soft); line-height: 1.5; }

/* System configuration's definition list — a label column and a value column, the shape the
   mock-up specified. Only this screen uses it; it is here rather than inline because the two
   columns have to line up across sections and an inline grid per section would not. */
.sc-kv { display: grid; grid-template-columns: 220px 1fr; gap: 10px 18px; font-size: 14px;
  margin: 0; }
.sc-kv dt { color: var(--text-soft); font-weight: 600; }
.sc-kv dd { margin: 0; font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 13px; }

/* Service tokens — the module credentials another system presents to call us.
   The generic .btn, .pill, .field and .muted do most of the work; what is here is the two things
   this screen has that no other does: the issue row, and the panel that shows a credential once. */
.st-h { font-size: 19px; font-weight: 700; margin: 0 0 6px; }
.st-lede { font-size: 14px; color: var(--text-soft); line-height: 1.55; margin: 0 0 20px;
  max-width: 74ch; }

/* The issue row. Name takes the slack because it is the field with something to say; module and
   environment are a slug and a two-value choice and do not grow. */
.st-issue { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap;
  padding: 16px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface); margin-bottom: 22px; }
.st-issue .field { margin-bottom: 0; }
.st-issue-name { flex: 1 1 260px; }
.st-issue input, .st-issue select { width: 100%; padding: 9px 12px; border-radius: 4px;
  border: 1px solid var(--grey-300); background: var(--surface); color: var(--text);
  font: inherit; font-size: 14px; min-height: 40px; }

/* THE VALUE, SHOWN ONCE. Amber rather than red — this is not an error, it is the one moment the
   credential exists, and it has to read as "act now" rather than "something went wrong". It is
   loud on purpose: the cost of it being missed is a token nobody can recover. */
.st-issued { border: 2px solid var(--status-red); border-radius: 10px; background: var(--tint-amber);
  padding: 18px; margin-bottom: 22px; }
.st-issued-h { font-size: 15px; font-weight: 700; margin: 0 0 8px; }
.st-issued-warn { font-size: 13.5px; font-weight: 600; line-height: 1.5; margin: 0 0 14px; }
.st-issued-row { display: flex; align-items: center; gap: 10px; margin-bottom: 12px;
  flex-wrap: wrap; }
.st-issued-value { flex: 1 1 380px; padding: 11px 13px; border-radius: 6px;
  border: 1px solid var(--grey-300); background: var(--surface);
  font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 13px;
  word-break: break-all; user-select: all; }
.st-issued-hint { font-size: 13px; color: var(--text-soft); line-height: 1.5; margin: 0 0 14px; }

.st-toolbar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.st-search { padding: 9px 12px; border-radius: 4px; border: 1px solid var(--grey-300);
  background: var(--surface); color: var(--text); font: inherit; font-size: 14px;
  min-height: 40px; min-width: 220px; }
.st-check { display: inline-flex; align-items: center; gap: 7px; font-size: 14px;
  color: var(--text-soft); font-weight: 600; }
.st-count { font-size: 13px; margin-left: auto; }

.st-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.st-table th { text-align: left; font-size: 12px; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-muted); font-weight: 700;
  padding: 8px 12px; border-bottom: 1px solid var(--border); }
.st-table td { padding: 11px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.st-table code { font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 12.5px; }
/* Revoked rows STAY — the audit is the reason. Dimmed so the live set reads first. */
.st-revoked { opacity: .55; }

.st-empty { font-size: 14px; color: var(--text-soft); padding: 26px 0; }
.st-error { font-size: 13.5px; color: var(--status-red); font-weight: 600; margin: 10px 0 0; }

/* ── Email automation ────────────────────────────────────────────────────────
   The lifecycle-event → email mapping read surface, ported from Agent's
   Configuration screen on 2026-07-31 ("should ONLY live in Core" — Roger).
   Reuses .ur-tabs, .dt, .pill and the drawer; only what is this screen's own
   lives here. */
.ea-eventrow { display: flex; align-items: flex-end; gap: 16px; margin: 4px 0 16px; flex-wrap: wrap; }
.ea-eventrow label { display: block; font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; color: var(--text-soft); margin-bottom: 6px; }
.ea-eventrow select { padding: 10px 12px; border: 1px solid var(--grey-300); border-radius: 9px; font: inherit; font-size: 15px; background: var(--surface); color: var(--text); min-width: min(430px, 90vw); }
.ea-fires { font-size: 13px; color: var(--text-soft); padding-bottom: 11px; }
.ea-open { font: inherit; font-weight: 600; color: var(--text); background: none; border: 0; padding: 0; cursor: pointer; text-align: left; }
.ea-open:hover { text-decoration: underline; }
.ea-seq { font-size: 12.5px; font-weight: 700; color: var(--text-soft); margin-right: 6px; }
.ea-name { font-weight: 600; }
.ea-sub { font-size: 12.5px; color: var(--text-soft); margin-top: 2px; line-height: 1.45; }
.ea-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.ea-pills .pill, .ea-trigger .pill { padding: 3px 9px; font-size: 12.5px; }
.ea-trigger { display: inline-flex; align-items: center; gap: 8px; }
/* the templates table is a listing, not a set of doors — rows do not invite a click */
tr.ea-static, table.dt tbody tr.ea-static:hover { cursor: default; background: transparent; }
.ea-note { font-size: 13px; color: var(--text-soft); margin: 4px 0 14px; }
.ea-note a { color: var(--accent); font-weight: 600; }
.ea-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-top: 4px; }
.ea-card { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 15px 18px; box-shadow: var(--shadow-card); }
.ea-card .k, .ea-fact .k, .ea-ladder .k { font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; color: var(--text-soft); }
.ea-card .v { font-size: 15px; font-weight: 600; margin-top: 7px; }
.ea-card .f { font-size: 12.5px; color: var(--text-soft); margin-top: 3px; }
.ea-summary { font-size: 14px; line-height: 1.55; margin: 0 0 18px; }
.ea-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 16px 24px; }
.ea-fact .v { font-size: 14px; margin-top: 5px; line-height: 1.5; }
.ea-ladder { border: 1px solid var(--border); background: var(--surface-2); border-radius: 8px; padding: 14px 16px; margin-top: 20px; }
.ea-ladder ol { margin: 9px 0 0; padding-left: 19px; font-size: 14px; line-height: 1.7; }
@media (max-width: 1000px) { .ea-cards { grid-template-columns: 1fr; } }
