/*
 * Blueprint builder overlay — first-draft design language.
 *
 * A Blueprint is NOT a spreadsheet and NOT a form. It is a sparse, designed grid
 * of cells. Only defined cells render (unused coordinates are invisible); cells
 * float with optional thin rounded borders and spacing between them.
 *
 * Uses the /app design tokens from public/client/css/variables.css
 * (--c-*, --sp-*, --r-*, --fs-*, --fw-*, --shadow-*).
 */

.bp {
  display: flex;
  height: 100%;
  min-height: 0;
  font-family: var(--font-sans);
  color: var(--c-ink);
}

/* ---- Main ------------------------------------------------------------ */
.bp__main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  position: relative;
}

.bp__toolbar {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  height: 60px;
  padding: var(--sp-3) var(--sp-5);
  border-bottom: var(--border);
  background: var(--c-surface);
}
.bp__toolbar-title {
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}
.bp__title-input {
  outline: none;
  border-radius: var(--r-sm);
  padding: 1px var(--sp-1);
  margin: -1px calc(-1 * var(--sp-1));
  transition: background var(--t-fast), box-shadow var(--t-fast);
  white-space: nowrap;
  cursor: text;
}
.bp__title-input:hover {
  background: var(--c-surface-hover);
}
.bp__title-input:focus {
  background: var(--c-surface-2);
  box-shadow: 0 0 0 2px var(--c-line-2);
}
.bp__toolbar-spacer {
  flex: 1;
}
.bp__modes {
  display: inline-flex;
  border: var(--border-2);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.bp__mode {
  border: 0;
  background: var(--c-surface);
  padding: var(--sp-1) var(--sp-4);
  font-size: var(--fs-sm);
  cursor: pointer;
  color: var(--c-ink-2);
}
.bp__mode + .bp__mode {
  border-left: var(--border-2);
}
.bp__mode.is-active {
  background: var(--c-accent);
  color: var(--c-ink-inv);
}

.bp__hint {
  display: none;
  padding: var(--sp-2) var(--sp-5);
  font-size: var(--fs-2xs);
  color: var(--c-ink-3);
  border-bottom: var(--border);
  background: var(--c-bg-sunken);
}

/* Form mode wrapper: a flex column where the canvas scrolls internally and
   the .bp__actions bar pins to the bottom as a fixed footer. */
.bp__form {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--c-surface-2);
}
/* Inside the wrapper the canvas is the scroll area (grows to fill, scrolls
   when content overflows); the sibling .bp__actions stays pinned below. */
.bp__form .bp__canvas {
  flex: 1 1 0;
  min-height: 0;
  overflow: auto;
}

.bp__canvas {
  flex: 1;
  overflow: auto;
  padding: var(--sp-5);
  background: var(--c-surface-2);
  display: flex;
  justify-content: flex-start;
  flex-direction: column;
  /* max-width: 880px; */
  margin-inline: auto;
  width: 100%;
}

/* The rendered Blueprint surface (the "paper"). */
.bp-surface {
  background: var(--c-surface);
  border: var(--border);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-md);
  padding: var(--sp-8);
  width: 100%;
  max-width: 820px;
  align-self: center;
  margin-block: var(--sp-2) var(--sp-6);
}

/* ---- Instructions bar (first child of .bp-surface) ------------------ */
.bp-surface-instructions {
  display: flex;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
  padding: var(--sp-3) var(--sp-4);
  background: var(--c-surface-2);
  border: 1px solid var(--c-line-2);
  border-radius: var(--r-2xl);
}
.bp-surface-instructions.is-empty {
  opacity: 0.7;
}
.bp-surface-instructions__text {
  flex: 1;
  min-width: 0;
  /* min-height: 400px; */
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--c-text-2);
  white-space: pre-wrap;
  word-break: break-word;
}
/* Read-only display div (click to enter edit mode). */
.bp-surface-instructions__text[role="textbox"] {
  cursor: text;
  padding: 0;
  transition: color 0.15s;
}
.bp-surface-instructions__text[role="textbox"]:hover {
  color: var(--c-text-1);
}
.bp-surface-instructions.is-empty .bp-surface-instructions__text[role="textbox"] {
  font-style: italic;
  color: var(--c-text-3);
}
/* Inline-editable textarea: styled to look like the text it replaces. */
textarea.bp-surface-instructions__text {
  width: 100%;
  min-height: 300px;
  background: transparent;
  border: none;
  outline: none;
  resize: none;
  font-family: inherit;
  padding: 0;
  overflow: auto;
}
textarea.bp-surface-instructions__text:focus {
  color: var(--c-text-1);
}
.bp-surface-instructions__text::placeholder {
  font-style: italic;
  color: var(--c-text-3);
}
/* Collapsed state: show the hint line instead of the body. */
.bp-surface-instructions.is-collapsed .bp-surface-instructions__text {
  display: none;
}
.bp-surface-instructions:not(.is-collapsed) .bp-surface-instructions__hint {
  display: none;
}
.bp-surface-instructions__hint {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-sm);
  color: var(--c-text-3);
  background: transparent;
  border: none;
  padding: 0;
  text-align: left;
  cursor: pointer;
  transition: color 0.15s;
}
.bp-surface-instructions__hint:hover {
  color: var(--c-text-2);
}
.bp-surface-instructions__btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--c-text-3);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.bp-surface-instructions__btn:hover {
  background: var(--c-surface-3);
  color: var(--c-text-1);
}

/* ---- Proposal-only instructions bar (inside the preview .bp-surface) -- */
.bp-proposal__preview .bp-surface-instructions {
  margin-bottom: var(--sp-4);
}
.bp-surface-instructions--proposal .bp-surface-instructions__text {
  min-height: 0;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-2);
}
.bp-surface-instructions__diff {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-2);
  padding-top: var(--sp-2);
  border-top: 1px dashed var(--c-line-2);
  font-size: var(--fs-xs);
}
.bp-surface-instructions__diff-cap {
  font-size: var(--fs-xs);
  color: var(--c-text-3);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.bp-surface-instructions__diff-before {
  color: var(--c-text-3);
  margin-inline: 0 var(--sp-2);
  white-space: pre-wrap;
  word-break: break-word;
  flex: 1 1 auto;
  min-width: 0;
}
.bp-surface-instructions__diff-arrow {
  color: var(--c-text-3);
}
.bp-surface-instructions__diff-after {
  color: var(--c-text-1);
  margin-inline: var(--sp-2) 0;
  white-space: pre-wrap;
  word-break: break-word;
  flex: 1 1 auto;
  min-width: 0;
}
/* Inline Included/Excluded pill button in the bar. */
.bp-surface-instructions__include {
  flex-shrink: 0;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 var(--sp-3);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  border: 1px solid var(--c-line-2);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--c-text-3);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.bp-surface-instructions__include:hover {
  background: var(--c-surface-3);
}
.bp-surface-instructions__include.is-on {
  background: var(--c-accent, var(--c-primary));
  border-color: transparent;
  color: white;
}
.bp-surface-instructions__include.is-on:hover {
  filter: brightness(0.96);
}

/* ---- The cell grid --------------------------------------------------- */
.bp-grid {
  display: grid;
  /* Doubled row tracks (see blueprint-grid.js): a pill track sits below each
     content row. row-gap is halved so an empty pill track is spacing-neutral
     (G/2 + 0 + G/2 == G); column spacing is unchanged. */
  column-gap: var(--sp-3);
  row-gap: calc(var(--sp-3) / 2);
  align-items: stretch;
}

/* Intelligent-IO suggestion pills: a grid item on the pill track under a cell,
   spanning its columns. Positioning only — `.io-alts` carries its own styling. */
.bp-grid > .io-alts-slot {
  min-width: 0;
  align-self: start;
}
.bp-grid > .io-alts-slot .io-alts {
  margin-top: 0;
}

/* Base cell: floats, no border by default. */
.bp-cell {
  min-height: 1.5rem;
  font-size: var(--fs-md);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.bp-cell[data-align="right"] {
  text-align: right;
  align-items: flex-end;
}
.bp-cell[data-align="center"] {
  text-align: center;
  align-items: center;
}
.bp-cell[data-bold="1"] {
  font-weight: var(--fw-semibold);
}

/* Label / key cells — quiet, no border. */
.bp-cell--label {
  color: var(--c-ink-2);
  font-size: var(--fs-sm);
  padding: var(--sp-1) 0;
}

/* Section header cells — a titled divider that opens a form section. */
.bp-cell--section {
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  color: var(--c-ink);
  align-items: flex-start;
  justify-content: flex-end;
  padding: var(--sp-3) 0 var(--sp-2);
  /* row-gap above is now G/2; add 1.5G of margin so total stays ~2G as before. */
  margin-top: calc(var(--sp-3) * 1.5);
  border-bottom: var(--border);
}
.bp-grid .bp-cell--section:first-child {
  margin-top: 0;
}

/* Markdown cells always get padding. */
.bp-cell--markdown {
  padding: var(--sp-3) var(--sp-4);
}
.bp-cell--markdown :is(h1, h2, h3) {
  margin: 0 0 var(--sp-2);
  line-height: var(--lh-tight);
}
.bp-cell--markdown h1 {
  font-size: var(--fs-2xl);
}
.bp-cell--markdown h2 {
  font-size: var(--fs-xl);
}
.bp-cell--markdown p {
  margin: 0 0 var(--sp-2);
  color: var(--c-ink-2);
  line-height: var(--lh-base);
}
.bp-cell--markdown p:last-child {
  margin-bottom: 0;
}
/* Line-addressable markdown blocks (showcase targeting, P8). The class is
 * applied to both <div> (prose) and <a> (linkified URL) elements; force block
 * so anchors stack one-per-line instead of collapsing to inline. */
.bp-md-line {
  display: block;
}
.bp-md-line > :first-child {
  margin-top: 0;
}
.bp-md-line > :last-child {
  margin-bottom: 0;
}

/* Showcase target highlight (P8) — see the stronger override rule after the
 * base cell/field styles below. Kept here as a forward reference only. */

/* The default USED data cell: light thin border, rounded, padded. */
.bp-cell--data,
.bp-cell--formula {
  border: var(--bw) solid var(--c-line-2);
  border-radius: var(--r-2xl);
  padding: var(--sp-2) var(--sp-4);
  background: var(--c-surface);
  box-shadow: var(--shadow-xs);
}
.bp-cell--formula {
  background: var(--c-accent-soft);
  font-variant-numeric: tabular-nums;
  box-shadow: none;
}

/* A data cell can opt OUT of its border (style.border = "none"): it "disappears". */
.bp-cell[data-border="none"] {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  padding-left: 0;
  padding-right: 0;
}

/* ---- Unified key/value field --------------------------------------- */
/* One bordered, rounded container holding BOTH the label and the value,
 * with a vertical divider between them. */
.bp-field {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  min-height: 2rem;
  border: var(--bw) solid var(--c-line-2);
  border-radius: var(--r-2xl);
  background: var(--c-surface);
  box-shadow: var(--shadow-xs);
  overflow: hidden;
}
.bp-field:focus-within {
  border-color: var(--c-line-strong);
}

/* ---- Showcase target highlight (P8) --------------------------------- */
/* Pulse a cell / markdown line when an assistant showcase pill targets it.
 * Placed AFTER the .bp-cell--data / .bp-field base rules and written with
 * compound selectors so it wins the cascade over their background + box-shadow
 * (the base rules are single-class (0,1,0); these are (0,2,0)). The JS in
 * applyCellTarget adds .bp-cell--target for 2600ms — the animation matches. */
.bp-cell--target,
.bp-cell.bp-cell--target,
.bp-field.bp-cell--target {
  border-radius: var(--r-lg);
  background: rgba(224, 130, 10, 0.18); /* --c-splash-amber at 18% */
  box-shadow: 0 0 0 3px var(--c-splash-amber), var(--shadow-md);
  animation: bp-target-pulse 2.6s ease-out;
}

@keyframes bp-target-pulse {
  0% {
    box-shadow: 0 0 0 0 var(--c-splash-amber);
    background: rgba(224, 130, 10, 0.28);
  }
  15% {
    box-shadow: 0 0 0 6px var(--c-splash-amber);
    background: rgba(224, 130, 10, 0.22);
  }
  30% {
    box-shadow: 0 0 0 3px var(--c-splash-amber);
    background: rgba(224, 130, 10, 0.18);
  }
  100% {
    box-shadow: 0 0 0 3px var(--c-splash-amber);
    background: rgba(224, 130, 10, 0.12);
  }
}

.bp-field__cap {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  font-size: var(--fs-xs);
  color: var(--c-ink-3);
  white-space: nowrap;
  padding: var(--sp-2) var(--sp-4);
  background: var(--c-surface-2);
  border-bottom: var(--bw) solid var(--c-line-2); /* the divider */
}
.bp-field__control {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  padding: var(--sp-2) var(--sp-4);
  font-variant-numeric: tabular-nums;
}
.bp-field[data-align="right"] .bp-field__control {
  justify-content: flex-end;
  text-align: right;
}
.bp-field[data-align="right"] .bp-input {
  text-align: right;
}

.bp-field--formula .bp-field__control {
  background: var(--c-accent-soft);
}
.bp-field--strong {
  font-weight: var(--fw-semibold);
}
.bp-field--strong .bp-field__cap {
  color: var(--c-ink);
}

/* ---- Group backing panel (painted behind a group's cells) ----------- */
.bp-group {
  border-radius: var(--r-xl);
  margin: calc(var(--sp-2) * -1);
  margin-top: 1rem;
  pointer-events: none;
  background: var(--c-surface-2);
  border: var(--bw) solid transparent;
}
.bp-group[data-group="ai"] {
  background: rgba(122, 90, 245, 0.06); /* --c-splash-violet, soft */
  border-color: rgba(122, 90, 245, 0.18);
}
/* Cells inside the AI group: tie their accents to the group hue. */
.bp-cell[data-group="ai"].bp-cell--formula,
.bp-field[data-group="ai"].bp-field--formula .bp-field__control {
  background: rgba(122, 90, 245, 0.10);
  color: var(--c-splash-violet);
}
.bp-field[data-group="ai"] .bp-field__cap {
  color: var(--c-splash-violet);
}
.bp-cell[data-group="ai"].bp-cell--markdown {
  color: var(--c-ink-2);
}

/* Value display (card mode) */
.bp-cell__value {
  font-variant-numeric: tabular-nums;
}
.bp-cell__value.is-empty {
  color: var(--c-ink-3);
}

/* Form input inside a data cell */
.bp-input {
  border: 0;
  background: transparent;
  font: inherit;
  color: inherit;
  width: 100%;
  outline: none;
  padding: 0;
  font-variant-numeric: tabular-nums;
}
.bp-input::placeholder {
  color: var(--c-ink-3);
}
.bp-cell--data:focus-within {
  border-color: var(--c-line-strong);
}

/* Table header cells */
.bp-cell--header {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--c-ink-3);
  border: 0;
  border-bottom: var(--border);
  border-radius: 0;
  padding: var(--sp-1) var(--sp-2);
  background: transparent;
  box-shadow: none;
}

/* ---- Edit mode: reveal the full grid -------------------------------- */
.bp-grid.is-edit .bp-cell,
.bp-grid.is-edit .bp-field {
  outline: var(--bw) dashed var(--c-line-2);
  outline-offset: 2px;
}
.bp-grid.is-edit .bp-group {
  outline: none;
}
.bp-cell--empty {
  border: var(--bw) dashed var(--c-line);
  border-radius: var(--r-2xl);
  min-height: 4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-line-2);
  cursor: pointer;
  font-size: var(--fs-lg);
  background: repeating-linear-gradient(
    45deg,
    transparent,
    transparent 6px,
    rgba(10, 10, 10, 0.012) 6px,
    rgba(10, 10, 10, 0.012) 12px
  );
}
.bp-cell--empty:hover {
  color: var(--c-ink-3);
  border-color: var(--c-line-2);
}

/* Edit-mode role badge */
.bp-cell__badge {
  align-self: flex-start;
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-ink-3);
  background: var(--c-surface-2);
  border-radius: var(--r-xs);
  padding: 0 4px;
  margin-bottom: 2px;
}

/* =====================================================================
 * P2 — server-backed base shell additions
 * ===================================================================== */

/* Full-viewport base host (peer of the canvas). */
.blueprint-base {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.blueprint-base .bp {
  width: 100%;
}

/* Blueprint registry list (header dropdown) */
.bp__empty {
  padding: var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--c-ink-3);
  text-align: center;
}
.bp__empty[data-csv-drop] {
  border: 2px dashed transparent;
  border-radius: var(--r-md);
  transition: border-color 0.15s, background-color 0.15s;
}
.bp__empty--drag {
  border-color: var(--c-accent, #2f6feb) !important;
  background: var(--c-surface-2);
}
.bp__empty-lead {
  margin: 2px 0;
}
.bp__empty-sub {
  margin: 2px 0 var(--sp-3);
}
.bp__csv-import-btn {
  margin-top: var(--sp-2);
}

/* CSV import mapping modal */
.csv-import__warn {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--c-surface-2);
  border: var(--bw) solid var(--c-line-2);
  border-radius: var(--r-xs);
  padding: 8px 12px;
  margin-bottom: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--c-ink-2);
}
.csv-import__summary {
  font-size: var(--fs-sm);
  color: var(--c-ink-3);
  margin-bottom: var(--sp-2);
}
.csv-import__table-wrap {
  max-height: 50vh;
  overflow: auto;
  border: var(--bw) solid var(--c-line-2);
  border-radius: var(--r-xs);
}
.csv-import__table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.csv-import__table th,
.csv-import__table td {
  text-align: left;
  padding: 6px 10px;
  border-bottom: var(--bw) solid var(--c-line-2);
  vertical-align: middle;
}
.csv-import__table th {
  position: sticky;
  top: 0;
  background: var(--c-surface-2);
  color: var(--c-ink-2);
  font-weight: 600;
}
.csv-import__col {
  font-weight: 500;
  color: var(--c-ink-1);
}
.csv-import__sample,
.csv-import__preview {
  font-family: var(--ff-mono, "SFMono-Regular", ui-monospace, monospace);
  color: var(--c-ink-3);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.csv-import__select {
  min-width: 160px;
}
.bp__lock-chip {
  margin-left: 6px;
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-ink-3);
  background: var(--c-surface-2);
  border: var(--bw) solid var(--c-line-2);
  border-radius: var(--r-xs);
  padding: 0 4px;
}

/* Main pane */
.bp__main-inner {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}
.bp__placeholder {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-ink-3);
  font-size: var(--fs-sm);
}
.bp__del-btn {
  border: 0;
  background: transparent;
  color: var(--c-ink-3);
  cursor: pointer;
  border-radius: var(--r-pill);
  padding: 4px;
  display: inline-flex;
}
.bp__del-btn:hover {
  background: var(--c-error-soft);
  color: var(--c-error-line);
}

/* "Move to" folder dropdown in the toolbar. `.bp__move` is the positioned
   wrapper (so the .menu can anchor to its bottom-right); the button mirrors
   the existing `.bp__del-btn` sizing so the two sit flush in the toolbar. */
.bp__move {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.bp__move-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  border: var(--border);
  border-radius: var(--r-pill);
  background: var(--c-surface);
  color: var(--c-ink-2);
  padding: 4px var(--sp-3);
  font-size: var(--fs-sm);
  cursor: pointer;
}
.bp__move-btn:hover {
  background: var(--c-surface-hover);
  color: var(--c-ink);
}
.bp__move-btn--listed {
  background: color-mix(in srgb, var(--c-splash-green) 14%, transparent);
  border-color: color-mix(in srgb, var(--c-splash-green) 40%, transparent);
  color: var(--c-splash-green);
}
.bp__move-btn--listed:hover {
  background: color-mix(in srgb, var(--c-splash-green) 20%, transparent);
}
.bp__move-menu {
  min-width: 200px;
  top: calc(100% + 14px);
}
.bp__error {
  padding: var(--sp-2) var(--sp-5);
  font-size: var(--fs-sm);
  color: var(--c-error-line);
  background: var(--c-error-soft);
  border-bottom: var(--border);
}
.bp__actions {
  display: flex;
  justify-content: flex-start;
  gap: var(--sp-2);
  flex: 0 0 auto;
  padding: var(--sp-3) var(--sp-5);
  border-top: var(--border);
  background: var(--c-surface);
}
.bp__actions-spacer {
  flex: 1;
}

/* Table mode */
.bp__table-canvas {
  align-items: flex-start;
}
.bp__rows {
  width: 100%;
  max-width: 820px;
  align-self: center;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.bp__rows-foot {
  width: 100%;
  max-width: 820px;
  align-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
}
.bp__rows-count {
  font-size: var(--fs-sm);
}
.bp__rows-more {
  font-size: var(--fs-sm);
}
.bp__row-wrap {
  display: flex;
  flex-direction: column;
}
.bp__row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  text-align: left;
  border: var(--border);
  border-radius: var(--r-xl);
  background: var(--c-surface);
  padding: var(--sp-2) var(--sp-3);
  cursor: pointer;
  font-size: var(--fs-sm);
  color: var(--c-ink);
  transition:
    background var(--t-fast),
    border-color var(--t-fast),
    transform var(--t-fast),
    box-shadow var(--t-fast);
}
.bp__row:hover {
  background: var(--c-surface-hover);
  transform: translateY(-1px);
  box-shadow: var(--shadow-xs);
}
.bp__row.is-open {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}
.bp__row-title {
  font-weight: var(--fw-medium);
  flex: 1;
}
.bp__row-date {
  font-size: var(--fs-2xs);
  color: var(--c-ink-3);
}
.bp__row-card {
  border: var(--border);
  border-top: 0;
  border-radius: 0 0 var(--r-xl) var(--r-xl);
  background: var(--c-surface-2);
  padding: var(--sp-5);
}
.bp__row-card .bp-surface {
  margin: 0;
}
.bp__row-tools {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}
.bp__row-tool {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  border: var(--border);
  border-radius: var(--r-md);
  background: var(--c-surface);
  color: var(--c-ink-2);
  padding: var(--sp-1) var(--sp-3);
  font-size: var(--fs-xs);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.bp__row-tool:hover {
  background: var(--c-surface-hover);
  color: var(--c-ink);
}
.bp__row-tool:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.bp__row-tool--danger {
  color: var(--c-danger, #c0392b);
}
.bp__row-tool--danger:hover {
  background: color-mix(in srgb, var(--c-danger, #c0392b) 8%, var(--c-surface));
}
.bp__row-editing-tag {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-accent);
  padding: var(--sp-1) var(--sp-2);
  background: color-mix(in srgb, var(--c-accent) 12%, transparent);
  border-radius: var(--r-sm);
}
.bp__row-edit-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
}
.bp__actions-spacer {
  flex: 1;
}
/* Export-only surface — white background + no shadow so html2canvas captures a
   clean snapshot. Everything else (padding, margin, border, radius, color) is
   inherited from `.bp-surface` / `.bp__row-card .bp-surface` so the PDF layout
   matches what the user sees on screen. */
.bp-surface--export {
  background: #fff;
  box-shadow: none;
}

/* Edit mode */
.bp__edit-canvas {
  align-items: stretch;
  padding: 0;
  max-width: none;
}

/* =====================================================================
 * Visual builder (Edit tab)
 * ===================================================================== */
.bpb {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 0;
}

/* Toolbar: grid + render controls, save status, view toggle. */
.bpb__bar {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin: 1rem 1rem 0;
  padding: var(--sp-2) var(--sp-3);
  border: var(--border);
  border-radius: var(--r-pill);
  background: var(--c-surface);
}
.bpb__bar-group {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.bpb__bar-label {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-ink-3);
}
.bpb__bar-spacer {
  flex: 1;
}
.bpb__select {
  border: var(--border);
  border-radius: var(--r-sm);
  background: var(--c-bg);
  color: var(--c-ink);
  font-size: var(--fs-xs);
  padding: 2px var(--sp-2);
}
.bpb__stepper {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
}
.bpb__step {
  width: 22px;
  height: 22px;
  border: var(--border);
  border-radius: var(--r-pill);
  background: var(--c-bg);
  color: var(--c-ink);
  cursor: pointer;
  line-height: 1;
}
.bpb__step:hover {
  background: var(--c-surface-hover);
}
.bpb__step:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.bpb__step:disabled:hover {
  background: var(--c-bg);
}
.bpb__step-val {
  min-width: 20px;
  text-align: center;
  font-size: var(--fs-sm);
}

.bpb__save {
  font-size: var(--fs-2xs);
  color: var(--c-ink-3);
}
.bpb__save--saving {
  color: var(--c-ink-2);
}
.bpb__save--saved {
  color: var(--c-success, #2e7d32);
}
.bpb__save--error {
  color: var(--c-danger, #c0392b);
}

.bpb__clear-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-2xs);
  color: var(--c-danger, #ef4444);
}
.bpb__clear-btn:hover:not(:disabled) {
  background: var(--c-danger, #ef4444);
  color: #fff;
  border-color: var(--c-danger, #ef4444);
}

/* Body: canvas | inspector (palette moved above as a horizontal strip). */
.bpb__body {
  display: grid;
  grid-template-columns: 1fr minmax(260px, 320px);
  gap: var(--sp-3);
  padding: 1rem;
  align-items: start;
}

/* Palette: horizontal strip under the toolbar. */
.bpb__palette {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-2) 1rem 0;
  padding: var(--sp-2) var(--sp-3);
  border: var(--border);
  border-radius: var(--r-md);
  background: var(--c-surface);
}
.bpb__palette-head {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-ink-3);
  padding: 0 var(--sp-1);
  white-space: nowrap;
}
.bpb__palette-hint {
  font-size: var(--fs-2xs);
  color: var(--c-ink-3);
  margin: 0;
  padding: 0 var(--sp-1);
  white-space: nowrap;
}
.bpb__tile {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2);
  border: var(--border);
  border-radius: var(--r-sm);
  background: var(--c-bg);
  color: var(--c-ink);
  font-size: var(--fs-xs);
  cursor: grab;
  user-select: none;
}
.bpb__tile:hover {
  background: var(--c-surface-hover);
  border-color: var(--c-accent, #3b82f6);
}
.bpb__tile:active {
  cursor: grabbing;
}

/* Canvas */
.bpb__canvas {
  border: var(--border);
  border-radius: var(--r-md);
  background: var(--c-bg-sunken);
  padding: var(--sp-4);
  min-height: 360px;
}
.bpb__canvas .bp-surface {
  margin: 0;
}

/* Selected cell + resize handle (over the shared edit grid) */
.bpb__canvas .bp-cell.is-selected,
.bpb__canvas .bp-field.is-selected {
  outline: 2px solid var(--c-accent, #3b82f6);
  outline-offset: -1px;
  position: relative;
}
.bpb__canvas [data-cell-id] {
  position: relative;
}
/* The resize handle sits at right:-4px/bottom:-4px (outside the box). .bp-field
 * clips with overflow:hidden for its rounded caption background, so let the
 * handle escape only while the field is selected. */
.bpb__canvas .bp-field.is-selected {
  overflow: visible;
}
.bpb__resize {
  position: absolute;
  right: -4px;
  bottom: -4px;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  background: var(--c-accent, #3b82f6);
  border: 2px solid var(--c-bg, #fff);
  cursor: nwse-resize;
  z-index: 3;
}
.bpb__canvas .bp-cell--empty.is-drop {
  background: color-mix(in srgb, var(--c-accent, #3b82f6) 18%, transparent);
  border-color: var(--c-accent, #3b82f6);
  color: var(--c-accent, #3b82f6);
}

/* ---- Row/column header strips with hover insert/delete buttons ---------- */
/* Headers live INSIDE .bp-surface (sharing its padded content box) so column
 * boundaries line up with the grid's tracks. The frame is a flex column:
 * top row = corner + col-heads; body row = row-heads + grid. Both col-heads
 * and the grid use the same repeat(cols,1fr) + column-gap, and row-heads
 * stretches to the grid's height via align-items:stretch. */
.bpb__edit-frame {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.bpb__edit-top {
  display: flex;
  flex-direction: row;
  align-items: stretch;
}
.bpb__edit-body {
  display: flex;
  flex-direction: row;
  align-items: stretch;
}
.bpb__corner {
  flex: 0 0 28px;
  width: 28px;
  height: 28px;
  border-radius: var(--r-sm) 0 0 0;
}
.bpb__col-heads {
  flex: 1 1 auto;
  display: grid;
  column-gap: var(--sp-3);
  height: 28px;
}
.bpb__row-heads {
  flex: 0 0 28px;
  position: relative;
}
.bpb__edit-body .bp-grid.is-edit {
  flex: 1 1 auto;
  position: relative; /* anchor for the marquee + row-heads overlay */
}
.bpb__head-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-pill);
  background: var(--c-surface-2);
  border: 1px solid var(--c-line-2);
  color: var(--c-ink-3);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  user-select: none;
  cursor: default;
}
.bpb__head-btn--col {
  /* border-radius: var(--r-sm) var(--r-sm) 0 0; */
  margin-bottom: 0.5rem; /* prevent tools from being cut off by the corner */
}
.bpb__head-btn--row {
  position: absolute;
  left: 0;
  right: 0;
  /* border-radius: var(--r-sm) 0 0 var(--r-sm); */
  overflow: hidden;
  margin-right: 0.5rem; /* prevent tools from being cut off by the corner */
}
.bpb__head-label {
  pointer-events: none;
}
.bpb__head-tools {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border-radius: var(--r-pill);
  background: var(--c-surface-2);
}
.bpb__head-btn--row .bpb__head-tools {
  flex-direction: column;
}
.bpb__head-btn:hover .bpb__head-tools {
  display: flex;
}
.bpb__head-add,
.bpb__head-del {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: none;
  border-radius: var(--r-pill);
  background: var(--c-surface);
  color: var(--c-ink-2);
  cursor: pointer;
  padding: 0;
}
.bpb__head-add:hover {
  background: var(--c-accent, #3b82f6);
  color: #fff;
}
.bpb__head-del:hover {
  background: var(--c-danger, #ef4444);
  color: #fff;
}

/* Marquee box-select rectangle */
.bpb__marquee {
  position: absolute;
  border: 1px solid var(--c-accent, #3b82f6);
  background: color-mix(in srgb, var(--c-accent, #3b82f6) 12%, transparent);
  pointer-events: none;
  z-index: 10;
}

/* Multi-select inspector hint */
.bpb__multiselect-hint {
  font-size: var(--fs-xs);
  color: var(--c-ink-3);
  margin: 0;
}

/* Inspector */
.bpb__inspector {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  border: var(--border);
  border-radius: var(--r-md);
  background: var(--c-surface);
  padding: var(--sp-3);
}
.bpb__inspector-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  text-align: center;
  color: var(--c-ink-3);
  font-size: var(--fs-xs);
  padding: var(--sp-5) var(--sp-2);
}
.bpb__sec {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.bpb__sec-head {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-ink-3);
  border-bottom: var(--border);
  padding-bottom: var(--sp-1);
}
.bpb__sec--actions {
  flex-direction: row;
  gap: var(--sp-2);
}
.bpb__row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-xs);
}
.bpb__row--wide {
  flex-direction: column;
  align-items: stretch;
}
.bpb__row-label {
  width: 78px;
  flex-shrink: 0;
  color: var(--c-ink-2);
}
.bpb__row--wide .bpb__row-label {
  width: auto;
}
.bpb__grid2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-2);
}
.bpb__grid2 .bpb__row-label {
  width: 54px;
}
.bpb__input {
  flex: 1;
  min-width: 0;
  border: var(--border);
  border-radius: var(--r-sm);
  background: var(--c-bg);
  color: var(--c-ink);
  font-size: var(--fs-xs);
  padding: 4px var(--sp-2);
}
.bpb__input--num {
  width: 100%;
}
.bpb__textarea {
  min-height: 72px;
  resize: vertical;
  font-family: inherit;
}
.bpb__id {
  font-family: var(--font-mono, monospace);
  font-size: var(--fs-2xs);
  color: var(--c-ink-3);
}
.bpb__warn {
  font-size: var(--fs-2xs);
  color: var(--c-danger, #c0392b);
  margin: 0;
}
.bpb__checks {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}
.bpb__check {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-xs);
  color: var(--c-ink-2);
}

/* Select options editor */
.bpb__opts {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}
.bpb__opt {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
}
.bpb__opt-del {
  border: 0;
  background: transparent;
  color: var(--c-ink-3);
  cursor: pointer;
  border-radius: var(--r-pill);
  padding: 2px;
}
.bpb__opt-del:hover {
  color: var(--c-danger, #c0392b);
}
.bpb__opt-add {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  border: var(--border);
  border-radius: var(--r-pill);
  background: var(--c-bg);
  color: var(--c-ink-2);
  font-size: var(--fs-2xs);
  padding: 4px var(--sp-2);
  cursor: pointer;
  align-self: flex-start;
}
.bpb__opt-add:hover {
  background: var(--c-surface-hover);
}

@media (max-width: 900px) {
  .bpb__body {
    grid-template-columns: 1fr;
  }
}

/* Lock panel */
.bp__lock {
  max-width: 560px;
  border: var(--border);
  border-radius: var(--r-lg);
  background: var(--c-surface);
  padding: var(--sp-6);
  margin-bottom: var(--sp-5);
}
.bp__lock-title {
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  margin-bottom: var(--sp-2);
}
.bp__lock p {
  color: var(--c-ink-2);
  font-size: var(--fs-sm);
  margin: 0 0 var(--sp-4);
}
.bp__lock-actions {
  display: flex;
  gap: var(--sp-2);
}
.bp__lock-canvas {
  flex-direction: column;
  align-items: center;
}
.bp-surface--muted {
  opacity: 0.6;
  pointer-events: none;
}

/* =====================================================================
 * P3 — assistant proposal overlay (Blueprint layout preview + diff)
 * ===================================================================== */

/* Wider overlay panel so the rendered preview has room. */
.proposal-overlay__panel--wide {
  width: min(760px, 100%);
}

/* Locked-blueprint banner inside the overlay. */
.bp-proposal__lock {
  color: var(--c-ink-2);
  font-size: var(--fs-sm);
}

/* Rendered preview of the proposed layout (card mode). */
.bp-proposal__preview {
  padding: var(--sp-4);
  border-bottom: var(--border);
}
.bp-proposal__preview .bp-surface {
  background: var(--c-surface-2);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
}

/* =====================================================================
 * Blueprint stage — floating assistant (1/3) + floating editor (2/3)
 * over a neutral gradient app-stage. Both cards have --r-2xl rounding,
 * --shadow-md, and --gap-edge gaps on all sides + between them.
 * ===================================================================== */

.blueprint-stage {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-rows: minmax(0, 1fr);
  gap: var(--gap-edge);
  padding: var(--gap-edge);
  background: linear-gradient(135deg, var(--c-bg-sunken) 0%, var(--c-surface) 100%);
  /* Do NOT transition grid-template-columns: animating `fr` units is poorly
   * specified and, during frequent reflows (e.g. the assistant streaming a
   * reply), visibly drifts the track widths. The focused↔split transition is
   * carried entirely by the .blueprint-base opacity/transform glide below —
   * the column collapse itself is instant and imperceptible (the base is
   * already faded/slided out by the time it happens). */
}

/* Focused landing state: only the assistant is shown, centered in the
 * viewport width. The blueprint-base column collapses to 0fr (its host stays
 * mounted so the editor isn't torn down — just visually hidden). */
.blueprint-stage.is-focused {
  grid-template-columns: 1fr 0fr;
  gap: 0;
}

/* The editor fills its grid cell as a floating rounded card. */
.blueprint-stage .blueprint-base {
  position: relative;
  inset: auto;
  width: 100%;
  height: 100%;
  min-height: 0;
  min-width: 0;
  border: var(--border);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  /* Premium glide-in: opacity + translate carry the focused↔split reveal.
   * No will-change (it promotes the base to a compositor layer at rest and
   * can cause sub-pixel rounding drift on the sibling assistant column). */
  transform: translateX(0);
  transition: opacity var(--t-reveal), transform var(--t-reveal);
}
/* Focused state: the base is hidden (column collapsed to 0fr). Fade + slide
 * it out so the reveal feels intentional rather than a sudden clip. */
.blueprint-stage.is-focused .blueprint-base {
  opacity: 0;
  transform: translateX(64px);
  pointer-events: none;
}

/* The assistant host is a grid item; propagate its stretched height down to
 * the .assistant panel through the imperative wrapper divs created by
 * mountAssistant (host > div > .assistant). min-width: 0 lets the 1fr column
 * shrink below its content's natural width (CSS Grid min-width:auto default).
 *
 * NB: do NOT set margin-inline:auto or max-width here without an explicit
 * width:100% — auto-margins flip a grid item's alignment from `stretch` to
 * content-sized, so without a fixed width the host shrinks to its content's
 * preferred width (which changes on every streamed chunk) and the whole
 * assistant visibly bounces in width while responding. The centered-cap is
 * scoped to .is-focused below, where width:100% pins it stable. */
.blueprint-stage .assistant-host,
.board-stage .assistant-host {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}
/* Focused landing state only: the assistant column expands to full viewport
 * width (1fr 0fr), so cap + center it for a comfortable reading measure. The
 * explicit width:100% keeps the grid item stretch-aligned (not content-sized)
 * so streaming a reply can't change its width. */
.blueprint-stage.is-focused .assistant-host {
  width: 100%;
  max-width: 640px;
  margin-inline: auto;
}
.blueprint-stage .assistant-host > div,
.blueprint-stage .assistant-host > div > div,
.board-stage .assistant-host > div,
.board-stage .assistant-host > div > div {
  flex: 1 1 0;
  min-height: 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* The assistant floats as a rounded card in its grid cell, always visible
 * (no FAB, no open transition). Overrides the default absolutely-positioned
 * floating panel shape from assistant.css. */
.blueprint-stage .assistant,
.blueprint-stage .assistant.is-open {
  position: relative;
  top: auto;
  left: auto;
  right: auto;
  bottom: auto;
  width: 100%;
  flex: 1 1 0;
  min-height: 0;
  max-width: none;
  border: var(--border);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-md);
  transform: none;
  opacity: 1;
  pointer-events: auto;
}

/* No floating FAB in the Blueprint stage — the panel is always present. */
.blueprint-stage .assistant-fab {
  display: none;
}

/* =====================================================================
 * Board stage — mirrors the blueprint stage: floating assistant (1/3) +
 * floating board editor (2/3) over a neutral gradient app-stage.
 * ===================================================================== */
.board-stage {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-rows: minmax(0, 1fr);
  gap: var(--gap-edge);
  padding: var(--gap-edge);
  background: linear-gradient(135deg, var(--c-bg-sunken) 0%, var(--c-surface) 100%);
}
.board-stage .board-base {
  position: relative;
  inset: auto;
  width: 100%;
  height: 100%;
  min-height: 0;
  min-width: 0;
  border: var(--border);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.board-stage .board-base .board-editor {
  height: 100%;
  padding: var(--sp-4);
}
.board-stage .assistant,
.board-stage .assistant.is-open {
  position: relative;
  top: auto;
  left: auto;
  right: auto;
  bottom: auto;
  width: 100%;
  flex: 1 1 0;
  min-height: 0;
  max-width: none;
  border: var(--border);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-md);
  transform: none;
  opacity: 1;
  pointer-events: auto;
}
.board-stage .assistant-fab {
  display: none;
}

/* ---- Context-switch wipe over the whole main pane -------------------- */
.bp__main-sweep {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  background:
    linear-gradient(
      105deg,
      transparent 0%,
      rgba(255, 255, 255, 0.82) 42%,
      var(--c-accent-soft) 50%,
      rgba(255, 255, 255, 0.82) 58%,
      transparent 100%
    ),
    rgba(255, 255, 255, 0.6);
  background-size: 220% 100%;
  animation: assistant-context-sweep 0.72s ease-in-out forwards;
}

/* ---- Table-node editor (dock Blueprint picker + records) ---- */
.tne__wrap {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  height: 100%;
}
.tne__tabs {
  flex: 0 0 auto;
}
.tne__pane {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}
.tne {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-3);
}
.tne__lead {
  margin: 0;
  color: var(--c-text-2);
  font-size: var(--fs-sm);
}
.tne__label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--c-text-2);
}
.tne__select {
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border: var(--bw) solid var(--c-line-2);
  border-radius: var(--r-lg);
  background: var(--c-surface-1);
  color: var(--c-text-1);
}
.tne__actions {
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
.tne__hint {
  font-size: var(--fs-sm);
}

/* ---- Public hosted Blueprint form ---- */
.bp-public-grid {
  width: 100%;
  padding: 1rem;
}
.analyzer-hint {
  margin: var(--sp-1) 0 var(--sp-2);
  font-size: var(--fs-sm);
}

/* ---- Blueprint-record board card (card-mode grid inside a tile/drawer) ---- */
.board-bp-card {
  width: 100%;
  border: var(--border);
  border-radius: var(--r-2xl);
  padding: 1rem;
}
.board-bp-card .bp-grid {
  width: 100%;
}

/* ---- New data cell types ---- */
/* The native `<select>` trigger is no longer used by `select`/`rating` cells —
 * they render the custom `.bp-custom-select` widget instead. The rule is kept
 * (and inert) so any stray `.bp-select`-classed element doesn't pick up the
 * old background chevron that would clash with the new control. */
.bp-select {
  appearance: none;
  background-image: none;
  padding-right: 0;
}

/* =====================================================================
 * Blueprint custom select — app-styled single-value dropdown used by `select`
 * and `rating` cells in form, card, and edit-preview contexts. The popup is
 * portaled to <body> with `position: fixed` (see bp-custom-select.js) so it is
 * never clipped by `.proposal-overlay__panel { overflow: scroll }` or any
 * ancestor `transform`/`clip`.
 * ===================================================================== */
.bp-custom-select {
  position: relative;
  display: block;
  width: 100%;
  font: inherit;
  color: inherit;
}
/* The hidden native bridge <select> carrying data-bp-input/data-field/…
 * is invisible-but-present so `recompute` / `collectData` + the fill-overlay
 * alternative-pill driver keep working unchanged. */
.bp-custom-select__bridge {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
  opacity: 0 !important;
  pointer-events: none !important;
}
.bp-custom-select__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  width: 100%;
  min-height: 36px;
  padding: 0 10px;
  border: var(--border-2);
  border-radius: var(--r-pill);
  background: var(--c-surface);
  color: var(--c-ink);
  font-size: var(--fs-sm);
  font-family: inherit;
  line-height: 1.2;
  cursor: pointer;
  text-align: left;
  transition: border-color var(--t-base), box-shadow var(--t-base), background var(--t-fast);
  outline: none;
}
.bp-custom-select__trigger:hover {
  border-color: var(--c-line-strong);
  background: var(--c-surface-2);
}
.bp-custom-select__trigger:focus,
.bp-custom-select.is-open .bp-custom-select__trigger {
  border-color: var(--c-accent);
  box-shadow: 0 0 0 3px var(--c-accent-soft);
  background: var(--c-surface);
}
.bp-custom-select__value {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bp-custom-select__value.bp-custom-select__placeholder {
  color: var(--c-ink-3);
  font-style: italic;
}
.bp-custom-select__chevron {
  flex: 0 0 auto;
  color: var(--c-ink-3);
  transition: transform var(--t-base);
}
.bp-custom-select.is-open .bp-custom-select__chevron {
  transform: rotate(180deg);
}

/* Portaled dropdown — lives on <body>, fixed-positioned by JS. */
.bp-custom-select__dropdown {
  z-index: var(--z-menu);
  background: var(--c-surface);
  border: var(--border-2);
  border-color: var(--c-line-strong);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  overflow-y: auto;
  max-height: 260px;
  padding: var(--sp-1) 0;
  animation: bp-cs-drop 0.16s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}
@keyframes bp-cs-drop {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.bp-custom-select__option {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  padding: 6px var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--c-ink);
  cursor: pointer;
  user-select: none;
  text-align: left;
  border-left: 2px solid transparent;
}
.bp-custom-select__option:hover,
.bp-custom-select__option.is-focused {
  background: var(--c-surface-hover);
}
.bp-custom-select__option.is-selected {
  background: var(--c-accent-soft);
  border-left-color: var(--c-accent);
  font-weight: var(--fw-medium);
  color: var(--c-ink);
}
.bp-custom-select__option-check {
  flex: 0 0 auto;
  color: var(--c-accent);
  opacity: 0;
}
.bp-custom-select__option.is-selected .bp-custom-select__option-check {
  opacity: 1;
}
.bp-custom-select__option-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Make the custom select fill the cell like the inputs it replaced. */
.bp-field__control .bp-custom-select,
.bp-cell .bp-custom-select {
  width: 100%;
}
.bp-textarea {
  resize: vertical;
  min-height: 60px;
  font-family: inherit;
  line-height: 1.4;
  white-space: pre-wrap;
}
.bp-checkbox {
  width: 18px;
  height: 18px;
  accent-color: var(--c-accent);
  cursor: pointer;
}
.bp-rating {
  appearance: none;
  cursor: pointer;
}
.bp-cell__img {
  max-width: 100%;
  height: auto;
  border-radius: var(--r-sm);
  border: 1px solid var(--c-border);
  display: block;
}
.bp-cell__link {
  color: var(--c-accent);
  text-decoration: none;
  word-break: break-all;
}
.bp-cell__link:hover {
  text-decoration: underline;
}
.bp-source-links {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-1);
  width: 100%;
}

/* ---- Divider & spacer static cells ---- */
.bp-cell--divider {
  padding: 0;
  min-height: 0;
  align-self: center;
  border: none;
  border-top: var(--border);
  height: 1px;
}
.bp-cell--spacer {
  padding: 0;
  min-height: 0;
  border: none;
  background: transparent;
}

/* ---- Chart cells (Chart.js for bar/line/pie/donut; SVG for gauge/sparkline — see blueprint-chart.js) ---- */
.bp-cell__chart {
  width: 100%;
  min-height: 180px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.bp-cell__chart-inner {
  width: 100%;
  height: 100%;
}
.bp-cell__chart-canvas {
  width: 100% !important;
  height: 100% !important;
}
.bp-chart {
  display: block;
  width: 100%;
  height: 100%;
  max-height: 240px;
}
.bp-chart-title {
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  fill: var(--c-text);
}
.bp-chart-label {
  font-size: 10px;
  fill: var(--c-text-muted);
}
.bp-chart-value {
  font-size: 10px;
  fill: var(--c-text-muted);
  font-weight: var(--fw-medium);
}
.bp-chart-axis {
  opacity: 0.6;
}
.bp-chart-bar {
  transition: opacity 0.15s;
}
.bp-chart-bar:hover {
  opacity: 0.8;
}
.bp-chart-slice {
  transition: opacity 0.15s;
}
.bp-chart-slice:hover {
  opacity: 0.85;
}
.bp-chart-dot {
  transition: r 0.15s;
}
.bp-chart-dot:hover {
  r: 5;
}
.bp-chart-gauge-text {
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  fill: var(--c-text);
}

/* ---- Per-cell proposal overlay badges ---- */
.bp-proposal-cell {
  position: relative;
}
.bp-proposal-cell--pending {
  outline: 2px solid var(--c-accent);
  outline-offset: -2px;
}
.bp-proposal-cell--accepted {
  outline: 2px solid var(--c-success, #22c55e);
  outline-offset: -2px;
}
.bp-proposal-cell--rejected {
  opacity: 0.4;
  outline: 2px solid var(--c-danger, #ef4444);
  outline-offset: -2px;
}
.bp-proposal-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 50%;
  font-size: 11px;
  font-weight: var(--fw-bold);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 5;
  padding: 0;
  line-height: 1;
}
.bp-proposal-badge--pending {
  background: var(--c-accent);
  color: var(--c-surface);
}
.bp-proposal-badge--accepted {
  background: var(--c-success, #22c55e);
  color: white;
}
.bp-proposal-badge--rejected {
  background: var(--c-danger, #ef4444);
  color: white;
}
.bp-proposal__layout-ops {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-top: 1px solid var(--c-border);
}
.bp-proposal__layout-label {
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
  flex: 1;
}

/* ---- Fill proposal overlay ---- */
.proposal-overlay__reply {
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--c-text);
  border-bottom: 1px solid var(--c-border);
  max-height: 120px;
  overflow-y: auto;
}
.proposal-overlay__reply p {
  margin: 0 0 var(--sp-1);
}
.proposal-overlay__reply p:last-child {
  margin-bottom: 0;
}
.bp-fill-alts {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 4px 0 0;
}
.bp-fill-alt {
  font-size: var(--fs-xs);
  padding: 2px 8px;
  border: 1px solid var(--c-border);
  border-radius: var(--r-sm);
  background: var(--c-surface);
  color: var(--c-text-muted);
  cursor: pointer;
}
.bp-fill-alt:hover {
  border-color: var(--c-accent);
  color: var(--c-accent);
}

/* =========================================================== Repeatable groups
   "Add row" button + per-row controls for repeatable line-item groups.
*/
.bp-repeatable__add {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-1) 0;
}
.bp-repeatable__add-btn {
  font-size: var(--fs-sm);
  color: var(--c-accent);
  background: transparent;
  border: 1px dashed var(--c-border);
  border-radius: var(--r-md);
  padding: var(--sp-1) var(--sp-3);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.bp-repeatable__add-btn:hover {
  border-color: var(--c-accent);
  background: var(--c-surface-2);
}
.bp-repeatable__add.is-disabled {
  opacity: 0.5;
}
.bp-repeatable__add-label {
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
}

/* =====================================================================
 * Compact Intelligent I/O widget — public blueprint form variant
 * The file-zone is an inline pill sitting in a flex row with the prompt
 * textarea and the Analyze button, so the whole widget is one line tall
 * (plus the status line below). Loaded after public-form.css so these
 * override the default (stacked) .io-widget layout.
 * ===================================================================== */

.pb-io-section .io-widget--compact {
  padding: var(--sp-3) var(--sp-4);
  gap: var(--sp-2);
}

.io-widget__row {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  width: 100%;
}

/* Prompt textarea grows to fill the row */
.io-widget__row .io-widget__prompt {
  flex: 1 1 auto;
  min-height: 38px;
  resize: none;
}

/* Analyze button stays compact in the row; positioned so the logo can
   overlay it during analysis. */
.io-widget__row .io-widget__btn {
  flex: 0 0 auto;
  white-space: nowrap;
  position: relative;
  overflow: hidden;
}

/* Compact file-zone: inline pill, not the big dashed drop area */
.io-widget__file-zone--compact {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  gap: var(--sp-1);
  border: var(--border-2);
  border-radius: var(--r-pill);
  padding: var(--sp-2) var(--sp-3);
  height: 100px;
  width: 100px;
  background: var(--c-surface);
  overflow: hidden;
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.io-widget__file-zone--compact:hover,
.io-widget__file-zone--compact.is-dragover {
  border-color: var(--c-accent);
  background: var(--c-accent-soft);
}
.io-widget__file-zone--compact.is-analyzing {
  border-color: var(--c-accent);
  background: var(--c-accent-soft);
}

/* Compact content: just the icon + "Add files" label — hidden once files
   are selected (chips take over the file-zone interior). */
.io-widget__file-zone--compact .io-widget__file-content {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-sm);
  color: var(--c-ink-2);
  white-space: nowrap;
}
.io-widget__file-zone--compact.has-files .io-widget__file-content {
  display: none;
}
.io-widget__file-zone--compact .io-widget__file-icon {
  display: inline-flex;
  width: 16px;
  height: 16px;
}
.io-widget__file-zone--compact .io-widget__file-icon svg {
  width: 16px;
  height: 16px;
}
.io-widget__file-zone--compact .io-widget__file-text {
  font-size: var(--fs-sm);
}

/* File chips: overlay INSIDE the file-zone (replacing the content) so three
   small pills fit within the 100×100 boundary. */
.io-widget__file-zone--compact .io-widget__file-list {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: var(--sp-1);
  background: transparent;
  border: 0;
  border-radius: inherit;
  box-shadow: none;
  min-width: 0;
  pointer-events: none;
}
.io-widget__file-zone--compact .io-widget__file-list:empty {
  display: none;
}
/* Chips themselves need pointer events for the remove button */
.io-widget__file-zone--compact .io-widget__file-chip {
  pointer-events: auto;
  font-size: 10px;
  border-radius: var(--r-pill);
  padding: 0 var(--sp-1);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.4;
}
.io-widget__file-zone--compact .io-widget__file-chip-remove {
  font-size: 10px;
  padding: 0 1px;
}

/* ---- Analyzing-logo overlay on the button (compact mode) ---- */
/* Logo is moved into the button via JS (io-widget.js). Hidden by default,
   revealed + animated while .is-analyzing is on the button. Sized 100×100
   to match the button. Span transforms are half the 200px variant values
   from form-preview.css (proportional to the 100px box). */
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  z-index: 10;
  opacity: 0;
  pointer-events: none;
  cursor: default;
  transform: translate(-50%, -50%) scale(0.84);
  transition: opacity 0.35s ease, transform var(--t-io-logo-enter);
}
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo::before,
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo > span {
  position: absolute;
  top: 50%;
  left: 50%;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  animation: none;
}
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo::before {
  content: "";
  width: 100%;
  height: 100%;
  background: radial-gradient(circle, #1a1a1a 60%, #0a0a0a 100%);
}
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo > span:nth-child(1) {
  width: 90%;
  height: 90%;
  z-index: 300;
  background: transparent;
  border: 3.5px solid #0a0a0a;
  transform: translate(calc(-50% + 2.58px), calc(-50% + 2.58px));
}
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo > span:nth-child(2) {
  width: 80%;
  height: 80%;
  background: radial-gradient(circle, #444444 55%, #1a1a1a 100%);
  transform: translate(calc(-50% + 5.19px), calc(-50% + 5.19px));
}
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo > span:nth-child(3) {
  width: 68%;
  height: 68%;
  background: radial-gradient(circle, #5a5a5a 55%, #444444 100%);
  transform: translate(calc(-50% + 7.78px), calc(-50% + 7.78px));
}
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo > span:nth-child(4) {
  width: 56%;
  height: 56%;
  background: radial-gradient(circle, #707070 55%, #5a5a5a 100%);
  transform: translate(calc(-50% + 10.36px), calc(-50% + 10.36px));
}
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo > span:nth-child(5) {
  width: 44%;
  height: 44%;
  background: radial-gradient(circle, #868686 55%, #707070 100%);
  transform: translate(calc(-50% + 12.97px), calc(-50% + 12.97px));
}
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo > span:nth-child(6) {
  width: 34%;
  height: 34%;
  background: radial-gradient(circle, #9b9b9b 55%, #868686 100%);
  transform: translate(calc(-50% + 15.56px), calc(-50% + 15.56px));
}
.io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo > span:nth-child(7) {
  width: 24%;
  height: 24%;
  background: #b5b5b5;
  transform: translate(calc(-50% + 18.14px), calc(-50% + 18.14px));
}

/* Reveal + pulse while analyzing. The button swaps to a light surface so
   the logo's dark gradient rings stay visible, and opacity:1 overrides the
   :disabled dimming while the logo is shown. */
.io-widget--compact .io-widget__btn.is-analyzing {
  background: var(--c-surface);
  color: var(--c-ink);
  opacity: 1;
}
.io-widget--compact .io-widget__btn.is-analyzing .io-widget__file-logo.app-brand__logo {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
.io-widget--compact .io-widget__btn.is-analyzing .io-widget__file-logo.app-brand__logo::before,
.io-widget--compact .io-widget__btn.is-analyzing .io-widget__file-logo.app-brand__logo > span {
  animation: io-logo-pulse 1.35s ease-in-out infinite;
}
.io-widget--compact
  .io-widget__btn.is-analyzing
  .io-widget__file-logo.app-brand__logo
  > span:nth-child(7) {
  animation-delay: 0s;
}
.io-widget--compact
  .io-widget__btn.is-analyzing
  .io-widget__file-logo.app-brand__logo
  > span:nth-child(6) {
  animation-delay: 0.08s;
}
.io-widget--compact
  .io-widget__btn.is-analyzing
  .io-widget__file-logo.app-brand__logo
  > span:nth-child(5) {
  animation-delay: 0.16s;
}
.io-widget--compact
  .io-widget__btn.is-analyzing
  .io-widget__file-logo.app-brand__logo
  > span:nth-child(4) {
  animation-delay: 0.24s;
}
.io-widget--compact
  .io-widget__btn.is-analyzing
  .io-widget__file-logo.app-brand__logo
  > span:nth-child(3) {
  animation-delay: 0.32s;
}
.io-widget--compact
  .io-widget__btn.is-analyzing
  .io-widget__file-logo.app-brand__logo
  > span:nth-child(2) {
  animation-delay: 0.4s;
}
.io-widget--compact
  .io-widget__btn.is-analyzing
  .io-widget__file-logo.app-brand__logo
  > span:nth-child(1) {
  animation-delay: 0.48s;
}
.io-widget--compact .io-widget__btn.is-analyzing .io-widget__file-logo.app-brand__logo::before {
  animation-delay: 0.56s;
}

@keyframes io-logo-pulse {
  0%, 100% {
    filter: brightness(1);
  }
  50% {
    filter: brightness(1.65);
  }
}

/* Done: flash + scale-past + fade (source-ordered after .is-analyzing). */
.io-widget--compact .io-widget__btn.is-complete .io-widget__file-logo.app-brand__logo {
  animation: io-logo-complete var(--t-io-logo-exit) forwards;
}

@keyframes io-logo-complete {
  0% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
    filter: brightness(1.9);
  }
  60% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1.04);
    filter: brightness(1.4);
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.84);
    filter: brightness(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo::before,
  .io-widget--compact .io-widget__btn .io-widget__file-logo.app-brand__logo > span,
  .io-widget--compact .io-widget__btn.is-complete .io-widget__file-logo.app-brand__logo {
    animation: none;
  }
}

/* Status line below the row */
.io-widget--compact .io-widget__status {
  font-size: var(--fs-xs);
}

/* ---- Manage exposure dialog ---- */
.bp-exposure__statuses {
  display: inline-flex;
  border: var(--border-2);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.bp-exposure__slug {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  border: var(--border);
  border-radius: var(--r-sm);
  padding: var(--sp-1) var(--sp-2);
  background: var(--c-surface-2);
}
.bp-exposure__slug .muted {
  font-family: var(--font-mono, monospace);
  font-size: var(--fs-xs);
  white-space: nowrap;
}
.bp-exposure__slug .input {
  border: 0;
  background: transparent;
  font: inherit;
  outline: none;
  flex: 1;
  min-width: 0;
}
.bp-exposure__url {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.bp-exposure__url code {
  font-family: var(--font-mono, monospace);
  font-size: var(--fs-xs);
  color: var(--c-ink-2);
  background: var(--c-surface-2);
  border: var(--border);
  border-radius: var(--r-sm);
  padding: var(--sp-1) var(--sp-2);
  flex: 1;
  min-width: 0;
  word-break: break-all;
}

/* ---- Multi-select (checkbox group) ----
 * A compact vertical stack of pill-style checkbox labels rendered inside a
 * data cell's control slot. Each label wraps a hidden native checkbox (kept
 * for collection semantics) + a square indicator + the option text. Sits
 * inside .bp-field__control so it inherits the field's padding and stretches
 * to the cell width. Use the cell's rowSpan to grow the field when there
 * are many options; the cell auto-shows a scrollbar when its row-track
 * height caps the option list.
 */
.bp-multi {
  width: 100%;
  padding: var(--sp-1) 0;
  max-height: 100%;
  overflow: auto;
  /* Auto-fit pill grid: 2 columns when roomy, degrades to 1 column on
   * narrow cells (label-value pairs in 2-column layouts). */
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: var(--sp-2);
  align-content: start;
}
.bp-multi__opt {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-2);
  border: var(--bw) solid var(--c-line-2);
  border-radius: var(--r-lg);
  background: var(--c-surface);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
  min-width: 0;
}
.bp-multi__opt:hover {
  border-color: var(--c-line-strong);
  background: var(--c-surface-2);
}
.bp-multi__opt.is-checked {
  border-color: var(--c-accent);
  background: var(--c-accent-soft);
  color: var(--c-ink);
}
.bp-multi__input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  margin: 0;
  pointer-events: none; /* the label handles clicks */
}
.bp-multi__opt:focus-within {
  outline: 2px solid var(--c-accent);
  outline-offset: 1px;
}
.bp-multi__box {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border: 1.5px solid var(--c-line-strong);
  border-radius: 4px;
  background: var(--c-surface);
  position: relative;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.bp-multi__opt.is-checked .bp-multi__box {
  border-color: var(--c-accent);
  background: var(--c-accent);
}
.bp-multi__opt.is-checked .bp-multi__box::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 4px;
  height: 8px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: translate(-50%, -60%) rotate(45deg);
}
.bp-multi__label {
  font-size: var(--fs-xs);
  color: var(--c-ink-2);
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bp-multi__opt.is-checked .bp-multi__label {
  color: var(--c-ink);
  font-weight: var(--fw-medium);
}
.bp-multi__empty {
  color: var(--c-ink-3);
  font-size: var(--fs-xs);
  font-style: italic;
  padding: var(--sp-1) var(--sp-2);
}

/* Read-only card display for a multi-select (already joined by the renderer
 * into a .bp-cell__value span — no extra styling needed, but keep the option
 * list compact when card mode shows the raw checkbox group container). */
.bp-cell--data .bp-multi {
  pointer-events: none;
}

/* =====================================================================
 * Mobile reflow (<600px viewport) — auto-flow every runtime blueprint grid
 * into 2 columns. Wide cells (colSpan > 1) snap to a full-width row of
 * their own; narrow cells (colSpan == 1) pack 2-per-row. Group backing
 * panels (fixed grid-row placement that can't track flowing cells) are
 * hidden; IO-suggestion pills and repeatable "Add row" buttons stack as
 * full-width rows. The visual builder edit grid (.is-edit) is excluded.
 * The renderer's inline grid-column/grid-row/grid-template-columns carry
 * the desktop layout — !important neutralizes them on mobile only.
 * ===================================================================== */
@media (max-width: 600px) {
  .bp-grid:not(.is-edit) {
    grid-template-columns: repeat(2, 1fr) !important;
    grid-auto-flow: row;
    row-gap: var(--sp-3);
  }
  .bp-grid:not(.is-edit) > .bp-cell,
  .bp-grid:not(.is-edit) > .bp-field {
    grid-row: auto !important;
    grid-column: auto !important;
    /* Spatial order from the renderer's --bp-r/--bp-c custom props so
       auto-flowed layout matches authored sequence even when the cells
       array isn't sorted (proposal appends arrive in insertion order).
       --bp-c is a same-row tiebreaker so two narrow cells pack left-first. */
    order: calc(var(--bp-r, 0) * 1000 + var(--bp-c, 0));
  }
  .bp-grid:not(.is-edit) > .bp-cell[data-cs="1"],
  .bp-grid:not(.is-edit) > .bp-field[data-cs="1"] {
    grid-column: span 1 !important;
  }
  .bp-grid:not(.is-edit) > .bp-cell[data-cs]:not([data-cs="1"]),
  .bp-grid:not(.is-edit) > .bp-field[data-cs]:not([data-cs="1"]) {
    grid-column: 1 / -1 !important;
  }
  .bp-grid:not(.is-edit) > .bp-group {
    display: none;
  }
  .bp-grid:not(.is-edit) > .io-alts-slot,
  .bp-grid:not(.is-edit) > .bp-repeatable__add {
    grid-column: 1 / -1 !important;
    grid-row: auto !important;
    /* Same spatial ordering axis (Add-row carries r+0.5; pill slots r-0.5). */
    order: calc(var(--bp-r, 0) * 1000);
  }
}
