/* Design tokens are defined in ui/themes/*.css — load a theme before this file. */

/* ─── theme switcher (inline in header) ─────────────────────────────────── */
.theme-switcher {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 4px 12px 4px 8px;
  background: var(--lift);
  border: 1px solid var(--border);
  border-radius: var(--r);
  transition: border-color .15s;
  flex-shrink: 0;
}
.theme-switcher:hover { border-color: var(--bhi); }
.theme-switcher-icon { display: flex; flex-shrink: 0; }
/* #theme-select now lives inside the user menu and is styled as a compact boxed
   dropdown (.user-menu-select) — see the dropdown system below. It used to have
   its own bare, mono, hardcoded-caret treatment here, which fought the class it
   shares with the model picker sitting right under it. */

/* ─── header separator between theme switcher and user section ───────────── */
.header-sep {
  width: 1px;
  height: 20px;
  background: var(--border);
  flex-shrink: 0;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* Code is shown as typed: a programming-font ligature turns `<=` into `≤`,
   which is a different character from what runs. */
code, kbd, pre, samp, .sem-mono, [class*="-sql"] { font-variant-ligatures: none; }

body {
  background: var(--void);
  color: var(--text);
  font-family: var(--sans);
  font-size: 14px;
  height: 100vh;
  overflow: hidden;
}

/* ─── auth overlay ───────────────────────────────────────────────────────── */
/* Signed-out frame (spec 005a): the form on the left, the brand panel on the
   right on wide screens. Shared by sign-in, SSO return and the link screens. */
#auth-overlay {
  position: fixed;
  inset: 0;
  background: var(--depth);
  display: flex;
  z-index: 200;
  overflow: auto;
}
.auth-main {
  flex: 1 1 520px;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 24px;
}
.auth-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 40px 44px;
  width: 440px;
  max-width: calc(100vw - 32px);
}
.auth-title {
  font-family: var(--display);
  font-size: 26px;
  line-height: 1.2;
  font-weight: 600;
  letter-spacing: -0.02em;
  text-align: center;
  margin-bottom: 6px;
}
.auth-title + .auth-sub { margin-top: 0; }
#sso-btn { margin-top: 10px; }

.auth-brand {
  flex: 1 1 540px;
  min-width: 0;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 28px;
  padding: 56px clamp(28px, 5vw, 72px);
  background: var(--wing-bg, #384064);
  color: var(--wing-ink, #fff);
}
.auth-petal { position: absolute; display: block; }
.auth-petal--a { right: -60px; top: -130px; width: 300px; height: 250px; background: var(--accent, #2e60a8); border-radius: 0 160px 0 160px; opacity: .9; }
.auth-petal--b { left: -90px; bottom: -110px; width: 320px; height: 260px; background: var(--wing-raised, #2c3352); border-radius: 0 140px 0 140px; }
.auth-brand > :not(.auth-petal) { position: relative; max-width: 540px; }
.auth-brand > .auth-brand-journey { max-width: 640px; }
.auth-brand-lead { font-family: var(--display); font-size: clamp(26px, 2.6vw, 36px); line-height: 1.22; font-weight: 600; letter-spacing: -0.01em; }
.auth-brand-demo { display: flex; flex-direction: column; gap: 12px; }
.auth-brand-q { align-self: flex-end; max-width: 380px; padding: 12px 16px; border-radius: 12px; background: #fff; color: #384064; font-size: 15px; }
.auth-brand-a {
  display: flex; flex-direction: column; gap: 14px;
  padding: 22px 24px;
  border-radius: 28px 4px 28px 4px;
  background: #f3f8fd; color: #384064;
  font-size: 15px;
}
.auth-brand-a strong { font-weight: 600; }
.auth-brand-prov { display: flex; align-items: center; gap: 8px; font-size: 13px; color: #2e60a8; }
.auth-brand-bars { display: flex; align-items: flex-end; gap: 10px; height: 110px; border-bottom: 1px solid #d6e2f0; }
.auth-brand-bars span { flex: 1; border-radius: 6px 6px 0 0; background: #2e60a8; }
.auth-brand-bars span:nth-child(2) { background: #4d8ec1; }
.auth-brand-bars span:nth-child(3) { background: #7fb6e3; }
.auth-brand-bars span:nth-child(n+4) { background: #acdbfc; }
.auth-brand-axis { display: flex; gap: 10px; font-size: 12px; color: #5b6485; }
.auth-brand-axis span { flex: 1; text-align: center; }
.auth-brand-journey { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; }
.auth-brand-journey li { padding: 5px 12px; border-radius: 9999px; border: 1px solid var(--wing-border, #5b6485); color: var(--wing-muted, #c9d4ea); font-size: 13px; white-space: nowrap; }
.auth-brand-journey li.is-on { background: var(--wing-accent, #acdbfc); border-color: transparent; color: #384064; font-weight: 500; }
@media (max-width: 960px) { .auth-brand { display: none; } }
.auth-logo {
  display: flex;
  justify-content: center;
  margin-bottom: 14px;
  color: var(--text);          /* the Imago wordmark is drawn in currentColor */
}
.auth-sub {
  font-size: var(--page-sub-size, 12px);
  color: var(--muted);
  text-align: center;
  margin-bottom: 28px;
}
.auth-signed-out {
  font-size: var(--type-meta, 12.5px);
  line-height: 1.5;
  color: var(--muted);
  background: var(--lift);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 10px 12px;
  margin-bottom: 20px;
}
.auth-tabs {
  display: flex;
  background: var(--lift);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 3px;
  gap: 3px;
  margin-bottom: 24px;
}
.auth-tab {
  flex: 1;
  padding: 8px;
  background: transparent;
  border: none;
  border-radius: 6px;
  color: var(--muted);
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all .15s;
}
.auth-tab.active {
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 1px 3px rgba(0,0,0,.3);
}
.auth-form-panel { display: none; }
.auth-form-panel.active { display: block; }

/* subtle administrator link under the login form */
.auth-alt {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  text-align: center;
}
.auth-alt a {
  font-family: var(--mono);
  font-size: max(11px, var(--type-floor, 0px));
  letter-spacing: .3px;
  color: var(--subtle-ink, var(--faint));
  text-decoration: none;
  transition: color .15s;
}
.auth-alt a:hover { color: var(--accent); }

/* ─── shared form styles ─────────────────────────────────────────────────── */
.form-group { margin-bottom: 14px; }
.form-group label {
  display: block;
  font-size: max(10px, var(--label-min-size, 0px));
  font-weight: 500;
  color: var(--muted);
  text-transform: var(--label-case, uppercase);
  letter-spacing: var(--label-tracking, 1px);
  margin-bottom: 5px;
  font-family: var(--label-font, var(--mono));
}
.form-group input,
.form-group .dd-trigger,
.form-group select {
  width: 100%;
  min-height: max(var(--control-h, 0px), var(--touch-min, 0px));
  background: var(--field-bg, var(--lift));
  border: 1px solid var(--field-border, var(--border));
  border-radius: var(--control-r, var(--r));
  color: var(--text);
  font-family: var(--sans);
  font-size: 14px;
  padding: 10px 13px;
  outline: none;
  transition: border-color .2s, box-shadow .2s;
  appearance: none;
}
.form-group input::placeholder { color: var(--faint); }
.form-group input:focus,
.form-group select:focus {
  border-color: var(--accent);
  box-shadow: var(--dd-ring);
}
.form-group input[type="password"] { letter-spacing: .1em; }

.form-error {
  font-size: 12px;
  color: var(--rose);
  min-height: 18px;
  margin-top: -6px;
  margin-bottom: 4px;
}
.form-hint {
  font-size: max(11px, var(--type-floor, 0px));
  color: var(--subtle-ink, var(--faint));
  margin-top: 4px;
  line-height: 1.5;
}
.form-actions {
  display: flex;
  gap: 8px;
  margin-top: 6px;
}

/* ═══ dropdown system ══════════════════════════════════════════════════════
   Every dropdown in the portal — native <select> controls and the
   button-triggered popover menus — is styled from here. Two registers, and
   only two:

     boxed   (default)      a control you set: forms, panels, filter bars
     inline  (.dd-inline)   a value you edit in place: the Explorer breadcrumb

   The caret is two gradient wedges tinted from the control's OWN colour, so it
   re-skins with every theme and brightens on hover/focus. Do not go back to
   SVG data-URI carets with a baked-in hex: the three that used to live here
   were slate-blue on every theme and vanished on the light ones.

   Adding a dropdown? Add its selector to the groups below — don't restyle it
   locally, or the portal goes back to eight different dropdowns.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  --dd-r:     var(--r);   /* standard control corner — matches .btn          */
  --dd-r-sm:  7px;        /* compact control corner — matches .btn-sm        */
  --dd-pop-r: 12px;       /* popover corner                                  */
  --dd-caret: 4.5px;      /* half-chevron box; the mark is 2 halves wide     */
  --dd-caret-w: .8px;     /* chevron stroke — reads like the 1.4px SVG icons */
  /* Four of the six themes predate --shadow-md / --ring, hence the fallbacks. */
  --dd-shadow: var(--shadow-md, 0 14px 36px -10px rgba(0,0,0,.45));
  --dd-ring:   var(--ring, 0 0 0 3px var(--accent-bg));
}

/* ── the shared mark: one chevron, every dropdown ─────────────────────────
   Two square boxes side by side, each carrying a single diagonal stripe: "\"
   then "/" meet at the shared bottom corner and read as one thin chevron. It's
   built from currentColor, so it inherits whatever the control's ink is — and
   it's a stroke, not a filled triangle, which is the icon language everywhere
   else in the portal (all our SVGs are stroke-width 1.4). */
.form-group .dd-trigger,
.form-group select,
.schema-controls .dd-trigger,
.schema-controls select,
.sem-field .dd-trigger,
.sem-field select,
.ppl-field .dd-trigger,
.user-menu-select,
.dash-filter-select,
.actions-toolbar .dd-trigger,
.ask-filter .dd-trigger,
.exp-seg .dd-trigger,
.exp-seg select {
  --dd-caret-ink: color-mix(in srgb, currentColor 62%, transparent);
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  outline: none;
  background-image:
    linear-gradient(45deg, transparent calc(50% - var(--dd-caret-w)),
      var(--dd-caret-ink) calc(50% - var(--dd-caret-w)) calc(50% + var(--dd-caret-w)),
      transparent calc(50% + var(--dd-caret-w))),
    linear-gradient(135deg, transparent calc(50% - var(--dd-caret-w)),
      var(--dd-caret-ink) calc(50% - var(--dd-caret-w)) calc(50% + var(--dd-caret-w)),
      transparent calc(50% + var(--dd-caret-w)));
  background-size: var(--dd-caret) var(--dd-caret), var(--dd-caret) var(--dd-caret);
  background-repeat: no-repeat, no-repeat;
  transition: border-color .15s, box-shadow .15s, color .15s;
}
.form-group .dd-trigger:hover, .form-group select:hover,
.schema-controls .dd-trigger:hover, .schema-controls select:hover,
.sem-field .dd-trigger:hover, .sem-field select:hover,
.ppl-field .dd-trigger:hover,
.user-menu-select:hover,
.dash-filter-select:hover,
.actions-toolbar .dd-trigger:hover,
.ask-filter .dd-trigger:hover,
.exp-seg .dd-trigger:hover, .exp-seg select:hover,
.form-group .dd-trigger:focus-visible, .form-group select:focus-visible,
.schema-controls .dd-trigger:focus-visible, .schema-controls select:focus-visible,
.sem-field .dd-trigger:focus-visible, .sem-field select:focus-visible,
.ppl-field .dd-trigger:focus-visible,
.user-menu-select:focus-visible,
.dash-filter-select:focus-visible,
.actions-toolbar .dd-trigger:focus-visible,
.ask-filter .dd-trigger:focus-visible,
.exp-seg .dd-trigger:focus-visible, .exp-seg select:focus-visible { --dd-caret-ink: currentColor; }

/* ── boxed register ──────────────────────────────────────────────────────── */
.form-group .dd-trigger,
.form-group select,
.schema-controls .dd-trigger,
.schema-controls select,
.sem-field .dd-trigger,
.sem-field select,
.ppl-field .dd-trigger {
  background-color: var(--lift);
  border: 1px solid var(--border);
  border-radius: var(--dd-r);
  color: var(--text);
  font-family: var(--sans);
  font-size: 13.5px;
  padding: 9px 32px 9px 12px;
  background-position: right 17.5px center, right 13px center;
}
.form-group .dd-trigger,
.form-group select { font-size: 14px; padding: 10px 32px 10px 13px; }

/* compact boxed — inside menu rows, dashboard filter bars and page toolbars */
.user-menu-select,
.dash-filter-select,
.actions-toolbar .dd-trigger {
  background-color: var(--lift);
  border: 1px solid var(--border);
  border-radius: var(--dd-r-sm);
  color: var(--text);
  font-family: var(--sans);
  font-size: 12px;
  padding: 5px 26px 5px 9px;
  background-position: right 14.5px center, right 10px center;
}

/* shared interaction for both boxed sizes */
.form-group .dd-trigger:hover, .form-group select:hover,
.schema-controls .dd-trigger:hover, .schema-controls select:hover,
.sem-field .dd-trigger:hover, .sem-field select:hover,
.ppl-field .dd-trigger:hover,
.user-menu-select:hover,
.dash-filter-select:hover,
.actions-toolbar .dd-trigger:hover,
.ask-filter .dd-trigger:hover { border-color: var(--bhi); }

.schema-controls .dd-trigger:focus-visible, .schema-controls select:focus-visible,
.sem-field .dd-trigger:focus-visible, .sem-field select:focus-visible,
.ppl-field .dd-trigger:focus-visible,
.user-menu-select:focus-visible,
.dash-filter-select:focus-visible,
.actions-toolbar .dd-trigger:focus-visible,
.ask-filter .dd-trigger:focus-visible {
  border-color: var(--accent);
  box-shadow: var(--dd-ring);
}

.form-group .dd-trigger:disabled, .form-group select:disabled,
.schema-controls .dd-trigger:disabled, .schema-controls select:disabled,
.sem-field .dd-trigger:disabled, .sem-field select:disabled,
.ppl-field .dd-trigger:disabled,
.user-menu-select:disabled,
.dash-filter-select:disabled,
.actions-toolbar .dd-trigger:disabled,
.ask-filter .dd-trigger:disabled,
.exp-seg .dd-trigger:disabled, .exp-seg select:disabled {
  color: var(--faint);
  cursor: not-allowed;
  --dd-caret-ink: color-mix(in srgb, currentColor 45%, transparent);
}

/* ── inline register — the select IS the value, not a field around it ────── */
.exp-seg .dd-trigger,
.exp-seg select {
  background-color: transparent;
  border: 0;
  border-radius: 3px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 500;
  padding: 0 16px 0 0;
  margin: 0;
  background-position: right 6.5px center, right 2px center;
}
.exp-seg .dd-trigger:focus-visible, .exp-seg select:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* The native option list is OS-drawn; Windows and Linux honour these, macOS
   ignores them. Setting them is still the difference between a readable list
   and white-on-white on the light themes. */
select option {
  background: var(--surface);
  color: var(--text);
}

/* ── popover menus — one shell for all of them ───────────────────────────── */
.user-menu-dropdown,
.session-picker-dropdown,
.cxn-menu,
.export-menu,
.dd-pop {
  position: absolute;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--dd-pop-r);
  box-shadow: var(--dd-shadow);
  padding: 6px;
  animation: menuIn .14s ease;
}
@keyframes menuIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }

/* ── popover items ───────────────────────────────────────────────────────── */
.user-menu-item,
.cxn-menu button,
.export-menu button,
.session-item,
.session-new-btn,
.dd-item {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 8px 10px;
  background: none;
  border: 0;
  border-radius: 8px;
  color: var(--text);
  font-family: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  transition: background .12s;
}
.user-menu-item:hover,
.cxn-menu button:hover,
.export-menu button:hover,
.session-item:hover,
.session-new-btn:hover,
.dd-item:hover { background: color-mix(in srgb, var(--text) 7%, transparent); }

.user-menu-item:focus-visible,
.cxn-menu button:focus-visible,
.export-menu button:focus-visible,
.session-item:focus-visible,
.session-new-btn:focus-visible,
.dd-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.cxn-menu button.is-danger,
.export-menu button.is-danger { color: var(--rose); }

@media (prefers-reduced-motion: reduce) {
  .user-menu-dropdown,
  .session-picker-dropdown,
  .cxn-menu,
  .export-menu,
  .dd-pop { animation: none; }
}

/* ── the option list (js/dropdown.js) ─────────────────────────────────────
   A native <select>'s open list is drawn by the OS and cannot be styled, so
   every select is enhanced into this trigger + listbox. The trigger copies the
   select's own classes, so it picks up the boxed / compact / inline register
   above verbatim; the list is the same popover shell as every other menu.
   The <select> itself stays in the DOM as the source of truth — see the file
   header — so `sel.value`, `innerHTML` rewrites and onchange="" keep working. */
.dd-wrap { position: relative; display: inline-block; max-width: 100%; }
/* full-width contexts: the wrapper must not shrink-wrap the control */
.form-group .dd-wrap,
.ppl-field .dd-wrap,
.sem-field .dd-wrap { display: block; width: 100%; }

.dd-trigger {
  display: block;
  width: 100%;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.35;
}
.exp-seg .dd-trigger { width: auto; max-width: 40ch; }

/* Kept for its value + events, never seen. Not display:none — code still
   focuses it and reads layout off it. */
.dd-native {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
  clip-path: inset(50%);
}

.dd-list {
  top: calc(100% + 5px);
  left: 0;
  z-index: 400;
  min-width: 100%;
  max-height: 288px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.dd-wrap.dd-up .dd-list { top: auto; bottom: calc(100% + 5px); }
.dd-list[hidden] { display: none; }
/* the breadcrumb's selects are narrow; their lists shouldn't be */
.exp-seg .dd-list { min-width: max(100%, 220px); }

.dd-item {
  white-space: nowrap;
  font-size: 13px;
}
.dd-item.is-selected {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.dd-item:disabled { color: var(--faint); cursor: not-allowed; }

/* ─── buttons ────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: max(var(--control-h, 0px), var(--touch-min, 0px));
  padding: 9px 18px;
  border-radius: var(--control-r, var(--r));
  font-family: var(--control-font, var(--display));
  font-size: var(--control-size, 13px);
  font-weight: var(--control-weight, 600);
  cursor: pointer;
  border: 1px solid transparent;
  transition: opacity .15s, transform .1s;
  white-space: nowrap;
}
.btn:disabled { opacity: .4; cursor: not-allowed; }
.btn:not(:disabled):hover { opacity: .88; }
.btn:not(:disabled):active { transform: scale(.98); }

.btn-primary  { background: var(--gold); color: var(--on-accent, var(--void)); }
.btn-ghost    { background: var(--control-bg, var(--lift)); color: var(--text); border-color: var(--control-border, var(--border)); }
.btn-danger   { background: rgba(244,63,94,.1); color: var(--rose); border-color: rgba(244,63,94,.25); }
.btn-success  { background: rgba(16,185,129,.1); color: var(--emerald); border-color: rgba(16,185,129,.25); }
.btn-full     { width: 100%; }
.btn-sm       { min-height: max(var(--control-sm-h, 0px), var(--touch-min, 0px)); padding: 6px 12px; font-size: var(--control-sm-size, 11px); }

/* ─── header ─────────────────────────────────────────────────────────────── */
header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 20px;
  height: 56px;
  background: var(--depth);
  border-bottom: 1px solid var(--border);
  position: relative;
  z-index: 10;
  flex-shrink: 0;
}
header::after {
  content: '';
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent 0%, var(--gold) 45%, transparent 100%);
  opacity: .22;
}
.header-logo { display: flex; align-items: center; flex-shrink: 0; color: var(--text); }
.header-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 12px;
}
.header-account {
  font-size: 12px;
  color: var(--muted);
  font-family: var(--mono);
}
.header-account strong { color: var(--text); font-weight: 500; }
.header-user {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px;
  background: var(--lift);
  border: 1px solid var(--border);
  border-radius: 20px;
  cursor: pointer;
  transition: border-color .15s;
}
.header-user:hover { border-color: var(--bhi); }
.user-avatar {
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--gold-bg);
  border: 1px solid var(--gold-dim);
  color: var(--gold);
  font-family: var(--mono);
  font-size: max(10px, var(--type-floor, 0px));
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.user-name-display {
  font-size: 12px;
  font-weight: 500;
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ─── user menu dropdown ─────────────────────────────────────────────────── */
.header-user-menu { position: relative; }
.header-user { color: var(--text); font-family: inherit; }
.user-menu-caret { color: var(--muted); margin-left: 1px; flex-shrink: 0; transition: transform .15s; }
.header-user[aria-expanded="true"] .user-menu-caret { transform: rotate(180deg); }

/* Face, edge, corner, shadow and animation come from the dropdown system. */
.user-menu-dropdown {
  top: calc(100% + 8px);
  right: 0;
  min-width: 260px;
  z-index: 300;
}
.user-menu-head { padding: 8px 10px 10px; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.user-menu-name  { font-size: 13px; font-weight: 600; color: var(--text);
  display: flex; align-items: center; gap: 8px; }
/* Everyone can see their own role, and this is where they already look to see
   who they are signed in as. */
.user-menu-role {
  font-size: max(10.5px, var(--type-floor, 0px)); font-weight: 600; text-transform: capitalize; color: var(--muted);
  background: color-mix(in srgb, var(--text) 8%, transparent);
  padding: 2px 7px; border-radius: 999px;
}
.user-menu-email { font-size: max(11.5px, var(--type-floor, 0px)); color: var(--muted); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-menu-account {
  display: flex; align-items: center; gap: 6px; margin-top: 8px;
  font-size: 12px; font-weight: 500; color: var(--text);
}
.user-menu-account svg { color: var(--accent); flex-shrink: 0; }
.user-menu-account:empty { display: none; }

.user-menu-section { padding: 2px 0 6px; margin-bottom: 6px; border-bottom: 1px solid var(--border); }
.user-menu-row {
  display: flex; align-items: center; gap: 9px; padding: 7px 10px;
  font-size: 13px; color: var(--text);
}
.user-menu-row > svg { color: var(--muted); flex-shrink: 0; }
.user-menu-row > span { flex: 1; }
/* .user-menu-select and .user-menu-item are styled by the dropdown system. */
.user-menu-select { max-width: 140px; }
.user-menu-item svg { color: var(--muted); flex-shrink: 0; }
.user-menu-item > span:first-of-type { flex: 1; }
.user-menu-badge {
  font-size: max(10.5px, var(--type-floor, 0px)); color: var(--accent); font-weight: 600;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  padding: 2px 7px; border-radius: 999px;
  max-width: 108px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ─── modal ──────────────────────────────────────────────────────────────── */
.modal-overlay {
  position: fixed; inset: 0; z-index: 500;
  background: rgba(0,0,0,.55);
  display: flex; align-items: center; justify-content: center;
  padding: 20px; animation: menuIn .14s ease;
}
.modal-overlay[hidden] { display: none; }
.modal-card {
  width: 100%; max-width: 480px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 16px; box-shadow: 0 24px 60px rgba(0,0,0,.5);
  padding: 22px 22px 18px; max-height: 85vh; overflow-y: auto;
}
.modal-card--wide { max-width: 860px; }
.modal-hdr { display: flex; align-items: center; justify-content: space-between; }
.modal-hdr h3 { margin: 0; font-size: 16px; font-weight: 600; color: var(--text); }
.modal-close {
  background: none; border: none; color: var(--muted); cursor: pointer;
  padding: 5px; border-radius: 6px; display: flex; transition: background .12s, color .12s;
}
.modal-close:hover { background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text); }
.modal-sub { font-size: var(--type-meta, 12.5px); color: var(--muted); line-height: 1.5; margin: 10px 0 16px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }

/* The app's own alert/confirm/prompt, drawn twice on this shell: by
   src/components/dialog.tsx for both React roots and by _dialog() in
   js/dashboard-render.js for the renderer island. It sits a layer above
   .modal-overlay because ModelSettingsModal raises its save error from inside
   an open modal. */
.modal-overlay.dialog-overlay { z-index: 600; }
.dialog-card { max-width: 420px; }
.dialog-card .modal-hdr h3 { display: flex; align-items: center; gap: 8px; }
.dialog-card .dlg-icon { display: flex; flex-shrink: 0; }
.dialog-card.is-danger .dlg-icon,
.dialog-card.is-error .dlg-icon { color: var(--rose); }
.dialog-card.is-notice .dlg-icon { color: var(--accent); }
.dialog-card .dlg-msg { white-space: pre-wrap; }
.dialog-card .modal-actions { flex-wrap: wrap; }

/* ─── model picker ───────────────────────────────────────────────────────── */
.model-list { display: flex; flex-direction: column; gap: 8px; }
.model-loading { font-size: 13px; color: var(--muted); padding: 16px; text-align: center; }
.model-option {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; position: relative;
  border: 1px solid var(--border); border-radius: 12px;
  cursor: pointer; transition: border-color .12s, background .12s;
}
.model-option:hover { border-color: var(--bhi); }
.model-option.selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
.model-option input { position: absolute; opacity: 0; pointer-events: none; }
.model-option-body { flex: 1; min-width: 0; }
.model-option-label {
  font-size: var(--type-secondary, 13.5px); font-weight: 600; color: var(--text);
  display: flex; align-items: center; gap: 8px;
}
.model-tag {
  font-size: max(10px, var(--label-min-size, 0px)); font-weight: 600; text-transform: var(--label-case, uppercase); letter-spacing: var(--label-tracking, .04em);
  color: var(--muted); background: color-mix(in srgb, var(--text) 8%, transparent);
  padding: 1px 6px; border-radius: 4px;
}
.model-option-desc { font-size: 12px; color: var(--muted); margin-top: 3px; }
.model-check {
  flex-shrink: 0; color: var(--accent); opacity: 0;
  width: 20px; height: 20px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  transition: opacity .12s;
}
.model-option.selected .model-check { opacity: 1; }

/* ─── app shell: rail on the ground, one sheet for everything else ─────────
   Imago layout (spec 004 §Shell, tmp/mockups/Rail.dc.html). The rail sits on
   --void with no border; the top bar and every page sit on a single sheet
   inset 12px from the window. Tokens the older themes lack fall back to their
   nearest existing value, so all eight themes render this shell. */
#app { display: flex; flex-direction: row; height: 100vh; background: var(--void); }
.app-main {
  flex: 1;
  min-width: 0;
  display: flex;
  padding: 12px 12px 12px 0;
}
.app-sheet {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--depth);
  border: 1px solid var(--border);
  border-radius: var(--r-sheet, 20px);
}

/* ─── the rail ─────────────────────────────────────────────────────────────── */
.left-nav {
  width: 252px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 18px 12px 14px 14px;
  background: var(--void);
  overflow: hidden;
  transition: width .2s cubic-bezier(.4, 0, .2, 1);
}
.nav-brand { display: flex; align-items: center; min-height: 36px; padding: 0 8px; color: var(--text); }
.nav-brand-mark { display: none; }

.nav-workspace {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  min-width: 0;
}
.nav-workspace-badge {
  width: 32px; height: 32px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 9px;
  background: var(--wing-bg, var(--accent));
  color: var(--wing-ink, var(--on-accent, #fff));
  font-size: 13px; font-weight: 600;
}
.nav-workspace-text { display: flex; flex-direction: column; min-width: 0; }
.nav-workspace-name { font-size: 14px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav-workspace-kind { font-size: 12px; color: var(--muted); }

.nav-section-label { padding: 0 12px 4px; font-size: var(--type-meta, 12.5px); color: var(--muted); white-space: nowrap; }

/* Only the areas scroll: Settings and the footer keep their place. The list
   scrolls with no bar (wheel, trackpad, touch, Tab); where there is more above
   or below, that edge fades (data-fade, set by LeftNav.tsx) — the cue a bar
   would have given. The 3px of padding, given back by the margin, keeps focus
   rings from being clipped at the list's edges. */
@property --nav-fade-start { syntax: '<length>'; inherits: false; initial-value: 0px; }
@property --nav-fade-end { syntax: '<length>'; inherits: false; initial-value: 0px; }
.nav-steps {
  flex: 1;
  min-height: 0;
  display: flex; flex-direction: column; gap: 14px;
  margin: -3px;
  padding: 3px;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  scroll-padding-block: 28px;
  scrollbar-width: none;
}
.nav-steps::-webkit-scrollbar { display: none; }
@media (min-width: 901px) {
  .nav-steps {
    --nav-fade-start: 0px;
    --nav-fade-end: 0px;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--nav-fade-start), #000 calc(100% - var(--nav-fade-end)), transparent 100%);
            mask-image: linear-gradient(to bottom, transparent 0, #000 var(--nav-fade-start), #000 calc(100% - var(--nav-fade-end)), transparent 100%);
    transition: --nav-fade-start .18s ease-out, --nav-fade-end .18s ease-out;
  }
  .nav-steps[data-fade~="start"] { --nav-fade-start: 28px; }
  .nav-steps[data-fade~="end"] { --nav-fade-end: 28px; }
}
.nav-group { display: flex; flex-direction: column; gap: 2px; }
/* Home sits above both groups, in no group of its own (LeftNav.tsx HOME). */
.nav-home { display: flex; flex-direction: column; }
.nav-pinned { padding-top: 10px; border-top: 1px solid var(--border); }

.nav-step {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 50px;
  padding: 6px 10px 6px 12px;
  border: 1px solid transparent;
  border-radius: var(--r-lg);
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color .12s, border-color .12s;
}
.nav-step:hover { background: var(--accent-bg); }
.nav-step:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 1px; }
.nav-step.active { background: var(--surface); border-color: var(--border); }

/* Each area's icon on a quiet tile; the current one is filled. */
.step-node {
  width: 32px; height: 32px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 9px;
  color: var(--muted);
  transition: background-color .12s, color .12s;
}
.nav-step:hover .step-node { color: var(--accent); }
.nav-step.active .step-node { background: var(--accent); color: var(--on-accent, #fff); }

.step-label { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.step-title { font-size: var(--type-body, 14.5px); font-weight: 500; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav-step.active .step-title { font-weight: 600; }
.step-desc { font-size: var(--type-meta, 12.5px); line-height: 1.35; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.step-count {
  min-width: 22px; height: 22px; padding: 0 7px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--r-pill, 9999px);
  background: var(--accent);
  color: var(--on-accent, #fff);
  font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.nav-footer {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 4px 0 8px;
  border-top: 1px solid var(--border);
}
.nav-made-by { display: flex; align-items: center; gap: 8px; min-width: 0; }
.nav-morpho-logo { width: 24px; height: 24px; object-fit: contain; flex-shrink: 0; }
.nav-made-by-text { font-size: 12px; color: var(--muted); white-space: nowrap; }
.nav-made-by-text strong { color: var(--text); font-weight: 600; }
.nav-collapse {
  width: 36px; height: 36px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--r);
  background: transparent; color: var(--muted);
  cursor: pointer;
}
.nav-collapse:hover { background: var(--accent-bg); color: var(--text); }
.nav-collapse:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 1px; }

/* Collapsed: icons only. The choice is remembered (imago.railCollapsed). */
.left-nav.is-collapsed { width: 76px; padding-left: 12px; padding-right: 12px; }
.left-nav.is-collapsed .nav-brand { justify-content: center; padding: 0; }
.left-nav.is-collapsed .nav-brand-full,
.left-nav.is-collapsed .nav-workspace-text,
.left-nav.is-collapsed .nav-section-label,
.left-nav.is-collapsed .step-label,
.left-nav.is-collapsed .nav-made-by-text { display: none; }
.left-nav.is-collapsed .nav-brand-mark { display: block; }
.left-nav.is-collapsed .nav-workspace { justify-content: center; padding: 8px 0; }
/* Collapsed, a short rule stands in for the second group's name. */
.left-nav.is-collapsed .nav-group + .nav-group,
.left-nav.is-collapsed .nav-home + .nav-group { padding-top: 12px; border-top: 1px solid var(--border); }
.left-nav.is-collapsed .nav-step { justify-content: center; padding: 6px 0; }
.left-nav.is-collapsed .step-count { position: absolute; top: 2px; right: 2px; min-width: 18px; height: 18px; padding: 0 5px; font-size: max(11px, var(--type-floor, 0px)); }
.left-nav.is-collapsed .nav-footer { flex-direction: column; padding: 10px 0 0; }

/* A collapsed rail names its items in one tooltip (LeftNav.tsx): fixed to the
   window, since the scrolling list would clip it, and styled as the Explorer's
   (.exp-profile-tip). It stays while the pointer is on it and Escape closes it. */
.nav-tip {
  position: fixed; z-index: 450;
  display: flex; flex-direction: column; gap: 1px;
  max-width: 260px;
  padding: 7px 11px 8px;
  border-radius: var(--r, 8px);
  background: var(--surface); color: var(--text); border: 1px solid var(--bhi, var(--border));
  box-shadow: var(--shadow-md, 0 6px 20px color-mix(in srgb, var(--text) 18%, transparent));
  font-family: var(--sans); line-height: 1.35;
  transform: translateY(-50%);
  animation: nav-tip-in .12s ease-out;
}
/* the point, toward its item (moved by --nav-tip-arrow when the box is held
   off a window edge, never past the box's own corners) */
.nav-tip::before {
  content: ''; position: absolute; left: -5px;
  top: clamp(10px, calc(50% + var(--nav-tip-arrow, 0px)), calc(100% - 10px));
  width: 8px; height: 8px;
  background: var(--surface);
  border-left: 1px solid var(--bhi, var(--border)); border-bottom: 1px solid var(--bhi, var(--border));
  transform: translateY(-50%) rotate(45deg);
}
/* a workspace's name may be long: it wraps, and a word too long for the box breaks */
.nav-tip__title { font-size: var(--type-secondary, 13px); font-weight: 600; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.nav-tip__desc { font-size: var(--type-meta, 12.5px); color: var(--muted); }
@keyframes nav-tip-in {
  from { opacity: 0; transform: translate(-4px, -50%); }
  to   { opacity: 1; transform: translate(0, -50%); }
}

/* ─── the top bar, on the sheet ────────────────────────────────────────────── */
header.topbar {
  height: auto;
  min-height: 60px;
  padding: 10px 16px 10px 24px;
  gap: 12px 20px;
  flex-wrap: wrap;
  background: var(--depth);
  border-bottom: 1px solid var(--border);
}
header.topbar::after { display: none; }
.topbar-crumbs {
  display: flex; align-items: center; gap: 8px;
  flex: 1 1 220px; min-width: 0;
  font-size: 14px; color: var(--muted);
  white-space: nowrap; overflow: hidden;
}
.topbar-crumbs [aria-current] { color: var(--text); font-weight: 500; overflow: hidden; text-overflow: ellipsis; }
.topbar-sep { color: var(--bhi); }
header.topbar .header-right { margin-left: auto; }

/* ─── narrow windows: the rail becomes a strip above the sheet ─────────────── */
@media (max-width: 900px) {
  #app { flex-direction: column; width: 100%; overflow: hidden; }
  .left-nav, .left-nav.is-collapsed {
    width: auto;
    min-width: 0;
    max-width: 100%;
    flex-shrink: 0;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    padding: 10px 12px 0;
    overflow-x: auto;
    overflow-y: hidden;
  }
  .nav-workspace, .nav-section-label, .nav-footer, .step-desc { display: none; }
  .nav-brand { padding: 0 4px; flex: none; }
  .left-nav .nav-brand-full { display: none; }
  .left-nav .nav-brand-mark { display: block; }
  .nav-steps { flex: none; margin: 0; padding: 0; overflow: visible; -webkit-mask-image: none; mask-image: none; }
  /* The strip scrolls sideways with no bar, as the rail's list does up and
     down: the end with more beyond it fades (data-fade on the nav), a mouse
     wheel scrolls it (LeftNav.tsx), and the current area is kept in view. */
  .left-nav, .left-nav.is-collapsed { scrollbar-width: none; overscroll-behavior-x: contain; scroll-padding-inline: 28px; }
  .left-nav::-webkit-scrollbar { display: none; }
  .left-nav {
    --nav-fade-start: 0px;
    --nav-fade-end: 0px;
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--nav-fade-start), #000 calc(100% - var(--nav-fade-end)), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 var(--nav-fade-start), #000 calc(100% - var(--nav-fade-end)), transparent 100%);
    transition: --nav-fade-start .18s ease-out, --nav-fade-end .18s ease-out;
  }
  .left-nav[data-fade~="start"] { --nav-fade-start: 28px; }
  .left-nav[data-fade~="end"] { --nav-fade-end: 28px; }
  .nav-steps, .nav-group, .nav-home { flex-direction: row; }
  .left-nav.is-collapsed .nav-group + .nav-group,
  .left-nav.is-collapsed .nav-home + .nav-group { padding-top: 0; border-top: 0; }
  .nav-pinned { padding: 0; border: 0; }
  .nav-step, .left-nav.is-collapsed .nav-step { width: auto; min-height: 44px; padding: 6px 12px 6px 8px; justify-content: flex-start; }
  .left-nav.is-collapsed .step-label { display: flex; }
  .left-nav.is-collapsed .step-count { position: static; }
  .app-main { padding: 10px; min-height: 0; min-width: 0; width: 100%; }
  header.topbar { padding: 8px 12px 8px 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .left-nav, .nav-steps { transition: none; }
  .nav-tip { animation: none; }
}
@media (forced-colors: active) {
  .nav-tip, .nav-tip::before { border-color: CanvasText; }
}

/* ─── content area + step panels ─────────────────────────────────────────── */
.content-area {
  flex: 1;
  position: relative;
  overflow: hidden;
}
.step-panel {
  display: none;
  position: absolute;
  inset: 0;
  flex-direction: column;
  overflow: hidden;
}
.step-panel.active { display: flex; }

/* ─── panel header (shared by steps 1 & 2) ───────────────────────────────── */
.panel-hdr {
  padding: var(--page-hdr-pad, 22px 28px 18px);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  background: var(--depth);
}
.panel-hdr-text { flex: 1; min-width: 0; }
.panel-title {
  font-family: var(--display);
  font-size: var(--page-title-size, 18px);
  font-weight: 600;
  letter-spacing: var(--page-title-tracking, -.3px);
  margin-bottom: 4px;
}
.panel-subtitle { font-size: var(--page-sub-size, 13px); color: var(--muted); line-height: 1.6; max-width: 72ch; }
.panel-body {
  flex: 1;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}
.panel-body::-webkit-scrollbar { width: 5px; }
.panel-body::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }

/* ─── step 1: connections ────────────────────────────────────────────────── */
/* The connection list is a record table now — see .cxn-* in css/connectors.css.
   The old card-grid rules (.conn-card, .conn-type-badge, .badge-*) were removed
   with the markup that used them. */

/* add-connection form */
.add-conn-wrapper {
  padding: 28px;
  max-width: 580px;
}
.add-conn-wrapper h2 {
  font-family: var(--display);
  font-size: 16px;
  font-weight: 600;
  margin-bottom: 20px;
}
.empty-state-msg {
  padding: var(--empty-pad, 48px 28px);
  text-align: center;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.8;
}

/* ─── step 2: schema explorer — panel header controls ───────────────────── */
.schema-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
/* Styled by the dropdown system; only the width is local. */
.schema-controls .dd-trigger,
.schema-controls select { min-width: 200px; }

/* ─── step 2: ERD canvas ─────────────────────────────────────────────────── */
.erd-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
}

/* toolbar strip above canvas */
.erd-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  background: var(--depth);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.erd-toolbar input[type="search"] {
  flex: 1;
  max-width: 260px;
  background: var(--lift);
  border: 1px solid var(--border);
  border-radius: var(--r);
  color: var(--text);
  font-family: var(--sans);
  font-size: 13px;
  padding: 7px 12px;
  outline: none;
  transition: border-color .2s;
}
.erd-toolbar input[type="search"]::placeholder { color: var(--faint); }
.erd-toolbar input[type="search"]:focus { border-color: var(--accent-dim); }
.erd-controls { display: flex; gap: 4px; margin-left: auto; }
.erd-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  background: var(--lift);
  border: 1px solid var(--border);
  border-radius: var(--r);
  color: var(--muted);
  cursor: pointer;
  transition: color .15s, border-color .15s;
}
.erd-btn:hover { color: var(--accent); border-color: var(--accent-dim); }

/* dot-grid drawing pane */
.erd-canvas {
  flex: 1;
  position: relative;
  overflow: hidden;
  background-color: var(--void);
  background-image: radial-gradient(circle, var(--border) 1px, transparent 1px);
  background-size: 28px 28px;
  cursor: grab;
}
.erd-canvas:active { cursor: grabbing; }

/* panzoom target — contains all entity cards */
.erd-surface {
  position: absolute;
  top: 0; left: 0;
  transform-origin: 0 0;
  will-change: transform;
}

/* ── data-source group boxes (render behind entity cards) ─────────────────── */
.erd-group {
  position: absolute;
  border: 1.5px dashed var(--border);
  border-radius: 16px;
  background: color-mix(in srgb, var(--accent) 4%, transparent);
  pointer-events: none;
  z-index: 0;
}
.erd-group-label {
  position: absolute;
  top: -12px; left: 18px;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 3px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 20px;
  font-family: var(--mono);
  font-size: 11px; font-weight: 600; color: var(--text);
  white-space: nowrap;
}
.erd-group-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
.erd-group-count {
  font-size: max(10px, var(--type-floor, 0px)); color: var(--muted);
  background: color-mix(in srgb, var(--text) 8%, transparent);
  padding: 0 6px; border-radius: 10px;
}

/* bottom-centre usage hint */
.erd-hint {
  position: absolute;
  bottom: 14px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .4px;
  color: var(--faint);
  pointer-events: none;
  white-space: nowrap;
}

/* centred overlay for empty / error states */
.erd-message {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  font-size: 13px;
  color: var(--muted);
  pointer-events: none;
  line-height: 1.8;
  max-width: 320px;
}

/* ── entity cards ─────────────────────────────────────────────────────────── */
.erd-entity {
  position: absolute;
  width: 240px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  cursor: grab;
  user-select: none;
  box-shadow: 0 4px 20px rgba(0,0,0,.35), 0 1px 4px rgba(0,0,0,.3);
  transition: box-shadow .15s, border-color .15s;
}
.erd-entity:hover {
  border-color: var(--bhi);
  box-shadow: 0 8px 32px rgba(0,0,0,.5);
}
.erd-entity--drag {
  cursor: grabbing;
  border-color: var(--accent);
  box-shadow: 0 16px 48px rgba(0,0,0,.7), 0 0 0 1px var(--accent-dim);
}
.erd-entity-hdr {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 13px 9px;
  background: var(--lift);
  border-bottom: 2px solid var(--accent-dim);
}
.erd-entity-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--emerald);
  box-shadow: 0 0 6px rgba(16,185,129,.5);
  flex-shrink: 0;
}
.erd-entity-name {
  font-family: var(--display);
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.erd-entity-rows {
  font-family: var(--mono);
  font-size: 9px;
  color: var(--faint);
  flex-shrink: 0;
}
.erd-entity-cols { padding: 4px 0 6px; }
.erd-col {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 12px;
  transition: background .1s;
}
.erd-col:hover { background: var(--lift); }
.erd-col-gem {
  width: 6px; height: 6px;
  border-radius: 1px;
  transform: rotate(45deg);
  background: var(--faint);
  flex-shrink: 0;
  transition: background .15s;
}
/* The gem is the key sigil, and it says which kind of key this is — the same
   vocabulary the relationship lines use: accent = declared PK, violet = the FK
   side of a declared key, faint = an ordinary column. */
.erd-col--pk .erd-col-gem { background: var(--accent); box-shadow: 0 0 5px var(--accent-dim); }
.erd-col--fk .erd-col-gem {
  background: transparent;
  border: 1.5px solid var(--erd-fk);
  width: 7px; height: 7px;
}
.erd-col-name {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--cyan);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.erd-col--pk .erd-col-name { color: var(--accent); font-weight: 500; }
.erd-col--fk .erd-col-name { color: var(--erd-fk); }
.erd-col-type {
  font-family: var(--mono);
  font-size: 9px;
  color: var(--muted);
  background: var(--depth);
  padding: 2px 6px;
  border-radius: 3px;
  border: 1px solid var(--border);
  flex-shrink: 0;
}
.erd-no-cols { font-size: max(11px, var(--type-floor, 0px)); color: var(--subtle-ink, var(--faint)); padding: 6px 12px; font-style: italic; }

:root {
  /* The FK side needs a hue that cannot be mistaken for the accent that marks
     the PK side — morpho-dark's --violet is a pale blue that sits right next to
     it. Mixing in --rose pulls it warm on every theme while staying derived. */
  --erd-fk: var(--erd-key, color-mix(in srgb, var(--violet, #A78BFA) 45%, var(--rose, #FB7185)));
}

/* ── relationship layer ───────────────────────────────────────────────────
   One register: keys the database declares. Solid accent, dot at the one end,
   crow's foot at the many end. Inferred joins are not drawn here at all — a
   guess must not be able to pass for a fact, and the cheapest way to guarantee
   that is to have nothing on the board that isn't in the catalog. */
.erd-links {
  position: absolute;
  top: 0; left: 0;
  overflow: visible;
  pointer-events: none;   /* the cards own the pointer; lines are read-only */
  z-index: 1;
}
.erd-link-line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .75;
}
.erd-link-one  { fill: var(--accent); }
.erd-link-many {
  fill: none; stroke: var(--accent); stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.erd-links.hide-declared .erd-link--declared { display: none; }

/* ── confirmed and suspected joins (spec 010) ─────────────────────────────
   Confirmed: solid, in a deeper shade than the declared accent, with the same
   end marks — a person has stood behind it. Suspected: DASHED, a hollow dot and
   no crow's foot, so it can never be read as a key. Both colours are derived
   from theme tokens every theme defines, here rather than in a theme file
   (theme files carry no cache-buster, see --erd-fk above). The suspected layer
   is not hidden by CSS when off — erd.js does not route it at all. */
:root {
  --erd-confirmed: color-mix(in srgb, var(--accent) 62%, var(--text));
  --erd-suspect: color-mix(in srgb, var(--accent) 72%, var(--muted));
}
.erd-link--confirmed .erd-link-line { stroke: var(--erd-confirmed); }
.erd-link--confirmed .erd-link-one  { fill: var(--erd-confirmed); }
.erd-link--confirmed .erd-link-many { stroke: var(--erd-confirmed); }
.erd-link--suspected .erd-link-line { stroke: var(--erd-suspect); stroke-dasharray: 6 5; stroke-linecap: butt; }
.erd-link--suspected .erd-link-one  { fill: var(--surface); stroke: var(--erd-suspect); stroke-width: 1.6; }

/* Hovering a table traces its relationships and drops everything else back. */
.erd-wrap.is-focusing .erd-link             { opacity: .12; }
.erd-wrap.is-focusing .erd-link.is-lit      { opacity: 1; }
.erd-wrap.is-focusing .erd-link.is-lit .erd-link-line { stroke-width: 2.2; opacity: 1; }
.erd-wrap.is-focusing .erd-entity           { opacity: .5; }
.erd-wrap.is-focusing .erd-entity.is-focus,
.erd-wrap.is-focusing .erd-entity.is-related { opacity: 1; }
.erd-entity.is-focus   { border-color: var(--accent); }
.erd-entity.is-related { border-color: var(--erd-fk); }
.erd-entity.is-dimmed  { opacity: .12; pointer-events: none; }

/* ── source cluster label extras ─────────────────────────────────────────── */
.erd-group-schema {
  font-size: max(10px, var(--type-floor, 0px)); color: var(--muted);
  padding-left: 7px; margin-left: 1px;
  border-left: 1px solid var(--border);
}

/* ── legend: the key to the two registers, bottom-left of the canvas ─────── */
.erd-legend {
  position: absolute;
  left: 14px; bottom: 12px;
  display: flex; flex-direction: column; gap: 3px;
  padding: 9px 12px;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--r);
  backdrop-filter: blur(6px);
  z-index: 3;
}
.erd-legend:empty { display: none; }
.erd-legend-item {
  display: flex; align-items: center; gap: 8px;
  font-size: 11.5px; color: var(--muted);
  cursor: pointer; user-select: none;
}
.erd-legend-item:hover { color: var(--text); }
.erd-legend-item input { accent-color: var(--accent); margin: 0; cursor: pointer; }
.erd-legend-item b {
  font-family: var(--mono); font-size: 10.5px; font-weight: 500;
  color: var(--text); margin-left: auto; padding-left: 10px;
}
.erd-legend-swatch { flex-shrink: 0; overflow: visible; }
.erd-legend-declared  { stroke: var(--accent); stroke-width: 1.6; }
.erd-legend-confirmed { stroke: var(--erd-confirmed); stroke-width: 1.6; }
.erd-legend-suspected { stroke: var(--erd-suspect); stroke-width: 1.6; stroke-dasharray: 4 3; }
.erd-legend-note {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .04em;
  color: var(--subtle-ink, var(--faint)); padding-top: 4px; margin-top: 2px;
  border-top: 1px solid var(--border);
  cursor: help;
}

/* ── Imago (spec 005c): a quieter board, readable cards, the table panel ────
   Visual only — layout, routing and the declared-keys rule live in erd.js and
   are untouched. Card heights are measured from the DOM, so sizes may change. */
.erd-toolbar { padding: 12px 20px; gap: 12px; }
.erd-toolbar input[type="search"] {
  min-height: var(--control-h, 0px); font-size: 14px; max-width: 300px;
  background: var(--field-bg, var(--lift)); border-color: var(--field-border, var(--border));
  border-radius: var(--control-r, var(--r));
}
.erd-btn { width: 36px; height: 36px; background: var(--surface); border-color: var(--bhi); }
.erd-btn--wide { width: auto; font-size: 13.5px; }
.erd-btn:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 1px; }
.erd-canvas { background-color: var(--lift); background-image: radial-gradient(circle, var(--bhi) 1px, transparent 1px); background-size: 22px 22px; }
.erd-group { border: 1.5px dashed var(--bhi); background: color-mix(in srgb, var(--surface) 55%, transparent); }
.erd-group-label { font-family: var(--sans); font-size: var(--type-meta, 12.5px); font-weight: 500; }
.erd-entity { border-color: var(--bhi); box-shadow: var(--shadow-sm, none); }
.erd-entity:hover { border-color: var(--accent-dim); box-shadow: var(--shadow-md, 0 8px 24px rgba(0,0,0,.2)); }
.erd-entity:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 2px; }
.erd-entity--drag { box-shadow: var(--shadow-lg, 0 16px 48px rgba(0,0,0,.5)); }
.erd-entity.is-selected { border: 2px solid var(--accent); }
.erd-entity.is-selected .erd-entity-hdr { background: var(--accent-mid); }
.erd-entity-hdr { border-bottom: 1px solid var(--border); padding: 10px 13px; }
.erd-entity-dot { background: var(--accent); box-shadow: none; }
.erd-entity-name { font-size: 14px; }
.erd-entity-rows { font-family: var(--sans); font-size: max(11.5px, var(--type-floor, 0px)); color: var(--muted); font-variant-numeric: tabular-nums; }
.erd-col { padding: 5px 12px; }
.erd-col-name { font-family: var(--sans); font-size: 13px; color: var(--text); }
.erd-col--pk .erd-col-name { color: var(--accent); font-weight: 600; }
.erd-col--fk .erd-col-name { color: var(--erd-fk); font-weight: 500; }
.erd-col-type { font-family: var(--sans); font-size: max(11.5px, var(--type-floor, 0px)); background: none; border: 0; padding: 0; }
.erd-link-line { stroke-width: 2; opacity: .9; }
.erd-link-many { stroke-width: 1.8; }
.erd-hint { font-family: var(--sans); font-size: var(--type-meta, 12.5px); letter-spacing: 0; color: var(--muted); }
.erd-legend-item { font-size: 13px; }
.erd-legend-item b { font-family: var(--sans); font-size: 13px; }
.erd-legend-note { font-family: var(--sans); font-size: 12px; letter-spacing: 0; }
.erd-message { font-size: var(--type-body, 14.5px); }

.erd-stage { flex: 1; min-height: 0; display: flex; }
.erd-stage > .erd-canvas { flex: 1; min-width: 0; }
.erd-panel {
  width: 340px; flex: none;
  display: flex; flex-direction: column; gap: var(--panel-gap, 20px);
  padding: var(--panel-pad, 24px);
  overflow-y: auto;
  background: var(--depth);
  border-left: 1px solid var(--border);
}
.erd-panel-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.erd-panel-where { font-size: 13px; color: var(--muted); }
.erd-panel-name { font-family: var(--display); font-size: var(--type-panel-title, 22px); font-weight: 600; letter-spacing: -0.01em; margin-top: 2px; word-break: break-word; }
.erd-panel-meta { font-size: var(--type-secondary, 13.5px); color: var(--muted); margin-top: 4px; font-variant-numeric: tabular-nums; }
.erd-panel-close { width: 36px; height: 36px; flex: none; display: inline-flex; align-items: center; justify-content: center; border: 0; border-radius: var(--r); background: transparent; color: var(--muted); cursor: pointer; }
.erd-panel-close:hover { background: var(--accent-bg); color: var(--text); }
.erd-panel-desc { font-size: 14px; line-height: 1.55; padding: 14px 16px; background: var(--lift); border-radius: var(--r-lg); }
.erd-panel-sec { display: flex; flex-direction: column; gap: 10px; }
.erd-panel-sec h3 { font-size: 15px; font-weight: 600; }
.erd-panel-none { font-size: var(--type-secondary, 13.5px); color: var(--muted); }
.erd-panel-rels { list-style: none; display: flex; flex-direction: column; gap: 8px; }
.erd-panel-rels li { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--r); font-size: var(--type-secondary, 13.5px); }
.erd-panel-rels b { font-weight: 600; }
.erd-panel-rels code { font-family: var(--mono); font-size: 12px; color: var(--muted); }
.erd-panel-cols { list-style: none; display: flex; flex-direction: column; }
.erd-panel-cols li { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 7px 0; border-bottom: 1px solid var(--border); font-size: var(--type-secondary, 13.5px); }
.erd-panel-cols li:last-child { border-bottom: 0; }
.erd-panel-key { font-size: 11px; font-weight: 600; color: var(--accent); }
.erd-panel-col { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.erd-panel-type { font-size: var(--type-meta, 12.5px); color: var(--muted); }
.erd-panel-actions { margin-top: auto; padding-top: 4px; display: flex; gap: 8px; flex-wrap: wrap; }
/* The approved data-dictionary text (spec 007): a petal when Imago wrote it,
   square when a person did, with the provenance line under it. */
.erd-panel-dict { gap: 8px; }
.erd-panel-dict-text { margin: 0; font-size: 14px; line-height: 1.55; color: var(--text); }
.erd-panel-grain { margin: 0; font-size: var(--type-secondary, 13px); color: var(--muted); }
.erd-panel-coldesc { grid-column: 2 / -1; margin-top: -2px; font-size: var(--type-meta, 12.5px); color: var(--muted); line-height: 1.4; }
.erd-panel-rels small { color: var(--muted); font-size: var(--type-meta, 12.5px); }

/* ── Suspected, not declared (spec 010) ─────────────────────────────────────
   A suspected join is Imago's proposal: a dashed petal (.im-ai--suspected). A
   decided one is a person's: square (.im-panel). Sizes are density tokens with
   the old literal as fallback (spec 015). */
.erd-btn.is-on { color: var(--accent); border-color: var(--accent-dim); background: var(--accent-bg, var(--lift)); }
.erd-sus-intro { display: flex; gap: 8px; align-items: flex-start; margin: 0; font-size: var(--type-secondary, 13.5px); line-height: 1.5; color: var(--muted); }
.erd-sus-intro svg { flex: none; margin-top: 3px; }
.erd-sus-intro code { font-family: var(--mono); font-size: var(--type-meta, 12.5px); }
.erd-sus-scan { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.erd-sus-counts { margin: 0; font-size: var(--type-secondary, 13.5px); color: var(--muted); font-variant-numeric: tabular-nums; }
.erd-sus-scope { margin: 2px 0 0; font-size: var(--type-meta, 12.5px); color: var(--faint, var(--muted)); font-variant-numeric: tabular-nums; }
.erd-sus-list { display: flex; flex-direction: column; gap: 10px; }
.erd-sus { gap: 8px; }
.erd-sus.im-panel { padding: 12px 14px; }
.erd-sus-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.erd-sus-conf { font-size: var(--type-meta, 12.5px); font-weight: 600; color: var(--muted); }
.erd-sus-conf--high   { color: var(--accent); }
.erd-sus-conf--medium { color: var(--ai-ink, var(--accent)); }
.erd-sus-tag {
  font-size: var(--type-meta, 12.5px); color: var(--muted);
  padding: 1px 8px; border: 1px solid var(--border); border-radius: 999px;
}
/* one column per end, the verb between them: a long name wraps inside its own
   line instead of pushing the other end onto a ragged second row */
.erd-sus-pair { margin: 0; display: flex; flex-direction: column; gap: 1px; font-size: var(--type-body, 14px); }
.erd-sus-end { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; min-width: 0; }
.erd-sus-end b { font-weight: var(--weight-strong, 600); word-break: break-word; min-width: 0; }
.erd-sus-end small { flex: none; font-size: var(--type-meta, 12.5px); color: var(--muted); }
.erd-sus-arrow { font-size: var(--type-meta, 12.5px); color: var(--muted); }
.erd-sus-reasons { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; font-size: var(--type-secondary, 13.5px); color: var(--text); }
.erd-sus-reasons li { position: relative; padding-inline-start: 14px; line-height: 1.45; }
.erd-sus-reasons li::before { content: ''; position: absolute; inset-inline-start: 2px; top: .62em; width: 5px; height: 5px; border-radius: 50%; background: var(--erd-suspect); }
.erd-sus-note { margin: 0; font-size: var(--type-secondary, 13.5px); line-height: 1.45; color: var(--text); padding: 8px 10px; background: var(--lift); border-radius: var(--r); }
.erd-sus-quiet { margin: 0; font-size: var(--type-meta, 12.5px); color: var(--muted); }
.erd-sus-actions { display: flex; gap: 8px; flex-wrap: wrap; padding-top: 2px; }
.erd-sus-decided { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.erd-sus-group > summary { cursor: pointer; font-size: var(--type-section, 15px); font-weight: 600; padding: 4px 0; }
.erd-sus-group[open] > summary { margin-bottom: 10px; }
.erd-legend-note--error { color: var(--rose); }
@media (max-width: 900px) {
  .erd-stage { position: relative; }
  .erd-panel { position: absolute; inset: 0 0 0 auto; width: min(340px, 100%); z-index: 6; box-shadow: var(--shadow-lg, none); }
}

/* ── source / schema filter ──────────────────────────────────────────────── */
.erd-filter-wrap { position: relative; }
.erd-btn--wide {
  width: auto; padding: 0 11px; gap: 6px;
  font-family: var(--sans); font-size: 12px; font-weight: 500;
}
.erd-filter-pop {
  top: calc(100% + 6px); left: 0;
  z-index: 400;
  min-width: 252px; max-height: 340px; overflow-y: auto;
}
.erd-filter-hdr {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 4px 8px 8px;
  font-family: var(--label-font, var(--mono)); font-size: max(9.5px, var(--label-min-size, 0px)); letter-spacing: var(--label-tracking, .14em);
  text-transform: var(--label-case, uppercase); color: var(--subtle-ink, var(--faint));
  border-bottom: 1px solid var(--border);
  margin-bottom: 5px;
}
.erd-filter-all {
  background: none; border: 0; padding: 0;
  font-family: var(--sans); font-size: max(11px, var(--type-floor, 0px)); font-weight: 500;
  letter-spacing: 0; text-transform: none;
  color: var(--accent); cursor: pointer;
}
.erd-filter-all:disabled { color: var(--faint); cursor: default; }
.erd-filter-src + .erd-filter-src { margin-top: 2px; }
.erd-check {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 8px; border-radius: 7px;
  font-size: var(--type-meta, 12.5px); color: var(--text);
  cursor: pointer; user-select: none;
}
.erd-check:hover { background: color-mix(in srgb, var(--text) 7%, transparent); }
.erd-check input { accent-color: var(--accent); margin: 0; cursor: pointer; flex-shrink: 0; }
.erd-check-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.erd-check-count {
  font-family: var(--mono); font-size: max(10px, var(--type-floor, 0px)); color: var(--muted);
  background: color-mix(in srgb, var(--text) 8%, transparent);
  padding: 1px 6px; border-radius: 10px; flex-shrink: 0;
}
.erd-filter-schemas { padding-left: 16px; border-left: 1px solid var(--border); margin-left: 14px; }
.erd-check--sub { font-family: var(--mono); font-size: max(11.5px, var(--type-floor, 0px)); color: var(--muted); }
.erd-check--sub:has(input:checked) { color: var(--text); }
.erd-filter-empty { padding: 12px 10px; font-size: 12px; color: var(--subtle-ink, var(--faint)); text-align: center; }

@media (prefers-reduced-motion: reduce) {
  .erd-entity, .erd-link, .erd-link-line { transition: none; }
}

/* ─── step 3: the Ask (design 024: one column, web/public/css/ask.css) ─── */
#panel-3.active { flex-direction: column; }
#conn-source-list { display: flex; flex-direction: column; gap: 5px; }

/* sidebar sections (reused in analyst left/right) */
.side-section { padding: 14px; }
.side-section + .side-section { border-top: 1px solid var(--border); }
.side-label {
  font-family: var(--label-font, var(--mono));
  font-size: max(9px, var(--label-min-size, 0px));
  text-transform: var(--label-case, uppercase);
  letter-spacing: var(--label-tracking, 1.6px);
  color: var(--faint);
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 9px;
}
.side-label::after { content: ''; flex: 1; height: 1px; background: var(--border); }

/* loading skeleton placeholders */
@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position:  200% 0; }
}

.rail-empty { font-size: 12px; color: var(--faint); line-height: 1.8; }

/* the insight list (analyst right rail) */
.insight-count {
  margin-left: auto;
  padding: 1px 6px;
  background: var(--lift);
  border: 1px solid var(--border);
  border-radius: 3px;
  color: var(--muted);
  flex-shrink: 0;
}
.kept-card {
  padding: 9px 11px;
  margin-bottom: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 2px solid var(--gold-dim);
  border-radius: 0 var(--r) var(--r) 0;
}
.kept-title { font-size: 12px; font-weight: 500; line-height: 1.4; }
.kept-meta {
  font-family: var(--mono);
  font-size: 9px;
  color: var(--faint);
  margin-top: 4px;
  line-height: 1.6;
  word-break: break-word;
}
.kept-btns { display: flex; gap: 3px; margin-top: 6px; }
.kept-act {
  width: 20px; height: 18px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 3px;
  color: var(--faint);
  font-size: max(10px, var(--type-floor, 0px));
  cursor: pointer;
  transition: color .15s, border-color .15s;
}
.kept-act:hover:not(:disabled) { color: var(--gold); border-color: var(--gold-dim); }
.kept-act:disabled { opacity: .35; cursor: default; }
.kept-actions { display: flex; gap: 6px; margin-top: 10px; }

.empty-state {
  margin: auto;
  text-align: center;
  max-width: 400px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  padding-bottom: 40px;
}
.empty-hex { animation: hex-breathe 5s ease-in-out infinite; }
@keyframes hex-breathe {
  0%, 100% { opacity: .45; transform: scale(1); }
  50%       { opacity: .72; transform: scale(1.06); }
}
.empty-state h2 {
  font-family: var(--display);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -.3px;
}
.empty-state p { font-size: 13px; color: var(--muted); line-height: 1.8; }
@keyframes dot-pulse {
  0%, 100% { box-shadow: 0 0 0 0   rgba(232,184,75,0); }
  50%       { box-shadow: 0 0 0 5px rgba(232,184,75,.22); }
}

/* ECharts sizes itself from its container, so the box it initialises on has to
   fill the wrapper the height buttons resize — not collapse to nothing. */
.chart-wrap    { position: relative; height: 200px; }
.chart-box     { width: 100%; height: 100%; }
.chart-wrap > .chart-error { position: absolute; inset: 0; display: grid; place-items: center;
                             font-size: 12px; color: var(--muted); }

/* insight cards */
.insight-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: 12px 13px; margin-bottom: 7px; position: relative; overflow: hidden; }
.insight-card::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--gold); }
.insight-card.high::before { background: var(--rose); box-shadow: 0 0 8px rgba(244,63,94,.35); }
.insight-text { font-size: 12px; line-height: 1.65; }

.action-type { font-family: var(--label-font, var(--mono)); font-size: max(9px, var(--label-min-size, 0px)); text-transform: var(--label-case, uppercase); letter-spacing: var(--label-tracking, .8px); color: var(--violet); background: rgba(167,139,250,.1); border: 1px solid rgba(167,139,250,.2); padding: 2px 8px; border-radius: 4px; display: inline-block; margin-bottom: 8px; }
.btn-approve { background: rgba(16,185,129,.1); border-color: rgba(16,185,129,.25); color: var(--emerald); }
.btn-approve:hover { background: rgba(16,185,129,.18); }
.btn-reject  { background: var(--lift); border-color: var(--border); color: var(--muted); }
.btn-reject:hover { background: var(--bhi); color: var(--text); }
/* Sits opposite the type chip on the card's first line. */
.action-when { float: right; font-size: 10px; font-family: var(--mono); color: var(--muted); }
.action-status { font-size: 10px; font-family: var(--mono); margin-top: 6px; }
.action-status.approved, .action-status.executed,
.action-status.investigated { color: var(--emerald); }
/* Still open: the analyst has answered and the user has yet to say what
   that means, so it reads as in-progress rather than done. */
.action-status.investigating { color: var(--gold); }
.action-status.rejected { color: var(--rose); }
.action-status.unavailable { color: var(--muted); }

/* ── the Actions history page ──────────────────────────────────────────────
   The rail is a working list; this is the record behind it. Built from the
   Data Explorer's toolbar and pager registers (explorer.css) so the two data
   pages read as the same product, but the rows WRAP: a proposal and its
   outcome are sentences, not cells. */
/* The send button while a turn is in flight: still busy, but now a way out. */
.send-btn.is-stopping { display: inline-flex; align-items: center; gap: 7px; }

.actions-body { display: flex; flex-direction: column; gap: 14px; min-height: 0; }
.actions-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.actions-search { display: flex; gap: 6px; }
.actions-search input {
  font-family: var(--mono); font-size: 12px; color: var(--text);
  background: var(--surface); border: 1px solid var(--border); border-radius: 6px;
  padding: 5px 11px; min-width: 220px;
}
.actions-search input:focus { outline: none; border-color: var(--accent); }
.actions-count { font-family: var(--mono); font-size: 12px; color: var(--muted); margin-left: auto; }
.actions-count b { color: var(--accent); font-weight: 600; }
.actions-empty { max-width: 46ch; }

.actions-table-wrap {
  overflow: auto; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-lg);
}
.actions-table { border-collapse: separate; border-spacing: 0; width: 100%; }
.actions-table thead th {
  position: sticky; top: 0; z-index: 2; background: var(--depth);
  text-align: left; padding: 9px 14px; border-bottom: 1px solid var(--bhi);
  font-family: var(--display); font-size: 12.5px; font-weight: 600; color: var(--text);
}
.actions-table tbody td {
  padding: 10px 14px; border-bottom: 1px solid var(--border);
  font-size: 12px; color: var(--text); vertical-align: top;
}
.actions-table tbody tr:hover td { background: var(--accent-bg); }
/* One still wanting a decision is marked down the edge — it is the only row
   the user has anything to do about. */
.actions-table tbody tr.is-open td:first-child { box-shadow: inset 2px 0 0 var(--gold); }
.actions-table .action-type { margin-bottom: 0; }
.actions-table .action-status { margin-top: 0; white-space: nowrap; }
.acth-title { font-family: var(--display); font-size: 13px; font-weight: 500; margin-bottom: 3px; }
.acth-detail, .acth-outcome {
  font-size: 11px; color: var(--muted); line-height: 1.6; max-width: 52ch; overflow-wrap: anywhere;
}
.acth-when { font-family: var(--mono); font-size: 10px; color: var(--muted); white-space: nowrap; }
.acth-do { white-space: nowrap; }
.acth-do button {
  padding: 5px 10px; border-radius: 6px; font-size: 11px; font-weight: 500; cursor: pointer;
  border: 1px solid; font-family: var(--display); transition: all .15s; margin-left: 6px;
}

/* ── Imago (spec 005g): readable rows, word pills, the story panel ───────── */
.actions-body { padding: var(--page-body-pad, 24px 32px 36px); }
.actions-search input {
  font-family: var(--sans); font-size: 14px; min-height: max(var(--control-h, 0px), var(--touch-min, 0px));
  background: var(--field-bg, var(--surface)); border-color: var(--field-border, var(--border));
  border-radius: var(--control-r, 6px); padding: 0 12px; min-width: 240px;
}
.actions-count { font-family: var(--sans); font-size: 14px; font-variant-numeric: tabular-nums; }
.actions-empty { font-size: 15px; }
.actions-split { display: flex; flex-wrap: wrap; gap: 0; align-items: flex-start; min-height: 0; }
.actions-split > .actions-table-wrap { flex: 999 1 560px; min-width: 0; }
.actions-table thead th { background: var(--lift); font-family: var(--sans); font-size: 13px; padding: var(--row-head-pad-y, 11px) var(--row-pad-x, 16px); border-bottom-color: var(--border); color: var(--subtle-ink, var(--text)); font-weight: var(--weight-strong, 600); }
.actions-table tbody td { font-size: var(--type-body, 14px); padding: var(--row-pad-y, 14px) var(--row-pad-x, 16px); }
.actions-table tbody tr.is-open td:first-child { box-shadow: none; }
.actions-table tbody tr.is-selected td { background: var(--accent-mid); }
.actions-table .action-type { font-size: 13px; font-weight: 600; color: var(--ai-ink, var(--accent)); background: none; border: 0; padding: 0; }
.actions-table .action-type::first-letter { text-transform: uppercase; }
.acth-title {
  display: block; text-align: left; background: none; border: 0; padding: 0; cursor: pointer;
  font-family: var(--sans); font-size: var(--type-body, 15px); font-weight: var(--weight-strong, 600); color: var(--text); margin-bottom: 4px;
}
.acth-title:hover { color: var(--accent); text-decoration: underline; }
.acth-title:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 2px; border-radius: 4px; }
.acth-detail, .acth-outcome { font-size: var(--type-secondary, 13.5px); }
/* Under Imago the detail is one line: the full sentence is in the story panel a
   click away, and wrapping it is most of what made a row twice the mockup's.
   An unbreakable line is also the cell's minimum width, though, and the table
   took that width from "What happened", which then wrapped onto three lines
   and grew those rows by a third. So under Imago the detail is sized to zero
   and stretched to the cell, capped at the base rule's 52ch: min-width beats
   max-width, so a bare `min-width: 100%` would undo that cap in every theme.
   It contributes nothing to the column's width, and with the cap the other
   themes keep min(cell, 52ch) exactly as before.
   `clip` with a margin, not `hidden`: hidden also cut the pixel of ink an "f"
   hangs past the box, which every theme draws and the older ones must keep. */
.acth-detail { white-space: var(--row-sub-wrap, normal); overflow: clip; overflow-clip-margin: 4px;
  text-overflow: ellipsis; width: var(--row-sub-width, auto); min-width: min(100%, 52ch); }
.acth-when { font-family: var(--sans); font-size: 13px; }
.acth-do button { min-height: max(34px, var(--touch-min, 0px)); padding: 0 12px; font-family: var(--sans); font-size: var(--type-secondary, 13.5px); border-radius: var(--r); }

.acth-story {
  flex: 1 1 340px; max-width: 400px; margin-left: 16px;
  display: flex; flex-direction: column; gap: 12px;
  padding: 22px; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--lift);
}
.acth-story-top { display: flex; justify-content: space-between; align-items: center; }
.acth-story-close { width: 36px; height: 36px; display: inline-grid; place-items: center; border: 0; border-radius: var(--r); background: transparent; color: var(--muted); cursor: pointer; }
.acth-story-close:hover { background: var(--accent-bg); color: var(--text); }
.acth-story-title { font-family: var(--display); font-size: 20px; line-height: 1.3; font-weight: 600; }
.acth-story-kind { font-size: var(--type-secondary, 13.5px); color: var(--muted); }
.acth-timeline { list-style: none; display: flex; flex-direction: column; gap: 16px; padding-left: 20px; border-left: 2px solid var(--border); margin-top: 6px; }
.acth-timeline li { position: relative; display: flex; flex-direction: column; gap: 2px; font-size: 14px; }
.acth-timeline li::before { content: ''; position: absolute; left: -27px; top: 4px; width: 12px; height: 12px; background: var(--text); border-radius: 2px; }
.acth-timeline li.is-agent::before { background: var(--accent); border-radius: 7px 1px 7px 1px; }
.acth-timeline li.is-waiting::before { background: var(--surface); border: 2px solid var(--bhi); border-radius: 50%; }
.acth-timeline strong { font-weight: 600; }
.acth-timeline span { font-size: 13px; color: var(--muted); }
.acth-timeline p { margin-top: 4px; color: var(--text); line-height: 1.55; }
.acth-story-outcome { padding: 12px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); }
/* With a story open, its outcome and dates are in the panel: the table drops
   those two columns rather than squeezing every sentence into a sliver. */
.actions-split.has-story .actions-table th:nth-child(4), .actions-split.has-story .actions-table td:nth-child(4),
.actions-split.has-story .actions-table th:nth-child(5), .actions-split.has-story .actions-table td:nth-child(5) { display: none; }
.acth-story { position: sticky; top: 0; }
@media (max-width: 1100px) { .acth-story { max-width: none; margin: 14px 0 0; flex-basis: 100%; position: static; } }

/* spinner */
.spin {
  display: inline-block; width: 13px; height: 13px;
  border: 2px solid rgba(7,9,15,.4); border-top-color: var(--void);
  border-radius: 50%; animation: spin .7s linear infinite; vertical-align: middle;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* scrollbars */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-track { background: transparent; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ── toasts (bottom-centre, with optional inline action like Undo) ─────────── */
.toast-wrap {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  z-index: 1000; display: flex; flex-direction: column; gap: 10px; align-items: center;
  pointer-events: none;
}
.toast {
  pointer-events: auto; display: flex; align-items: center; gap: 14px;
  padding: 11px 12px 11px 16px; border-radius: 10px;
  background: var(--lift); color: var(--text); border: 1px solid var(--bhi);
  box-shadow: var(--shadow-lg, 0 16px 44px rgba(0,0,0,.5));
  font-size: 13px; opacity: 0; transform: translateY(10px);
  transition: opacity .22s ease, transform .22s ease;
}
.toast.toast-in { opacity: 1; transform: translateY(0); }
.toast-msg { font-weight: 500; }
.toast-action {
  background: none; border: none; color: var(--accent); font: inherit; font-weight: 600;
  cursor: pointer; padding: 4px 6px; border-radius: 6px;
}
.toast-action:hover { background: var(--accent-bg); }
.toast-close {
  background: none; border: none; color: var(--muted); cursor: pointer;
  font-size: 17px; line-height: 1; padding: 0 4px;
}
.toast-close:hover { color: var(--text); }
@media (prefers-reduced-motion: reduce) { .toast { transition: none; } }

/* ── two-factor authentication ─────────────────────────────────────────────
   Shared by the account-menu modal, the sign-in screen's second step and the
   admin console's enrolment gate — TwoFactor.tsx is one component in three
   places, so its classes are its own rather than borrowed from any of them. */

.mfa-panel { display: flex; flex-direction: column; gap: 10px; }
.mfa-note { font-size: var(--type-meta, 12.5px); color: var(--muted); line-height: 1.5; }
.mfa-qr {
  width: 190px; height: 190px; align-self: center;
  background: #fff; border-radius: var(--dd-r); padding: 8px;
}
.mfa-secret {
  display: flex; flex-direction: column; gap: 4px; align-items: center;
  background: var(--lift); border: 1px solid var(--border);
  border-radius: var(--dd-r); padding: 10px;
}
.mfa-secret-label {
  font-size: max(10.5px, var(--label-min-size, 0px)); text-transform: var(--label-case, uppercase); letter-spacing: var(--label-tracking, .05em); color: var(--subtle-ink, var(--faint));
}
.mfa-secret code { font-family: var(--mono); font-size: 13px; letter-spacing: .08em; }
.mfa-codes {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px 18px;
  list-style: none; margin: 4px 0; padding: 0;
}
.mfa-codes code { font-family: var(--mono); font-size: var(--type-secondary, 13.5px); letter-spacing: .06em; }
.mfa-status { font-size: var(--type-meta, 12.5px); color: var(--muted); }
/* No amber in the theme variables: running out of recovery codes is
   answered in the same colour as anything else that is going wrong. */
.mfa-status.low { color: var(--rose); }
.mfa-form { display: flex; flex-direction: column; gap: 6px; }
.mfa-form label {
  font-size: max(11px, var(--label-min-size, 0px)); font-weight: 600; text-transform: var(--label-case, uppercase); letter-spacing: var(--label-tracking, .05em);
  color: var(--muted); margin-top: 8px;
}
.mfa-form input {
  background: var(--lift);
  border: 1px solid var(--border);
  border-radius: var(--dd-r);
  color: var(--text);
  font-family: var(--mono);
  font-size: 16px;
  letter-spacing: .18em;
  padding: 10px 13px;
  outline: none;
}
.mfa-form input:focus-visible { border-color: var(--accent); box-shadow: var(--dd-ring); }
.mfa-error { color: var(--rose); font-size: var(--type-meta, 12.5px); }
.mfa-ok { color: var(--emerald); font-size: var(--type-meta, 12.5px); }

/* ── Assistant text rendered from Markdown (src/components/Markdown.tsx) ─────
   The Studio's chat bubble, its proposal card and the Analyst's answers. The
   bubble keeps `pre-wrap` for plain text; rendered Markdown already carries its
   own breaks, and pre-wrap would add a blank line between every block. */
.md { white-space: normal; overflow-wrap: anywhere; }
.md > :first-child { margin-top: 0; }
.md > :last-child { margin-bottom: 0; }
.md p, .md ul, .md ol, .md blockquote, .md pre, .md .md-table { margin: 0 0 .6em; }
.md ul, .md ol { padding-inline-start: 1.3em; }
.md li + li { margin-top: .2em; }
.md .md-heading { font-weight: 600; font-size: 1em; margin: .8em 0 .3em; }
.md code { font-family: var(--mono); font-size: .9em; padding: .05em .3em; border-radius: 4px;
           background: var(--lift, rgba(127, 127, 127, .12)); }
.md pre { padding: .6em .8em; border-radius: 6px; overflow-x: auto;
          background: var(--lift, rgba(127, 127, 127, .12)); }
.md pre code { padding: 0; background: none; }
.md blockquote { padding-inline-start: .8em; border-inline-start: 2px solid var(--border);
                 color: var(--muted); }
.md a { color: var(--accent); text-decoration: underline; }
.md .md-table { overflow-x: auto; }
.md table { border-collapse: collapse; font-size: .92em; }
.md th, .md td { padding: .3em .6em; border: 1px solid var(--border); text-align: start; }
