/* Intable — app shell layout (only what Spectrum CSS doesn't ship).
 * Sizing, typography, color, modal & raw-px rules: see docs/ui.md
 * (§ Sizing & Typography Standards).
 *
 * File map:
 *   § 1  Dynamic property bridges  (CSS-var → property bindings)
 *   § 2  Reset & theme base
 *   § 3  Shared primitives         (subdued text, stack, row, scroll-list)
 *   § 4  App shell                 (navbar, main, sidebar, content)
 *   § 5  Grid                      (page header, table, cells, pinned, group, pager)
 *   § 6  Views                     (chart, kanban, calendar)
 *   § 7  Dialogs & forms           (modal helpers, fields, switches, prompt)
 *   § 8  Module specifics          (settings, column dialog, conditional, manager,
 *                                  schema map, ERD, filter, tags, pipeline, action progress)
 *   § 9  Utilities
 */

/* ===== § 1  Dynamic property bridges =====
 * Pure data-driven values (a column's resized width, a progress %, a tag's
 * hex colour, etc.) MUST pass through CSS custom properties. The element
 * carries `style="--name:value"`; the actual CSS property binding lives
 * here so app.css owns "which property" and the template only owns "what
 * value". No raw `width:`, `background:`, etc. should appear in HTML. */
.spectrum-ProgressBar-fill { inline-size: var(--fill, 0%); }
.chart-bar-fill            { inline-size: var(--fill, 0%); }
.sidebar-tag-dot,
.tag-swatch                { background: var(--tag-color, var(--spectrum-gray-400)); }
.cond-preview {
  background:  var(--cond-bg,   var(--spectrum-negative-color-900));
  color:       var(--cond-fg,   var(--spectrum-white));
  font-weight: var(--cond-bold, var(--spectrum-medium-font-weight));
}
.spectrum-Table-cell[style*="--col-w"],
.spectrum-Table-headCell[style*="--col-w"] { inline-size: var(--col-w); }
.spectrum-Table-cell {
  background-color: var(--cell-bg,   transparent);
  color:            var(--cell-fg,   inherit);
  font-weight:      var(--cell-bold, inherit);
  user-select:      none;
}
/* Re-enable text selection inside active editors so users can edit
 * cell content normally. The grid copies via the TSV pipeline, not the
 * browser's native text selection. */
.spectrum-Table-cell input,
.spectrum-Table-cell textarea,
.spectrum-Table-cell [contenteditable="true"] { user-select: text; }
.grid-tag {
  --mod-tag-background-color: var(--tag-bg, var(--spectrum-tag-background-color));
  --mod-tag-content-color:    var(--tag-fg, var(--spectrum-tag-content-color));
  --mod-tag-border-color:     transparent;
}
/* Relation cell — clickable chip; uses Spectrum Link tokens so the colour
 * tracks the theme without bespoke palette work. */
.grid-relation-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--spectrum-spacing-75);
  padding: 2px 6px;
  margin-inline-end: var(--spectrum-spacing-75);
  background: transparent;
  border: 1px solid var(--spectrum-gray-300);
  border-radius: var(--spectrum-corner-radius-100);
  cursor: pointer;
  color: var(--spectrum-accent-content-color-default);
  text-decoration: none;
  font: inherit;
  line-height: 1;
}
.grid-relation-chip:hover {
  background: var(--spectrum-gray-100);
  border-color: var(--spectrum-accent-color-900);
}
.grid-relation-chip-icon { flex: none; }
.grid-relation-chip-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 220px; }
/* Relation value when the row id couldn't be resolved (target row missing
 * from cache, e.g. dangling reference). Plain text, no affordance. */
.grid-relation-plain { color: var(--spectrum-neutral-content-color-default); opacity: 0.7; }
/* Relation hover preview — floating Spectrum-styled mini-table, populated
 * from the in-memory target cache (no network on hover). */
.grid-relation-preview {
  position: fixed;
  z-index: 1000;
  max-width: 360px;
  max-height: 360px;
  overflow: auto;
  background: var(--spectrum-background-layer-2-color);
  border: var(--spectrum-border-width-100) solid var(--spectrum-gray-300);
  border-radius: var(--spectrum-corner-radius-100);
  box-shadow: var(--spectrum-drop-shadow-color) 0 4px 12px;
  padding: var(--spectrum-spacing-100);
  pointer-events: none;
  opacity: 0;
  transition: opacity 80ms;
}
.grid-relation-preview.is-visible { opacity: 1; }
.grid-relation-preview .spectrum-Table { width: 100%; }
.grid-relation-preview th {
  text-align: start;
  color: var(--spectrum-neutral-content-color-default);
  opacity: 0.7;
  font-weight: var(--spectrum-bold-font-weight);
  white-space: nowrap;
  padding-inline-end: var(--spectrum-spacing-200);
  vertical-align: top;
}
.grid-relation-preview td {
  word-break: break-word;
  padding-block: var(--spectrum-spacing-50);
}
/* Row-form multiselect picker — chip toggles share .grid-tag tokens but
 * stay muted until clicked. Active state lights up via --tag-bg. */
.it-multiselect {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spectrum-spacing-75);
}
.it-chip-toggle {
  --mod-tag-background-color: transparent;
  --mod-tag-content-color:    var(--spectrum-neutral-content-color-default);
  --mod-tag-border-color:     var(--spectrum-gray-300);
  cursor: pointer;
  opacity: 0.75;
}
.it-chip-toggle.is-on {
  --mod-tag-background-color: var(--tag-bg, var(--spectrum-tag-background-color-selected));
  --mod-tag-content-color:    var(--tag-fg, var(--spectrum-white));
  --mod-tag-border-color:     transparent;
  opacity: 1;
}

/* ===== § 2  Reset & theme base ===== */
html, body { block-size: 100%; margin: 0; padding: 0; overflow: hidden; }

html.spectrum body {
  display: flex;
  flex-direction: column;
  background: var(--spectrum-background-base-color);
  color: var(--spectrum-neutral-content-color-default);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ===== § 3  Shared primitives =====
 * Recurring layout/colour patterns. Module rules only carry what differs
 * from these primitives (gap overrides, scroll bounds, hover, etc.). */

/* Vertical stack (flex column with the default sizeS gap). All "list"-like
 * containers compose with this — both <ul>/<ol> and plain <div>. */
.chart-bars, .chart-card-stats, .chart-stat,
.cond-list,
.col-manager-list,
.dialog-card-list,
.kanban-column-body,
.pipeline-list,
.select-options-list,
.settings-general,
.tag-manage-list, .tag-assign-list,
.action-progress {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-75);
  min-block-size: 0;
}

/* The <ul>/<ol> variants also drop list defaults. */
.chart-bars,
.cond-list,
.col-manager-list,
.pipeline-list,
.select-options-list,
.tag-manage-list, .tag-assign-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* Horizontal row (flex with vertical centre + the sizeS gap). */
.action-progress-bar-wrap,
.chart-bar-row,
.col-manager-row,
.cond-row,
.csv-type-row,
.filter-row,
.grid-headcell,
.it-actions-cell,
.kanban-column-header,
.pipeline-row,
.select-option-row,
.tag-row, .tag-add-row,
.tag-color-picker, .tag-color-inline {
  display: flex;
  align-items: center;
  gap: var(--spectrum-spacing-75);
}
.it-actions-cell { white-space: nowrap; }
.recycle-tabs { margin-block-end: var(--spectrum-spacing-200); flex-wrap: wrap; }

/* Plugins tab — card per plugin with enable switch on the right and the
 * list of provided actions beneath. */
.plugin-card-list {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-200);
}
.plugin-card {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-100);
  padding: var(--spectrum-spacing-300);
  background: var(--spectrum-background-layer-1-color);
  border: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  border-radius: var(--spectrum-corner-radius-100);
}
.plugin-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spectrum-spacing-200);
}
.plugin-card-title {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-50);
  min-inline-size: 0;
}
.plugin-card-title h3 { margin: 0; }
.plugin-card-desc { margin: 0; }
.plugin-action-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-75);
}
.plugin-action-row {
  display: flex;
  align-items: flex-start;
  gap: var(--spectrum-spacing-100);
}
.plugin-action-body { flex: 1; min-inline-size: 0; }
.plugin-action-title {
  display: flex;
  align-items: baseline;
  gap: var(--spectrum-spacing-100);
  flex-wrap: wrap;
}
.plugin-action-desc { margin: 2px 0 0 0; }
/* Manifest icon shorthand `circle:<color>` renders as a small filled dot
 * — pulls the colour from the value-formatters palette. */
.plugin-action-icon-dot {
  inline-size: 10px;
  block-size: 10px;
  border-radius: 50%;
  background: var(--dot-color, var(--spectrum-gray-400));
  flex-shrink: 0;
  margin-block-start: 6px;
}
/* Active recycle-tab needs a clearer hit — the vendor `is-selected`
 * alone is too subtle inside a dark dialog body. */
.recycle-tabs .spectrum-ActionButton.is-selected {
  --mod-actionbutton-background-color-default: var(--spectrum-neutral-background-color-selected-default);
  --mod-actionbutton-content-color-default:    var(--spectrum-white);
}

/* Audit log change chips: comma-separated field summaries inside a table
 * cell. Kept inline so multi-field diffs stay on one row visually. */
.audit-change {
  font-family: var(--spectrum-code-font-family);
  font-size: var(--spectrum-font-size-50);
  color: var(--spectrum-neutral-content-color-default);
}
/* Audit "Source" chip — Spectrum Tag rendered as a clickable button that
 * navigates to the Action Log entry that produced this row mutation. */
.audit-source-chip {
  cursor: pointer;
  border: none;
  font: inherit;
}
.audit-source-chip:hover { --mod-tag-background-color: var(--spectrum-tag-background-color-hover); }

/* Toolbar (flex with the sizeM gap; supports --split + --bounded modifiers).
 * Used by .grid-page-header, .kanban-toolbar, .filter-popover-header. */
.it-toolbar {
  display: flex;
  align-items: center;
  gap: var(--spectrum-spacing-200);
  flex-shrink: 0;
}
.it-toolbar--split   { justify-content: space-between; }
.it-toolbar--bounded {
  padding: var(--spectrum-spacing-200) var(--spectrum-spacing-300);
  border-block-end: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
}

.pipeline-row.is-dragging,
.col-manager-row.is-dragging,
.kanban-card.is-dragging { opacity: 0.4; }

/* Subdued text — secondary information, captions, empty/hint copy. */
.it-text-subdued,
.cal-cell-day, .cal-cell-more,
.chart-bar-value, .chart-card-empty, .chart-hint, .chart-stat-label,
.col-manager-handle, .col-manager-type-icon, .col-manager-type,
.cond-empty,
.filter-empty,
.formula-hint,
.grid-cell-attachment-icon,
.grid-empty-cell,
.grid-group-chevron, .grid-group-count,
.grid-headcell-type-icon,
.grid-page-header-meta,
.grid-pager-info,
.kanban-empty,
.pipeline-hint, .pipeline-step-key,
.sidebar-tag-count,
.tag-manage-empty, .tag-row-count {
  color: var(--spectrum-neutral-subdued-content-color-default);
}

/* Truncate to one line with ellipsis. Apply on titles, labels, cell text
 * that must not push horizontal scroll. */
.it-truncate,
.app-sidebar-header h2,
.cal-cell-card,
.chart-bar-label,
.col-manager-name,
.grid-page-header-name,
.grid-row-panel-header h3,
.pipeline-step-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-inline-size: 0;
}

/* Square swatch / color-picker button — 24×24 (component-height-75) circle
 * for tags, rounded square for cond/select-option color inputs. */
.it-swatch,
.cond-color,
.select-option-color {
  inline-size: var(--spectrum-component-height-75);
  block-size: var(--spectrum-component-height-75);
  padding: 0;
  border: var(--spectrum-border-width-100) solid var(--spectrum-gray-300);
  border-radius: var(--spectrum-corner-radius-100);
  background: transparent;
  cursor: pointer;
  appearance: none;
}

/* Bordered card box — module containers that share border+radius. Paddings
 * stay per-class since each module's content density differs. */
.col-manager-row, .pipeline-row {
  border: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  border-radius: var(--spectrum-corner-radius-100);
  background: var(--spectrum-background-layer-1-color);
}

/* Scrollable list bound — common ceiling for dialog/popover panels. */
.col-manager-list,
.dialog-card-list,
.select-options-list,
.tag-manage-list, .tag-assign-list {
  max-block-size: 60vh;
  overflow: auto;
}

/* ===== § 4  App shell ===== */
.app-navbar {
  display: flex;
  align-items: center;
  block-size: 44px;
  flex-shrink: 0;
  padding: 0 var(--spectrum-spacing-200);
  background: var(--spectrum-background-layer-1-color);
  border-block-end: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  gap: var(--spectrum-spacing-100);
}

.app-navbar-brand {
  /* spectrum-Body adds a block-end margin to flow paragraph text; in a
   * navbar flex row that pulls the brand vertically off-centre. Zero it. */
  --mod-body-margin: 0;
  color: var(--spectrum-neutral-content-color-default);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: var(--spectrum-spacing-100);
  padding: 0 var(--spectrum-spacing-75);
}
.app-navbar-brand svg { opacity: 0.85; }

.app-navbar-spacer  { flex: 1; }
.app-navbar-actions { display: flex; align-items: center; gap: var(--spectrum-spacing-75); }

/* Main shell — Spectrum SplitView (vendor) gives us:
 *   • flex row + overflow:hidden on the root
 *   • full-height panes + theme background via --mod-splitview-background-color
 *   • draggable splitter + gripper styling
 * We only override what's app-specific: fill remaining height, per-pane bg,
 * resizable sidebar bounds. */
.spectrum-SplitView { flex: 1; min-block-size: 0; }

.app-sidebar {
  --mod-splitview-background-color: var(--spectrum-background-layer-1-color);
  display: flex;
  flex-direction: column;
  inline-size: var(--sidebar-w, 260px);
  min-inline-size: 200px;
  max-inline-size: 480px;
  flex-shrink: 0;
}
.app-sidebar.is-collapsed { display: none; }

.app-sidebar-header {
  padding: var(--spectrum-spacing-200) var(--spectrum-spacing-200) var(--spectrum-spacing-100);
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-100);
}
.app-sidebar-header h2 { margin: 0; }

.app-sidebar-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spectrum-spacing-75);
}
.app-sidebar-actions #sidebar-expand-all { margin-inline-start: auto; }

.app-sidebar-search,
.app-sidebar-search .spectrum-Textfield { inline-size: 100%; }

.sidebar-tag-dot {
  display: inline-block;
  inline-size: var(--spectrum-spacing-200);
  block-size: var(--spectrum-spacing-200);
  border-radius: 50%;
  margin-inline: var(--spectrum-spacing-75) var(--spectrum-spacing-100);
  flex-shrink: 0;
}
.sidebar-tag-count { margin-inline-start: auto; flex-shrink: 0; }

.app-sidebar-body {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--spectrum-spacing-75) var(--spectrum-spacing-100) var(--spectrum-spacing-200);
}
.app-sidebar-body .sidebar-action { margin-inline-start: auto; flex-shrink: 0; }

#app-sidebar-resize { cursor: col-resize; }

/* Grid column drag-reorder: vertical accent line on the matching edge. */
.spectrum-Table-headCell.is-col-drop-before { box-shadow: inset 2px 0 0 0 var(--spectrum-accent-color-900); }
.spectrum-Table-headCell.is-col-drop-after  { box-shadow: inset -2px 0 0 0 var(--spectrum-accent-color-900); }

/* Sidebar drag-reorder indicators: before/after = horizontal line at the
 * matching edge; into = subtle background tint (folder reparent). */
.app-sidebar-body .spectrum-TreeView-item.is-drop-into > .spectrum-TreeView-itemLink {
  background: var(--spectrum-accent-background-color-default);
}
.app-sidebar-body .spectrum-TreeView-item.is-drop-before > .spectrum-TreeView-itemLink {
  box-shadow: inset 0 2px 0 0 var(--spectrum-accent-color-900);
}
.app-sidebar-body .spectrum-TreeView-item.is-drop-after > .spectrum-TreeView-itemLink {
  box-shadow: inset 0 -2px 0 0 var(--spectrum-accent-color-900);
}

.sidebar-loading,
.app-content-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  padding: var(--spectrum-spacing-300);
}

.app-content {
  --mod-splitview-background-color: var(--spectrum-background-base-color);
  flex: 1;
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
}

/* ===== § 5  Grid ===== */
.app-grid-wrapper {
  flex: 1;
  min-block-size: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* .grid-page-header layout = .it-toolbar.it-toolbar--bounded.it-toolbar--split
 * (applied in grid.js template). Only its child layout below stays unique. */
.grid-page-header-title {
  min-inline-size: 0;
  display: flex;
  align-items: baseline;
  gap: var(--spectrum-spacing-200);
  flex: 1;
}
.grid-page-header-name { margin: 0; }
.grid-page-header-meta    { flex-shrink: 0; }
.grid-page-header-actions { display: flex; align-items: center; gap: var(--spectrum-spacing-100); flex-shrink: 0; }
/* Search expands with the available header width up to a sensible max. */
.grid-page-header-search {
  --spectrum-search-inline-size: 100%;
  --spectrum-search-min-inline-size: 200px;
  flex: 1;
  max-inline-size: 360px;
}

.grid-page-body {
  flex: 1;
  min-block-size: 0;
  overflow: auto;
  padding: 0 var(--spectrum-spacing-300) var(--spectrum-spacing-200);
}

.spectrum-Table-headCell.is-pinned,
.spectrum-Table-cell.is-pinned {
  position: sticky;
  inset-inline-start: 0;
  background: var(--spectrum-background-layer-1-color);
  z-index: 2;
  border-inline-end: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
}
.spectrum-Table-headCell.is-pinned { z-index: 3; }

.spectrum-Table-headCell { position: relative; }
.grid-headcell-resizer {
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  inline-size: 6px;
  cursor: col-resize;
  user-select: none;
}
.grid-headcell-resizer:hover { background: var(--spectrum-accent-color-700); opacity: 0.4; }

.grid-headcell-type-icon { margin-inline-end: var(--spectrum-spacing-75); flex-shrink: 0; }
.grid-headcell-sort      { margin-inline-start: var(--spectrum-spacing-75); opacity: 0.7; }
.grid-headcell-display-marker { margin-inline-start: var(--spectrum-spacing-75); flex-shrink: 0; color: var(--spectrum-accent-color-900); }

.grid-addcol-headcell { inline-size: var(--spectrum-spacing-700); text-align: center; padding: 0; }

.grid-view-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-block-size: 0;
}

#grid-table { inline-size: max-content; min-inline-size: 100%; }

.grid-error-banner { padding: var(--spectrum-spacing-300); color: var(--spectrum-negative-content-color-default); }
.grid-loading-wrap { display: flex; align-items: center; justify-content: center; padding: var(--spectrum-spacing-700); }
.grid-empty-cell   { text-align: center; padding: var(--spectrum-spacing-300); }

/* Group-by header row */
.grid-group-header { cursor: pointer; background: var(--spectrum-gray-100); }
.grid-group-header:hover { background: var(--spectrum-gray-200); }
.grid-group-header-cell { padding: var(--spectrum-spacing-75) var(--spectrum-spacing-200); }
.grid-group-chevron { display: inline-block; inline-size: var(--spectrum-spacing-300); }
.grid-group-count   { margin-inline-start: var(--spectrum-spacing-200); }

/* Attachment cells — px: thumbnail 32×32 is a UX choice for inline preview. */
.grid-cell-attachment      { display: inline-block; margin-inline-end: var(--spectrum-spacing-75); vertical-align: middle; }
.grid-cell-attachment-thumb,
.grid-cell-attachment img  {
  inline-size: 32px;
  block-size: 32px;
  object-fit: cover;
  border-radius: var(--spectrum-corner-radius-75);
  border: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  margin-inline-end: var(--spectrum-spacing-75);
  vertical-align: middle;
}
.grid-cell-attachment-link { display: inline-flex; align-items: center; gap: var(--spectrum-spacing-75); text-decoration: none; }

/* Hover preview for image cells — wraps each thumb so the large preview
 * can sit as a sibling. Preview is `position: fixed` so it escapes the
 * cell's clip box; max 80vh keeps a 10% gutter top + bottom and
 * `block-size: auto` preserves the source resolution (never upscales
 * past the image's natural size). */
.grid-cell-attachment-wrap     { position: relative; display: inline-block; }
.grid-cell-attachment-preview {
  position: fixed;
  inset-block-start: 10vh;
  inset-inline-start: 50vw;
  transform: translateX(-50%);
  max-inline-size: 90vw;
  max-block-size: 80vh;
  inline-size: auto;
  block-size: auto;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  z-index: 100;
  border-radius: var(--spectrum-corner-radius-100);
  background: var(--spectrum-gray-50);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
  transition: opacity 0.12s;
}
.grid-cell-attachment-wrap:hover .grid-cell-attachment-preview {
  opacity: 1;
  visibility: visible;
}

/* Row-form attachment preview — large, framed image alongside the upload
 * picker. Auto-fits the field width up to a comfortable max. */
.it-attachment-preview {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-75);
  margin-block-end: var(--spectrum-spacing-100);
}
.it-attachment-image {
  inline-size: 100%;
  max-inline-size: 480px;
  max-block-size: 320px;
  object-fit: contain;
  border-radius: var(--spectrum-corner-radius-100);
  border: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  background: var(--spectrum-gray-50);
}
.it-attachment-file {
  display: inline-flex;
  align-items: center;
  gap: var(--spectrum-spacing-75);
  margin-block-end: var(--spectrum-spacing-100);
}

/* Range selection */
.spectrum-Table-cell.is-range-selected {
  background: var(--spectrum-accent-color-100);
  outline: 1px solid var(--spectrum-accent-color-700);
  outline-offset: -1px;
}
/* Ctrl/Cmd-click action selection — persistent highlight on the row
 * so the user can see which rows the next Run will target. */
.spectrum-Table-row.is-selected > .spectrum-Table-cell {
  background: var(--spectrum-accent-color-200);
}
/* Run-action button badge: small count chip overlaying the icon. */
.grid-run-selection-badge {
  position: absolute;
  inset-block-start: 2px;
  inset-inline-end: 2px;
  min-inline-size: 14px;
  block-size: 14px;
  padding: 0 4px;
  border-radius: 7px;
  background: var(--spectrum-accent-color-900);
  color: var(--spectrum-white);
  font-size: var(--spectrum-font-size-50);
  font-weight: var(--spectrum-bold-font-weight);
  line-height: 14px;
  text-align: center;
}
[data-action="run-action"] { position: relative; }

/* Plugin-supplied run-time dialogs. Each plugin loads its own CSS via
 * the shared Spectrum primitives, but the option list patterns (a
 * stack of labelled checkboxes with a hint underneath each) repeat. */
.detect-steps-heading { margin: var(--spectrum-spacing-200) 0 var(--spectrum-spacing-100); }
.detect-steps {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-100);
}
.detect-step .spectrum-Checkbox-label {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Selection stats — inline-style status strip above the pager.
 * Only shows when a drag-rectangle includes numeric cells. */
.grid-selection-stats {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spectrum-spacing-300);
  padding: var(--spectrum-spacing-75) var(--spectrum-spacing-300);
  border-block-start: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  background: var(--spectrum-gray-75);
  flex-shrink: 0;
}
.grid-selection-stats.is-hidden { display: none; }
.grid-selection-stat { display: inline-flex; align-items: center; gap: var(--spectrum-spacing-75); }
.grid-selection-stat-label { color: var(--spectrum-neutral-content-color-default); opacity: 0.65; text-transform: uppercase; letter-spacing: 0.04em; }

/* Pager */
.grid-pager {
  display: flex;
  align-items: center;
  gap: var(--spectrum-spacing-200);
  padding: var(--spectrum-spacing-100) var(--spectrum-spacing-300);
  border-block-start: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  flex-shrink: 0;
}
.grid-pager-info { margin-inline-start: auto; }
.grid-pager-size { inline-size: auto; min-inline-size: 0; }

/* Row-detail panel — docked right, non-modal.
 * px: panel width 380 — UX choice, no Spectrum token matches. */
.grid-row-panel {
  position: fixed;
  inset-block: 44px 0;
  inset-inline-end: 0;
  inline-size: 380px;
  display: flex;
  flex-direction: column;
  background: var(--spectrum-background-layer-1-color);
  border-inline-start: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  z-index: 200;
  box-shadow: -2px 0 8px rgb(0 0 0 / 4%);
}
.grid-row-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--spectrum-spacing-200) var(--spectrum-spacing-300);
  border-block-end: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
}
.grid-row-panel-header h3 { margin: 0; }
.grid-row-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--spectrum-spacing-300);
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-100);
}
.grid-row-panel-footer {
  padding: var(--spectrum-spacing-200) var(--spectrum-spacing-300);
  border-block-start: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  display: flex;
  justify-content: flex-end;
}

/* Views toolbar button — show active view name next to icon. */
[data-action="views"] .spectrum-ActionButton-label {
  margin-inline-start: var(--spectrum-spacing-75);
  max-inline-size: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.views-popover .spectrum-Menu-item .spectrum-ActionButton { margin-inline-start: var(--spectrum-spacing-100); }

/* Filter badge on toolbar button */
.grid-filter-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--spectrum-spacing-300);
  min-block-size: var(--spectrum-spacing-300);
  padding: 0 var(--spectrum-spacing-75);
  margin-inline-start: var(--spectrum-spacing-75);
  border-radius: var(--spectrum-corner-radius-100);
  background: var(--spectrum-accent-color-900);
  color: var(--spectrum-white);
}

/* ===== § 6  Views ===== */

/* Chart view — stats summary */
.chart-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--spectrum-spacing-200);
  padding: var(--spectrum-spacing-300);
}
.chart-card        { padding: var(--spectrum-spacing-200); }
.chart-card-title  { margin: 0 0 var(--spectrum-spacing-100); }
.chart-card-empty  { opacity: 0.6; }
.chart-card-stats  { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--spectrum-spacing-100); margin: 0; }
.chart-stat        { gap: var(--spectrum-spacing-50); }
.chart-stat-label  { text-transform: uppercase; }
.chart-stat-value  { margin: 0; }
.chart-bar-row     { gap: var(--spectrum-spacing-100); }
.chart-bar-label   { inline-size: 80px; }
.chart-bar         { flex: 1; block-size: var(--spectrum-spacing-200); background: var(--spectrum-gray-100); border-radius: var(--spectrum-corner-radius-75); overflow: hidden; }
.chart-bar-fill    { block-size: 100%; background: var(--spectrum-accent-color-700); }
.chart-bar-value   { inline-size: 32px; text-align: end; }
.chart-hint        { padding: 0 var(--spectrum-spacing-300) var(--spectrum-spacing-200); }

/* Kanban view — toolbar comes from .it-toolbar.it-toolbar--bounded. */
.kanban-empty         { padding: var(--spectrum-spacing-700); text-align: center; }
.kanban-toolbar-label { margin: 0; }
.kanban-board { flex: 1; overflow: auto; padding: var(--spectrum-spacing-300); }
.kanban-board-inner {
  display: flex;
  gap: var(--spectrum-spacing-200);
  align-items: flex-start;
  block-size: 100%;
}
.kanban-column {
  display: flex;
  flex-direction: column;
  inline-size: 280px;
  min-inline-size: 280px;
}
.kanban-column-header { justify-content: space-between; margin-block-end: var(--spectrum-spacing-100); }
.kanban-column-title  { margin: 0; }
.kanban-column-body {
  gap: var(--spectrum-spacing-100);
  overflow-y: auto;
  flex: 1;
  min-block-size: 80px;
}
.kanban-column-body.is-drop-target {
  outline: var(--spectrum-border-width-200) dashed var(--spectrum-accent-color-700);
  outline-offset: -2px;
}
.kanban-card { cursor: grab; }

/* Calendar view */
.cal-toolbar-spacer { flex: 1; }
.cal-grid { flex: 1; display: flex; flex-direction: column; min-block-size: 0; }
.cal-grid-head, .cal-grid-body { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal-grid-head { border-block-end: var(--spectrum-border-width-100) solid var(--spectrum-gray-200); background: var(--spectrum-gray-100); }
.cal-grid-headcell { padding: var(--spectrum-spacing-75) var(--spectrum-spacing-200); color: var(--spectrum-neutral-subdued-content-color-default); }
.cal-grid-body { flex: 1; min-block-size: 0; overflow-y: auto; }
.cal-cell {
  border-inline-end: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  border-block-end: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  padding: var(--spectrum-spacing-75);
  min-block-size: 96px;
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-50);
}
.cal-cell.is-outside { background: var(--spectrum-gray-50); color: var(--spectrum-neutral-subdued-content-color-default); }
.cal-cell.is-today .cal-cell-day {
  background: var(--spectrum-accent-color-900);
  color: var(--spectrum-white);
  border-radius: var(--spectrum-corner-radius-100);
  padding: 0 var(--spectrum-spacing-75);
  display: inline-block;
  align-self: start;
}
.cal-cell-card {
  padding: var(--spectrum-spacing-50) var(--spectrum-spacing-75);
  border-radius: var(--spectrum-corner-radius-75);
  background: var(--spectrum-accent-color-100);
  color: var(--spectrum-accent-color-1100);
  cursor: pointer;
}
.cal-cell-card:hover { background: var(--spectrum-accent-color-200); }

/* ===== § 7  Dialogs & forms ===== */
.it-prompt-dialog { max-inline-size: 480px; }
.it-prompt-input  { margin-block-start: var(--spectrum-spacing-100); }
.it-dialog-message { margin: 0; }

.it-field { margin-block-end: var(--spectrum-spacing-200); }
.it-field-control,
.it-field-picker  { inline-size: 100%; }
.it-field-checkbox {
  display: flex;
  align-items: center;
  gap: var(--spectrum-spacing-100);
  margin-block-end: var(--spectrum-spacing-200);
  cursor: pointer;
}
.it-field-switch { display: flex; margin-block-end: var(--spectrum-spacing-100); }

/* Dialog button group — vendor `buttongroup.css` not bundled; dialog.css uses
 * flex with no gap. Spectrum 2 spec is spacing-200 (16px) for sizeM. */
.spectrum-Dialog-buttonGroup { gap: var(--spectrum-spacing-200); }

/* Modal viewport fallback — the vendor uses `block-size: stretch` last
 * which not every browser/version resolves; force the wrapper to fill
 * the viewport so flex centering doesn't collapse to top-left. */
.spectrum-Modal-wrapper {
  inline-size: 100vw;
  block-size: 100vh;
  inset-inline-start: 0;
  inset-block-start: 0;
}

/* Confirm dialogs (just message + buttons) come out narrower than form
 * dialogs by default — give them a comfortable minimum so the title and
 * destructive action label don't crowd. */
.spectrum-Dialog .it-dialog-message {
  margin: 0;
  min-inline-size: 320px;
  max-inline-size: 480px;
}

/* View tabs placement — vendor tabs.css owns visual recipe.
 * The vendor selection-indicator block-size token sometimes resolves to 0
 * in our bundle (subset stripping); pin it explicitly so the active-tab
 * underline is always visible. Bold the active label for stronger affordance. */
.view-tabs,
.settings-tabs {
  padding: 0 var(--spectrum-spacing-300);
  flex-shrink: 0;
  --mod-tabs-divider-size: var(--spectrum-border-width-200);
  --mod-tabs-selection-indicator-color: var(--spectrum-accent-color-900);
}
.view-tabs .spectrum-Tabs-item.is-selected .spectrum-Tabs-itemLabel,
.settings-tabs .spectrum-Tabs-item.is-selected .spectrum-Tabs-itemLabel {
  font-weight: var(--spectrum-bold-font-weight);
}

/* ===== § 8  Module specifics ===== */

/* — Settings hub (modules/settings) —
 * Spectrum Dialog sizeL caps at --mod-dialog-confirm-large-width (640px).
 * Settings needs more breathing room: widen the dialog via that same knob,
 * then let the host fill it. */
.spectrum-Dialog:has(.settings-host) {
  --mod-dialog-width: min(80vw, 1200px);
}
/* Settings host owns its own panel scroll — silence the dialog body's
 * default overflow so we don't end up with two vertical scrollbars. */
.spectrum-Dialog:has(.settings-host) .spectrum-Dialog-content { overflow: hidden; }

/* When a Dialog body hosts a vertically scrolling form, keep the inputs
 * from kissing the scrollbar / the modal's right edge — give them an
 * inline-end gutter equal to a sizeM spacing token. Applies to any
 * `<form>` that's a direct child of the dialog content (row form, bind
 * dialog, webhook dialog, …). */
.spectrum-Dialog-content > form { padding-inline-end: var(--spectrum-spacing-200); }
.settings-host {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-200);
  block-size: 70vh;
  min-block-size: 480px;
  inline-size: 100%;
  min-inline-size: 0;
  overflow: hidden;
}
.settings-tabs { padding: 0; flex-shrink: 0; overflow-x: auto; }
.settings-panel {
  flex: 1;
  min-block-size: 0;
  min-inline-size: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding-inline-end: var(--spectrum-spacing-200);
}
.settings-toolbar { display: flex; justify-content: flex-end; margin-block-end: var(--spectrum-spacing-200); }
.settings-table   { inline-size: 100%; }
/* Settings empty-state long descriptions wrap, don't push horizontal scroll. */
.settings-panel .spectrum-IllustratedMessage-description { max-inline-size: 480px; }

/* — Import / Export modal (modules/dialogs/import-export) —
 * Auto-height shell: dialog grows with content up to a soft cap, no
 * forced empty space + no inner scrollbar unless the file list is long. */
.spectrum-Dialog:has(.iex-host) { --mod-dialog-width: min(70vw, 720px); }
.iex-host {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-200);
  inline-size: 100%;
  max-block-size: 70vh;
  min-inline-size: 0;
}
.iex-tabs {
  flex-shrink: 0;
  padding: 0;
  --mod-tabs-divider-size: var(--spectrum-border-width-200);
}
.iex-tabs .spectrum-Tabs-item.is-disabled {
  opacity: 0.45;
  pointer-events: none;
}
.iex-panel {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: auto;
  padding-inline-end: var(--spectrum-spacing-200);
}
.iex-body {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-300);
  padding-block-start: var(--spectrum-spacing-100);
}
.iex-field   { display: flex; flex-direction: column; gap: var(--spectrum-spacing-75); }
.iex-hint    { color: var(--spectrum-gray-700); }
.iex-status  { color: var(--spectrum-gray-800); min-block-size: 1.2em; }

/* Hidden native file input — the dropzone is the visible affordance. */
.iex-fileinput-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.iex-dropzone {
  display: flex;
  align-items: center;
  justify-content: center;
  min-block-size: 96px;
  padding: var(--spectrum-spacing-300);
  border: var(--spectrum-border-width-200) dashed var(--spectrum-gray-400);
  border-radius: var(--spectrum-corner-radius-100);
  background: var(--spectrum-gray-75);
  text-align: center;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}
.iex-dropzone:hover,
.iex-dropzone:focus-visible { border-color: var(--spectrum-accent-color-900); outline: none; }
.iex-dropzone.is-drag {
  border-color: var(--spectrum-accent-color-900);
  background: var(--spectrum-accent-background-color-default);
}
.iex-dropzone-cta { display: flex; flex-direction: column; gap: var(--spectrum-spacing-75); }
.iex-link { color: var(--spectrum-accent-color-900); text-decoration: underline; }

.iex-filelist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-75);
}
.iex-fileitem {
  display: flex;
  align-items: center;
  gap: var(--spectrum-spacing-200);
  padding: var(--spectrum-spacing-100) var(--spectrum-spacing-200);
  background: var(--spectrum-gray-75);
  border-radius: var(--spectrum-corner-radius-100);
}
.iex-fileitem-name { flex: 1 1 auto; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.iex-fileitem-size { color: var(--spectrum-gray-700); font-variant-numeric: tabular-nums; }

/* — Column dialog (modules/dialogs/column) — */
.column-format-section { margin-block: var(--spectrum-spacing-200); }
.column-divider {
  border: 0;
  border-block-start: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  margin-block: var(--spectrum-spacing-200);
}
.col-type-trigger        { inline-size: 100%; }
.col-type-trigger-label  { display: inline-flex; align-items: center; gap: var(--spectrum-spacing-100); }
.col-type-trigger-icon   { color: var(--spectrum-neutral-subdued-content-color-default); }

.select-options-heading  { margin: 0 0 var(--spectrum-spacing-100); }
.select-options-list     { margin-block-end: var(--spectrum-spacing-100); max-block-size: 280px; }
/* .select-option-color picks up base styles from .it-swatch (§ 3). */
.select-option-value,
.select-option-label { flex: 1; min-inline-size: 0; }

.formula-hint        { margin-block-start: var(--spectrum-spacing-75); }
.formula-hint code   {
  background: var(--spectrum-gray-100);
  padding: 0 var(--spectrum-spacing-75);
  border-radius: var(--spectrum-corner-radius-75);
}

/* — Conditional formatting (modules/dialogs/column-formats/conditional) — */
.cond-block   { margin-block: var(--spectrum-spacing-200); }
.cond-summary { cursor: pointer; list-style: none; padding: var(--spectrum-spacing-75) 0; }
.cond-summary::-webkit-details-marker { display: none; }
.cond-empty   { margin: var(--spectrum-spacing-75) 0; }
.cond-list    { margin-block-end: var(--spectrum-spacing-100); }
.cond-val     { flex: 1; min-inline-size: 0; }
.cond-preview {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--spectrum-component-height-75);
  block-size: var(--spectrum-component-height-75);
  border-radius: var(--spectrum-corner-radius-100);
  border: var(--spectrum-border-width-100) solid var(--spectrum-gray-300);
}
/* .cond-color picks up base styles from .it-swatch (§ 3). */
.cond-bold-switch .spectrum-Switch-label { font-weight: var(--spectrum-bold-font-weight); }

/* — Column manager (modules/dialogs/column-manager) — */
.col-manager-row     { padding: var(--spectrum-spacing-75) var(--spectrum-spacing-100); }
.col-manager-handle  { cursor: grab; }
.col-manager-name    { flex: 1; }

/* — Schema map (modules/dialogs/schema-map) & ERD (modules/dialogs/erd) —
 * Both diagrams render through Apache eCharts (vendored). The container is
 * a sized canvas; eCharts paints SVG inside. */
.schema-map,
.erd-canvas {
  inline-size: 100%;
  block-size: 72vh;
  background: var(--spectrum-gray-50);
  border-radius: var(--spectrum-corner-radius-100);
}
/* Action bind side-panel — dock-right, persists every change so there
 * is no Save button. Each `.action-bind-row` is one connection: action
 * field on the left, an arrow, column picker on the right (n8n-style). */
.action-bind-panel {
  position: fixed;
  inset-block: 44px 0;                  /* navbar height = 44 */
  inset-inline-end: 0;
  inline-size: 420px;
  display: flex;
  flex-direction: column;
  background: var(--spectrum-background-layer-1-color);
  border-inline-start: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  box-shadow: -4px 0 16px rgb(0 0 0 / 0.12);
  z-index: 80;
}
.action-bind-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spectrum-spacing-100);
  padding: var(--spectrum-spacing-200) var(--spectrum-spacing-300);
  border-block-end: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
  flex-shrink: 0;
}
.action-bind-panel-header h3 { margin: 0; }
.action-bind-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--spectrum-spacing-200) var(--spectrum-spacing-300);
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-100);
}
.action-bind-desc { margin: 0 0 var(--spectrum-spacing-200); }
.action-bind-section {
  margin: var(--spectrum-spacing-200) 0 var(--spectrum-spacing-100);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.action-bind-section:first-child { margin-block-start: 0; }

.action-bind-group {
  border-inline-start: var(--spectrum-border-width-200) solid var(--spectrum-accent-color-700);
  padding-inline-start: var(--spectrum-spacing-200);
  margin-block-end: var(--spectrum-spacing-200);
}
.action-bind-group-title {
  margin: 0 0 var(--spectrum-spacing-100);
  font-weight: var(--spectrum-bold-font-weight);
}
.action-bind-group-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--spectrum-spacing-100);
  margin-block-end: var(--spectrum-spacing-100);
}
.action-bind-group-body {
  margin-block-start: var(--spectrum-spacing-100);
  padding-block-start: var(--spectrum-spacing-100);
  border-block-start: var(--spectrum-border-width-100) dashed var(--spectrum-gray-200);
}
.action-bind-group-body:empty {
  margin-block-start: 0;
  padding-block-start: 0;
  border-block-start: none;
}
.action-bind-row--relation { margin-block-end: var(--spectrum-spacing-100); }
.action-bind-empty {
  margin: var(--spectrum-spacing-75) 0 var(--spectrum-spacing-100);
  color: var(--spectrum-neutral-subdued-content-color-default);
}

/* The mapping row itself — left label, arrow, right picker. */
.action-bind-row {
  display: grid;
  grid-template-columns: 1fr auto minmax(0, 1.4fr);
  align-items: center;
  gap: var(--spectrum-spacing-100);
  margin-block-end: var(--spectrum-spacing-75);
}
.action-bind-left {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-inline-size: 0;
}
.action-bind-name {
  font-weight: var(--spectrum-medium-font-weight);
  font-size: var(--spectrum-font-size-75);
  color: var(--spectrum-neutral-content-color-default);
}
.action-bind-types {
  font-family: var(--spectrum-code-font-family);
  font-size: var(--spectrum-font-size-50);
  color: var(--spectrum-neutral-subdued-content-color-default);
}
.action-bind-connector {
  display: inline-flex;
  color: var(--spectrum-gray-500);
}
.action-bind-required { color: var(--spectrum-negative-color-900); }
.action-bind-picker { inline-size: 100%; }

/* Diagram dialogs need a wider modal than the default `large` size —
 * graph/tree layouts collapse into an unreadable lump in a narrow column.
 * The canvas owns its own bounds — silence the dialog body scroll so the
 * vendor `Dialog-content { overflow-y:auto }` doesn't add a second bar. */
.spectrum-Dialog:has(.erd-canvas),
.spectrum-Dialog:has(.schema-map) {
  --mod-dialog-width: min(90vw, 1400px);
}
.spectrum-Dialog:has(.erd-canvas) .spectrum-Dialog-content,
.spectrum-Dialog:has(.schema-map) .spectrum-Dialog-content { overflow: hidden; }

/* — Filter popover (modules/grid/filter-panel) — */
.filter-popover {
  display: flex;
  flex-direction: column;
  padding: var(--spectrum-spacing-200);
  gap: var(--spectrum-spacing-200);
  background: var(--spectrum-background-layer-1-color);
}
/* .filter-popover-header layout comes from .it-toolbar.it-toolbar--split. */
.filter-popover-body {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-75);
  min-block-size: var(--spectrum-component-height-100);
}
.filter-empty             { margin: 0; }
.filter-row-column        { flex: 2;   min-inline-size: 0; }
.filter-row-operator      { flex: 1.4; min-inline-size: 0; }
.filter-row-value         { flex: 2;   min-inline-size: 0; }
.filter-popover-footer {
  display: flex;
  justify-content: space-between;
  gap: var(--spectrum-spacing-100);
  padding-block-start: var(--spectrum-spacing-100);
  border-block-start: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
}

/* — Manage tags dialog (modules/dialogs/tags) — */
.tag-manage-list   { gap: var(--spectrum-spacing-100); max-block-size: 420px; }
.tag-manage-empty  { margin: 0; }
.tag-row           { gap: var(--spectrum-spacing-100); }
.tag-row-name      { flex: 1; min-inline-size: 0; }
.tag-row-count     { min-inline-size: var(--spectrum-spacing-300); text-align: end; }
.tag-color-picker  { flex-shrink: 0; }
.tag-color-inline  { gap: var(--spectrum-spacing-75); }
/* Swatch sizes follow Spectrum's Swatch component scale (16/18/24 = S/M/L). */
.tag-swatch {
  inline-size: var(--spectrum-spacing-300);
  block-size: var(--spectrum-spacing-300);
  border-radius: 50%;
  border: var(--spectrum-border-width-200) solid transparent;
  padding: 0;
  cursor: pointer;
  appearance: none;
}
.tag-color-inline .tag-swatch {
  inline-size: var(--spectrum-spacing-200);
  block-size: var(--spectrum-spacing-200);
  border-width: var(--spectrum-border-width-100);
}
.tag-swatch.is-selected {
  border-color: var(--spectrum-neutral-content-color-default);
  box-shadow: inset 0 0 0 2px var(--spectrum-background-base-color);
}
.tag-manage-add {
  margin-block-start: var(--spectrum-spacing-300);
  padding-block-start: var(--spectrum-spacing-200);
  border-block-start: var(--spectrum-border-width-100) solid var(--spectrum-gray-200);
}
.tag-manage-add h3 { margin: 0; }
.tag-add-row       { gap: var(--spectrum-spacing-100); margin-block-start: var(--spectrum-spacing-100); }
.tag-add-name-wrap { flex: 1; min-inline-size: 0; }
.tag-assign-list   { gap: var(--spectrum-spacing-100); max-block-size: 360px; }
.tag-assign-row    { gap: var(--spectrum-spacing-100); }

/* — Pipeline (Table Settings → Pipeline tab) — */
.pipeline-list      { gap: var(--spectrum-spacing-75); }
.pipeline-row       { gap: var(--spectrum-spacing-200); padding: var(--spectrum-spacing-100) var(--spectrum-spacing-200); cursor: grab; }
.pipeline-step-no   {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--spectrum-component-height-75);
  block-size: var(--spectrum-component-height-75);
  border-radius: 50%;
  background: var(--spectrum-accent-color-900);
  color: var(--spectrum-white);
}
.pipeline-step-label { flex: 1; }
.pipeline-step-key   { flex-shrink: 0; }
.pipeline-hint       { margin: var(--spectrum-spacing-200) 0 0; }

/* — Action progress (modules/dialogs/action-progress) — */
.action-progress              { gap: var(--spectrum-spacing-200); min-inline-size: 480px; }
.action-progress-bar-wrap     { gap: var(--spectrum-spacing-200); }
.action-progress-bar-wrap .spectrum-ProgressBar { flex: 1; }
.action-progress-pct          { min-inline-size: 48px; text-align: end; color: var(--spectrum-neutral-subdued-content-color-default); }
.action-progress-log {
  background: var(--spectrum-gray-100);
  border-radius: var(--spectrum-corner-radius-100);
  padding: var(--spectrum-spacing-200);
  max-block-size: 320px;
  overflow-y: auto;
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
}
.action-desc { color: var(--spectrum-neutral-subdued-content-color-default); margin: 0 0 var(--spectrum-spacing-200); }

/* — CSV import (modules/dialogs/csv) — */
.csv-preview-table    { margin-block-start: var(--spectrum-spacing-100); inline-size: 100%; }
.csv-type-row         { gap: var(--spectrum-spacing-100); margin-block-end: var(--spectrum-spacing-75); }
.csv-type-label       { flex: 1; }
.csv-details          { margin-block-end: var(--spectrum-spacing-200); }
.csv-details-summary  { cursor: pointer; }
.csv-preview-wrap,
.csv-types-wrap       { max-block-size: 240px; overflow: auto; margin-block-start: var(--spectrum-spacing-100); }

/* ===== § 9  Utilities ===== */
.is-hidden { display: none !important; }

/* ===== Login overlay ===== */
.it-login-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--spectrum-background-base-color, #fff);
}
.it-login-card {
  display: flex;
  flex-direction: column;
  gap: var(--spectrum-spacing-200, 12px);
  width: 320px;
  max-width: calc(100vw - 32px);
  padding: var(--spectrum-spacing-400, 24px);
}
.it-login-brand {
  display: flex;
  align-items: center;
  gap: var(--spectrum-spacing-100, 8px);
  justify-content: center;
  font-size: var(--spectrum-font-size-300, 18px);
}
.it-login-subtitle {
  text-align: center;
  color: var(--spectrum-neutral-content-color-default);
  margin: 0 0 var(--spectrum-spacing-100, 8px);
}
.it-login-submit { margin-top: var(--spectrum-spacing-100, 8px); }
