:root {
  --blue:        #2563eb;
  --blue-hover:  #1d4ed8;
  --blue-light:  #eff6ff;
  --purple:      #9333ea;
  --purple-light:#fdf4ff;
  --green:       #16a34a;
  --green-light: #dcfce7;
  --red:         #dc2626;
  --red-light:   #fee2e2;
  --amber:       #92400e;
  --amber-light: #fef3c7;
  --gray-900:    #171717;
  --gray-700:    #404040;
  --gray-500:    #737373;
  --gray-400:    #a3a3a3;
  --gray-300:    #d4d4d4;
  --gray-200:    #e5e5e5;
  --gray-100:    #f5f5f5;
  --gray-50:     #fafafa;
}

/* DM Sans, served from this app (static/wizard/fonts), not from Google: no
   visitor's address goes to a third party, and it loads with the page. One
   variable file per character set covers every weight. SIL Open Font
   License 1.1 (fonts/OFL.txt). */
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 100 1000;
  font-display: swap;
  src: url(fonts/dm-sans-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 100 1000;
  font-display: swap;
  src: url(fonts/dm-sans-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

* { box-sizing: border-box; }

body {
  font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: var(--gray-50);
  color: var(--gray-900);
  -webkit-font-smoothing: antialiased;
  margin: 0;
}

.hidden { display: none !important; }
.hidden-for-member { display: none !important; }

/* ── Logged-out screen ─────────────────────────────────────────────── */
#login-screen { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 1.5rem; }
#login-section { max-width: 380px; width: 100%; margin: 0; }
#login-section h2 { margin-top: 0; }
.login-brand, .sidebar-logo { display: flex; align-items: center; gap: 0.65rem; }
.login-brand { margin-bottom: 1.5rem; }

/* ── App shell: persistent sidebar + full-page content, ShipStudio-style ─ */
.app-shell { display: flex; min-height: 100vh; }

.sidebar {
  width: 15.5rem; flex-shrink: 0; background: #fff; border-right: 1px solid var(--gray-200);
  display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh;
}
.sidebar-logo { padding: 1.35rem 1.15rem; border-bottom: 1px solid var(--gray-100); }
.logo-mark { height: 2.15rem; width: auto; flex-shrink: 0; display: block; }
.logo-title { font-weight: 800; font-size: 0.98rem; color: var(--gray-900); line-height: 1.15; }
.logo-subtitle { font-size: 0.7rem; color: var(--gray-400); line-height: 1.2; margin-top: 0.1rem; }

.sidebar-nav { flex: 1; padding: 1rem 0.65rem; overflow-y: auto; }
.nav-section-label { padding: 0.4rem 0.7rem; font-size: 0.66rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--gray-400); }
.nav-item {
  display: flex; align-items: center; gap: 0.6rem; width: 100%;
  padding: 0.55rem 0.75rem; margin-bottom: 0.15rem; border-radius: 8px;
  font-family: inherit; font-size: 0.85rem; font-weight: 600; color: var(--gray-600);
  background: transparent; border: none; cursor: pointer; text-align: left;
  transition: background 0.12s ease, color 0.12s ease;
}
.nav-item:hover { background: var(--gray-100); color: var(--gray-900); }
.nav-item.active { background: var(--purple-light); color: var(--purple); }
.nav-item .nav-icon { width: 1.1rem; text-align: center; flex-shrink: 0; }

.sidebar-footer { padding: 0.9rem; border-top: 1px solid var(--gray-100); }
.sidebar-user { display: flex; align-items: center; gap: 0.55rem; margin-bottom: 0.65rem; }
.user-avatar {
  width: 1.85rem; height: 1.85rem; border-radius: 999px; flex-shrink: 0;
  background: linear-gradient(135deg, #2563eb, #9333ea); color: #fff; font-size: 0.72rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.user-email { font-size: 0.76rem; font-weight: 600; color: var(--gray-700); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

.main-content { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.content-header {
  background: linear-gradient(135deg, #1e40af 0%, #2563eb 45%, #9333ea 100%);
  padding: 1.75rem 2.5rem; color: #fff; flex-shrink: 0;
  display: flex; flex-direction: column; align-items: center; text-align: center;
}
.content-header h1 { margin: 0; font-size: 1.4rem; font-weight: 800; }
.content-header p { margin: 0.3rem 0 0; color: rgba(255,255,255,0.85); font-size: 0.85rem; }
.content-logo-strip { display: flex; justify-content: center; padding: 1.3rem 0 0.3rem; flex-shrink: 0; }
.logo-mark-banner { height: 3.4rem; filter: drop-shadow(0 3px 6px rgba(0,0,0,0.16)); }
.content-body { flex: 1; padding: 1.75rem 2.5rem 3rem; }

/* ── Cards / sections ────────────────────────────────────────────────── */
section.panel { background: #fff; border: 1px solid var(--gray-200); border-radius: 14px; padding: 1.5rem 1.75rem; margin-bottom: 1.5rem; }

.section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.25rem; }
.section-head h2 { margin: 0; font-size: 1.05rem; font-weight: 700; }
.section-head h3 { margin: 0; font-size: 0.92rem; font-weight: 700; }
.section-head-group { display: flex; align-items: center; gap: 0.6rem; }
.hint { color: var(--gray-500); font-size: 0.85rem; margin: 0.25rem 0 0.9rem; line-height: 1.5; }

/* ── Login card ──────────────────────────────────────────────────────── */
#login-section { max-width: 380px; margin: 4rem auto; }
#login-section h2 { margin-top: 0; }

/* ── Buttons ─────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
  padding: 0.6rem 1.25rem; font-weight: 600; font-size: 0.87rem; border-radius: 10px;
  transition: background 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
  cursor: pointer; border: none; font-family: inherit;
}
.btn:active { transform: scale(0.98); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }

.btn-primary { background: var(--blue); color: #fff; box-shadow: 0 2px 8px rgba(37,99,235,0.20); }
.btn-primary:hover:not(:disabled) { background: var(--blue-hover); box-shadow: 0 4px 16px rgba(37,99,235,0.30); }
.btn-success { background: var(--green); color: #fff; box-shadow: 0 2px 8px rgba(22,163,74,0.20); }
.btn-success:hover:not(:disabled) { background: #15803d; box-shadow: 0 4px 16px rgba(22,163,74,0.30); }
.btn-ghost { background: transparent; color: var(--gray-500); border: 1px solid var(--gray-300); }
.btn-ghost:hover:not(:disabled) { color: var(--gray-900); background: var(--gray-100); }
.btn-danger { background: transparent; color: var(--red); border: 1px solid #fecaca; }
.btn-danger:hover:not(:disabled) { background: var(--red-light); }
/* Solid variant -- deliberately separate from .btn-danger above (which stays
   ghost-style for Archive/Remove elsewhere) so this only affects buttons
   that opt in, e.g. Team's Deactivate. */
.btn-danger-solid { background: var(--red); color: #fff; }
.btn-danger-solid:hover:not(:disabled) { background: #b91c1c; }
.btn-sm { padding: 0.4rem 0.8rem; font-size: 0.78rem; border-radius: 8px; }

/* ── Form inputs ─────────────────────────────────────────────────────── */
label { display: block; margin-bottom: 0.9rem; font-size: 0.85rem; font-weight: 600; color: var(--gray-700); }

/* Plain `input` (not an attribute selector) so every field is caught
   regardless of whether the HTML wrote out type="text" explicitly -- an
   attribute selector like input[type=text] silently misses any <input>
   without that attribute, even though the browser treats it as text by
   default. That gap was why several fields (schema, table name, external
   key column, and others across the page) rendered as unstyled, inline
   native inputs instead of the same block-level rounded field as everything
   else, both losing the rounded-corner style and breaking left alignment
   with their labels (inline width varies with label text length; block
   width doesn't). Checkboxes/radios keep native styling on purpose. */
.input, input:not([type=checkbox]):not([type=radio]), select, textarea {
  display: block; width: 100%; margin-top: 0.35rem; padding: 0.6rem 0.8rem;
  background: #fff; border: 1px solid var(--gray-300); border-radius: 10px;
  font-family: inherit; font-size: 0.87rem; font-weight: 400; color: var(--gray-900);
  transition: border-color 0.15s ease, box-shadow 0.15s ease; outline: none;
  box-sizing: border-box;
}
.input:focus, input:focus, select:focus, textarea:focus { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(37,99,235,0.08); }
input:read-only { background: var(--gray-100); color: var(--gray-700); cursor: not-allowed; }
input:read-only:focus { border-color: var(--gray-300); box-shadow: none; }
textarea { font-family: 'SFMono-Regular', Consolas, monospace; font-size: 0.8rem; }
form { margin-top: 0.75rem; }
.field-hint { color: var(--gray-500); font-size: 0.78rem; margin: 0.3rem 0 0.9rem; line-height: 1.45; }

/* ── details/summary as a soft toggle ───────────────────────────────── */
details { border: 1px dashed var(--gray-300); border-radius: 10px; padding: 0.75rem 1rem; margin-top: 0.75rem; }
details[open] { border-style: solid; }
details summary { cursor: pointer; font-weight: 600; font-size: 0.85rem; color: var(--blue); }

/* ── Badges ──────────────────────────────────────────────────────────── */
.badge { display: inline-flex; align-items: center; padding: 0.2rem 0.6rem; border-radius: 999px; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.01em; white-space: nowrap; }
.badge-blue   { background: #dbeafe; color: #1e40af; }
.badge-purple { background: #fae8ff; color: #7e22ce; }
.badge-green  { background: var(--green-light); color: #15803d; }
.badge-red    { background: var(--red-light); color: #b91c1c; }
.badge-amber  { background: var(--amber-light); color: var(--amber); }
.badge-gray   { background: #f3f4f6; color: #374151; }

/* ── Warning / notice boxes ─────────────────────────────────────────── */
.warning { background: var(--amber-light); border: 1px solid #fcd34d; color: var(--amber); border-radius: 8px; padding: 0.6rem 0.8rem; margin: 0.5rem 0; font-size: 0.82rem; }
.notice { background: var(--blue-light); border: 1px solid #bfdbfe; color: #1e40af; border-radius: 8px; padding: 0.7rem 0.9rem; margin: 0.5rem 0 0.9rem; font-size: 0.83rem; line-height: 1.5; }
.success-box { background: var(--green-light); border: 1px solid #86efac; color: #15803d; border-radius: 8px; padding: 0.7rem 0.9rem; margin: 0.5rem 0; font-size: 0.85rem; }

/* ── Searchable pick list (target-db select, existing-table pick) ────── */
.pick-list { margin-top: 0.6rem; max-height: 22rem; overflow-y: auto; border: 1px solid var(--gray-200); border-radius: 10px; }
.pick-row {
  display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
  padding: 0.55rem 0.9rem; font-size: 0.83rem; cursor: pointer;
  border-bottom: 1px solid var(--gray-100); background: #fff; transition: background 0.1s ease;
}
.pick-row:last-child { border-bottom: none; }
.pick-row:hover { background: var(--blue-light); }
.pick-row.selected { background: var(--blue-light); color: var(--blue-hover); font-weight: 600; }
.pick-row.disabled { cursor: not-allowed; color: var(--gray-400); background: var(--gray-50); }
.pick-row.disabled:hover { background: var(--gray-50); }
.pick-row .label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pick-row .code { font-family: 'SFMono-Regular', Consolas, monospace; color: var(--gray-400); font-size: 0.75rem; flex-shrink: 0; }
.pick-empty { padding: 1rem; text-align: center; color: var(--gray-400); font-size: 0.83rem; }
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.75rem; margin-top: 0.75rem; }
/* Connection tiles sit side by side -- Details now opens in a modal (see
   openModal/buildConnectionDetailContent) instead of expanding the card
   inline, so every card just stays its normal tile size. */
#connections-grid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.connection-card { border: 1px solid var(--gray-200); border-radius: 12px; padding: 1rem 1.15rem; }
.connection-card .name { font-weight: 700; font-size: 0.95rem; }
.connection-card .meta { color: var(--gray-500); font-size: 0.78rem; margin-top: 0.15rem; }
.connection-card .row { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.85rem; }

/* ── Connection detail chips (org profile, used inside the popout) ───── */
/* Grid, not flex+space-between -- two max-content columns size themselves
   independently and reliably. Flex with justify-content:space-between
   doesn't compute intrinsic (max-content) width the same way across
   browsers, which was letting long values (instance URL, org ID) overrun
   the popout's own auto-sized width instead of the box growing to fit. */
.connection-detail { display: grid; grid-template-columns: max-content max-content; column-gap: 1.25rem; row-gap: 0.45rem; }
.connection-detail .detail-row { display: contents; }
.connection-detail .detail-row .k { color: var(--gray-400); font-size: 0.78rem; white-space: nowrap; }
.connection-detail .detail-row .v { color: var(--gray-900); font-weight: 600; font-size: 0.78rem; text-align: right; white-space: nowrap; justify-self: end; }
.connection-detail .detail-row .v.code { font-family: 'SFMono-Regular', Consolas, monospace; font-weight: 400; }

/* ── Panel 1: connection cards (browse/manage, no dropdown/active-select) ── */
.conn-details-btn { margin-top: 0.4rem; }
/* One shared "ⓘ" badge+popout system for every nuanced control across the
   wizard (direction arrows, read-only-reason badges, Initial load, picklist
   refresh interval, About Repair) instead of repeating a positioned popout
   per call site -- see wizard.js's INFO_TEXT/openInfoPopout. */
.info-badge { border: none; cursor: pointer; font-family: inherit; }
.info-badge:hover { filter: brightness(0.95); }

/* Icon-only info badges (no visible text) get their own real button
   treatment instead of the tiny text-badge pill every other info-badge
   uses -- a bare "ⓘ" Unicode glyph crammed into a 0.7rem pill rendered
   inconsistently (and small) across fonts/browsers. A proper circular
   button with an inline SVG "i" is crisp everywhere and reads as a real,
   clickable affordance rather than stray punctuation next to a label. */
.info-badge.icon-only {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none;
  width: 1.25rem; height: 1.25rem;
  padding: 0; border-radius: 50%;
  background: var(--blue-light); color: var(--blue);
}
.info-badge.icon-only:hover { background: var(--blue); color: #fff; filter: none; }
.info-badge.icon-only svg { width: 0.85rem; height: 0.85rem; display: block; }
.info-popout {
  position: fixed; z-index: 50;
  width: 22rem; max-width: 90vw;
  background: #fff; border: 1px solid var(--gray-200); border-radius: 12px; box-shadow: 0 12px 32px rgba(0,0,0,0.14);
  padding: 0.85rem 1rem;
}
.info-popout p { color: var(--gray-600); font-size: 0.82rem; line-height: 1.55; margin: 0; }

/* ── "How to ensure valid values" badge + tabbed popout (Sync objects and
   Field Rules pages) -- richer than the single-paragraph info-popout above
   so it gets its own singleton rather than overloading INFO_TEXT. No fixed
   height and no overflow on the popout or its panels: the box always sizes
   to whichever single tab panel is showing, so nothing in it ever scrolls. */
/* Purple pulled from .content-header's own gradient (var(--purple), its
   100% stop) -- vivid enough to read as a call to action, not just another
   muted badge-blue label. */
.rules-help-trigger { border: none; cursor: pointer; font-family: inherit; background: var(--purple); color: #fff; font-weight: 700; }
.rules-help-trigger:hover { filter: brightness(0.9); }
.rules-help-popout {
  position: fixed; z-index: 50;
  width: 30rem; max-width: 90vw;
  background: #fff; border: 1px solid var(--gray-200); border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.14);
  padding: 0.9rem 1rem 1.1rem;
}
.rules-help-close { position: absolute; top: 0.6rem; right: 0.6rem; width: 1.6rem; height: 1.6rem; font-size: 1rem; }
.rules-help-tabs { display: flex; margin: 0 1.7rem 0.8rem 0; border-bottom: 1px solid var(--gray-200); }
.rules-help-tab {
  font-family: inherit; font-size: 0.78rem; font-weight: 600; color: var(--gray-500);
  background: none; border: none; border-bottom: 2px solid transparent;
  padding: 0.4rem 0.1rem; margin-right: 1rem; cursor: pointer;
}
.rules-help-tab:hover { color: var(--gray-900); }
.rules-help-tab.active { color: var(--blue-hover); border-bottom-color: var(--blue-hover); }
.rules-help-panel { display: none; }
.rules-help-panel.active { display: block; }
.rules-help-panel p { margin: 0 0 0.6rem; font-size: 0.81rem; line-height: 1.5; color: var(--gray-600); }
.rules-help-panel p:last-child { margin-bottom: 0; }
.rules-help-panel ul { margin: 0 0 0.6rem; padding-left: 1.1rem; font-size: 0.8rem; line-height: 1.5; color: var(--gray-600); }
.rules-help-panel li + li { margin-top: 0.15rem; }
.rules-help-panel code { font-size: 0.74rem; }
.rules-help-panel pre {
  margin: 0 0 0.6rem; padding: 0.6rem 0.7rem; font-size: 0.72rem; line-height: 1.45;
  white-space: pre-wrap; word-break: break-word;
}

/* ── Page-level tabs (Activity's "Needs attention" / "Recent sync history")
   -- same underline-tab idea as .rules-help-tab above, sized for switching a
   whole panel section rather than a small popout. ────────────────────────── */
.page-tabs { display: flex; gap: 1.5rem; margin: 1.1rem 0 1.1rem; border-bottom: 1px solid var(--gray-200); }
.page-tab {
  font-family: inherit; font-size: 0.87rem; font-weight: 600; color: var(--gray-500);
  background: none; border: none; border-bottom: 2px solid transparent;
  padding: 0 0 0.65rem; cursor: pointer;
}
.page-tab:hover { color: var(--gray-900); }
.page-tab.active { color: var(--blue-hover); border-bottom-color: var(--blue-hover); }
.page-tab-panel { display: none; }
.page-tab-panel.active { display: block; }
.connection-card h4 {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--gray-500); font-weight: 700; margin: 0 0 0.5rem;
  display: flex; align-items: baseline; gap: 0.5rem;
}
.connection-edit-form, .target-db-edit-form { margin-top: 0.6rem; padding-top: 0.6rem; border-top: 1px solid var(--gray-200); }

/* Two visually independent boxes, not a flowing list under one header --
   the Salesforce side is org-level (shared across every sync-target on
   that org) and the Postgres side is exclusive to this one sync-target;
   that asymmetry is exactly what read as confusing before, so the boundary
   between them needs to be obvious, not just an h4 label. */
.detail-subpanel {
  border: 1px solid var(--gray-200); border-radius: 10px; background: var(--gray-50);
  padding: 0.85rem 1rem;
}
.detail-subpanel + .detail-subpanel { margin-top: 0.65rem; }
.detail-subpanel .connection-edit-form, .detail-subpanel .target-db-edit-form { border-top-color: var(--gray-300); }
.subpanel-tag {
  text-transform: none; letter-spacing: normal; font-weight: 500;
  color: var(--gray-400); font-size: 0.68rem;
}

/* Add Connection flow: three narrow panels, left to right, each revealed
   only once the previous one is resolved -- a wide flowing form/column was
   genuinely hard to read. ~1/5-1/4 of a typical page width per panel;
   overflow-x lets it scroll rather than crush on narrow viewports instead
   of wrapping panels onto a second row (which would defeat the point). */
.setup-panels-row {
  display: flex; align-items: flex-start; gap: 1.25rem;
  overflow-x: auto; padding-bottom: 0.25rem;
}
.setup-panel {
  flex: 1 1 240px; min-width: 220px; max-width: 300px;
  border: 1px solid var(--gray-200); border-radius: 12px; background: var(--gray-50);
  padding: 1rem 1.15rem;
}
.setup-panel-title {
  font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--purple); font-weight: 700; margin: 0 0 0.75rem;
}
.panel-block { margin-top: 0.85rem; }
.panel-block:first-child { margin-top: 0; }

/* ---- Provision Database: a genuinely sequential interview, not a dashboard --
   one .provision-step shown at a time, unlike every other page's single-panel
   layout. ---- */
.provision-steps-bar { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.9rem 0 1.3rem; }
.provision-step-dot {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.01em;
  padding: 0.3rem 0.75rem; border-radius: 999px;
  background: var(--gray-100); color: var(--gray-500);
}
.provision-step-dot.active { background: var(--purple-light); color: var(--purple); }
.provision-step-dot.done { background: var(--green-light); color: #15803d; }
/* Grid, not flex: a grid row stretches every cell to the row's tallest
   child by default (align-items defaults to stretch), which is exactly
   "same dimensions" for these two panels -- flex's flex-start left them
   free to size to their own content independently, which is what produced
   the mismatch. The explain column is 1fr (not a fixed max-width) so it
   widens to fill whatever room is available instead of staying narrow and
   wrapping its longer explanations into extra height. */
.provision-step-row { display: grid; grid-template-columns: minmax(300px, 440px) minmax(400px, 1fr); gap: 1.5rem; max-width: 1280px; }
@media (max-width: 980px) { .provision-step-row { grid-template-columns: 1fr; } }
.provision-step {
  border: 1px solid var(--gray-200); border-radius: 12px;
  background: var(--gray-50); padding: 1rem 1.2rem;
}
.provision-step label { display: block; margin-top: 0.6rem; font-size: 0.82rem; color: var(--gray-700); }
.provision-step label:first-child { margin-top: 0; }
.provision-step label input, .provision-step label select { margin-top: 0.25rem; }

/* ---- Provision Database: the right-hand "why" panel next to each step --
   wider than the left panel is tall on purpose: more horizontal room means
   each explanation wraps into fewer lines, which is what actually keeps
   its height in check -- a narrower column with the same text just pushes
   the height problem down the page instead of solving it. ---- */
.provision-explain {
  border: 1px solid var(--gray-200); border-radius: 12px;
  background: #fff; padding: 0.9rem 1.15rem;
}
.provision-explain h4 {
  margin: 0 0 0.7rem; font-size: 0.74rem; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--purple); font-weight: 700;
}
.provision-explain dl { margin: 0; }
.provision-explain dt { font-size: 0.82rem; font-weight: 700; color: var(--gray-900); margin-top: 0.65rem; }
.provision-explain dt:first-child { margin-top: 0; }
.provision-explain dd { margin: 0.2rem 0 0; font-size: 0.8rem; line-height: 1.45; color: var(--gray-500); }
.provision-explain code {
  font-family: 'SFMono-Regular', Consolas, monospace; font-size: 0.76rem;
  background: var(--gray-100); padding: 0.05rem 0.3rem; border-radius: 4px; color: var(--gray-700);
}
.provision-summary { display: flex; flex-direction: column; gap: 0.4rem; margin-top: 0.6rem; }
.provision-summary .row {
  display: flex; justify-content: space-between; gap: 1rem;
  font-size: 0.82rem; padding: 0.4rem 0.7rem; border-radius: 8px; background: var(--gray-50);
  border: 1px solid var(--gray-200);
}
.provision-summary .row .k { color: var(--gray-500); font-weight: 600; }
.provision-summary .row .v { font-family: 'SFMono-Regular', Consolas, monospace; font-size: 0.78rem; }

.endpoint-bar {
  display: flex; align-items: center; gap: 0.85rem;
  padding: 0.85rem 1.1rem; border: 1px solid var(--gray-200); border-radius: 12px; background: var(--gray-50);
}
.endpoint-bar + .endpoint-bar { margin-top: 0.6rem; }
.endpoint-bar .endpoint-icon { font-size: 1.4rem; flex-shrink: 0; }
.endpoint-bar .endpoint-info { flex: 1; min-width: 0; }
.endpoint-bar .endpoint-name { font-weight: 700; font-size: 0.9rem; }
.endpoint-bar .endpoint-meta { color: var(--gray-500); font-size: 0.78rem; margin-top: 0.1rem; }

/* ── Split pane: object multi-select (left) + target config (right) ──── */
.split-pane { display: flex; gap: 1.75rem; align-items: flex-start; }
.split-col { min-width: 0; }
.split-col-object { flex: 2 1 700px; }
.split-col-target { flex: 1 1 420px; }
#target-placeholder { padding: 2.5rem 1rem; text-align: center; }

.dual-pane { display: flex; gap: 0.75rem; }
.dual-pane .pane { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.dual-pane .pane-head { display: flex; align-items: center; justify-content: space-between; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; color: var(--gray-500); margin-bottom: 0.4rem; }
.dual-pane .pane-count { color: var(--gray-400); font-weight: 600; text-transform: none; letter-spacing: 0; }
.dual-pane .pane-list {
  /* flex:1 alone leaves the default min-height:auto on a flex child, which
     lets it grow to fit ALL its content (every Salesforce object) instead of
     respecting height/overflow -- min-height:0 is what actually makes the
     20rem cap + scrollbar take effect rather than the whole page growing. */
  flex: 1 1 20rem; min-height: 0; max-height: 20rem; overflow-y: auto;
  border: 1px solid var(--gray-200); border-radius: 10px; background: #fff;
}
.dual-pane .obj-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.75rem; font-size: 0.8rem; border-bottom: 1px solid var(--gray-100); cursor: pointer; }
.dual-pane .obj-row:last-child { border-bottom: none; }
.dual-pane .obj-row:hover { background: var(--blue-light); }
.dual-pane .obj-row.focused { background: var(--purple-light); color: #7e22ce; font-weight: 600; }
.dual-pane .obj-row .oname { flex: 1; min-width: 0; overflow-wrap: break-word; }
.dual-pane .obj-row .ocode { color: var(--gray-400); font-size: 0.72rem; flex-shrink: 0; overflow-wrap: break-word; max-width: 45%; text-align: right; }
.dual-pane .obj-row .move-x { color: var(--red); font-weight: 700; flex-shrink: 0; }
.dual-pane .obj-row .move-plus { color: var(--blue); font-weight: 700; flex-shrink: 0; }

.mode-select-row { display: flex; align-items: center; gap: 0.75rem; }
.mode-select-row select { margin-top: 0; }

/* ── Wizard nav ─────────────────────────────────────────────────────── */
.wizard-nav { display: flex; align-items: center; justify-content: flex-end; gap: 0.6rem; margin-top: 1.25rem; padding-top: 1.1rem; border-top: 1px solid var(--gray-100); }

/* ── Preview / activate output ───────────────────────────────────────── */
pre { background: var(--gray-900); color: #e5e5e5; padding: 0.85rem 1rem; border-radius: 10px; overflow-x: auto; font-size: 0.78rem; line-height: 1.5; }

/* ── Simple table (super-admin tenant list) ───────────────────────────── */
table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
th, td { text-align: left; padding: 0.55rem 0.5rem; border-bottom: 1px solid var(--gray-100); }
th { color: var(--gray-500); font-weight: 700; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.02em; }

/* ── Activity page (both tabs): a dense log, not a data-entry form -- smaller
   text and tighter rows than the app's default table sizing. ────────────── */
#activity-content table { font-size: 0.78rem; }
#activity-content th, #activity-content td { padding: 0.32rem 0.5rem; }
#activity-content th { font-size: 0.66rem; }

/* ── "Needs attention" (outbox-failed-table): fixed layout so the narrow,
   fixed-format columns (Salesforce Id is always 18 chars) sit tight against
   their neighbors instead of being stretched by auto layout. Last error is
   the only column left without an explicit width, so it's the one that
   grows to absorb whatever space the others don't need. Column widths in a
   fixed-layout table come from the header row, so Salesforce Id's width has
   to live on the <th> even though only the <td> gets the monospace font --
   the overflow/ellipsis on the <td> is just a safety net in case a specific
   font ever renders wider than expected, so it can never bleed into
   Attempts next to it again. ──────────────────────────────────────────── */
#outbox-failed-table { table-layout: fixed; }
#outbox-failed-table th:nth-child(1), #outbox-failed-table td:nth-child(1) { width: 7.5rem; }
#outbox-failed-table th:nth-child(2), #outbox-failed-table td:nth-child(2) { width: 5rem; }
#outbox-failed-table th:nth-child(3), #outbox-failed-table td:nth-child(3) { width: 9.5rem; }
#outbox-failed-table td:nth-child(3) {
  font-family: 'SFMono-Regular', Consolas, monospace; font-size: 0.72rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#outbox-failed-table th:nth-child(4), #outbox-failed-table td:nth-child(4) { width: 4.5rem; text-align: center; }
#outbox-failed-table th:nth-child(6), #outbox-failed-table td:nth-child(6) { width: 10.5rem; }
#outbox-failed-table td:nth-child(6) { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#outbox-failed-table th:nth-child(7), #outbox-failed-table td:nth-child(7) { width: 4.5rem; }

/* ── "Recent sync history" (audit-log-table): same fixed-layout idea as
   outbox-failed-table above -- Direction/Status are fixed-format, short
   content, so they get just enough width to sit tight against each other
   without overlapping; Detail is the only column left unsized, so it's the
   one that grows to fill whatever the others don't need. ────────────────── */
#audit-log-table { table-layout: fixed; }
#audit-log-table th:nth-child(1), #audit-log-table td:nth-child(1) { width: 7rem; }
#audit-log-table th:nth-child(2), #audit-log-table td:nth-child(2) { width: 9.5rem; }
#audit-log-table td:nth-child(2) {
  font-family: 'SFMono-Regular', Consolas, monospace; font-size: 0.72rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#audit-log-table th:nth-child(3), #audit-log-table td:nth-child(3) { width: 5rem; }
#audit-log-table th:nth-child(4), #audit-log-table td:nth-child(4) { width: 10.5rem; }
#audit-log-table td:nth-child(4) { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#audit-log-table th:nth-child(5), #audit-log-table td:nth-child(5) { width: 5rem; }
#audit-log-table th:nth-child(7), #audit-log-table td:nth-child(7) { width: 10.5rem; }
#audit-log-table td:nth-child(7) { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#outbox-failed-table .btn-sm { padding: 0.22rem 0.5rem; font-size: 0.68rem; border-radius: 6px; }

/* ── Panel 4: "Tables in sync" -- Stacksync-style collapsible rows ────── */
.sync-row { border: 1px solid var(--gray-200); border-radius: 12px; margin-bottom: 0.75rem; overflow: hidden; background: #fff; }
.sync-row.draft { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(37,99,235,0.08); }
.sync-row-head { display: flex; align-items: center; gap: 0.75rem; padding: 0.4rem; cursor: pointer; }
.sync-row-head .obj-box, .sync-row-head .tbl-box {
  flex: 1; min-width: 0; padding: 0.65rem 0.9rem; border-radius: 8px; background: var(--gray-100);
  font-size: 0.85rem; font-weight: 600; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sync-row-actions { display: flex; align-items: center; gap: 0.35rem; flex-shrink: 0; padding-right: 0.5rem; }
.draft-select-cb { flex-shrink: 0; width: 1.05rem; height: 1.05rem; margin-left: 0.4rem; cursor: pointer; }
.draft-pending-badge { margin-left: 0.5rem; }

.batch-activate-bar {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: 0.6rem 0.9rem; margin-bottom: 0.75rem;
  background: var(--blue-light); border: 1px solid #bfdbfe; border-radius: 10px;
  font-size: 0.83rem; color: #1e40af;
}
.batch-activate-bar .batch-select-all { display: flex; align-items: center; gap: 0.45rem; font-weight: 600; cursor: pointer; }
.batch-activate-bar .batch-select-all input { cursor: pointer; }
.sync-row-toggle { display: flex; align-items: center; gap: 0.4rem; padding: 0.75rem 1rem; font-size: 0.78rem; color: var(--gray-500); cursor: pointer; border-top: 1px solid var(--gray-100); }
.sync-row-toggle:hover { color: var(--gray-900); background: var(--gray-50); }
/* A CSS-drawn triangle, not the Unicode &#9662; glyph -- a font glyph's own
   metrics vary by font/OS/browser and can render visibly off-baseline next
   to real text no matter how align-items/line-height are tuned. Borders
   give a fixed, symmetric 8x5px box that centers exactly like any other
   flex item, with nothing left to font rendering. */
.sync-row-toggle .chev {
  display: inline-block; flex-shrink: 0; width: 0; height: 0;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform 0.15s ease;
}
.sync-row-toggle.open .chev { transform: rotate(180deg); }
.field-rules-object-toggle .obj-name { font-weight: 700; font-size: 0.95rem; color: var(--gray-900); }
/* .hint's base rule (line 95) carries paragraph-style vertical margins and
   line-height:1.5, meant for standalone block text elsewhere -- reset both
   here so its flex item centers on the same line as .chev/.obj-name instead
   of sitting ~5px off per those margins. */
.field-rules-object-toggle .hint { margin: 0 0 0 0.15rem; line-height: 1; }
.sync-row-body { display: none; padding: 1rem 1.1rem 1.2rem; border-top: 1px solid var(--gray-100); }
.sync-row-body.open { display: block; }

.field-rules-table td { vertical-align: top; }
.field-rules-table td:first-child { font-weight: 600; white-space: nowrap; }
/* "Record Type reference" is the longest label READ_ONLY_REASON_BADGE
   produces -- sized down so its pill stays single-line at roughly the same
   width as the column's other badges instead of standing out oversized. */
.field-rules-table .badge[data-info="record_type_reference"] { font-size: 0.64rem; }
/* Full value breakdown -- only ever rendered inside the click-to-view popout
   modal (see showFieldRuleValuesPopout), never inline in a table cell. */
.field-rules-list { margin: 0.2rem 0 0; padding-left: 1.3rem; font-size: 0.82rem; color: var(--gray-600); }
.field-rules-list li { margin-bottom: 0.2rem; }

.org-type-toggle { display: inline-flex; border: 1px solid var(--gray-300); border-radius: 8px; overflow: hidden; margin-top: 0.35rem; }
.org-type-toggle button {
  padding: 0.5rem 1rem; border: none; background: #fff; color: var(--gray-600); cursor: pointer;
  font-family: inherit; font-size: 0.82rem; font-weight: 500; border-right: 1px solid var(--gray-200);
}
.org-type-toggle button:last-child { border-right: none; }
.org-type-toggle button.active { background: var(--blue); color: #fff; }
.org-type-toggle button:hover:not(.active) { background: var(--gray-100); }

.dir-control { display: inline-flex; align-items: center; border: 1px solid var(--gray-300); border-radius: 8px; overflow: hidden; flex-shrink: 0; }
.dir-control button {
  width: 1.9rem; height: 1.9rem; display: flex; align-items: center; justify-content: center;
  border: none; background: #fff; color: var(--gray-400); cursor: pointer; font-size: 0.85rem;
  border-right: 1px solid var(--gray-200);
}
.dir-control button:last-child { border-right: none; }
.dir-control button.active { background: var(--purple); color: #fff; }
.dir-control button:disabled { cursor: not-allowed; opacity: 0.3; }
.dir-control button:hover:not(:disabled):not(.active) { background: var(--gray-100); color: var(--gray-700); }

.field-map-table { border: 1px solid var(--gray-200); border-radius: 10px; overflow: hidden; margin-top: 0.75rem; }
/* Same grid-template-columns as .field-map-row below it, purely so the
   search box's cell is genuinely the Salesforce-side column's width --
   the box itself is then sized as a fraction of that cell, not the row. */
/* 4 grid children (sf-search, spacer, spacer, pg-search) auto-place into
   columns 1 and 4 of the same template as .field-map-row below -- so each
   box lines up under its own side without needing to hardcode which column
   is which. */
.field-search-row { display: grid; grid-template-columns: 1fr 9rem auto 1fr 9rem; gap: 0.6rem; margin-bottom: 0.5rem; }
.field-search-box { width: 25%; margin-top: 0; }

.field-map-row { display: grid; grid-template-columns: 1fr 9rem auto 1fr 9rem; align-items: center; gap: 0.6rem; padding: 0.5rem 0.9rem; font-size: 0.82rem; border-bottom: 1px solid var(--gray-100); background: #fff; }
.field-map-row:last-child { border-bottom: none; }
.field-map-row .fname { font-weight: 600; display: flex; align-items: center; gap: 0.4rem; min-width: 0; }
.field-map-row .fname span.n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.field-map-row .col-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.field-map-row select.col-select { margin-top: 0; padding: 0.35rem 0.5rem; font-size: 0.78rem; }
.field-map-row input.col-name-input { margin-top: 0; padding: 0.35rem 0.5rem; font-size: 0.78rem; }
.type-badge {
  display: inline-flex; align-items: center; font-family: 'SFMono-Regular', Consolas, monospace;
  font-size: 0.7rem; color: var(--gray-500); background: var(--gray-100); border-radius: 4px;
  padding: 0.15rem 0.4rem; white-space: nowrap;
}

.field-map-pagination { display: flex; align-items: center; justify-content: center; gap: 1rem; margin-top: 0.75rem; font-size: 0.8rem; color: var(--gray-500); }
.field-map-pagination a { color: var(--blue); cursor: pointer; font-weight: 600; }
.field-map-pagination a.disabled { color: var(--gray-300); cursor: not-allowed; pointer-events: none; }

.draft-actions { display: flex; align-items: center; justify-content: flex-end; gap: 0.6rem; margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--gray-100); }

/* ── Toasts (replaces native alert() for in-app messaging) ───────────── */
#toast-container {
  position: fixed; top: 1.25rem; right: 1.25rem; z-index: 10000;
  display: flex; flex-direction: column; gap: 0.6rem; max-width: 24rem; width: calc(100% - 2.5rem);
}
.toast {
  background: #fff; border: 1px solid var(--gray-200); border-left: 4px solid var(--gray-300);
  border-radius: 12px; box-shadow: 0 12px 32px rgba(0,0,0,0.16);
  padding: 0.85rem 1rem; font-size: 0.85rem; color: var(--gray-900);
  display: flex; flex-direction: column; gap: 0.5rem;
  animation: toast-in 0.2s ease;
}
.toast-error   { border-left-color: var(--red); }
.toast-success { border-left-color: var(--green); }
.toast-info    { border-left-color: var(--blue); }
.toast-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.6rem; }
.toast-row .msg { white-space: pre-line; line-height: 1.45; }
.toast-close { cursor: pointer; color: var(--gray-400); background: none; border: none; font-size: 1.1rem; line-height: 1; padding: 0; flex-shrink: 0; }
.toast-close:hover { color: var(--gray-900); }
.toast-copy-row { display: flex; gap: 0.4rem; }
.toast-copy-row input { font-size: 0.72rem; font-family: 'SFMono-Regular', Consolas, monospace; margin-top: 0; }
@keyframes toast-in { from { opacity: 0; transform: translateX(1rem); } to { opacity: 1; transform: translateX(0); } }

/* ── Modal: centered popup instead of content expanding inline and pushing
   the rest of the page out of view. z-index sits below the toast layer so a
   success/error toast fired from within a modal action still reads clearly
   on top of it. ─────────────────────────────────────────────────────── */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(15, 23, 42, 0.5);
  display: flex; align-items: center; justify-content: center;
  z-index: 5000; padding: 1.5rem;
  animation: modal-fade-in 0.15s ease;
}
.modal-box {
  background: #fff; border-radius: 14px; width: 100%; max-width: 560px;
  max-height: 94vh; overflow-y: auto; padding: 1.75rem;
  position: relative; box-shadow: 0 24px 60px rgba(0, 0, 0, 0.28);
  animation: modal-pop-in 0.18s ease;
}
.modal-close {
  position: absolute; top: 0.9rem; right: 0.9rem; width: 1.9rem; height: 1.9rem;
  display: flex; align-items: center; justify-content: center;
  background: var(--gray-100); border: none; border-radius: 999px;
  font-size: 1.2rem; line-height: 1; cursor: pointer; color: var(--gray-500);
}
.modal-close:hover { background: var(--gray-200); color: var(--gray-900); }
.modal-title { margin: 0 1.75rem 1rem 0; font-size: 1.05rem; font-weight: 700; }
.modal-box.modal-wide { max-width: 780px; }
@keyframes modal-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-pop-in { from { opacity: 0; transform: translateY(0.5rem) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }

/* ── Automation-impact scan (validation rules / triggers / flows / etc.),
   shown in a wide modal from the object setup screen and the active-configs
   list's refresh button ─────────────────────────────────────────────── */
.automation-category { margin-top: 1.1rem; }
.automation-category:first-of-type { margin-top: 1.25rem; }
.automation-category h4 {
  margin: 0 0 0.5rem; font-size: 0.85rem; font-weight: 700; color: var(--gray-700);
  display: flex; align-items: center; gap: 0.5rem;
}
.automation-empty { margin: 0; font-size: 0.85rem; color: var(--gray-500); }
.automation-empty.automation-warning { color: var(--amber-600, #b45309); }
.automation-item {
  padding: 0.55rem 0.7rem; border: 1px solid var(--gray-200); border-radius: 8px;
  margin-bottom: 0.4rem; background: var(--gray-50);
}
.automation-item-head { display: flex; align-items: center; gap: 0.5rem; }
.automation-item-name { font-size: 0.85rem; font-weight: 600; color: var(--gray-900); }
.automation-item-summary { margin: 0.25rem 0 0; font-size: 0.8rem; color: var(--gray-600); }

/* ── Danger zone (destructive/archive actions), inside a modal ───────── */
.danger-zone {
  margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--gray-200);
}
.danger-zone p.field-hint { margin: 0 0 0.5rem; }

/* ── Sync Maps: org -> connection -> table topology diagram ─────────── */
/* Deliberately no overflow-x/-y here: CSS forces overflow-y to 'auto' the
   moment overflow-x is anything but 'visible' (they can't be split visible/
   scroll on one axis each), which was silently clipping every hover panel
   taller than the canvas. The org-chart already wraps horizontally via
   flex-wrap, so a horizontal scrollbar was never load-bearing -- showing
   hover content in full matters more here. */
#sync-map-canvas { padding-bottom: 0.5rem; }
.sync-map-logo { width: 1rem; height: 1rem; flex: none; vertical-align: -0.15em; margin-right: 0.15rem; }
.modal-title .sync-map-logo { width: 1.1rem; height: 1.1rem; }
.sync-map-org-header {
  width: fit-content; margin: 0 auto 1.5rem;
  border: 1px solid var(--gray-300); border-radius: 10px; background: #fff;
  padding: 0.6rem 1rem;
}
.sync-map-org-header-row1 { display: flex; align-items: center; gap: 0.5rem; font-weight: 700; font-size: 0.95rem; }
.sync-map-org-domain { font-weight: 400; font-size: 0.78rem; color: var(--gray-500); }
.sync-map-org-header-row2 { font-size: 0.78rem; color: var(--gray-500); margin-top: 0.25rem; }
.sync-map-org-header-row2 strong { color: var(--gray-700); }
.sync-map-connections {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start; gap: 1.25rem;
  border: 1px dashed var(--gray-300); border-radius: 12px; background: var(--gray-50);
  padding: 1.25rem;
}
.sync-map-connections-empty { color: var(--gray-500); font-size: 0.85rem; }
.sync-map-connection {
  border: 1px solid var(--gray-200); border-radius: 12px; background: #fff;
  padding: 0.85rem 1rem; min-width: 260px; max-width: 100%;
}
.sync-map-connection-head { display: flex; align-items: center; gap: 0.4rem; font-weight: 700; font-size: 0.88rem; }
/* No max-width above (was 380px) and nowrap here (no wrap, no scroll) --
   together these let the card grow to fit its own widest field (usually
   this host line) instead of clipping a long hostname behind a horizontal
   scrollbar. min-width keeps a short card from looking cramped; there is
   no upper cap beyond the flex container's own available width, so an
   unusually long hostname just makes that one card wider (and, via
   flex-wrap, pushes later cards to their own row) rather than scrolling. */
.sync-map-connection-host {
  font-size: 0.78rem; color: var(--gray-500); margin: 0.2rem 0;
  white-space: nowrap;
}
.sync-map-connection-host strong, .sync-map-connection-target strong { color: var(--gray-700); }
.sync-map-connection-target { font-size: 0.78rem; color: var(--gray-500); margin: 0.2rem 0 0.4rem; }
.sync-map-connection-error { font-size: 0.78rem; color: var(--red); margin: 0.2rem 0 0; }
.sync-map-status-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; display: inline-block; flex: none; }
.sync-map-status-dot.active { background: var(--green); }
/* Deliberately not var(--amber)/var(--red) here -- those are tuned for
   text-on-light-background badges, not a bare color-only dot with nothing
   else to tell them apart at a glance; --amber (#92400e) in particular
   reads as a dark brown, too close to red at this tiny size. Bright,
   unambiguous yellow/red instead. */
.sync-map-status-dot.pending { background: #facc15; }
.sync-map-status-dot.failed { background: #ef4444; }
.sync-map-status-dot.inactive { background: var(--gray-400); }
.sync-map-detail-table { width: 100%; border-collapse: collapse; margin-top: 0.75rem; }
.sync-map-detail-table th, .sync-map-detail-table td { text-align: left; padding: 0.4rem 0.5rem; border-bottom: 1px solid var(--gray-200); font-size: 0.83rem; }
.sync-map-view-all-btn { display: block; margin-top: 0.5rem; width: 100%; }
.sync-map-viewall-actions { display: flex; align-items: center; justify-content: flex-end; gap: 1rem; margin-top: 1.1rem; }
.sync-map-table-pagination { display: flex; align-items: center; gap: 0.6rem; margin-right: auto; }
.sync-map-table-pagination .hint { margin: 0; font-size: 0.72rem; white-space: nowrap; }

/* Plain, always-visible status-color key -- nothing on this page is
   hover-only anymore (every node's own detail is already shown inline, see
   buildConnectionNode), so this is a reference legend, not something to
   reveal. */
.sync-map-legend { display: flex; flex-wrap: wrap; gap: 1rem; margin: 0 0 1rem; font-size: 0.82rem; color: var(--gray-700); }
.sync-map-legend-row { display: inline-flex; align-items: center; gap: 0.4rem; }
