/* ===========================================================================
   Conduit — API-to-SQL console
   Light interface. Sans for chrome; mono reserved for machine data
   (endpoint paths, field names, SQL types, log lines).
   =========================================================================== */

:root {
  /* dashboard counter tiles — themeable on the Setup page */
  --tile-bg:            #ffffff;
  --tile-border:        #e5e9f0;
  --tile-value-color:   #0f172a;
  --tile-label-color:   #5b6b83;
  --tile-sub-color:     #94a3b8;
  /* the highlighted "Published" tile */
  --tile-pub-bg:        #f0fdfa;
  --tile-pub-border:    #ccfbf1;
  --tile-pub-value:     #0f766e;

  /* scheduler-polling indicator */
  --sched-dot-color:    #0d9488;
  --sched-dot-size:     14px;

  /* surfaces */
  --canvas:      #f5f7fa;
  --surface:     #ffffff;
  --surface-2:   #f8fafc;
  --surface-3:   #f1f5f9;

  /* lines */
  --border:      #e4e9f0;
  --border-mid:  #d3dbe6;
  --border-firm: #b9c4d2;

  /* ink */
  --ink:         #0f172a;
  --muted:       #5b6b83;
  --faint:       #94a3b8;

  /* brand */
  --primary:     #0d9488;
  --primary-700: #0f766e;
  --primary-600: #0d9488;
  --primary-100: #ccfbf1;
  --primary-50:  #f0fdfa;

  /* pills & badges — default to the primary tints but independently themeable */
  --pill-text: var(--primary-700);
  --pill-bg: var(--primary-50);
  --pill-border: var(--primary-100);
  --pill-idle-text: var(--muted);
  --pill-idle-bg: var(--surface);
  --pill-idle-border: var(--border-mid);
  --signal:      #0d9488;   /* alias used by inline styles */

  /* status */
  --danger:      #d92d20;
  --danger-50:   #fef3f2;
  --warn:        #b54708;
  --warn-50:     #fffaeb;
  --ok:          #039855;

  /* --- themeable: appsettings.json > Theme, overridden on the Setup page (/api/settings) --- */
  --btn-text:          #ffffff;   /* text on primary buttons */
  --menu-bg:           #ffffff;   /* sidebar background */
  --menu-text:         #5b6b83;   /* menu item colour */
  --menu-active-text:  #0f766e;   /* selected menu item */
  --menu-active-bg:    #f0fdfa;
  --menu-hover-bg:     #f1f5f9;
  --menu-group-color:  #94a3b8;   /* group headings (Clients / Configuration / Log) */
  --menu-group-size:   13.5px;    /* same as the menu items by default */
  --modal-header-bg:   #0d9488;
  --modal-header-text: #ffffff;
  --modal-body-bg:     #ffffff;
  --modal-border:      #0d9488;

  --radius:      10px;
  --radius-lg:   14px;
  --ring:        0 0 0 3px rgba(13,148,136,.16);
  --shadow-sm:   0 1px 2px rgba(16,24,40,.05);
  --shadow:      0 1px 3px rgba(16,24,40,.08), 0 1px 2px rgba(16,24,40,.04);
  --shadow-lg:   0 20px 48px rgba(16,24,40,.18);

  --sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Code", "JetBrains Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.app { display: grid; grid-template-columns: 232px 1fr; min-height: 100vh; }

/* ---- sidebar ---- */
.rail {
  background: var(--menu-bg);
  border-right: 1px solid var(--border);
  padding: 20px 14px;
  display: flex; flex-direction: column; gap: 24px;
  position: sticky; top: 0; height: 100vh;
}
.brand { display: flex; align-items: center; gap: 10px; padding: 4px 8px 0; }
.brand-mark {
  width: 26px; height: 26px; border-radius: 8px;
  background: linear-gradient(140deg, #2dd4bf, var(--primary-700));
  box-shadow: 0 2px 6px rgba(13,148,136,.32);
}
.brand-name { font-size: 16px; font-weight: 650; letter-spacing: -.01em; }

.nav { display: flex; flex-direction: column; gap: 2px; }
.nav-item {
  text-align: left; background: none; border: 0; color: var(--menu-text);
  font-family: var(--sans); font-size: 13.5px; font-weight: 500;
  padding: 9px 12px; border-radius: 8px; cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.nav-item:hover { color: var(--ink); background: var(--menu-hover-bg); }
.nav-item.is-active { color: var(--menu-active-text); background: var(--menu-active-bg); font-weight: 600; }

.rail-foot {
  margin-top: auto; display: flex; align-items: center; gap: 8px;
  font-size: 11.5px; color: var(--faint); padding: 0 8px;
}

/* ---- main ---- */
.main { padding: 32px 36px 80px; width: 100%; }
.view { max-width: 1180px; }
/* the activity table and customer cards benefit from the full width */
#view-activity, #view-customers, #view-connectors, #view-sources { max-width: 98%; width: 98%; }
/* full width, balanced by .main's own left/right padding */
#view-dashboard { max-width: 100%; width: 100%; }
.view { display: none; }
.view.is-active { display: block; animation: rise .18s ease; }
@keyframes rise { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.view-head { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 22px; gap: 20px; }
h1 { font-size: 24px; font-weight: 650; margin: 0; letter-spacing: -.02em; }
.sub { color: var(--muted); margin: 4px 0 0; font-size: 13.5px; }

.stack { display: flex; flex-direction: column; gap: 12px; }

/* ---- cards ---- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 18px 20px; box-shadow: var(--shadow-sm);
  transition: box-shadow .15s ease, border-color .15s ease;
}
/* Created/modified byline. A normal block at the end of the card's content rather than
   absolutely positioned — cards vary in height (a connector's steps table, a producer's
   single row), and letting the card grow to fit this avoids ever overlapping a button. */
.tracking-byline {
  margin-top: 10px; text-align: right; font-size: 11px; line-height: 1.5; color: var(--faint);
}
.card:hover { box-shadow: var(--shadow); border-color: var(--border-mid); }
.card-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.card-title { font-weight: 600; font-size: 15.5px; letter-spacing: -.01em; display: flex; align-items: center; gap: 8px; }
.card-meta { color: var(--muted); font-size: 12.5px; margin-top: 3px; }

/* pipeline flow — the signature element */
.steps-flow { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; }
.flow {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-family: var(--mono); font-size: 12px; color: var(--muted);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 10px; padding: 8px 12px;
}
.flow .node {
  background: var(--surface); border: 1px solid var(--border-mid);
  padding: 3px 9px; border-radius: 7px; color: var(--ink); box-shadow: var(--shadow-sm);
}
.flow .wire { width: 22px; height: 2px; background: var(--border-firm); border-radius: 2px; position: relative; }
.flow .wire::after {
  content: ""; position: absolute; right: -3px; top: -3px;
  border: 4px solid transparent; border-left-color: var(--border-firm);
}
.flow.is-live { background: var(--primary-50); border-color: var(--primary-100); }
.flow.is-live .wire { background: var(--primary); }
.flow.is-live .wire::after { border-left-color: var(--primary); }
.flow-tag { margin-left: auto; font-size: 10.5px; color: var(--faint); text-transform: uppercase; letter-spacing: .06em; font-weight: 600; }

.seq {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 7px; border-radius: 999px;
  background: var(--primary); color: var(--btn-text);
  font-family: var(--mono); font-size: 11px; font-weight: 700;
}

/* status pills */
.pill {
  font-size: 11px; font-weight: 650; letter-spacing: .03em; padding: 4px 10px;
  border-radius: 999px; border: 1px solid; text-transform: uppercase; white-space: nowrap;
}
.pill-draft     { color: var(--muted);       border-color: var(--border-mid); background: var(--surface-2); }
.pill-published { color: var(--pill-text); border-color: var(--pill-border); background: var(--pill-bg); }
.pill-paused    { color: var(--warn);        border-color: #fde3b7; background: var(--warn-50); }

.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.dot.dot-live {
  width: var(--sched-dot-size); height: var(--sched-dot-size);
  background: var(--sched-dot-color); box-shadow: 0 0 0 0 rgba(13,148,136,.5);
  animation: pulse 2s infinite;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(13,148,136,.45); }
  70%  { box-shadow: 0 0 0 7px rgba(13,148,136,0); }
  100% { box-shadow: 0 0 0 0 rgba(13,148,136,0); }
}

/* ---- buttons ---- */
.btn {
  font-family: var(--sans); font-size: 13px; font-weight: 550;
  background: var(--surface); color: var(--ink); border: 1px solid var(--border-mid);
  padding: 8px 14px; border-radius: 9px; cursor: pointer; box-shadow: var(--shadow-sm);
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  transition: background .12s ease, border-color .12s ease, box-shadow .12s ease, transform .06s ease;
}
.btn:hover { background: var(--surface-2); border-color: var(--border-firm); }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: none; box-shadow: var(--ring); }
.btn:disabled { opacity: .5; cursor: default; transform: none; }

.btn-primary { background: var(--primary); color: var(--btn-text); border-color: var(--primary); box-shadow: 0 1px 2px rgba(13,148,136,.28); }
.btn-primary:hover { background: var(--primary-700); border-color: var(--primary-700); }
.btn-ghost { background: transparent; border-color: transparent; box-shadow: none; color: var(--muted); }
.btn-ghost:hover { background: var(--surface-3); color: var(--ink); }
.btn-danger { color: var(--danger); border-color: #f3c9c5; background: var(--surface); }
.btn-danger:hover { background: var(--danger-50); border-color: var(--danger); }
.btn-sm { padding: 6px 11px; font-size: 12.5px; border-radius: 8px; }
.btn-group { display: flex; gap: 8px; flex-wrap: wrap; }


/* A divider between the password form and the SSO button, so the two are read as
   alternatives rather than steps. */
.login-or {
  display: flex; align-items: center; gap: 10px;
  margin: 16px 0 12px; color: var(--muted); font-size: 12px;
}
.login-or::before, .login-or::after {
  content: ""; flex: 1; height: 1px; background: var(--border);
}
#login-sso .btn { width: 100%; justify-content: center; }

/* ---- file inputs -------------------------------------------------------
   Styled through ::file-selector-button rather than the usual trick of hiding
   the input behind a real button. The hidden-input approach needs a scripted
   .click(), and that was one of the suspects when the certificate file dialog
   stalled — this keeps the browser's own native control and only restyles the
   button inside it, so there is nothing between the click and the OS dialog. */
.field input[type="file"] {
  font-family: var(--sans); font-size: 13px; color: var(--muted);
  padding: 0; border: 0; background: none; cursor: pointer;
}
.field input[type="file"]::file-selector-button {
  font-family: var(--sans); font-size: 12.5px; font-weight: 550;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--border-mid);
  padding: 6px 11px; border-radius: 8px; margin-right: 10px;
  cursor: pointer; box-shadow: var(--shadow-sm);
  transition: background .12s ease, border-color .12s ease;
}
.field input[type="file"]::file-selector-button:hover {
  background: var(--surface-2); border-color: var(--border-firm);
}
.field input[type="file"]:focus-visible::file-selector-button {
  outline: none; box-shadow: var(--ring);
}

/* ---- form controls ---- */
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink); margin-bottom: 6px; }
.field input, .field select, .field textarea,
.col-row input, .col-row select,
.custom-row input, .custom-row select,
.param-row input, .param-row select,
.pathtag-row input, .pathtag-row select,
.seq-main input {
  width: 100%; background-color: var(--surface); color: var(--ink);
  border: 1px solid var(--border-mid); border-radius: 9px;
  font-family: var(--sans); font-size: 13.5px;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.field input, .field select { height: 40px; padding: 0 12px; }
.field textarea { padding: 10px 12px; font-family: var(--mono); font-size: 12.5px; line-height: 1.6; resize: vertical; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--border-firm); }
.field input:focus, .field select:focus, .field textarea:focus,
.col-row input:focus, .col-row select:focus,
.custom-row input:focus, .custom-row select:focus,
.param-row input:focus, .param-row select:focus,
.pathtag-row input:focus, .pathtag-row select:focus,
.seq-main input:focus { outline: none; border-color: var(--primary); box-shadow: var(--ring); }
.field input::placeholder, .custom-row input::placeholder,
.param-row input::placeholder, .col-row input::placeholder,
.pathtag-row input::placeholder { color: var(--faint); }

/* value-bearing fields read as data */
#w-recordspath, #w-table, [data-field], [data-dest], [data-pval], [data-cval],
[data-tagval], [data-tagobj], [data-tagcol],
#s-swagger, #s-base, #s-akname { font-family: var(--mono); font-size: 12.5px; }

/* custom dropdown chevron */
select {
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235b6b83' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
  padding-right: 34px !important; cursor: pointer;
}

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.hint { color: var(--muted); font-size: 12px; margin-top: 6px; line-height: 1.5; }

/* checkbox row */
.chk {
  display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--ink);
  margin-bottom: 16px; cursor: pointer; user-select: none;
}
.chk input { width: 16px; height: 16px; accent-color: var(--primary); margin: 0; }

input[type=checkbox] { accent-color: var(--primary); }

/* ---- modal ---- */
.overlay {
  position: fixed; inset: 0; background: rgba(15,23,42,.42);
  backdrop-filter: blur(3px); display: flex; align-items: center; justify-content: center;
  z-index: 40; padding: 3vh 2vw;
}
.overlay[hidden] { display: none; }
.panel {
  width: 90%; height: 90%; max-width: 1500px;
  background: var(--surface);
  border: 2px solid var(--modal-border);     /* matches the header */
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; overflow: hidden;
  animation: pop .18s cubic-bezier(.2,.9,.3,1);
}
@keyframes pop { from { transform: scale(.98); opacity: .4; } to { transform: none; opacity: 1; } }

.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 22px; background: var(--modal-header-bg); color: var(--modal-header-text);
}
.panel-head h2 { margin: 0; font-size: 16.5px; font-weight: 650; letter-spacing: -.01em; color: var(--modal-header-text); }
.panel-body { padding: 24px 26px 28px; overflow-y: auto; flex: 1; background: var(--modal-body-bg); }

.icon-btn {
  background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.28);
  color: var(--modal-header-text); width: 30px; height: 30px; border-radius: 8px;
  font-size: 17px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .12s ease, transform .12s ease;
}
.icon-btn:hover { background: rgba(255,255,255,.3); }
.icon-btn:active { transform: scale(.94); }
.icon-btn:focus-visible { outline: 2px solid var(--modal-header-text); outline-offset: 2px; }

.panel-actions {
  display: flex; gap: 10px; margin-top: 26px; padding-top: 20px;
  border-top: 1px solid var(--border);
}

/* wizard step rail */
.steps { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 22px; }
.steps span {
  font-size: 12.5px; font-weight: 550; color: var(--pill-idle-text);
  padding: 6px 13px; border-radius: 999px;
  border: 1px solid var(--pill-idle-border); background: var(--pill-idle-bg);
}
.steps span.on { color: var(--pill-text); border-color: var(--pill-border); background: var(--pill-bg); font-weight: 650; }

.section-label {
  font-size: 12px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--muted); margin: 24px 0 10px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.section-label span { font-weight: 500; letter-spacing: 0; text-transform: none; font-size: 12px; color: var(--faint); }
.section-label:first-child { margin-top: 0; }

/* per-step chips */
.step-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 20px; padding-bottom: 16px; border-bottom: 1px solid var(--border); }
.step-tab {
  font-family: var(--sans); font-size: 12.5px; font-weight: 550;
  background: var(--pill-idle-bg); color: var(--pill-idle-text);
  border: 1px solid var(--pill-idle-border); border-radius: 999px;
  padding: 6px 14px; cursor: pointer; box-shadow: var(--shadow-sm);
  transition: all .12s ease;
}
.step-tab:hover { color: var(--ink); border-color: var(--border-firm); }
.step-tab.on { background: var(--primary); color: var(--btn-text); border-color: var(--primary); }

/* run-order rows */
.seq-row {
  display: grid; grid-template-columns: 30px 1fr auto; gap: 14px; align-items: center;
  border: 1px solid var(--border); border-radius: 11px; padding: 12px 14px;
  margin-bottom: 8px; background: var(--surface); box-shadow: var(--shadow-sm);
}
.seq-main { min-width: 0; }
.seq-ep { font-family: var(--mono); font-size: 13px; margin-bottom: 7px; color: var(--ink); }
.seq-ep .m { color: var(--primary-700); font-size: 11px; font-weight: 700; margin-right: 8px; }
.seq-main input { height: 32px; padding: 0 10px; font-family: var(--mono); font-size: 12px; }
.seq-tools { display: flex; gap: 6px; align-items: center; }
.seq-tools .btn { padding: 5px 10px; }

/* column pickers */
.cols { border: 1px solid var(--border); border-radius: 11px; max-height: 340px; overflow-y: auto; background: var(--surface); }
.col-row {
  display: grid; grid-template-columns: 22px 1fr 1fr 170px; align-items: center; gap: 10px;
  padding: 9px 14px; border-bottom: 1px solid var(--border);
}
.col-row:last-child { border-bottom: 0; }
.col-row:hover { background: var(--surface-2); }
.col-row input:not([type=checkbox]), .col-row select { height: 32px; padding: 0 10px; font-size: 12.5px; }
.col-row input[type=checkbox] { width: 16px; height: 16px; margin: 0; }
.col-name { font-family: var(--mono); font-size: 12.5px; color: var(--ink); word-break: break-all; }
.col-type { color: var(--faint); font-size: 11px; margin-top: 1px; }
.col-tools { display: flex; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }

.custom-list { display: flex; flex-direction: column; gap: 8px; }
.custom-row { display: grid; grid-template-columns: minmax(160px,1fr) minmax(180px,1.3fr) minmax(150px,190px) 36px; gap: 10px; align-items: center; }
.env-row { grid-template-columns: minmax(160px,1fr) minmax(180px,1.3fr) 36px; }
.param-row  { display: grid; grid-template-columns: minmax(180px,1fr) 152px minmax(180px,1.4fr) 36px; gap: 10px; align-items: center; }
.custom-row input, .custom-row select, .param-row input, .param-row select,
.pathtag-row input, .pathtag-row select { height: 36px; padding: 0 11px; font-size: 13px; }
.row-head {
  font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--faint); margin-bottom: 0;
}
/* custom column supplied by the producer's standard-columns template:
   name + type are fixed there, so mark it and let the value stand out as the gap to fill */
.custom-row.is-template input[data-cname] {
  background-color: var(--surface-3);
  background-color: color-mix(in srgb, var(--primary) 8%, #fff);
  border-color: var(--primary);
  color: var(--primary-700);
  font-weight: 650;
}
.custom-row.is-template input[data-cval]:placeholder-shown { border-color: var(--primary); }

.mini-btn {
  background: var(--surface); border: 1px solid var(--border-mid); color: var(--danger);
  border-radius: 9px; height: 36px; width: 36px; font-size: 17px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow-sm);
  transition: all .12s ease;
}
.mini-btn:hover { border-color: var(--danger); background: var(--danger-50); }
.mini-select {
  font-family: var(--sans); font-size: 12.5px; background-color: var(--surface); color: var(--ink);
  border: 1px solid var(--border-mid); border-radius: 8px; padding: 6px 8px; box-shadow: var(--shadow-sm);
}

.token-hint { color: var(--muted); font-size: 12px; margin-top: 10px; line-height: 1.7; }
.token-hint code, .hint code {
  font-family: var(--mono); font-size: 11.5px; color: var(--primary-700);
  background: var(--primary-50); border: 1px solid var(--primary-100);
  padding: 1px 6px; border-radius: 5px;
}
.pg-block { border: 1px solid var(--border); border-radius: 11px; padding: 16px 16px 2px; margin-top: 8px; background: var(--surface-2); }

/* endpoint rows */
.ep {
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 11px;
  margin-bottom: 8px; background: var(--surface); cursor: pointer; transition: all .12s ease;
}
.ep:hover { border-color: var(--border-firm); box-shadow: var(--shadow-sm); }
.ep.sel { border-color: var(--primary); background: var(--primary-50); box-shadow: var(--ring); }
.ep .m { font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--primary-700); margin-right: 8px; }
.ep .p { font-family: var(--mono); font-size: 13px; color: var(--ink); }
.ep .s { color: var(--muted); font-size: 12.5px; margin-top: 3px; }

/* activity log */
.log-feed { display: flex; flex-direction: column; }
/* time | connector | producer | action | level | message */
.log-line, .log-head {
  display: grid;
  grid-template-columns: 168px minmax(100px,1fr) minmax(90px,.85fr) 86px minmax(100px,.95fr) 96px 52px minmax(180px,2fr);
  gap: 14px; padding: 9px 14px; align-items: baseline;
}
.log-line {
  border-bottom: 1px solid var(--border); background: var(--surface);
  font-family: var(--mono); font-size: 12.5px;
}
.log-line:last-child { border-bottom: 0; }

/* pinned column headings; rows scroll underneath */
.log-head {
  position: sticky; top: 0; z-index: 2;
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); background: var(--surface-2);
  border-bottom: 1px solid var(--border-mid); padding-top: 11px; padding-bottom: 11px;
}

/* scrollable body; in the fixed Activity layout it flexes to fill what's left */
.log-scroll {
  max-height: calc(100vh - 330px); min-height: 160px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
}
.log-scroll::-webkit-scrollbar { width: 10px; }
.log-scroll::-webkit-scrollbar-thumb {
  background: var(--border-mid); border-radius: 999px; border: 3px solid var(--surface);
}
.log-scroll::-webkit-scrollbar-thumb:hover { background: var(--border-firm); }
.log-line .who { color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.log-line .sub-who { color: var(--muted); }
.log-line:hover { background: var(--surface-2); }
.log-line .ts { color: var(--faint); white-space: nowrap; }
.log-line .step { color: var(--ink); font-weight: 600; }
.log-line .msg { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lvl { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.lvl-info  { color: var(--primary-700); }
.lvl-warn  { color: var(--warn); }
.lvl-error { color: var(--danger); }

.empty {
  color: var(--muted); font-size: 13.5px; padding: 36px 20px; text-align: center;
  border: 1px dashed var(--border-mid); border-radius: var(--radius-lg); background: var(--surface);
}

/* toast */
.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  background: var(--ink); color: #fff; padding: 12px 20px; border-radius: 10px;
  font-size: 13.5px; font-weight: 500; z-index: 60; box-shadow: var(--shadow-lg);
  max-width: min(560px, 92vw);
}
.toast.err { background: var(--danger); }

/* keep browser autofill from repainting our controls */
input:-webkit-autofill, input:-webkit-autofill:hover, input:-webkit-autofill:focus,
select:-webkit-autofill, textarea:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 1000px var(--surface) inset;
  box-shadow: 0 0 0 1000px var(--surface) inset;
  caret-color: var(--ink);
  transition: background-color 9999s ease-out 0s;
}

/* scrollbars */
.cols::-webkit-scrollbar, .panel-body::-webkit-scrollbar { width: 10px; }
.cols::-webkit-scrollbar-thumb, .panel-body::-webkit-scrollbar-thumb {
  background: var(--border-mid); border-radius: 999px; border: 3px solid var(--surface);
}
.cols::-webkit-scrollbar-thumb:hover, .panel-body::-webkit-scrollbar-thumb:hover { background: var(--border-firm); }

@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }
  .rail { position: static; height: auto; flex-direction: row; align-items: center; gap: 16px; padding: 12px 14px; }
  .nav { flex-direction: row; }
  .rail-foot { display: none; }
  .main { padding: 22px 16px 60px; }
  .overlay { padding: 0; }
  .panel { width: 100%; height: 100%; border-radius: 0; border-width: 0 0 0 0; }
  .field-row, .custom-row, .param-row, .col-row { grid-template-columns: 1fr; }
  .log-line { grid-template-columns: 1fr; gap: 3px; }
  .seq-row { grid-template-columns: 26px 1fr; }
  .seq-tools { grid-column: 1 / -1; justify-content: flex-end; }
}
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }

/* ===========================================================================
   Collapsible grouped menu
   =========================================================================== */
.brand { position: relative; }
.brand-logo { width: 26px; height: 26px; border-radius: 7px; object-fit: contain; flex: none; }
.rail-toggle {
  margin-left: auto; background: transparent; border: 1px solid transparent; color: var(--menu-text);
  width: 26px; height: 26px; border-radius: 7px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; transition: all .12s ease;
}
.rail-toggle:hover { background: var(--surface-3); color: var(--ink); border-color: var(--border); }
.rail-toggle svg { transition: transform .18s ease; }

.nav { gap: 14px; }
.nav-group { display: flex; flex-direction: column; gap: 2px; }
.nav-head {
  display: flex; align-items: center; gap: 7px; width: 100%;
  background: none; border: 0; cursor: pointer; padding: 4px 10px 5px;
  font-family: var(--sans); font-size: var(--menu-group-size); font-weight: 700;
  letter-spacing: 0; text-transform: none; color: var(--menu-group-color);
}
.nav-head:hover { color: var(--menu-text); }
/* headings read as names, not shouting: first letter up, the rest down */
.nav-head span { display: inline-block; text-transform: lowercase; }
.nav-head span::first-letter { text-transform: uppercase; }
.nav-head .chev { transform: rotate(90deg); transition: transform .16s ease; flex: none; }
.nav-group.is-closed .chev { transform: rotate(0deg); }
.nav-group.is-closed .nav-items { display: none; }
.nav-items { display: flex; flex-direction: column; gap: 2px; }

.nav-item { display: flex; align-items: center; gap: 10px; }
.nav-ico { width: 16px; text-align: center; font-size: 13px; flex: none; opacity: .85; }

/* collapsed rail: icons only */
body.nav-collapsed .app { grid-template-columns: 68px 1fr; }
body.nav-collapsed .rail { padding: 20px 10px; align-items: center; }
body.nav-collapsed .brand { justify-content: center; padding: 4px 0 0; }
body.nav-collapsed .brand-name,
body.nav-collapsed .nav-label,
body.nav-collapsed .nav-head span:not(.chev) { display: none; }
/* Sit the chevron BELOW the logo, not over it. The collapsed logo is capped at 44px, so
   its bottom is the rail's top padding (20px) + that height; place the toggle just under. */
body.nav-collapsed .rail-toggle {
  position: absolute;
  top: calc(min(var(--brand-logo-size, 48px), 44px) + 26px);
  left: 50%; transform: translateX(-50%); margin: 0;
}
body.nav-collapsed .rail-toggle svg { transform: rotate(180deg); }
/* Clear both the logo and the chevron before the nav starts. */
body.nav-collapsed .nav { margin-top: calc(min(var(--brand-logo-size, 48px), 44px) + 40px); gap: 10px; }
/* group labels mean nothing without text — show a divider instead */
body.nav-collapsed .nav-head { display: none; }
body.nav-collapsed .nav-group + .nav-group { border-top: 1px solid var(--border); padding-top: 10px; }
body.nav-collapsed .nav-group.is-closed .nav-items { display: flex; }
body.nav-collapsed .nav-item {
  justify-content: center;
  /* Negative side margins pull the item out into the rail's own 10px padding, so the
     selected/hover highlight spans the full 68px width instead of stopping short of the
     edges. The matching positive padding keeps the icon centred in the same place it was.
     Square corners because a full-bleed band with rounded ends looks like a mistake. */
  padding: 10px;
  margin-left: -10px;
  margin-right: -10px;
  width: calc(100% + 20px);
  border-radius: 0;
}
body.nav-collapsed .nav-ico { font-size: 15px; }
body.nav-collapsed .rail-foot { justify-content: center; }

/* ===========================================================================
   Setup page
   =========================================================================== */
.logo-row { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
.logo-preview {
  width: 76px; height: 76px; border-radius: 14px; flex: none;
  border: 1px solid var(--border); background: var(--surface-2);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.logo-preview img { width: 100%; height: 100%; object-fit: contain; }
.logo-preview .brand-mark { width: 34px; height: 34px; border-radius: 10px; }
.logo-actions { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.logo-actions .hint { margin-top: 2px; }

.theme-group { margin-bottom: 20px; }
.theme-group-label {
  font-size: 12px; font-weight: 650; color: var(--ink); margin-bottom: 10px;
}
.color-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; }
.color-field label { display: block; font-size: 12.5px; font-weight: 600; margin-bottom: 6px; }
.color-input {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--border-mid); border-radius: 9px; padding: 5px 8px 5px 5px;
  background: var(--surface); transition: border-color .12s ease, box-shadow .12s ease;
}
.color-input:focus-within { border-color: var(--primary); box-shadow: var(--ring); }
.color-input input[type=color] {
  width: 34px; height: 30px; padding: 0; border: 1px solid var(--border); border-radius: 7px;
  background: none; cursor: pointer; flex: none;
}
.color-input input[type=color]::-webkit-color-swatch-wrapper { padding: 2px; }
.color-input input[type=color]::-webkit-color-swatch { border: 0; border-radius: 5px; }
.color-input input[type=text] {
  border: 0; background: none; font-family: var(--mono); font-size: 12.5px;
  color: var(--ink); width: 100%; padding: 0; outline: none;
}


/* ---- activity filters ---- */
.filter-bar {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 14px 16px; margin-bottom: 10px; box-shadow: var(--shadow-sm);
}
.filter { display: flex; flex-direction: column; gap: 5px; min-width: 132px; }
.filter-grow { flex: 1 1 200px; }
.filter label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--faint);
}
.filter input, .filter select {
  height: 36px; padding: 0 11px; width: 100%;
  background-color: var(--surface); color: var(--ink);
  border: 1px solid var(--border-mid); border-radius: 9px;
  font-family: var(--sans); font-size: 13px;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.filter input:hover, .filter select:hover { border-color: var(--border-firm); }
.filter input:focus, .filter select:focus { outline: none; border-color: var(--primary); box-shadow: var(--ring); }
.filter-actions { display: flex; gap: 8px; align-items: center; margin-left: auto; }
.filter-note { font-size: 12px; color: var(--muted); margin: 0 2px 12px; }
.filter-note.is-warn { color: var(--warn); font-weight: 550; }

/* ===========================================================================
   Collapsible grouped menu
   =========================================================================== */
.brand { position: relative; }
.brand-logo { width: 26px; height: 26px; border-radius: 7px; object-fit: contain; flex: none; }
.rail-toggle {
  margin-left: auto; background: transparent; border: 1px solid transparent; color: var(--menu-text);
  width: 26px; height: 26px; border-radius: 7px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; transition: all .12s ease;
}
.rail-toggle:hover { background: var(--surface-3); color: var(--ink); border-color: var(--border); }
.rail-toggle svg { transition: transform .18s ease; }

.nav { gap: 14px; }
.nav-group { display: flex; flex-direction: column; gap: 2px; }
.nav-head {
  display: flex; align-items: center; gap: 7px; width: 100%;
  background: none; border: 0; cursor: pointer; padding: 4px 10px 5px;
  font-family: var(--sans); font-size: var(--menu-group-size); font-weight: 700;
  letter-spacing: 0; text-transform: none; color: var(--menu-group-color);
}
.nav-head:hover { color: var(--menu-text); }
/* headings read as names, not shouting: first letter up, the rest down */
.nav-head span { display: inline-block; text-transform: lowercase; }
.nav-head span::first-letter { text-transform: uppercase; }
.nav-head .chev { transform: rotate(90deg); transition: transform .16s ease; flex: none; }
.nav-group.is-closed .chev { transform: rotate(0deg); }
.nav-group.is-closed .nav-items { display: none; }
.nav-items { display: flex; flex-direction: column; gap: 2px; }

.nav-item { display: flex; align-items: center; gap: 10px; }
.nav-ico { width: 16px; text-align: center; font-size: 13px; flex: none; opacity: .85; }

/* collapsed rail: icons only */
body.nav-collapsed .app { grid-template-columns: 68px 1fr; }
body.nav-collapsed .rail { padding: 20px 10px; align-items: center; }
body.nav-collapsed .brand { justify-content: center; padding: 4px 0 0; }
body.nav-collapsed .brand-name,
body.nav-collapsed .nav-label,
body.nav-collapsed .nav-head span:not(.chev) { display: none; }
body.nav-collapsed .rail-toggle { position: absolute; top: calc(min(var(--brand-logo-size, 48px), 44px) + 26px); left: 50%; transform: translateX(-50%); margin: 0; }
body.nav-collapsed .rail-toggle svg { transform: rotate(180deg); }
body.nav-collapsed .nav { margin-top: calc(min(var(--brand-logo-size, 48px), 44px) + 40px); gap: 10px; }
/* group labels mean nothing without text — show a divider instead */
body.nav-collapsed .nav-head { display: none; }
body.nav-collapsed .nav-group + .nav-group { border-top: 1px solid var(--border); padding-top: 10px; }
body.nav-collapsed .nav-group.is-closed .nav-items { display: flex; }
body.nav-collapsed .nav-item {
  justify-content: center;
  /* Negative side margins pull the item out into the rail's own 10px padding, so the
     selected/hover highlight spans the full 68px width instead of stopping short of the
     edges. The matching positive padding keeps the icon centred in the same place it was.
     Square corners because a full-bleed band with rounded ends looks like a mistake. */
  padding: 10px;
  margin-left: -10px;
  margin-right: -10px;
  width: calc(100% + 20px);
  border-radius: 0;
}
body.nav-collapsed .nav-ico { font-size: 15px; }
body.nav-collapsed .rail-foot { justify-content: center; }

/* ===========================================================================
   Setup page
   =========================================================================== */
.logo-row { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
.logo-preview {
  width: 76px; height: 76px; border-radius: 14px; flex: none;
  border: 1px solid var(--border); background: var(--surface-2);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.logo-preview img { width: 100%; height: 100%; object-fit: contain; }
.logo-preview .brand-mark { width: 34px; height: 34px; border-radius: 10px; }
.logo-actions { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.logo-actions .hint { margin-top: 2px; }

.theme-group { margin-bottom: 20px; }
.theme-group-label {
  font-size: 12px; font-weight: 650; color: var(--ink); margin-bottom: 10px;
}
.color-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; }
.color-field label { display: block; font-size: 12.5px; font-weight: 600; margin-bottom: 6px; }
.color-input {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--border-mid); border-radius: 9px; padding: 5px 8px 5px 5px;
  background: var(--surface); transition: border-color .12s ease, box-shadow .12s ease;
}
.color-input:focus-within { border-color: var(--primary); box-shadow: var(--ring); }
.color-input input[type=color] {
  width: 34px; height: 30px; padding: 0; border: 1px solid var(--border); border-radius: 7px;
  background: none; cursor: pointer; flex: none;
}
.color-input input[type=color]::-webkit-color-swatch-wrapper { padding: 2px; }
.color-input input[type=color]::-webkit-color-swatch { border: 0; border-radius: 5px; }
.color-input input[type=text] {
  border: 0; background: none; font-family: var(--mono); font-size: 12.5px;
  color: var(--ink); width: 100%; padding: 0; outline: none;
}


/* ---- activity filters ---- */
.filter-bar {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 14px 16px; margin-bottom: 10px; box-shadow: var(--shadow-sm);
}
.filter { display: flex; flex-direction: column; gap: 5px; min-width: 132px; }
.filter-grow { flex: 1 1 200px; }
.filter label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--faint);
}
.filter input, .filter select {
  height: 36px; padding: 0 11px; width: 100%;
  background-color: var(--surface); color: var(--ink);
  border: 1px solid var(--border-mid); border-radius: 9px;
  font-family: var(--sans); font-size: 13px;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.filter input:hover, .filter select:hover { border-color: var(--border-firm); }
.filter input:focus, .filter select:focus { outline: none; border-color: var(--primary); box-shadow: var(--ring); }
.filter-actions { display: flex; gap: 8px; align-items: center; margin-left: auto; }
.filter-note { font-size: 12px; color: var(--muted); margin: 0 2px 12px; }
.filter-note.is-warn { color: var(--warn); font-weight: 550; }

@media (max-width: 1100px) {
  .log-line, .log-head { grid-template-columns: 140px 1fr 1fr 96px 52px; }
  .log-line .msg, .log-head span:last-child { grid-column: 1 / -1; white-space: normal; }
  .log-head span:last-child { display: none; }
}

/* ---- log retention + pagination ---- */
.retention-set { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.retention-set label { font-size: 13px; font-weight: 600; color: var(--ink); }
.retention-set span { font-size: 13.5px; color: var(--muted); }
.retention-set input {
  width: 96px; height: 40px; padding: 0 12px; text-align: center;
  background-color: var(--surface); color: var(--ink); font-family: var(--mono); font-size: 15px;
  border: 1px solid var(--border-mid); border-radius: 9px;
}
.retention-set input:focus { outline: none; border-color: var(--primary); box-shadow: var(--ring); }
.retention-info { font-family: var(--mono); font-size: 13px; color: var(--muted); }

.pager {
  flex: none; z-index: 3;
  display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  margin-top: 12px; padding: 12px 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: 0 -2px 10px rgba(16,24,40,.06);
}
.pager-size { display: flex; align-items: center; gap: 8px; }
.pager-size label { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); }
.pager-size select {
  height: 32px; padding: 0 10px; background-color: var(--surface); color: var(--ink);
  border: 1px solid var(--border-mid); border-radius: 8px; font-family: var(--sans); font-size: 12.5px;
}
.pager-nav { display: flex; align-items: center; gap: 10px; }
.pager-at { font-family: var(--mono); font-size: 12.5px; color: var(--muted); min-width: 74px; text-align: center; }

/* customer identifier shown inline in card metadata */
.acct {
  font-family: var(--mono); font-size: 11.5px; font-weight: 600;
  color: var(--pill-text); background: var(--pill-bg);
  border: 1px solid var(--pill-border); border-radius: 5px; padding: 1px 6px;
}


/* ===========================================================================
   Activity: page itself doesn't scroll — only the table body does.
   Applied via body.fixed-view, set when the Activity view is showing.
   =========================================================================== */
body.fixed-view { overflow: hidden; }
body.fixed-view .main {
  height: 100vh; overflow: hidden;
  padding-bottom: 24px; display: flex; flex-direction: column;
}
body.fixed-view #view-activity.is-active,
body.fixed-view #view-customers.is-active,
body.fixed-view #view-connectors.is-active,
body.fixed-view #view-dashboard.is-active,
body.fixed-view #view-sources.is-active {
  display: flex; flex-direction: column;
  flex: 1; min-height: 0;      /* min-height:0 lets the child scroll instead of stretching */
}
/* everything except the scroll area keeps its natural height */
body.fixed-view #view-activity > .view-head,
body.fixed-view #view-activity > .filter-bar,
body.fixed-view #view-activity > .filter-note,
body.fixed-view #view-customers > .view-head,
body.fixed-view #view-customers > .filter-bar,
body.fixed-view #view-customers > .filter-note,
body.fixed-view #view-connectors > .view-head,
body.fixed-view #view-connectors > .filter-bar,
body.fixed-view #view-connectors > .filter-note,
body.fixed-view #view-sources > .view-head,
body.fixed-view #view-sources > .filter-bar,
body.fixed-view #view-sources > .filter-note,
body.fixed-view #view-dashboard > .view-head { flex: none; }

body.fixed-view .log-scroll { flex: 1; min-height: 0; max-height: none; }

/* customer cards scroll; search above and pager below stay put */
body.fixed-view #customer-list,
body.fixed-view #connector-list,
body.fixed-view #source-list {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 2px 6px 6px 2px;   /* room so card shadows aren't clipped */
}
.card-scroll::-webkit-scrollbar { width: 10px; }
.card-scroll::-webkit-scrollbar-thumb {
  background: var(--border-mid); border-radius: 999px; border: 3px solid var(--canvas);
}
.card-scroll::-webkit-scrollbar-thumb:hover { background: var(--border-firm); }

/* Small screens keep normal page scrolling — a 100vh column is unusable there. */
@media (max-width: 860px) {
  body.fixed-view { overflow: auto; }
  body.fixed-view .main { height: auto; overflow: visible; display: block; }
  body.fixed-view #view-activity.is-active,
  body.fixed-view #view-customers.is-active,
  body.fixed-view #view-connectors.is-active,
  body.fixed-view #view-sources.is-active { display: block; }
  body.fixed-view .log-scroll { flex: none; max-height: 60vh; }
  body.fixed-view #customer-list,
  body.fixed-view #connector-list,
  body.fixed-view #source-list { overflow: visible; padding: 0; }
}


/* roomier cards on the Customer page */
.customer-card { padding: 22px 26px; }
.customer-card .card-title { font-size: 17px; }
.customer-card .card-meta { font-size: 13px; margin-top: 5px; }
.customer-card .card-row { align-items: flex-start; }

/* ---- confirmation / information dialog ---- */
.dialog-overlay { z-index: 70; }          /* above the form panel and toasts */
.dialog-panel {
  width: min(540px, 92vw); height: auto; max-height: 84vh;
  animation: pop .16s cubic-bezier(.2,.9,.3,1);
}
.dialog-panel .panel-body { padding: 22px 26px 24px; overflow-y: auto; }
.dialog-message {
  margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--ink); white-space: pre-line;
}
/* Stack traces and response bodies: monospace, wrapped, and scrollable rather than
   stretching the dialog to the width of the longest line. */
.detail-pre {
  font-family: var(--mono); font-size: 12px; line-height: 1.5;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; padding: 12px;
  max-height: 45vh; overflow: auto;
  white-space: pre-wrap; word-break: break-word;
  margin: 0;
}
.dialog-panel .panel-actions { margin-top: 22px; padding-top: 18px; justify-content: flex-end; }


/* numeric theme control (e.g. group heading size) */
.size-input {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--border-mid); border-radius: 9px; padding: 5px 12px 5px 8px;
  background: var(--surface); transition: border-color .12s ease, box-shadow .12s ease;
}
.size-input:focus-within { border-color: var(--primary); box-shadow: var(--ring); }
.size-input input {
  border: 0; background: none; outline: none; width: 100%; padding: 4px 2px;
  font-family: var(--mono); font-size: 13px; color: var(--ink);
}
.size-input span { font-size: 12.5px; color: var(--muted); }


/* ===========================================================================
   Responsive
   Phones get an off-canvas menu, stacked forms, and log rows as labelled cards.
   =========================================================================== */

/* narrow desktops / tablets: drop the least important log column first */
@media (max-width: 1250px) {
  .log-line, .log-head {
    grid-template-columns: 150px minmax(100px,1fr) minmax(100px,1fr) 96px 52px minmax(180px,2fr);
  }
  /* keyed by name, so adding or reordering columns can't shift what gets hidden */
  .log-head span[data-col="Producer"], .log-line span[data-label="Producer"],
  .log-head span[data-col="Type"],     .log-line span[data-label="Type"] { display: none; }
}

.mobile-bar { display: none; }
.nav-scrim { display: none; }
.filters-btn { display: none; }
.head-actions { display: flex; gap: 10px; align-items: center; }

@media (max-width: 860px) {
  /* --- top bar + off-canvas drawer --- */
  .mobile-bar {
    display: flex; align-items: center; gap: 12px;
    position: sticky; top: 0; z-index: 45;
    height: 56px; padding: 0 14px;
    background: var(--menu-bg); border-bottom: 1px solid var(--border);
  }
  .nav-toggle {
    display: flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 9px;
    background: var(--surface); color: var(--ink);
    border: 1px solid var(--border-mid); cursor: pointer;
  }
  .nav-toggle:active { transform: scale(.96); }
  .mobile-title { font-size: 16px; font-weight: 650; letter-spacing: -.01em; }

  .nav-scrim {
    display: block; position: fixed; inset: 0; z-index: 48;
    background: rgba(15,23,42,.45); backdrop-filter: blur(2px);
  }
  .nav-scrim[hidden] { display: none; }

  .app { grid-template-columns: 1fr; }

  .rail {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 50;
    width: 264px; height: 100dvh; padding: 18px 14px;
    flex-direction: column; align-items: stretch;
    transform: translateX(-100%); transition: transform .22s ease;
    box-shadow: 0 0 40px rgba(16,24,40,.18);
  }
  body.nav-open .rail { transform: none; }
  .rail-toggle { display: none; }          /* the drawer is the collapse control here */
  .nav { flex-direction: column; }
  .rail-foot { display: flex; }

  /* the desktop icon-strip mode has no meaning on a phone */
  body.nav-collapsed .app { grid-template-columns: 1fr; }
  body.nav-collapsed .brand-name,
  body.nav-collapsed .nav-label,
  body.nav-collapsed .nav-head span:not(.chev) { display: inline-block; }
  body.nav-collapsed .nav-head { display: flex; }
  body.nav-collapsed .nav-item {
    justify-content: flex-start;
    padding: 9px 12px;
    /* Undo the collapsed full-bleed highlight — on a phone the icon strip is disabled
       entirely, so items go back to the ordinary inset, rounded look. */
    margin-left: 0;
    margin-right: 0;
    width: 100%;
    border-radius: 8px;
  }

  /* --- page frame: normal scrolling, no 100vh columns --- */
  .main { padding: 18px 14px 40px; }
  #view-activity, #view-customers { max-width: 100%; width: 100%; }
  body.fixed-view { overflow: auto; }
  body.fixed-view .main { height: auto; overflow: visible; display: block; }
  body.fixed-view #view-activity.is-active,
  body.fixed-view #view-customers.is-active,
  body.fixed-view #view-connectors.is-active,
  body.fixed-view #view-sources.is-active { display: block; }
  body.fixed-view .log-scroll { flex: none; max-height: none; overflow: visible; border: 0; box-shadow: none; background: none; }
  body.fixed-view #customer-list { overflow: visible; padding: 0; }

  .view-head { flex-direction: column; align-items: stretch; gap: 12px; }
  .view-head .btn { width: 100%; }
  .head-actions { display: flex; gap: 8px; }
  .head-actions .btn { flex: 1; }

  /* filters collapse behind a toggle so the log is visible without scrolling */
  .filters-btn { display: inline-flex; }
  #activity-filters, #activity-note { display: none; }
  body.filters-open #activity-filters { display: flex; }
  body.filters-open #activity-note { display: block; }
  h1 { font-size: 21px; }

  /* --- filters stack --- */
  .filter-bar { flex-direction: column; align-items: stretch; gap: 10px; padding: 12px; }
  .filter, .filter-grow { min-width: 0; width: 100%; }
  .filter-actions { margin-left: 0; }
  .filter-actions .btn { flex: 1; }

  /* --- log rows become labelled cards --- */
  .log-head { display: none; }
  .log-scroll { border-radius: 0; }
  .log-feed { gap: 10px; }
  .log-line {
    display: block; padding: 12px 14px;
    border: 1px solid var(--border); border-radius: 11px;
    background: var(--surface); box-shadow: var(--shadow-sm);
  }
  .log-line > span { display: block; }
  .log-line > span::before {
    content: attr(data-label);
    display: block; margin-bottom: 1px;
    font-family: var(--sans); font-size: 9.5px; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; color: var(--faint);
  }
  .log-line > span + span { margin-top: 8px; }
  .log-line span[data-label="Producer"],
  .log-line span[data-label="Type"] { display: block; }   /* undo the tablet hide */
  .log-line .msg { white-space: normal; overflow: visible; }

  /* --- pager --- */
  .pager { flex-direction: column; align-items: stretch; gap: 10px; }
  .pager-nav { justify-content: space-between; }
  .pager-nav .btn { flex: 1; }

  /* --- forms, cards, modal --- */
  .field-row, .custom-row, .param-row, .col-row, .color-grid { grid-template-columns: 1fr; }
  .custom-row .mini-btn, .param-row .mini-btn { justify-self: end; }
  .seq-row { grid-template-columns: 26px 1fr; }
  .seq-tools { grid-column: 1 / -1; justify-content: flex-end; }
  .card, .customer-card { padding: 16px; }
  .card-row { flex-direction: column; align-items: flex-start; gap: 8px; }
  .btn-group .btn { flex: 1 1 auto; }

  .overlay { padding: 0; }
  .panel { width: 100%; height: 100%; max-width: none; border-radius: 0; border-width: 0; }
  .panel-body { padding: 18px 16px 24px; }
  .dialog-panel { width: 100%; height: auto; max-height: 100%; border-radius: 0; }
  .steps, .step-tabs { gap: 6px; }
  .retention-set { flex-wrap: wrap; }
  .logo-row { flex-direction: column; }
}

/* very small phones */
@media (max-width: 420px) {
  .main { padding: 14px 10px 32px; }
  .btn { padding: 8px 11px; }
  .card-title { font-size: 15px; }
}

@media (prefers-reduced-motion: reduce) {
  .rail { transition: none; }
}

/* Connector type badge on producer cards */
.type-tag {
  display: inline-block; margin-right: 6px;
  font-family: var(--sans); font-size: 10.5px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); background: var(--surface-2);
  border: 1px solid var(--border-mid); border-radius: 5px; padding: 1px 6px;
}
/* "required" marker on field labels */
.req {
  font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--danger); margin-left: 6px;
}

/* active-filter chip (e.g. Activity narrowed to one connector) */
.chip-row { margin: 2px 0 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 6px 5px 12px; border-radius: 999px;
  background: var(--primary-50); border: 1px solid var(--primary-100);
  color: var(--primary-700); font-size: 12.5px;
}
.chip strong { font-weight: 650; }
.chip-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%;
  border: 0; cursor: pointer; font-size: 15px; line-height: 1;
  background: var(--primary-100); color: var(--primary-700);
}
.chip-x:hover { background: var(--primary); color: #fff; }

/* time zone picker in the Activity header, beside Refresh */
.zone-pick { display: flex; align-items: center; gap: 8px; }
.zone-pick label {
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--faint); white-space: nowrap;
}
.zone-pick select {
  height: 38px; padding: 0 32px 0 12px;
  background-color: var(--surface); color: var(--ink);
  border: 1px solid var(--border-mid); border-radius: 9px;
  font-family: var(--sans); font-size: 13px;
}
.zone-pick select:focus { outline: none; border-color: var(--primary); box-shadow: var(--ring); }
@media (max-width: 860px) {
  .zone-pick { width: 100%; }
  .zone-pick select { flex: 1; width: 100%; }
  .head-actions { flex-wrap: wrap; }
}

/* path tag rows on the Request step */
.pathtag-row {
  display: grid; grid-template-columns: 160px 190px 1fr; gap: 10px;
  align-items: center; padding: 7px 0;
}
.pathtag-row.row-head {
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--faint); padding-bottom: 2px;
}
.pathtag-row .tag-name code {
  font-family: var(--mono); font-size: 12.5px; color: var(--primary-700);
  background: var(--primary-50); border: 1px solid var(--primary-100);
  border-radius: 6px; padding: 3px 8px;
}
.tag-sql { display: grid; grid-template-columns: 1.4fr 1fr; gap: 8px; }
@media (max-width: 860px) {
  .pathtag-row { grid-template-columns: 1fr; gap: 6px; }
  .pathtag-row.row-head { display: none; }
  .tag-sql { grid-template-columns: 1fr; }
}


/* divider between the Path values and Request parameters blocks */
.section-sep {
  height: 1px; margin: 18px 0 4px;
  background: var(--border); border: 0;
}

/* action buttons on an endpoint row */
.row-actions { display: flex; gap: 8px; align-items: center; flex-shrink: 0; }
@media (max-width: 860px) { .row-actions { width: 100%; } .row-actions .btn { flex: 1; } }

/* inline validation for the request body box */
.hint-ok { color: var(--primary-700); }
.hint-bad { color: var(--danger, #b42318); }

/* live sample of the pill colours on the Setup page */
.pill-preview {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 14px; margin-bottom: 14px;
  background: var(--canvas); border: 1px solid var(--border); border-radius: 10px;
}

/* connection test results */
.ok  { color: var(--primary-700); font-weight: 600; }
.bad { color: var(--danger); font-weight: 600; }

/* ===========================================================================
   Brand: logo on its own line, site name beneath it
   These come last on purpose — the rules above appear twice in this file, so
   anything earlier would be silently overridden by the duplicate block.
   =========================================================================== */
.brand {
  display: flex; flex-direction: column;
  align-items: var(--brand-align, flex-start);
  padding: var(--brand-top, 4px) 8px 0 var(--brand-left, 0px);
}
/* logo and name centred on each other, whatever the group's position */
.brand-stack {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--brand-gap, 4px);
  min-width: 0;
}
.brand-logo,
.brand-mark {
  width: var(--brand-logo-size, 48px);
  height: var(--brand-logo-size, 48px);
  border-radius: 12px;
}
.brand-logo { object-fit: contain; }
.brand-name {
  font-size: var(--brand-name-size, 16px);
  color: var(--brand-name-color, var(--ink));
  font-weight: 650; letter-spacing: -.01em; line-height: 1.2;
  text-align: var(--brand-text-align, left); word-break: break-word;
}
/* the toggle sat in the flex row; with a column it needs pinning */
.rail-toggle { position: absolute; top: 4px; right: 4px; margin: 0; }

body.nav-collapsed .brand { align-items: center; padding: var(--brand-top, 4px) 0 0; }
body.nav-collapsed .brand-logo,
body.nav-collapsed .brand-mark {
  width: min(var(--brand-logo-size, 48px), 44px);
  height: min(var(--brand-logo-size, 48px), 44px);
  border-radius: 9px;
}
body.nav-collapsed .rail-toggle { position: absolute; top: calc(min(var(--brand-logo-size, 48px), 44px) + 26px); left: 50%; right: auto; transform: translateX(-50%); }

/* the Setup preview should match what the sidebar shows */
.logo-preview .brand-mark { width: 48px; height: 48px; border-radius: 12px; }

/* A dropdown inside a colour/size grid: the base rule only covers .field select
   and the row types, so a select here would otherwise fall back to browser
   defaults and sit oddly next to the colour and size boxes. */
.color-field select {
  /* 42px to match the colour swatch box, the tallest of the three controls that
     share this grid — they were 42 / 35 / 40 before. */
  width: 100%; height: 42px; padding: 0 12px;
  background-color: var(--surface); color: var(--ink);
  border: 1px solid var(--border-mid); border-radius: 9px;
  font-family: var(--sans); font-size: 13.5px;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.color-field select:hover { border-color: var(--border-firm); }
.color-field select:focus { outline: none; border-color: var(--primary); box-shadow: var(--ring); }

/* the size box was shorter than the colour box beside it */
.size-input { min-height: 42px; box-sizing: border-box; }

/* ===========================================================================
   Dashboard
   =========================================================================== */
.tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 14px; margin-bottom: 18px;
}
.tile {
  background: var(--tile-bg); border: 1px solid var(--tile-border); border-radius: 12px;
  padding: 16px 18px; box-shadow: var(--shadow-sm);
}
.tile-value { font-size: 30px; font-weight: 700; letter-spacing: -.02em; color: var(--tile-value-color); line-height: 1.1; }
.tile-label { font-size: 12.5px; font-weight: 600; color: var(--tile-label-color); margin-top: 4px; }
.tile-sub { font-size: 11.5px; color: var(--tile-sub-color); margin-top: 2px; }
.tile-pub { border-color: var(--tile-pub-border); background: var(--tile-pub-bg); }
.tile-pub .tile-value { color: var(--tile-pub-value); }

/* health colours are fixed rather than themed — a red that isn't red helps nobody */
.dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; flex: none; margin-right: 8px; }
.dot.ok   { background: #16a34a; }
.dot.warn { background: #d97706; }
.dot.err  { background: #dc2626; }
.dot.idle { background: #94a3b8; }

.health-bar {
  display: flex; height: 12px; border-radius: 999px; overflow: hidden;
  background: var(--surface-2); margin: 4px 0 12px;
}
.hb { display: block; transition: width .4s ease; }
.hb.ok { background: #16a34a; } .hb.warn { background: #d97706; }
.hb.err { background: #dc2626; } .hb.idle { background: #cbd5e1; }
.health-keys { display: flex; flex-wrap: wrap; gap: 18px; font-size: 12.5px; color: var(--muted); }
.hk { display: flex; align-items: center; }

/* small tiles carry the same fields as the old table rows */
.mini-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  gap: 12px;
}
.mini {
  border: 1px solid var(--border); border-left: 3px solid var(--border-mid);
  border-radius: 10px; padding: 12px 14px; background: var(--surface);
  cursor: pointer; transition: background .12s ease, box-shadow .12s ease, transform .12s ease;
}
.mini:hover { background: var(--surface-2); box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.mini.health-error   { border-left-color: #dc2626; }
.mini.health-warning { border-left-color: #d97706; }
.mini.health-healthy { border-left-color: #16a34a; }
.mini.health-unknown,
.mini.health-pending { border-left-color: #cbd5e1; }
.mini-err { border-left-color: #dc2626; }

.mini-head { display: flex; align-items: center; min-width: 0; }
.mini-name {
  font-weight: 650; font-size: 13.5px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mini-sub { font-size: 11.5px; color: var(--faint); margin: 3px 0 10px 17px; }
.mini-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.mini-stats div { display: flex; flex-direction: column; min-width: 0; }
.mini-stats b {
  font-family: var(--mono); font-size: 12.5px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mini-stats span { font-size: 10.5px; color: var(--faint); margin-top: 1px; }
.mini-msg {
  font-family: var(--mono); font-size: 11.5px; color: var(--muted);
  line-height: 1.5; word-break: break-word; margin-left: 17px;
}

/* legend entries are buttons because they filter the tiles below */
.hk {
  display: flex; align-items: center; background: none; border: 1px solid transparent;
  border-radius: 999px; padding: 4px 10px; cursor: pointer;
  font-family: var(--sans); font-size: 12.5px; color: var(--muted);
  transition: all .12s ease;
}
.hk:hover { border-color: var(--border-mid); background: var(--surface-2); color: var(--ink); }
.hk.is-on { border-color: var(--primary); background: var(--pill-bg); color: var(--pill-text); font-weight: 600; }
.hb.unk { background: #cbd5e1; }

@media (max-width: 560px) {
  .mini-stats { grid-template-columns: repeat(2, 1fr); row-gap: 8px; }
}

/* ===========================================================================
   Dashboard: the page holds still; each tile area scrolls on its own.
   =========================================================================== */
body.fixed-view #dash-body {
  flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 0;
}
/* the counters and the health bar keep their natural height */
body.fixed-view #dash-body > .tiles,
body.fixed-view #dash-body > .card:first-of-type { flex: none; }

.dash-panels { display: flex; gap: 14px; align-items: stretch; }
body.fixed-view .dash-panels { flex: 1; min-height: 0; }

.dash-panel { display: flex; flex-direction: column; min-width: 0; margin-bottom: 0; }
.dash-panel:first-child { flex: 2 1 0; }
.dash-panel:last-child  { flex: 1 1 0; }
.dash-panel:only-child  { flex: 1 1 0; }
.dash-panel > .section-label { flex: none; }

/* the scrolling part */
body.fixed-view .dash-panel > .mini-grid,
body.fixed-view .dash-panel > .empty {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 2px 6px 6px 2px;      /* room so tile shadows aren't clipped */
  align-content: start;
}
.mini-grid::-webkit-scrollbar { width: 10px; }
.mini-grid::-webkit-scrollbar-thumb {
  background: var(--border-mid); border-radius: 999px; border: 3px solid var(--surface);
}
.mini-grid::-webkit-scrollbar-thumb:hover { background: var(--border-firm); }

/* narrow screens: stack the panels and let the page scroll again */
@media (max-width: 1000px) {
  .dash-panels { flex-direction: column; }
  body.fixed-view .dash-panel > .mini-grid { max-height: 46vh; }
}

/* ===========================================================================
   Sign-in and users
   =========================================================================== */
/* display:flex would otherwise beat the [hidden] attribute and leave the sign-in
   screen covering the console forever */
.login-screen[hidden] { display: none; }
.login-screen {
  position: fixed; inset: 0; z-index: 200; display: flex;
  align-items: center; justify-content: center; padding: 24px;
  background: var(--canvas);
}
body.signed-out .app { display: none; }
.login-card {
  width: 100%; max-width: 380px; background: var(--surface);
  border: 1px solid var(--border); border-radius: 16px; padding: 32px 30px;
  box-shadow: 0 18px 48px rgba(15, 23, 42, .12);
}
.login-brand { display: flex; justify-content: center; margin-bottom: 18px; }
.login-brand .brand-mark, .login-brand .brand-logo { width: 52px; height: 52px; border-radius: 13px; }
.login-card h1 { font-size: 20px; text-align: center; }
.login-card .sub { text-align: center; margin-bottom: 22px; }
.login-card .btn { width: 100%; justify-content: center; margin-top: 6px; }
.login-msg { color: var(--danger); font-size: 12.5px; min-height: 18px; margin: 2px 0 6px; }

/* the account chip pinned to the bottom of the menu */
.user-chip { margin-top: auto; padding-top: 14px; position: relative; }
.user-btn {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: none; border: 1px solid transparent; border-radius: 10px;
  padding: 8px; cursor: pointer; text-align: left; font-family: var(--sans);
  transition: all .12s ease;
}
.user-btn:hover { background: var(--menu-active-bg); border-color: var(--border); }
.user-avatar {
  width: 30px; height: 30px; border-radius: 50%; flex: none;
  background: var(--primary); color: var(--btn-text);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700;
}
.user-meta { display: flex; flex-direction: column; min-width: 0; }
.user-meta b { font-size: 12.5px; color: var(--menu-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-meta span { font-size: 11px; color: var(--faint); }
body.nav-collapsed .user-meta { display: none; }
body.nav-collapsed .user-btn { justify-content: center; }

.user-menu {
  position: absolute; bottom: calc(100% - 4px); left: 8px; right: 8px; z-index: 20;
  background: var(--surface); border: 1px solid var(--border-mid); border-radius: 10px;
  box-shadow: var(--shadow-md); overflow: hidden;
}
.user-menu-item {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: 10px 12px; font-family: var(--sans); font-size: 12.5px; color: var(--ink); cursor: pointer;
}
.user-menu-item:hover { background: var(--surface-2); }

.perm-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.perm {
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--border-mid); color: var(--muted); background: var(--surface);
}
.perm-edit { border-color: var(--pill-border); background: var(--pill-bg); color: var(--pill-text); font-weight: 600; }
.perm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; margin-bottom: 14px; }
.perm-field label { display: block; font-size: 12.5px; font-weight: 600; margin-bottom: 6px; }
.perm-field select {
  width: 100%; height: 40px; padding: 0 12px; background-color: var(--surface); color: var(--ink);
  border: 1px solid var(--border-mid); border-radius: 9px; font-family: var(--sans); font-size: 13.5px;
}
.perm-field select:focus { outline: none; border-color: var(--primary); box-shadow: var(--ring); }

/* View-only pages: hide the controls that would only earn a 403 */
.view[data-access="View"] .btn-primary,
.view[data-access="View"] .btn-danger { display: none; }

/* The account badge takes over pushing to the bottom, so the scheduler line sits
   directly beneath it instead of the two splitting the free space between them. */
.user-chip ~ .rail-foot { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.user-chip { margin-top: auto; padding-top: 14px; }

/* ===========================================================================
   Activity: clickable error rows + detail modal
   =========================================================================== */
.log-line.has-detail { cursor: pointer; }
.log-line.has-detail:hover { background: var(--surface-2); }
.detail-cue { color: var(--primary); font-weight: 600; font-size: 11.5px; margin-left: 6px; white-space: nowrap; }

.log-detail .ld-meta { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.ld-step { font-weight: 650; color: var(--ink); }
.ld-when { color: var(--faint); font-size: 12.5px; margin-left: auto; }
.ld-message {
  font-family: var(--mono); font-size: 12.5px; color: var(--ink); line-height: 1.55;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 10px 12px; margin-bottom: 14px; word-break: break-word;
}
.ld-trace {
  font-family: var(--mono); font-size: 11.5px; line-height: 1.5; color: var(--muted);
  background: #0f172a; color: #e2e8f0; border-radius: 8px; padding: 14px 16px;
  max-height: 46vh; overflow: auto; white-space: pre-wrap; word-break: break-word;
}

/* ===========================================================================
   On/off toggle (dashboard Errors switch)
   =========================================================================== */
.toggle { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
.toggle-label { font-size: 12.5px; font-weight: 600; color: var(--muted); }
.toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle-track {
  position: relative; width: 38px; height: 22px; border-radius: 999px;
  background: var(--border-mid); transition: background .15s ease; flex: none;
}
.toggle-thumb {
  position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 2px rgba(15,23,42,.25); transition: transform .15s ease;
}
.toggle input:checked + .toggle-track { background: var(--primary); }
.toggle input:checked + .toggle-track .toggle-thumb { transform: translateX(16px); }
.toggle input:focus-visible + .toggle-track { box-shadow: var(--ring); }

/* ===========================================================================
   Collapsible setup panels
   =========================================================================== */
.panel-card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-sm); margin-bottom: 14px; overflow: hidden; }
.panel-toggle-head {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 16px 18px; background: none; border: 0; cursor: pointer;
  font-family: var(--sans); text-align: left;
}
.panel-toggle-head:hover { background: var(--surface-2); }
.panel-title { font-size: 13px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); flex: 1; }
.panel-sub { font-size: 12px; font-weight: 400; letter-spacing: 0; text-transform: none;
  color: var(--faint); margin-left: 8px; }
.panel-chev { flex: none; color: var(--faint); transition: transform .2s ease; }
.panel-card.open .panel-chev { transform: rotate(180deg); }
.panel-card-body { padding: 0 18px 18px; }
.panel-card:not(.open) .panel-card-body { display: none; }
.panel-card.open .panel-toggle-head { border-bottom: 1px solid var(--border); }

/* ===========================================================================
   Scheduler polling — beating heart

   No @keyframes here on purpose. Windows' Settings > Accessibility > Visual effects >
   "Animation effects" toggle sets prefers-reduced-motion, and the blanket rule earlier in
   this file kills every CSS animation under that query — which stopped this indicator dead
   on any machine with the setting off. The beat is driven from requestAnimationFrame in
   app.js instead, which no OS setting can switch off, and it writes the custom properties
   below each frame.
   =========================================================================== */
.heart {
  position: relative; display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: var(--sched-dot-size); height: var(--sched-dot-size);
  color: var(--sched-dot-color);
  transform-origin: center;
  transform: scale(var(--heart-scale, 1));
  will-change: transform;
}
.heart svg { width: 100%; height: 100%; display: block; }
.heart .heart-fill { fill: currentColor; }
.heart .heart-glyph { display: block; width: 100%; height: 100%; line-height: var(--sched-dot-size);
  font-size: calc(var(--sched-dot-size) * 0.95); text-align: center; }
/* the outer glow that pulses with the beat */
.heart::after {
  content: ""; position: absolute; inset: -30%; border-radius: 50%;
  background: radial-gradient(circle, var(--sched-dot-color) 0%, transparent 68%);
  filter: blur(2px); z-index: -1; pointer-events: none;
  transform-origin: center;
  opacity: var(--heart-glow-opacity, .3);
  transform: scale(var(--heart-glow-scale, 1));
}
/* ---- scheduler indicator: ECG-style waveform ---- */
.heart.wave-mode {
  width: calc(var(--sched-dot-size) * 3.2);
  height: var(--sched-dot-size);
  transform: none;               /* the trace scrolls internally instead of the mark beating */
  opacity: var(--heart-wave-opacity, .9);
  color: var(--sched-dot-color);
  overflow: hidden;
}
.heart.wave-mode::after { display: none; }   /* no round glow blob for the wave */
.sched-wave-svg {
  width: 100%; height: 100%; display: block; overflow: hidden;
  filter: drop-shadow(0 0 1.5px var(--sched-dot-color));
}
/* The path holds two cycles; app.js scrolls the group across one of them (48 user units)
   per period and wraps, so the join never shows. The transform is set as an attribute on
   the <g> from script — nothing here animates it. */

/* ===========================================================================
   Menu-icon picker (Setup)
   =========================================================================== */
.icon-rows { display: flex; flex-direction: column; gap: 8px; }
.icon-row { display: flex; align-items: center; gap: 12px; padding: 8px;
  border: 1px solid var(--border); border-radius: 9px; background: var(--surface-2); }
.icon-row-name { font-size: 13px; font-weight: 600; color: var(--ink); flex: 1; }
.icon-current { width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  color: var(--menu-text); flex: none; }
.icon-current svg { width: 20px; height: 20px; }
.icon-pick-btn { }
.icon-size-input { width: 84px; }
.icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); gap: 6px;
  max-height: 260px; overflow-y: auto; padding: 4px; }
.icon-opt { display: flex; align-items: center; justify-content: center; height: 40px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface); cursor: pointer;
  color: var(--ink); }
.icon-opt:hover { border-color: var(--primary); background: var(--surface-2); }
.icon-opt.sel { border-color: var(--primary); background: var(--menu-active-bg); color: var(--menu-active-text); }
.icon-opt svg { width: 20px; height: 20px; }

/* ===========================================================================
   DB-source column mapping grid (wizard Request step)
   =========================================================================== */
.bodymap { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.bodymap-head, .bodymap-row {
  display: grid; grid-template-columns: 28px 1fr 1.4fr 110px; gap: 8px; align-items: center;
}
.bodymap-head { font-size: 11px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  color: var(--faint); padding: 0 2px 2px; }
.bodymap-row { padding: 3px 2px; }
.bodymap-col { font-family: var(--mono); font-size: 12px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bodymap-path { font-family: var(--mono); font-size: 12px; }
.bodymap-row select { font-size: 12px; }
